@falai/agent 3.4.4 → 4.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -34
- package/dist/cjs/core/Agent.d.ts +22 -378
- package/dist/cjs/core/Agent.d.ts.map +1 -1
- package/dist/cjs/core/Agent.js +104 -1178
- package/dist/cjs/core/Agent.js.map +1 -1
- package/dist/cjs/core/CompactionEngine.d.ts.map +1 -1
- package/dist/cjs/core/CompactionEngine.js +5 -3
- package/dist/cjs/core/CompactionEngine.js.map +1 -1
- package/dist/cjs/core/FlowSpec.d.ts +136 -0
- package/dist/cjs/core/FlowSpec.d.ts.map +1 -0
- package/dist/cjs/core/FlowSpec.js +522 -0
- package/dist/cjs/core/FlowSpec.js.map +1 -0
- package/dist/cjs/core/Migrate.d.ts +38 -0
- package/dist/cjs/core/Migrate.d.ts.map +1 -0
- package/dist/cjs/core/Migrate.js +270 -0
- package/dist/cjs/core/Migrate.js.map +1 -0
- package/dist/cjs/core/Prompt.d.ts +54 -0
- package/dist/cjs/core/Prompt.d.ts.map +1 -0
- package/dist/cjs/core/Prompt.js +143 -0
- package/dist/cjs/core/Prompt.js.map +1 -0
- package/dist/cjs/core/Runner.d.ts +160 -0
- package/dist/cjs/core/Runner.d.ts.map +1 -0
- package/dist/cjs/core/Runner.js +1131 -0
- package/dist/cjs/core/Runner.js.map +1 -0
- package/dist/cjs/core/Speak.d.ts +37 -0
- package/dist/cjs/core/Speak.d.ts.map +1 -0
- package/dist/cjs/core/Speak.js +364 -0
- package/dist/cjs/core/Speak.js.map +1 -0
- package/dist/cjs/core/Understand.d.ts +28 -0
- package/dist/cjs/core/Understand.d.ts.map +1 -0
- package/dist/cjs/core/Understand.js +353 -0
- package/dist/cjs/core/Understand.js.map +1 -0
- package/dist/cjs/core/contracts.d.ts +122 -0
- package/dist/cjs/core/contracts.d.ts.map +1 -0
- package/dist/cjs/core/contracts.js +11 -0
- package/dist/cjs/core/contracts.js.map +1 -0
- package/dist/cjs/core/falai.d.ts +57 -0
- package/dist/cjs/core/falai.d.ts.map +1 -0
- package/dist/cjs/core/falai.js +43 -0
- package/dist/cjs/core/falai.js.map +1 -0
- package/dist/cjs/core/predicate.d.ts +9 -0
- package/dist/cjs/core/predicate.d.ts.map +1 -0
- package/dist/cjs/core/predicate.js +58 -0
- package/dist/cjs/core/predicate.js.map +1 -0
- package/dist/cjs/index.d.ts +26 -31
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +46 -68
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/persistence/MemoryStore.d.ts +15 -0
- package/dist/cjs/persistence/MemoryStore.d.ts.map +1 -0
- package/dist/cjs/persistence/MemoryStore.js +39 -0
- package/dist/cjs/persistence/MemoryStore.js.map +1 -0
- package/dist/cjs/persistence/MongoStore.d.ts +42 -0
- package/dist/cjs/persistence/MongoStore.d.ts.map +1 -0
- package/dist/cjs/persistence/MongoStore.js +60 -0
- package/dist/cjs/persistence/MongoStore.js.map +1 -0
- package/dist/cjs/persistence/OpenSearchStore.d.ts +86 -0
- package/dist/cjs/persistence/OpenSearchStore.d.ts.map +1 -0
- package/dist/cjs/persistence/OpenSearchStore.js +120 -0
- package/dist/cjs/persistence/OpenSearchStore.js.map +1 -0
- package/dist/cjs/persistence/PostgresStore.d.ts +41 -0
- package/dist/cjs/persistence/PostgresStore.d.ts.map +1 -0
- package/dist/cjs/persistence/PostgresStore.js +58 -0
- package/dist/cjs/persistence/PostgresStore.js.map +1 -0
- package/dist/cjs/persistence/PrismaStore.d.ts +65 -0
- package/dist/cjs/persistence/PrismaStore.d.ts.map +1 -0
- package/dist/cjs/persistence/PrismaStore.js +95 -0
- package/dist/cjs/persistence/PrismaStore.js.map +1 -0
- package/dist/cjs/persistence/RedisStore.d.ts +34 -0
- package/dist/cjs/persistence/RedisStore.d.ts.map +1 -0
- package/dist/cjs/persistence/RedisStore.js +61 -0
- package/dist/cjs/persistence/RedisStore.js.map +1 -0
- package/dist/cjs/persistence/SQLiteStore.d.ts +45 -0
- package/dist/cjs/persistence/SQLiteStore.d.ts.map +1 -0
- package/dist/cjs/persistence/SQLiteStore.js +74 -0
- package/dist/cjs/persistence/SQLiteStore.js.map +1 -0
- package/dist/cjs/persistence/sessionRow.d.ts +14 -0
- package/dist/cjs/persistence/sessionRow.d.ts.map +1 -0
- package/dist/cjs/persistence/sessionRow.js +50 -0
- package/dist/cjs/persistence/sessionRow.js.map +1 -0
- package/dist/cjs/providers/DeepSeekProvider.d.ts.map +1 -1
- package/dist/cjs/providers/DeepSeekProvider.js +8 -3
- package/dist/cjs/providers/DeepSeekProvider.js.map +1 -1
- package/dist/cjs/providers/GeminiProvider.d.ts +4 -3
- package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/cjs/providers/GeminiProvider.js +4 -3
- package/dist/cjs/providers/GeminiProvider.js.map +1 -1
- package/dist/cjs/providers/OpenAICompatibleProvider.d.ts +4 -0
- package/dist/cjs/providers/OpenAICompatibleProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenAICompatibleProvider.js +2 -0
- package/dist/cjs/providers/OpenAICompatibleProvider.js.map +1 -1
- package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenRouterProvider.js +2 -4
- package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
- package/dist/cjs/providers/ProviderAdapter.d.ts +1 -1
- package/dist/cjs/providers/ProviderAdapter.d.ts.map +1 -1
- package/dist/cjs/providers/ProviderAdapter.js +33 -10
- package/dist/cjs/providers/ProviderAdapter.js.map +1 -1
- package/dist/cjs/types/agent.d.ts +153 -383
- package/dist/cjs/types/agent.d.ts.map +1 -1
- package/dist/cjs/types/agent.js +1 -1
- package/dist/cjs/types/ai.d.ts +32 -1
- package/dist/cjs/types/ai.d.ts.map +1 -1
- package/dist/cjs/types/compaction.d.ts +3 -1
- package/dist/cjs/types/compaction.d.ts.map +1 -1
- package/dist/cjs/types/errors.d.ts +9 -12
- package/dist/cjs/types/errors.d.ts.map +1 -1
- package/dist/cjs/types/errors.js +14 -17
- package/dist/cjs/types/errors.js.map +1 -1
- package/dist/cjs/types/flow.d.ts +265 -513
- package/dist/cjs/types/flow.d.ts.map +1 -1
- package/dist/cjs/types/flow.js +7 -1
- package/dist/cjs/types/flow.js.map +1 -1
- package/dist/cjs/types/history.d.ts +7 -18
- package/dist/cjs/types/history.d.ts.map +1 -1
- package/dist/cjs/types/history.js.map +1 -1
- package/dist/cjs/types/index.d.ts +9 -15
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/types/index.js +4 -14
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/cjs/types/session.d.ts +94 -64
- package/dist/cjs/types/session.d.ts.map +1 -1
- package/dist/cjs/types/session.js +5 -1
- package/dist/cjs/types/session.js.map +1 -1
- package/dist/cjs/types/tool.d.ts +37 -207
- package/dist/cjs/types/tool.d.ts.map +1 -1
- package/dist/cjs/types/tool.js +5 -14
- package/dist/cjs/types/tool.js.map +1 -1
- package/dist/cjs/utils/clock.d.ts +28 -0
- package/dist/cjs/utils/clock.d.ts.map +1 -0
- package/dist/cjs/utils/clock.js +64 -0
- package/dist/cjs/utils/clock.js.map +1 -0
- package/dist/cjs/utils/duration.d.ts +11 -0
- package/dist/cjs/utils/duration.d.ts.map +1 -0
- package/dist/cjs/utils/duration.js +31 -0
- package/dist/cjs/utils/duration.js.map +1 -0
- package/dist/cjs/utils/history.d.ts +4 -1
- package/dist/cjs/utils/history.d.ts.map +1 -1
- package/dist/cjs/utils/history.js +2 -2
- package/dist/cjs/utils/history.js.map +1 -1
- package/dist/cjs/utils/index.d.ts +4 -10
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +14 -61
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/json.d.ts +2 -0
- package/dist/cjs/utils/json.d.ts.map +1 -1
- package/dist/cjs/utils/json.js +5 -0
- package/dist/cjs/utils/json.js.map +1 -1
- package/dist/cjs/utils/outcomes.d.ts +48 -0
- package/dist/cjs/utils/outcomes.d.ts.map +1 -0
- package/dist/cjs/utils/outcomes.js +51 -0
- package/dist/cjs/utils/outcomes.js.map +1 -0
- package/dist/cjs/utils/schema.d.ts +50 -0
- package/dist/cjs/utils/schema.d.ts.map +1 -0
- package/dist/cjs/utils/schema.js +138 -0
- package/dist/cjs/utils/schema.js.map +1 -0
- package/dist/cjs/utils/streamingMessage.d.ts +3 -2
- package/dist/cjs/utils/streamingMessage.d.ts.map +1 -1
- package/dist/cjs/utils/streamingMessage.js +38 -4
- package/dist/cjs/utils/streamingMessage.js.map +1 -1
- package/dist/cjs/utils/template.d.ts +13 -149
- package/dist/cjs/utils/template.d.ts.map +1 -1
- package/dist/cjs/utils/template.js +31 -363
- package/dist/cjs/utils/template.js.map +1 -1
- package/dist/cjs/utils/usage.d.ts +19 -0
- package/dist/cjs/utils/usage.d.ts.map +1 -0
- package/dist/cjs/utils/usage.js +35 -0
- package/dist/cjs/utils/usage.js.map +1 -0
- package/dist/core/Agent.d.ts +22 -378
- package/dist/core/Agent.d.ts.map +1 -1
- package/dist/core/Agent.js +107 -1181
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/CompactionEngine.d.ts.map +1 -1
- package/dist/core/CompactionEngine.js +5 -3
- package/dist/core/CompactionEngine.js.map +1 -1
- package/dist/core/FlowSpec.d.ts +136 -0
- package/dist/core/FlowSpec.d.ts.map +1 -0
- package/dist/core/FlowSpec.js +516 -0
- package/dist/core/FlowSpec.js.map +1 -0
- package/dist/core/Migrate.d.ts +38 -0
- package/dist/core/Migrate.d.ts.map +1 -0
- package/dist/core/Migrate.js +264 -0
- package/dist/core/Migrate.js.map +1 -0
- package/dist/core/Prompt.d.ts +54 -0
- package/dist/core/Prompt.d.ts.map +1 -0
- package/dist/core/Prompt.js +133 -0
- package/dist/core/Prompt.js.map +1 -0
- package/dist/core/Runner.d.ts +160 -0
- package/dist/core/Runner.d.ts.map +1 -0
- package/dist/core/Runner.js +1127 -0
- package/dist/core/Runner.js.map +1 -0
- package/dist/core/Speak.d.ts +37 -0
- package/dist/core/Speak.d.ts.map +1 -0
- package/dist/core/Speak.js +360 -0
- package/dist/core/Speak.js.map +1 -0
- package/dist/core/Understand.d.ts +28 -0
- package/dist/core/Understand.d.ts.map +1 -0
- package/dist/core/Understand.js +349 -0
- package/dist/core/Understand.js.map +1 -0
- package/dist/core/contracts.d.ts +122 -0
- package/dist/core/contracts.d.ts.map +1 -0
- package/dist/core/contracts.js +10 -0
- package/dist/core/contracts.js.map +1 -0
- package/dist/core/falai.d.ts +57 -0
- package/dist/core/falai.d.ts.map +1 -0
- package/dist/core/falai.js +40 -0
- package/dist/core/falai.js.map +1 -0
- package/dist/core/predicate.d.ts +9 -0
- package/dist/core/predicate.d.ts.map +1 -0
- package/dist/core/predicate.js +54 -0
- package/dist/core/predicate.js.map +1 -0
- package/dist/index.d.ts +26 -31
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -24
- package/dist/index.js.map +1 -1
- package/dist/persistence/MemoryStore.d.ts +15 -0
- package/dist/persistence/MemoryStore.d.ts.map +1 -0
- package/dist/persistence/MemoryStore.js +35 -0
- package/dist/persistence/MemoryStore.js.map +1 -0
- package/dist/persistence/MongoStore.d.ts +42 -0
- package/dist/persistence/MongoStore.d.ts.map +1 -0
- package/dist/persistence/MongoStore.js +56 -0
- package/dist/persistence/MongoStore.js.map +1 -0
- package/dist/persistence/OpenSearchStore.d.ts +86 -0
- package/dist/persistence/OpenSearchStore.d.ts.map +1 -0
- package/dist/persistence/OpenSearchStore.js +116 -0
- package/dist/persistence/OpenSearchStore.js.map +1 -0
- package/dist/persistence/PostgresStore.d.ts +41 -0
- package/dist/persistence/PostgresStore.d.ts.map +1 -0
- package/dist/persistence/PostgresStore.js +54 -0
- package/dist/persistence/PostgresStore.js.map +1 -0
- package/dist/persistence/PrismaStore.d.ts +65 -0
- package/dist/persistence/PrismaStore.d.ts.map +1 -0
- package/dist/persistence/PrismaStore.js +91 -0
- package/dist/persistence/PrismaStore.js.map +1 -0
- package/dist/persistence/RedisStore.d.ts +34 -0
- package/dist/persistence/RedisStore.d.ts.map +1 -0
- package/dist/persistence/RedisStore.js +57 -0
- package/dist/persistence/RedisStore.js.map +1 -0
- package/dist/persistence/SQLiteStore.d.ts +45 -0
- package/dist/persistence/SQLiteStore.d.ts.map +1 -0
- package/dist/persistence/SQLiteStore.js +70 -0
- package/dist/persistence/SQLiteStore.js.map +1 -0
- package/dist/persistence/sessionRow.d.ts +14 -0
- package/dist/persistence/sessionRow.d.ts.map +1 -0
- package/dist/persistence/sessionRow.js +45 -0
- package/dist/persistence/sessionRow.js.map +1 -0
- package/dist/providers/DeepSeekProvider.d.ts.map +1 -1
- package/dist/providers/DeepSeekProvider.js +8 -3
- package/dist/providers/DeepSeekProvider.js.map +1 -1
- package/dist/providers/GeminiProvider.d.ts +4 -3
- package/dist/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/providers/GeminiProvider.js +4 -3
- package/dist/providers/GeminiProvider.js.map +1 -1
- package/dist/providers/OpenAICompatibleProvider.d.ts +4 -0
- package/dist/providers/OpenAICompatibleProvider.d.ts.map +1 -1
- package/dist/providers/OpenAICompatibleProvider.js +2 -0
- package/dist/providers/OpenAICompatibleProvider.js.map +1 -1
- package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
- package/dist/providers/OpenRouterProvider.js +2 -4
- package/dist/providers/OpenRouterProvider.js.map +1 -1
- package/dist/providers/ProviderAdapter.d.ts +1 -1
- package/dist/providers/ProviderAdapter.d.ts.map +1 -1
- package/dist/providers/ProviderAdapter.js +34 -11
- package/dist/providers/ProviderAdapter.js.map +1 -1
- package/dist/types/agent.d.ts +153 -383
- package/dist/types/agent.d.ts.map +1 -1
- package/dist/types/agent.js +1 -1
- package/dist/types/ai.d.ts +32 -1
- package/dist/types/ai.d.ts.map +1 -1
- package/dist/types/compaction.d.ts +3 -1
- package/dist/types/compaction.d.ts.map +1 -1
- package/dist/types/errors.d.ts +9 -12
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/errors.js +12 -15
- package/dist/types/errors.js.map +1 -1
- package/dist/types/flow.d.ts +265 -513
- package/dist/types/flow.d.ts.map +1 -1
- package/dist/types/flow.js +7 -1
- package/dist/types/flow.js.map +1 -1
- package/dist/types/history.d.ts +7 -18
- package/dist/types/history.d.ts.map +1 -1
- package/dist/types/history.js.map +1 -1
- package/dist/types/index.d.ts +9 -15
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -7
- package/dist/types/index.js.map +1 -1
- package/dist/types/session.d.ts +94 -64
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/session.js +5 -1
- package/dist/types/session.js.map +1 -1
- package/dist/types/tool.d.ts +37 -207
- package/dist/types/tool.d.ts.map +1 -1
- package/dist/types/tool.js +6 -13
- package/dist/types/tool.js.map +1 -1
- package/dist/utils/clock.d.ts +28 -0
- package/dist/utils/clock.d.ts.map +1 -0
- package/dist/utils/clock.js +59 -0
- package/dist/utils/clock.js.map +1 -0
- package/dist/utils/duration.d.ts +11 -0
- package/dist/utils/duration.d.ts.map +1 -0
- package/dist/utils/duration.js +26 -0
- package/dist/utils/duration.js.map +1 -0
- package/dist/utils/history.d.ts +4 -1
- package/dist/utils/history.d.ts.map +1 -1
- package/dist/utils/history.js +2 -2
- package/dist/utils/history.js.map +1 -1
- package/dist/utils/index.d.ts +4 -10
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -21
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/json.d.ts +2 -0
- package/dist/utils/json.d.ts.map +1 -1
- package/dist/utils/json.js +4 -0
- package/dist/utils/json.js.map +1 -1
- package/dist/utils/outcomes.d.ts +48 -0
- package/dist/utils/outcomes.d.ts.map +1 -0
- package/dist/utils/outcomes.js +48 -0
- package/dist/utils/outcomes.js.map +1 -0
- package/dist/utils/schema.d.ts +50 -0
- package/dist/utils/schema.d.ts.map +1 -0
- package/dist/utils/schema.js +129 -0
- package/dist/utils/schema.js.map +1 -0
- package/dist/utils/streamingMessage.d.ts +3 -2
- package/dist/utils/streamingMessage.d.ts.map +1 -1
- package/dist/utils/streamingMessage.js +38 -4
- package/dist/utils/streamingMessage.js.map +1 -1
- package/dist/utils/template.d.ts +13 -149
- package/dist/utils/template.d.ts.map +1 -1
- package/dist/utils/template.js +28 -355
- package/dist/utils/template.js.map +1 -1
- package/dist/utils/usage.d.ts +19 -0
- package/dist/utils/usage.d.ts.map +1 -0
- package/dist/utils/usage.js +31 -0
- package/dist/utils/usage.js.map +1 -0
- package/docs/README.md +37 -19
- package/docs/concepts/architecture.md +117 -239
- package/docs/concepts/collection.md +170 -0
- package/docs/concepts/pipeline.md +132 -378
- package/docs/concepts/runs-and-waits.md +192 -0
- package/docs/guides/actions-and-events.md +276 -0
- package/docs/guides/branching.md +119 -208
- package/docs/guides/compaction.md +63 -158
- package/docs/guides/conditions.md +164 -128
- package/docs/guides/error-handling.md +168 -164
- package/docs/guides/flow-control.md +210 -349
- package/docs/guides/flows-from-json.md +224 -0
- package/docs/guides/instructions.md +125 -161
- package/docs/guides/persistence.md +182 -206
- package/docs/guides/streaming.md +50 -114
- package/docs/guides/testing.md +284 -0
- package/docs/guides/triggers.md +401 -0
- package/docs/migration/README.md +8 -15
- package/docs/migration/v1-to-v2.md +1 -1
- package/docs/migration/v2-3-to-v2-4.md +2 -2
- package/docs/migration/v2-6-to-v2-7.md +4 -4
- package/docs/migration/v3-to-v4.md +452 -0
- package/docs/reference/actions-events-conditions.md +396 -0
- package/docs/reference/agent.md +244 -0
- package/docs/reference/branches.md +75 -203
- package/docs/reference/errors.md +188 -144
- package/docs/reference/fields.md +125 -0
- package/docs/reference/flow-spec.md +248 -0
- package/docs/reference/flow.md +104 -192
- package/docs/reference/instruction.md +83 -137
- package/docs/reference/outcomes.md +273 -0
- package/docs/reference/providers.md +525 -302
- package/docs/reference/session.md +210 -0
- package/docs/reference/step.md +194 -312
- package/docs/reference/stores.md +496 -0
- package/docs/reference/tool.md +162 -231
- package/docs/reference/trigger.md +180 -0
- package/docs/rfc/v4-one-flow.md +477 -0
- package/docs/start/01-install.md +59 -44
- package/docs/start/02-first-agent.md +97 -147
- package/docs/start/03-collect-data.md +78 -183
- package/docs/start/04-add-tools.md +159 -227
- package/docs/start/05-go-to-production.md +167 -164
- package/examples/01-quickstart.ts +26 -16
- package/examples/02-fields.ts +75 -0
- package/examples/03-tools.ts +79 -119
- package/examples/04-instructions.ts +60 -87
- package/examples/05-branches.ts +78 -0
- package/examples/06-triggers-and-waits.ts +148 -0
- package/examples/07-streaming.ts +34 -60
- package/examples/08-store-and-migration.ts +97 -0
- package/examples/09-flows-from-json.ts +107 -0
- package/package.json +9 -6
- package/src/core/Agent.ts +116 -1512
- package/src/core/CompactionEngine.ts +7 -4
- package/src/core/FlowSpec.ts +712 -0
- package/src/core/Migrate.ts +256 -0
- package/src/core/Prompt.ts +156 -0
- package/src/core/Runner.ts +1181 -0
- package/src/core/Speak.ts +451 -0
- package/src/core/Understand.ts +422 -0
- package/src/core/contracts.ts +111 -0
- package/src/core/falai.ts +86 -0
- package/src/core/predicate.ts +56 -0
- package/src/index.ts +119 -147
- package/src/persistence/MemoryStore.ts +37 -0
- package/src/persistence/MongoStore.ts +89 -0
- package/src/persistence/OpenSearchStore.ts +153 -0
- package/src/persistence/PostgresStore.ts +89 -0
- package/src/persistence/PrismaStore.ts +127 -0
- package/src/persistence/RedisStore.ts +90 -0
- package/src/persistence/SQLiteStore.ts +103 -0
- package/src/persistence/sessionRow.ts +45 -0
- package/src/providers/DeepSeekProvider.ts +8 -3
- package/src/providers/GeminiProvider.ts +4 -3
- package/src/providers/OpenAICompatibleProvider.ts +6 -0
- package/src/providers/OpenRouterProvider.ts +2 -4
- package/src/providers/ProviderAdapter.ts +36 -8
- package/src/types/agent.ts +124 -397
- package/src/types/ai.ts +33 -1
- package/src/types/compaction.ts +3 -1
- package/src/types/errors.ts +13 -16
- package/src/types/flow.ts +249 -550
- package/src/types/history.ts +7 -20
- package/src/types/index.ts +87 -139
- package/src/types/session.ts +135 -70
- package/src/types/tool.ts +42 -267
- package/src/utils/clock.ts +70 -0
- package/src/utils/duration.ts +33 -0
- package/src/utils/history.ts +3 -2
- package/src/utils/index.ts +8 -66
- package/src/utils/json.ts +5 -0
- package/src/utils/outcomes.ts +56 -0
- package/src/utils/schema.ts +145 -0
- package/src/utils/streamingMessage.ts +34 -4
- package/src/utils/template.ts +32 -423
- package/src/utils/usage.ts +37 -0
- package/dist/adapters/MemoryAdapter.d.ts +0 -47
- package/dist/adapters/MemoryAdapter.d.ts.map +0 -1
- package/dist/adapters/MemoryAdapter.js +0 -204
- package/dist/adapters/MemoryAdapter.js.map +0 -1
- package/dist/adapters/MongoAdapter.d.ts +0 -97
- package/dist/adapters/MongoAdapter.d.ts.map +0 -1
- package/dist/adapters/MongoAdapter.js +0 -196
- package/dist/adapters/MongoAdapter.js.map +0 -1
- package/dist/adapters/OpenSearchAdapter.d.ts +0 -169
- package/dist/adapters/OpenSearchAdapter.d.ts.map +0 -1
- package/dist/adapters/OpenSearchAdapter.js +0 -471
- package/dist/adapters/OpenSearchAdapter.js.map +0 -1
- package/dist/adapters/PostgreSQLAdapter.d.ts +0 -85
- package/dist/adapters/PostgreSQLAdapter.d.ts.map +0 -1
- package/dist/adapters/PostgreSQLAdapter.js +0 -308
- package/dist/adapters/PostgreSQLAdapter.js.map +0 -1
- package/dist/adapters/PrismaAdapter.d.ts +0 -115
- package/dist/adapters/PrismaAdapter.d.ts.map +0 -1
- package/dist/adapters/PrismaAdapter.js +0 -406
- package/dist/adapters/PrismaAdapter.js.map +0 -1
- package/dist/adapters/RedisAdapter.d.ts +0 -72
- package/dist/adapters/RedisAdapter.d.ts.map +0 -1
- package/dist/adapters/RedisAdapter.js +0 -286
- package/dist/adapters/RedisAdapter.js.map +0 -1
- package/dist/adapters/SQLiteAdapter.d.ts +0 -86
- package/dist/adapters/SQLiteAdapter.d.ts.map +0 -1
- package/dist/adapters/SQLiteAdapter.js +0 -337
- package/dist/adapters/SQLiteAdapter.js.map +0 -1
- package/dist/adapters/index.d.ts +0 -17
- package/dist/adapters/index.d.ts.map +0 -1
- package/dist/adapters/index.js +0 -11
- package/dist/adapters/index.js.map +0 -1
- package/dist/adapters/sessionRow.d.ts +0 -22
- package/dist/adapters/sessionRow.d.ts.map +0 -1
- package/dist/adapters/sessionRow.js +0 -48
- package/dist/adapters/sessionRow.js.map +0 -1
- package/dist/cjs/adapters/MemoryAdapter.d.ts +0 -47
- package/dist/cjs/adapters/MemoryAdapter.d.ts.map +0 -1
- package/dist/cjs/adapters/MemoryAdapter.js +0 -208
- package/dist/cjs/adapters/MemoryAdapter.js.map +0 -1
- package/dist/cjs/adapters/MongoAdapter.d.ts +0 -97
- package/dist/cjs/adapters/MongoAdapter.d.ts.map +0 -1
- package/dist/cjs/adapters/MongoAdapter.js +0 -200
- package/dist/cjs/adapters/MongoAdapter.js.map +0 -1
- package/dist/cjs/adapters/OpenSearchAdapter.d.ts +0 -169
- package/dist/cjs/adapters/OpenSearchAdapter.d.ts.map +0 -1
- package/dist/cjs/adapters/OpenSearchAdapter.js +0 -475
- package/dist/cjs/adapters/OpenSearchAdapter.js.map +0 -1
- package/dist/cjs/adapters/PostgreSQLAdapter.d.ts +0 -85
- package/dist/cjs/adapters/PostgreSQLAdapter.d.ts.map +0 -1
- package/dist/cjs/adapters/PostgreSQLAdapter.js +0 -312
- package/dist/cjs/adapters/PostgreSQLAdapter.js.map +0 -1
- package/dist/cjs/adapters/PrismaAdapter.d.ts +0 -115
- package/dist/cjs/adapters/PrismaAdapter.d.ts.map +0 -1
- package/dist/cjs/adapters/PrismaAdapter.js +0 -410
- package/dist/cjs/adapters/PrismaAdapter.js.map +0 -1
- package/dist/cjs/adapters/RedisAdapter.d.ts +0 -72
- package/dist/cjs/adapters/RedisAdapter.d.ts.map +0 -1
- package/dist/cjs/adapters/RedisAdapter.js +0 -290
- package/dist/cjs/adapters/RedisAdapter.js.map +0 -1
- package/dist/cjs/adapters/SQLiteAdapter.d.ts +0 -86
- package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +0 -1
- package/dist/cjs/adapters/SQLiteAdapter.js +0 -341
- package/dist/cjs/adapters/SQLiteAdapter.js.map +0 -1
- package/dist/cjs/adapters/index.d.ts +0 -17
- package/dist/cjs/adapters/index.d.ts.map +0 -1
- package/dist/cjs/adapters/index.js +0 -21
- package/dist/cjs/adapters/index.js.map +0 -1
- package/dist/cjs/adapters/sessionRow.d.ts +0 -22
- package/dist/cjs/adapters/sessionRow.d.ts.map +0 -1
- package/dist/cjs/adapters/sessionRow.js +0 -52
- package/dist/cjs/adapters/sessionRow.js.map +0 -1
- package/dist/cjs/constants/index.d.ts +0 -1
- package/dist/cjs/constants/index.d.ts.map +0 -1
- package/dist/cjs/constants/index.js +0 -4
- package/dist/cjs/constants/index.js.map +0 -1
- package/dist/cjs/core/AutoChainExecutor.d.ts +0 -97
- package/dist/cjs/core/AutoChainExecutor.d.ts.map +0 -1
- package/dist/cjs/core/AutoChainExecutor.js +0 -288
- package/dist/cjs/core/AutoChainExecutor.js.map +0 -1
- package/dist/cjs/core/BranchEvaluator.d.ts +0 -55
- package/dist/cjs/core/BranchEvaluator.d.ts.map +0 -1
- package/dist/cjs/core/BranchEvaluator.js +0 -125
- package/dist/cjs/core/BranchEvaluator.js.map +0 -1
- package/dist/cjs/core/DirectiveChainTracker.d.ts +0 -49
- package/dist/cjs/core/DirectiveChainTracker.d.ts.map +0 -1
- package/dist/cjs/core/DirectiveChainTracker.js +0 -121
- package/dist/cjs/core/DirectiveChainTracker.js.map +0 -1
- package/dist/cjs/core/Events.d.ts +0 -26
- package/dist/cjs/core/Events.d.ts.map +0 -1
- package/dist/cjs/core/Events.js +0 -144
- package/dist/cjs/core/Events.js.map +0 -1
- package/dist/cjs/core/Flow.d.ts +0 -183
- package/dist/cjs/core/Flow.d.ts.map +0 -1
- package/dist/cjs/core/Flow.js +0 -551
- package/dist/cjs/core/Flow.js.map +0 -1
- package/dist/cjs/core/FlowRouter.d.ts +0 -183
- package/dist/cjs/core/FlowRouter.d.ts.map +0 -1
- package/dist/cjs/core/FlowRouter.js +0 -1047
- package/dist/cjs/core/FlowRouter.js.map +0 -1
- package/dist/cjs/core/PersistenceManager.d.ts +0 -114
- package/dist/cjs/core/PersistenceManager.d.ts.map +0 -1
- package/dist/cjs/core/PersistenceManager.js +0 -336
- package/dist/cjs/core/PersistenceManager.js.map +0 -1
- package/dist/cjs/core/PromptComposer.d.ts +0 -47
- package/dist/cjs/core/PromptComposer.d.ts.map +0 -1
- package/dist/cjs/core/PromptComposer.js +0 -397
- package/dist/cjs/core/PromptComposer.js.map +0 -1
- package/dist/cjs/core/PromptSectionCache.d.ts +0 -48
- package/dist/cjs/core/PromptSectionCache.d.ts.map +0 -1
- package/dist/cjs/core/PromptSectionCache.js +0 -108
- package/dist/cjs/core/PromptSectionCache.js.map +0 -1
- package/dist/cjs/core/ResponseEngine.d.ts +0 -43
- package/dist/cjs/core/ResponseEngine.d.ts.map +0 -1
- package/dist/cjs/core/ResponseEngine.js +0 -235
- package/dist/cjs/core/ResponseEngine.js.map +0 -1
- package/dist/cjs/core/ResponseGenerationError.d.ts +0 -30
- package/dist/cjs/core/ResponseGenerationError.d.ts.map +0 -1
- package/dist/cjs/core/ResponseGenerationError.js +0 -35
- package/dist/cjs/core/ResponseGenerationError.js.map +0 -1
- package/dist/cjs/core/ResponseModal.d.ts +0 -305
- package/dist/cjs/core/ResponseModal.d.ts.map +0 -1
- package/dist/cjs/core/ResponseModal.js +0 -1414
- package/dist/cjs/core/ResponseModal.js.map +0 -1
- package/dist/cjs/core/ResponsePipeline.d.ts +0 -220
- package/dist/cjs/core/ResponsePipeline.d.ts.map +0 -1
- package/dist/cjs/core/ResponsePipeline.js +0 -1040
- package/dist/cjs/core/ResponsePipeline.js.map +0 -1
- package/dist/cjs/core/SessionFinalizer.d.ts +0 -34
- package/dist/cjs/core/SessionFinalizer.d.ts.map +0 -1
- package/dist/cjs/core/SessionFinalizer.js +0 -88
- package/dist/cjs/core/SessionFinalizer.js.map +0 -1
- package/dist/cjs/core/SessionManager.d.ts +0 -112
- package/dist/cjs/core/SessionManager.d.ts.map +0 -1
- package/dist/cjs/core/SessionManager.js +0 -308
- package/dist/cjs/core/SessionManager.js.map +0 -1
- package/dist/cjs/core/SignalCoordinator.d.ts +0 -103
- package/dist/cjs/core/SignalCoordinator.d.ts.map +0 -1
- package/dist/cjs/core/SignalCoordinator.js +0 -207
- package/dist/cjs/core/SignalCoordinator.js.map +0 -1
- package/dist/cjs/core/SignalEvaluator.d.ts +0 -86
- package/dist/cjs/core/SignalEvaluator.d.ts.map +0 -1
- package/dist/cjs/core/SignalEvaluator.js +0 -319
- package/dist/cjs/core/SignalEvaluator.js.map +0 -1
- package/dist/cjs/core/SignalProcessor.d.ts +0 -152
- package/dist/cjs/core/SignalProcessor.d.ts.map +0 -1
- package/dist/cjs/core/SignalProcessor.js +0 -505
- package/dist/cjs/core/SignalProcessor.js.map +0 -1
- package/dist/cjs/core/Step.d.ts +0 -184
- package/dist/cjs/core/Step.d.ts.map +0 -1
- package/dist/cjs/core/Step.js +0 -599
- package/dist/cjs/core/Step.js.map +0 -1
- package/dist/cjs/core/StepLifecycle.d.ts +0 -43
- package/dist/cjs/core/StepLifecycle.d.ts.map +0 -1
- package/dist/cjs/core/StepLifecycle.js +0 -180
- package/dist/cjs/core/StepLifecycle.js.map +0 -1
- package/dist/cjs/core/StreamingToolExecutor.d.ts +0 -142
- package/dist/cjs/core/StreamingToolExecutor.d.ts.map +0 -1
- package/dist/cjs/core/StreamingToolExecutor.js +0 -490
- package/dist/cjs/core/StreamingToolExecutor.js.map +0 -1
- package/dist/cjs/core/ToolLoopExecutor.d.ts +0 -133
- package/dist/cjs/core/ToolLoopExecutor.d.ts.map +0 -1
- package/dist/cjs/core/ToolLoopExecutor.js +0 -568
- package/dist/cjs/core/ToolLoopExecutor.js.map +0 -1
- package/dist/cjs/core/ToolManager.d.ts +0 -250
- package/dist/cjs/core/ToolManager.d.ts.map +0 -1
- package/dist/cjs/core/ToolManager.js +0 -1104
- package/dist/cjs/core/ToolManager.js.map +0 -1
- package/dist/cjs/core/createAgent.d.ts +0 -35
- package/dist/cjs/core/createAgent.d.ts.map +0 -1
- package/dist/cjs/core/createAgent.js +0 -39
- package/dist/cjs/core/createAgent.js.map +0 -1
- package/dist/cjs/core/flow-namespace.d.ts +0 -64
- package/dist/cjs/core/flow-namespace.d.ts.map +0 -1
- package/dist/cjs/core/flow-namespace.js +0 -182
- package/dist/cjs/core/flow-namespace.js.map +0 -1
- package/dist/cjs/core/toolGates.d.ts +0 -24
- package/dist/cjs/core/toolGates.d.ts.map +0 -1
- package/dist/cjs/core/toolGates.js +0 -52
- package/dist/cjs/core/toolGates.js.map +0 -1
- package/dist/cjs/types/persistence.d.ts +0 -254
- package/dist/cjs/types/persistence.d.ts.map +0 -1
- package/dist/cjs/types/persistence.js +0 -7
- package/dist/cjs/types/persistence.js.map +0 -1
- package/dist/cjs/types/prompt-cache.d.ts +0 -15
- package/dist/cjs/types/prompt-cache.d.ts.map +0 -1
- package/dist/cjs/types/prompt-cache.js +0 -6
- package/dist/cjs/types/prompt-cache.js.map +0 -1
- package/dist/cjs/types/signals.d.ts +0 -263
- package/dist/cjs/types/signals.d.ts.map +0 -1
- package/dist/cjs/types/signals.js +0 -11
- package/dist/cjs/types/signals.js.map +0 -1
- package/dist/cjs/types/template.d.ts +0 -84
- package/dist/cjs/types/template.d.ts.map +0 -1
- package/dist/cjs/types/template.js +0 -3
- package/dist/cjs/types/template.js.map +0 -1
- package/dist/cjs/utils/condition.d.ts +0 -63
- package/dist/cjs/utils/condition.d.ts.map +0 -1
- package/dist/cjs/utils/condition.js +0 -239
- package/dist/cjs/utils/condition.js.map +0 -1
- package/dist/cjs/utils/event.d.ts +0 -6
- package/dist/cjs/utils/event.d.ts.map +0 -1
- package/dist/cjs/utils/event.js +0 -20
- package/dist/cjs/utils/event.js.map +0 -1
- package/dist/cjs/utils/id.d.ts +0 -33
- package/dist/cjs/utils/id.d.ts.map +0 -1
- package/dist/cjs/utils/id.js +0 -84
- package/dist/cjs/utils/id.js.map +0 -1
- package/dist/cjs/utils/serialize.d.ts +0 -36
- package/dist/cjs/utils/serialize.d.ts.map +0 -1
- package/dist/cjs/utils/serialize.js +0 -77
- package/dist/cjs/utils/serialize.js.map +0 -1
- package/dist/cjs/utils/session.d.ts +0 -124
- package/dist/cjs/utils/session.d.ts.map +0 -1
- package/dist/cjs/utils/session.js +0 -396
- package/dist/cjs/utils/session.js.map +0 -1
- package/dist/constants/index.d.ts +0 -2
- package/dist/constants/index.d.ts.map +0 -1
- package/dist/constants/index.js +0 -4
- package/dist/constants/index.js.map +0 -1
- package/dist/core/AutoChainExecutor.d.ts +0 -97
- package/dist/core/AutoChainExecutor.d.ts.map +0 -1
- package/dist/core/AutoChainExecutor.js +0 -284
- package/dist/core/AutoChainExecutor.js.map +0 -1
- package/dist/core/BranchEvaluator.d.ts +0 -55
- package/dist/core/BranchEvaluator.d.ts.map +0 -1
- package/dist/core/BranchEvaluator.js +0 -121
- package/dist/core/BranchEvaluator.js.map +0 -1
- package/dist/core/DirectiveChainTracker.d.ts +0 -49
- package/dist/core/DirectiveChainTracker.d.ts.map +0 -1
- package/dist/core/DirectiveChainTracker.js +0 -117
- package/dist/core/DirectiveChainTracker.js.map +0 -1
- package/dist/core/Events.d.ts +0 -26
- package/dist/core/Events.d.ts.map +0 -1
- package/dist/core/Events.js +0 -137
- package/dist/core/Events.js.map +0 -1
- package/dist/core/Flow.d.ts +0 -183
- package/dist/core/Flow.d.ts.map +0 -1
- package/dist/core/Flow.js +0 -547
- package/dist/core/Flow.js.map +0 -1
- package/dist/core/FlowRouter.d.ts +0 -183
- package/dist/core/FlowRouter.d.ts.map +0 -1
- package/dist/core/FlowRouter.js +0 -1043
- package/dist/core/FlowRouter.js.map +0 -1
- package/dist/core/PersistenceManager.d.ts +0 -114
- package/dist/core/PersistenceManager.d.ts.map +0 -1
- package/dist/core/PersistenceManager.js +0 -332
- package/dist/core/PersistenceManager.js.map +0 -1
- package/dist/core/PromptComposer.d.ts +0 -47
- package/dist/core/PromptComposer.d.ts.map +0 -1
- package/dist/core/PromptComposer.js +0 -393
- package/dist/core/PromptComposer.js.map +0 -1
- package/dist/core/PromptSectionCache.d.ts +0 -48
- package/dist/core/PromptSectionCache.d.ts.map +0 -1
- package/dist/core/PromptSectionCache.js +0 -104
- package/dist/core/PromptSectionCache.js.map +0 -1
- package/dist/core/ResponseEngine.d.ts +0 -43
- package/dist/core/ResponseEngine.d.ts.map +0 -1
- package/dist/core/ResponseEngine.js +0 -231
- package/dist/core/ResponseEngine.js.map +0 -1
- package/dist/core/ResponseGenerationError.d.ts +0 -30
- package/dist/core/ResponseGenerationError.d.ts.map +0 -1
- package/dist/core/ResponseGenerationError.js +0 -31
- package/dist/core/ResponseGenerationError.js.map +0 -1
- package/dist/core/ResponseModal.d.ts +0 -305
- package/dist/core/ResponseModal.d.ts.map +0 -1
- package/dist/core/ResponseModal.js +0 -1410
- package/dist/core/ResponseModal.js.map +0 -1
- package/dist/core/ResponsePipeline.d.ts +0 -220
- package/dist/core/ResponsePipeline.d.ts.map +0 -1
- package/dist/core/ResponsePipeline.js +0 -1035
- package/dist/core/ResponsePipeline.js.map +0 -1
- package/dist/core/SessionFinalizer.d.ts +0 -34
- package/dist/core/SessionFinalizer.d.ts.map +0 -1
- package/dist/core/SessionFinalizer.js +0 -84
- package/dist/core/SessionFinalizer.js.map +0 -1
- package/dist/core/SessionManager.d.ts +0 -112
- package/dist/core/SessionManager.d.ts.map +0 -1
- package/dist/core/SessionManager.js +0 -301
- package/dist/core/SessionManager.js.map +0 -1
- package/dist/core/SignalCoordinator.d.ts +0 -103
- package/dist/core/SignalCoordinator.d.ts.map +0 -1
- package/dist/core/SignalCoordinator.js +0 -203
- package/dist/core/SignalCoordinator.js.map +0 -1
- package/dist/core/SignalEvaluator.d.ts +0 -86
- package/dist/core/SignalEvaluator.d.ts.map +0 -1
- package/dist/core/SignalEvaluator.js +0 -312
- package/dist/core/SignalEvaluator.js.map +0 -1
- package/dist/core/SignalProcessor.d.ts +0 -152
- package/dist/core/SignalProcessor.d.ts.map +0 -1
- package/dist/core/SignalProcessor.js +0 -498
- package/dist/core/SignalProcessor.js.map +0 -1
- package/dist/core/Step.d.ts +0 -184
- package/dist/core/Step.d.ts.map +0 -1
- package/dist/core/Step.js +0 -594
- package/dist/core/Step.js.map +0 -1
- package/dist/core/StepLifecycle.d.ts +0 -43
- package/dist/core/StepLifecycle.d.ts.map +0 -1
- package/dist/core/StepLifecycle.js +0 -176
- package/dist/core/StepLifecycle.js.map +0 -1
- package/dist/core/StreamingToolExecutor.d.ts +0 -142
- package/dist/core/StreamingToolExecutor.d.ts.map +0 -1
- package/dist/core/StreamingToolExecutor.js +0 -483
- package/dist/core/StreamingToolExecutor.js.map +0 -1
- package/dist/core/ToolLoopExecutor.d.ts +0 -133
- package/dist/core/ToolLoopExecutor.d.ts.map +0 -1
- package/dist/core/ToolLoopExecutor.js +0 -564
- package/dist/core/ToolLoopExecutor.js.map +0 -1
- package/dist/core/ToolManager.d.ts +0 -250
- package/dist/core/ToolManager.d.ts.map +0 -1
- package/dist/core/ToolManager.js +0 -1098
- package/dist/core/ToolManager.js.map +0 -1
- package/dist/core/createAgent.d.ts +0 -35
- package/dist/core/createAgent.d.ts.map +0 -1
- package/dist/core/createAgent.js +0 -36
- package/dist/core/createAgent.js.map +0 -1
- package/dist/core/flow-namespace.d.ts +0 -64
- package/dist/core/flow-namespace.d.ts.map +0 -1
- package/dist/core/flow-namespace.js +0 -179
- package/dist/core/flow-namespace.js.map +0 -1
- package/dist/core/toolGates.d.ts +0 -24
- package/dist/core/toolGates.d.ts.map +0 -1
- package/dist/core/toolGates.js +0 -49
- package/dist/core/toolGates.js.map +0 -1
- package/dist/types/persistence.d.ts +0 -254
- package/dist/types/persistence.d.ts.map +0 -1
- package/dist/types/persistence.js +0 -6
- package/dist/types/persistence.js.map +0 -1
- package/dist/types/prompt-cache.d.ts +0 -15
- package/dist/types/prompt-cache.d.ts.map +0 -1
- package/dist/types/prompt-cache.js +0 -5
- package/dist/types/prompt-cache.js.map +0 -1
- package/dist/types/signals.d.ts +0 -263
- package/dist/types/signals.d.ts.map +0 -1
- package/dist/types/signals.js +0 -10
- package/dist/types/signals.js.map +0 -1
- package/dist/types/template.d.ts +0 -84
- package/dist/types/template.d.ts.map +0 -1
- package/dist/types/template.js +0 -2
- package/dist/types/template.js.map +0 -1
- package/dist/utils/condition.d.ts +0 -63
- package/dist/utils/condition.d.ts.map +0 -1
- package/dist/utils/condition.js +0 -230
- package/dist/utils/condition.js.map +0 -1
- package/dist/utils/event.d.ts +0 -6
- package/dist/utils/event.d.ts.map +0 -1
- package/dist/utils/event.js +0 -17
- package/dist/utils/event.js.map +0 -1
- package/dist/utils/id.d.ts +0 -33
- package/dist/utils/id.d.ts.map +0 -1
- package/dist/utils/id.js +0 -77
- package/dist/utils/id.js.map +0 -1
- package/dist/utils/serialize.d.ts +0 -36
- package/dist/utils/serialize.d.ts.map +0 -1
- package/dist/utils/serialize.js +0 -72
- package/dist/utils/serialize.js.map +0 -1
- package/dist/utils/session.d.ts +0 -124
- package/dist/utils/session.d.ts.map +0 -1
- package/dist/utils/session.js +0 -379
- package/dist/utils/session.js.map +0 -1
- package/docs/concepts/directives.md +0 -369
- package/docs/reference/adapters.md +0 -543
- package/docs/reference/create-agent.md +0 -216
- package/docs/reference/directive.md +0 -242
- package/docs/reference/signals.md +0 -368
- package/examples/02-data-extraction.ts +0 -90
- package/examples/05-branching.ts +0 -140
- package/examples/06-flow-control.ts +0 -103
- package/examples/08-persistence.ts +0 -98
- package/examples/09-signals.ts +0 -144
- package/src/adapters/MemoryAdapter.ts +0 -281
- package/src/adapters/MongoAdapter.ts +0 -341
- package/src/adapters/OpenSearchAdapter.ts +0 -693
- package/src/adapters/PostgreSQLAdapter.ts +0 -487
- package/src/adapters/PrismaAdapter.ts +0 -617
- package/src/adapters/RedisAdapter.ts +0 -439
- package/src/adapters/SQLiteAdapter.ts +0 -496
- package/src/adapters/index.ts +0 -43
- package/src/adapters/sessionRow.ts +0 -57
- package/src/constants/index.ts +0 -2
- package/src/core/AutoChainExecutor.ts +0 -397
- package/src/core/BranchEvaluator.ts +0 -161
- package/src/core/DirectiveChainTracker.ts +0 -144
- package/src/core/Events.ts +0 -164
- package/src/core/Flow.ts +0 -665
- package/src/core/FlowRouter.ts +0 -1540
- package/src/core/PersistenceManager.ts +0 -446
- package/src/core/PromptComposer.ts +0 -448
- package/src/core/PromptSectionCache.ts +0 -125
- package/src/core/ResponseEngine.ts +0 -338
- package/src/core/ResponseGenerationError.ts +0 -53
- package/src/core/ResponseModal.ts +0 -1902
- package/src/core/ResponsePipeline.ts +0 -1404
- package/src/core/SessionFinalizer.ts +0 -108
- package/src/core/SessionManager.ts +0 -372
- package/src/core/SignalCoordinator.ts +0 -263
- package/src/core/SignalEvaluator.ts +0 -404
- package/src/core/SignalProcessor.ts +0 -663
- package/src/core/Step.ts +0 -782
- package/src/core/StepLifecycle.ts +0 -242
- package/src/core/StreamingToolExecutor.ts +0 -609
- package/src/core/ToolLoopExecutor.ts +0 -749
- package/src/core/ToolManager.ts +0 -1379
- package/src/core/createAgent.ts +0 -40
- package/src/core/flow-namespace.ts +0 -227
- package/src/core/toolGates.ts +0 -72
- package/src/types/persistence.ts +0 -303
- package/src/types/prompt-cache.ts +0 -17
- package/src/types/signals.ts +0 -338
- package/src/types/template.ts +0 -98
- package/src/utils/condition.ts +0 -296
- package/src/utils/event.ts +0 -16
- package/src/utils/id.ts +0 -91
- package/src/utils/serialize.ts +0 -86
- package/src/utils/session.ts +0 -501
|
@@ -1,274 +1,152 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
3
|
-
description: "The
|
|
2
|
+
title: "Agent architecture"
|
|
3
|
+
description: "The seven words the rest of the docs use, and the line between what the model decides and what the code decides."
|
|
4
4
|
type: concept
|
|
5
5
|
order: 1
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
#
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
|
23
|
-
|
|
24
|
-
| **
|
|
25
|
-
| **
|
|
26
|
-
| **
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
8
|
+
# Agent architecture
|
|
9
|
+
|
|
10
|
+
The AI understands. The code is in control.
|
|
11
|
+
|
|
12
|
+
@falai/agent runs a conversation as a set of small programs called flows. The model has two jobs: read what the customer wrote, and phrase what the assistant says. Every other decision is code: which flow runs, which step comes next, which field is still missing, how long to wait, what to send and when.
|
|
13
|
+
|
|
14
|
+
## The words
|
|
15
|
+
|
|
16
|
+
These seven words are the whole design. The rest of the docs use them without explaining them again.
|
|
17
|
+
|
|
18
|
+
| Word | What it is | Where it lives |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| **Agent** | The configuration: fields, flows, provider, registries. One instance serves every session. | `f.agent(options)` returns an `Agent` |
|
|
21
|
+
| **Flow** | A trigger plus an ordered list of steps. | `Flow`, built with `f.flow()` |
|
|
22
|
+
| **Trigger** | When a run of the flow starts: `message`, `mention`, `silence`, `event`, or none (the host starts it). | `Trigger`, in `flow.on[]` |
|
|
23
|
+
| **Step** | One thing the run does: the model talks (`prompt` / `collect`), a fixed text goes out (`say`), the host does something (`do`), the run parks (`wait`), the code forks (`if`). | `Step`, in `flow.steps[]` |
|
|
24
|
+
| **Field** | One piece of data to collect, authored once on the agent with its own `ask`. | `FieldDef`, in `falai().fields()` |
|
|
25
|
+
| **Run** | One live execution of a flow inside a session. A session holds many runs; at most one is asking. That run holds the floor: the next message is read as its answer. | `Run`, in `session.runs[]` |
|
|
26
|
+
| **Turn** | One call to `agent.turn(input)`: something happened, here is what to send and when to wake up. | `TurnInput` in, `TurnResult` out |
|
|
27
|
+
|
|
28
|
+
Four registries live on the agent. Instructions are written inline, wherever they apply. Flows name registry entries as strings, and the names are checked when the agent is built.
|
|
29
|
+
|
|
30
|
+
| On the agent | What it holds | Named from |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| `actions` | Host code a `do` step runs. Returns `{ ok }`, `{ skipped }`, `{ failed }` or `{ defer }`. | `do: 'notify'` |
|
|
33
|
+
| `events` | Host events a trigger or a `wait` may name, each with an optional `direction`. | `on: [{ event: 'stage_entered' }]`, `wait: { event: 'meeting_booked' }` |
|
|
34
|
+
| `conditions` | Host predicates a JSON `if` may name, with an argument. | `if: { tagsAny: ['vip'] }` |
|
|
35
|
+
| `tools` | Typed functions the model may call while it speaks. They return `{ value?, data? }`, never movement. | `tools: ['checkAvailability']` on a step or a flow |
|
|
36
|
+
| `instructions` | Rules the prompt carries while they apply: `must`, `never`, `should`. | Not named: written inline where they apply, on the agent, a flow, a step, or the idle speaker |
|
|
37
|
+
|
|
38
|
+
The **host** is your program: the one that receives a message from the channel, loads the session, calls `turn()`, saves, sends and schedules. The framework does none of those.
|
|
39
|
+
|
|
40
|
+
## How they fit
|
|
41
|
+
|
|
42
|
+
```text
|
|
43
|
+
Agent (immutable, one instance for every session)
|
|
44
|
+
├── fields nome, empresa, confirmado, … authored once, typed
|
|
45
|
+
├── flows[] Flow = on[] (triggers) + steps[]
|
|
46
|
+
│ step: talk | say | do | wait | if
|
|
47
|
+
│ movement: then / else → step id | 'end' | { step, clear } | { flow, input }
|
|
48
|
+
├── actions do: 'notify' ┐
|
|
49
|
+
├── events event: 'meeting_booked' │ host registries,
|
|
50
|
+
├── conditions if: { inStage: 'x' } │ referenced by name
|
|
51
|
+
├── tools the model may call these ┘
|
|
52
|
+
├── instructions must / never / should
|
|
53
|
+
├── idle speaks when no run holds the floor ('silent' mutes it)
|
|
54
|
+
└── provider talks to the model
|
|
55
|
+
|
|
56
|
+
Session (one per conversation; the host saves it)
|
|
57
|
+
├── data the collected fields, in any order
|
|
58
|
+
├── runs[] live runs: running | asking | waiting | suspended
|
|
59
|
+
├── claims which flows already ran here, so repeat: 'once' and cooldowns hold
|
|
60
|
+
└── inputs the last 50 input ids, for replays
|
|
61
|
+
|
|
62
|
+
turn(input) ── message | wake | event | start ──▶ TurnResult
|
|
63
|
+
session, changed, messages[], schedule[], llmCalls, …
|
|
63
64
|
```
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
### Agent
|
|
68
|
-
|
|
69
|
-
An `Agent<TContext, TData>` is the top-level handle. It binds the four ingredients of a conversational system: a **schema** (what to collect), a **provider** (which LLM to call), a set of **flows** (what goals to pursue), and an optional **persistence** adapter (where to keep sessions). Anything ambient — auth, feature flags, services — rides on `TContext`. Anything collected — names, dates, choices — lives in `TData`. Both type parameters are inferred once at the agent boundary and propagate through every flow, step, tool, and hook beneath it.
|
|
70
|
-
|
|
71
|
-
The agent owns the registry. It assigns a deterministic id to every flow, step, and tool; it enforces a single `schema` at every `collect` site; it holds the chosen provider and the session lifecycle. It exposes `respond(params)` and `respondStream(params)` for handling user input, plus `dispatch(target, session)` for redirecting from outside a turn. One agent serves many concurrent conversations — a session id keys into the persistence adapter, and `respond` is otherwise stateless from the caller's perspective.
|
|
72
|
-
|
|
73
|
-
### Flow
|
|
66
|
+
## The two model calls
|
|
74
67
|
|
|
75
|
-
|
|
68
|
+
The model gets at most two calls per turn, and each has one job.
|
|
76
69
|
|
|
77
|
-
|
|
70
|
+
- **The understand call** reads the customer's message. It scores the candidate flows from 0 to 100, says which things the customer brought up, answers the `when` questions of the asking step, and extracts any field values the message carries. It never moves a run.
|
|
71
|
+
- **The speak call** phrases the assistant's reply for one talk step (or for the idle speaker) and extracts the fields that step is still collecting. It may call tools in rounds. It never moves a run either.
|
|
78
72
|
|
|
79
|
-
|
|
73
|
+
Everything else is code, in `src/core/Runner.ts`: which flows are eligible, which run holds the floor, which fields are pending, which step comes next, how long a wait is, what key a message gets, when a claim (a record that this flow already ran) blocks a start, what the result says. Code behaves the same on a replay; the model does not. So nothing the model says is applied before code checks it: unknown fields are dropped, values are coerced to the field's type, `enum` membership is enforced.
|
|
80
74
|
|
|
81
|
-
|
|
75
|
+
Two things follow. A flow with no talk steps costs zero model calls. And every result carries `llmCalls`, so a test asserts the budget instead of trusting it. [The turn pipeline](./pipeline.md) walks the eight phases and what each one spends.
|
|
82
76
|
|
|
83
|
-
|
|
77
|
+
## One agent, every session
|
|
84
78
|
|
|
85
|
-
|
|
79
|
+
An `Agent` is immutable configuration. Build it once and keep it for the life of the process. It holds no session, no context and no history of its own; those arrive on every `turn()`.
|
|
86
80
|
|
|
87
|
-
|
|
81
|
+
```ts
|
|
82
|
+
import type { Agent } from "@falai/agent";
|
|
83
|
+
declare const agent: Agent;
|
|
88
84
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
### Instruction
|
|
92
|
-
|
|
93
|
-
An `Instruction<TContext, TData>` is a single behavioral statement that shapes how the agent talks. Every instruction carries a `kind` discriminator — `must` for absolute do, `never` for absolute don't, `should` for conditional nudge — alongside a `prompt` (the rendered text) and optional activation conditions (`when` for AI strings, `if` for code predicates). One shape covers every behavioral nudge in the system; the only thing that differs from one instruction to the next is its severity and its scope.
|
|
94
|
-
|
|
95
|
-
An instruction owns its rendered position in the prompt. The composer renders each active instruction as a single bullet under the system prompt's `## Instructions` section, prefixed with its kind and a scope caption: `[Always]` for agent-level, `[In: <FlowTitle>]` for flow-level, `[Step: <stepId>]` for step-level. The set actually rendered on a turn is reported back as `appliedInstructions` on the response — observability is deterministic, derived from rendering, not self-reported by the model.
|
|
96
|
-
|
|
97
|
-
### Directive
|
|
98
|
-
|
|
99
|
-
A `Directive<TContext, TData>` is a flat object literal — not a class, not a builder, not a discriminated union — that any tool, hook, or branch returns to act on the turn. Every field is optional. A directive carries up to four orthogonal payloads: at most **one position field** (`goTo`, `goToStep`, `complete`, `abort`, or `reset`), zero or one **verbatim reply**, optional **state writes** (`dataUpdate` / `contextUpdate`), and optional **pre-LLM augmentation** (`appendPrompt`, `injectTools`, `halt`) plus optional `reason` strings inside object forms for traceability. The flatness is intentional — earlier drafts modeled directives as a discriminated union, but a flat object composes more naturally when a single decision point needs to write state, change position, and speak verbatim in one return value.
|
|
100
|
-
|
|
101
|
-
The directive is the single language the framework speaks for control flow. A tool that decides "this user is ineligible" returns `{ goTo: "denial", reply: "Sorry — you don't qualify." }`. A finalize hook that finishes a booking returns `{ complete: true, dataUpdate: { bookingId } }`. A prepare hook that detects a VIP returns `{ appendPrompt: ["This caller is VIP — confirm preferences first."] }`. All of these merge through one algorithm — position fields by precedence, state writes shallow-merged, `reply` last-wins — implemented as `flow.merge(a, b)` and applied uniformly across the turn pipeline.
|
|
102
|
-
|
|
103
|
-
The three pre-LLM fields (`appendPrompt`, `injectTools`, `halt`) have a one-turn lifetime: they only take effect in pre-LLM hooks (`onEnter`, `prepare`). When emitted from post-LLM hooks or persisted to `session.pendingDirective`, they are ignored with a WARN log. This keeps one type for all emitters while the engine enforces the phase boundary at runtime.
|
|
104
|
-
|
|
105
|
-
## Supporting concepts
|
|
106
|
-
|
|
107
|
-
The six primitives carry the weight. Four supporting pieces make them ergonomic.
|
|
108
|
-
|
|
109
|
-
### `flow` namespace
|
|
110
|
-
|
|
111
|
-
`flow` is a small runtime helper namespace exported from the package root. There are no constructor builders here — directives are object literals everywhere they appear in source. The namespace exists for runtime work: validating a directive that arrived from outside the framework (an RPC payload, a queue message), merging two directives by hand when composing custom orchestration, or narrowing an `unknown` value to `Directive` in a type guard.
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
import { flow } from "@falai/agent";
|
|
115
|
-
|
|
116
|
-
flow.isDirective(x); // type guard
|
|
117
|
-
flow.merge(a, b); // Algorithm 4 merge of two directives
|
|
118
|
-
flow.validate(d); // throws FlowConfigurationError on invalid shape
|
|
85
|
+
const r = await agent.turn({ sessionId: "demo", message: "oi" });
|
|
86
|
+
console.log(r.llmCalls); // 1: one flow, nothing to judge, one speak call
|
|
119
87
|
```
|
|
120
88
|
|
|
121
|
-
|
|
89
|
+
Here is the agent that call ran against:
|
|
122
90
|
|
|
123
|
-
|
|
91
|
+
```ts
|
|
92
|
+
import { falai } from "@falai/agent";
|
|
93
|
+
import type { AiProvider } from "@falai/agent";
|
|
124
94
|
|
|
125
|
-
|
|
95
|
+
declare const provider: AiProvider;
|
|
126
96
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
name: "BookingBot",
|
|
130
|
-
provider: new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY! }),
|
|
131
|
-
schema: { /* ... */ },
|
|
132
|
-
flows: [/* ... */],
|
|
97
|
+
const f = falai().fields({
|
|
98
|
+
nome: { type: "string", ask: "Pergunte o nome da pessoa, sem tom de formulário." },
|
|
133
99
|
});
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
The factory is the recommended construction path for application code. The class form (`new Agent(options)`) remains for power users who need to subclass — for example, to override `respond` for custom telemetry, or to add bespoke methods on top of the agent surface. Both share validation: misuse surfaces as `FlowConfigurationError` synchronously at construction, before any turn runs.
|
|
137
|
-
|
|
138
|
-
### `Agent.dispatch`
|
|
139
|
-
|
|
140
|
-
`agent.dispatch(target, session)` is the imperative entry point for redirecting a session from outside a turn — typically from a webhook, a cron job, or a UI button that jumps the user into a different flow. It accepts either a string shorthand (`"Feedback"` desugars to `{ goTo: "Feedback" }`) or a full `Directive`. Internally, it writes `session.pendingDirective`; the directive is consumed at the start of the next `respond` call before any other resolution runs. With a persistence adapter configured (and `autoSave` on — the default), dispatch persists immediately, so the queued directive survives process boundaries; without an adapter it is memory-only, and with `autoSave: false` persisting before the next turn is the caller's job. Because the save compare-and-swaps on the session version, a dispatch from a stale copy throws `SessionConflictError` instead of clobbering another writer.
|
|
141
|
-
|
|
142
|
-
```typescript
|
|
143
|
-
const updated = await agent.dispatch(
|
|
144
|
-
{ goTo: "Billing", reply: "Transferring you now." },
|
|
145
|
-
session,
|
|
146
|
-
);
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
Inside a turn, the same effect is reached by returning or dispatching a directive from a tool or hook — the per-turn bus handles the merge. Outside a turn, `Agent.dispatch` is the sanctioned entry point for setting the next position. There is one way to express each thing, and this is the one for "the user just clicked the cancel button in the UI; their next message should land in the Cancellation flow."
|
|
150
100
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
The diagram below maps the ownership and reference relationships between the six primitives and the two state surfaces. Solid arrows are ownership. Dashed lines are scoping or extension. The two state nodes (`Schema` and `Context`) are not primitives — they are the typed surfaces the primitives operate on, drawn at the bottom because everything else references them.
|
|
164
|
-
|
|
165
|
-
```mermaid
|
|
166
|
-
graph TB
|
|
167
|
-
Schema[(Schema<br/>TData)]
|
|
168
|
-
Context[(Context<br/>TContext)]
|
|
169
|
-
|
|
170
|
-
Agent --> Schema
|
|
171
|
-
Agent --> Context
|
|
172
|
-
Agent -->|owns| Flow
|
|
173
|
-
Agent -->|owns| Tool
|
|
174
|
-
Agent -->|owns| Instruction
|
|
175
|
-
|
|
176
|
-
Flow -->|owns| Step
|
|
177
|
-
Flow -->|requiredFields| Schema
|
|
178
|
-
Flow -.scoped.- Tool
|
|
179
|
-
Flow -.scoped.- Instruction
|
|
180
|
-
|
|
181
|
-
Step -->|collect / requires| Schema
|
|
182
|
-
Step -.scoped.- Tool
|
|
183
|
-
Step -.scoped.- Instruction
|
|
184
|
-
Step -->|branches| Step
|
|
185
|
-
Step -->|onEnter / prepare| Directive
|
|
186
|
-
Step -->|finalize| Directive
|
|
187
|
-
|
|
188
|
-
Tool -->|ctx.dispatch| Directive
|
|
189
|
-
Tool -->|ToolResult.directive| Directive
|
|
190
|
-
|
|
191
|
-
Directive -.merged via.-> FlowNS[flow.merge]
|
|
101
|
+
const agent = f.agent({
|
|
102
|
+
name: "Ana",
|
|
103
|
+
provider,
|
|
104
|
+
flows: [
|
|
105
|
+
f.flow({
|
|
106
|
+
id: "boas-vindas",
|
|
107
|
+
name: "Boas-vindas",
|
|
108
|
+
on: [{ message: [] }],
|
|
109
|
+
steps: [{ id: "nome", collect: ["nome"] }],
|
|
110
|
+
}),
|
|
111
|
+
],
|
|
112
|
+
});
|
|
192
113
|
|
|
193
|
-
|
|
194
|
-
classDef state fill:#0f172a,stroke:#64748b,color:#cbd5e1;
|
|
195
|
-
class Agent,Flow,Step,Tool,Instruction,Directive primitive;
|
|
196
|
-
class Schema,Context state;
|
|
114
|
+
export { agent };
|
|
197
115
|
```
|
|
198
116
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
The two state types — `Schema` for `TData`, `Context` for `TContext` — sit at the bottom because everything else points at them. They are not primitives in the same sense as the six types; they are the typed surfaces those primitives operate on, and they are owned by the agent.
|
|
202
|
-
|
|
203
|
-
Two things are deliberately absent from this diagram. There is no separate "router" primitive — flow selection is an internal pipeline phase, not a user-facing type. There is no separate "session" primitive in the declaration model — sessions are runtime state, indexed by `sessionId`, persisted by adapters, but not something application code constructs as a building block. Both of those concerns live in the [turn pipeline](./pipeline.md), where they are explained as steps in the per-turn sequence rather than parts of the static structure.
|
|
204
|
-
|
|
205
|
-
## The schema-first principle
|
|
206
|
-
|
|
207
|
-
`TData` is **agent-level**, not flow-level. One schema describes everything that can be collected across every flow. Flows declare which fields they need (`requiredFields`); steps declare which fields they extract (`collect`) and which they require (`requires`). This is what makes pre-extraction work: when the user message arrives, the engine extracts every collectable field it can in a single pass into `session.data`, then skips any step whose `collect` set is already satisfied.
|
|
208
|
-
|
|
209
|
-
The agent owns the schema, so the same field can be collected by step A in flow X and used as a prerequisite by step B in flow Y. The contracts at every site are the same shape — `(keyof TData)[]` — and TypeScript verifies them at compile time. Move a field name once at the schema and the failures surface immediately at every call site that references it.
|
|
117
|
+
The constructor checks the configuration before any turn runs: duplicate flow ids; every field, action, event, condition, tool and step id a flow names; the `with` of each `do` step against the action's parameters; the idle speaker's tool names. A bad name throws `FlowConfigurationError` when the agent is built, not on the turn that first reaches it.
|
|
210
118
|
|
|
211
|
-
|
|
119
|
+
Per turn, the host passes what only it knows:
|
|
212
120
|
|
|
213
|
-
|
|
121
|
+
| Input | What it is |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `sessionId`, `session?` | The session the host loaded, or nothing on a first turn. A wake never creates a session. |
|
|
124
|
+
| `context` | Your own data for this turn: the customer, the tenant, whatever your flows read. Typed by `falai<C>()`. Templates read it as `{{context.x}}`; predicates, actions and tools as `ctx.context`. |
|
|
125
|
+
| `history` | The conversation so far. Pass it on every input kind, wakes included; both calls read it. |
|
|
126
|
+
| `silenced?` | Why the assistant cannot speak right now. `do` steps still run, nothing is phrased, zero calls — unless you pass `{ reason, understand: true }`, which still spends the understand call. |
|
|
127
|
+
| `anchors?`, `claims?` | Host keys and claims from the customer's other sessions, for flows that run once per customer instead of once per session (see [Anchors](./runs-and-waits.md#anchors)). |
|
|
214
128
|
|
|
215
|
-
|
|
129
|
+
Then one of four input kinds: `{ message, id?, at? }`, `{ wake }`, `{ event, payload?, key }` or `{ start: { flow, input?, key } }`. [Agent](../reference/agent.md) lists every field.
|
|
216
130
|
|
|
217
|
-
|
|
131
|
+
## Never sends, never sleeps, never saves
|
|
218
132
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
A primitive sits on the side that owns its decision. A `Flow.when` is AI because intent classification is the AI's job. A `Step.if` is code because boolean checks against `data` are the code's job. A `Directive` is code because the merge algorithm is deterministic. An `Instruction` is rendered text the code controls; the model only chooses how to follow it. Pulling on either thread leads back to the same answer: language belongs to the AI, decisions belong to the code, and the framework is the seam.
|
|
222
|
-
|
|
223
|
-
The `when` / `if` split is the smallest visible expression of this principle. The same activation slot — on a flow, on a step, on an instruction, on a branch entry — accepts both: a string for the AI to evaluate, a function for the code to evaluate. When both are set, code runs first and short-circuits the AI call when the predicate already disqualifies the option. There is no unified condition type that abstracts the difference, because the difference is the point. One side spends tokens; the other does not. Authors choose explicitly, every time.
|
|
224
|
-
|
|
225
|
-
## What stays out
|
|
226
|
-
|
|
227
|
-
A few things are notably absent from the framework, and the absences are part of the architecture.
|
|
228
|
-
|
|
229
|
-
There is no built-in router DSL. The flow router is a single internal phase that scores flows by their `when`/`if` activation, applies a margin against the currently active flow to avoid thrashing, and lands on exactly one flow per turn. It is not exposed for subclassing or composition because there is nothing usefully variable about it at the application layer.
|
|
230
|
-
|
|
231
|
-
There is no per-flow schema. Every flow consumes the agent's `TData`. A flow that needs an extra structured field declares it on the agent schema and lists it in `requiredFields`. The "this flow has its own private state" pattern always becomes "this flow uses a subset of the shared schema."
|
|
232
|
-
|
|
233
|
-
There is no implicit messaging. The framework never emits a message of its own. Completion is a pure state transition — the active flow ends, the session goes idle, and any prose at that boundary comes from a developer-defined `reply` step or from the next flow's first step. Nothing speaks unless a step or a directive says it.
|
|
234
|
-
|
|
235
|
-
There is no glossary. Eight terms are defined in the callout at the top of this page, and every other term in the docs defines itself at first use on the page that introduces it. The framework's surface is small enough that a glossary would duplicate prose without adding clarity.
|
|
236
|
-
|
|
237
|
-
## Why six primitives
|
|
238
|
-
|
|
239
|
-
The set of six is the result of a few specific cuts. Each one collapsed a category of duplication into a single shape, and each one is worth naming for its own sake — not for migration purposes (the [migration guide](../migration/v1-to-v2.md) covers that), but because the surface visible today is the result of those choices.
|
|
240
|
-
|
|
241
|
-
**One word per concept.** The verb form `route()` is still the act of selecting a flow, and "routing" is still the gerund — but the noun for "a single conversational goal" is **Flow**. The system that selects one is the **FlowRouter**. There is no overlap between the noun and the verb, which keeps the surface readable when the two appear in the same sentence.
|
|
242
|
-
|
|
243
|
-
**One Instruction with a kind discriminator.** A behavioral statement is an `Instruction` with `kind: 'must' | 'never' | 'should'`. The three values cover absolute do, absolute don't, and conditional nudge — every behavioral statement an author wants to make falls into one of those categories, and the severity is visible at the call site. The renderer treats all three identically: same prompt position, same scope caption, same `appliedInstructions` reporting. Severity is what the model sees, not what the framework branches on.
|
|
244
|
-
|
|
245
|
-
**One Tool with optional metadata.** A `Tool` is a single interface. The simple case is `{ id, handler }`. The production case adds `validateInput`, `checkPermissions`, `isReadOnly`, `isConcurrencySafe`, `isDestructive`, and `maxResultSizeChars` — every one optional. There is no upgrade boundary mid-codebase: a tool that starts as a plain function adds metadata fields when it needs them, without changing type or import. The executor reads each field defensively (undefined falls back to safe defaults), so the same tool runs identically with two metadata fields or zero.
|
|
246
|
-
|
|
247
|
-
The remaining four primitives — Agent, Step, Flow, Directive — were always single-shape concepts. The six-primitive count is what survives those three consolidations plus the three that stood on their own.
|
|
248
|
-
|
|
249
|
-
## Construction shape
|
|
250
|
-
|
|
251
|
-
The level-1 entry point is `createAgent({ ... })` — one options object, generic inference flowing from `schema` through every `flows[].steps[].collect` reference. The class form `new Agent({ ... })` accepts the same options for power users who need to subclass.
|
|
252
|
-
|
|
253
|
-
```typescript
|
|
254
|
-
import { createAgent, GeminiProvider } from "@falai/agent";
|
|
255
|
-
|
|
256
|
-
const agent = createAgent({
|
|
257
|
-
name: "BookingBot",
|
|
258
|
-
provider: new GeminiProvider({ apiKey }),
|
|
259
|
-
schema: { /* TData shape */ },
|
|
260
|
-
flows: [/* FlowOptions[] */],
|
|
261
|
-
tools: [/* Tool[] */],
|
|
262
|
-
instructions: [/* Instruction[] */],
|
|
263
|
-
});
|
|
264
|
-
```
|
|
133
|
+
`turn()` does no I/O except the provider, your `do` handlers and the tools the model calls. It does not send a message, set a timer, read a clock you did not give it, or touch a store. It returns a plan:
|
|
265
134
|
|
|
266
|
-
|
|
135
|
+
| Result | What the host does with it |
|
|
136
|
+
|---|---|
|
|
137
|
+
| `changed: false` | Nothing. Save nothing, send nothing. |
|
|
138
|
+
| `session` | Save it with the version you loaded: `store.save(session, loadedVersion)`. A stale version throws `SessionConflictError`; discard everything and replay the same input. |
|
|
139
|
+
| `messages[]` | Send each one, honouring `afterMs`, keyed by `key` so a retry never sends twice. |
|
|
140
|
+
| `schedule[]` | Enqueue each wake with `jobId = key`. When it fires, call `turn({ wake: key })`. |
|
|
141
|
+
| `outcomes`, `started`, `ended`, `skipped` | Your execution log. |
|
|
267
142
|
|
|
268
|
-
|
|
143
|
+
The order matters: save first, then send and schedule. A message that leaves before the save is sent twice when the save loses a race; a message that leaves after it is not. The one exception is `do` handlers and tool handlers: they run inside the turn, before the save, so they run at least once and must be idempotent on `ctx.key`. [Runs and waits](./runs-and-waits.md#five-rules-that-always-hold) lists the five rules it rests on.
|
|
269
144
|
|
|
270
|
-
|
|
145
|
+
Time comes from `clock` on the agent (default: the system time), so a test passes `fakeClock()` and moves it by hand. Core code never reads `Date.now()`.
|
|
271
146
|
|
|
272
|
-
|
|
147
|
+
## Where next
|
|
273
148
|
|
|
274
|
-
|
|
149
|
+
- [The turn pipeline](./pipeline.md): the eight phases and what each one costs.
|
|
150
|
+
- [Runs and waits](./runs-and-waits.md): the floor, waits, wakes, keys, claims.
|
|
151
|
+
- [Field collection](./collection.md): pending fields, `ask`, `extract`, `maxAsks`.
|
|
152
|
+
- [Your first agent](../start/02-first-agent.md): the same words, one file at a time.
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Field collection"
|
|
3
|
+
description: "Declare each field once, then let the two model calls fill it and the code decide what is still missing."
|
|
4
|
+
type: concept
|
|
5
|
+
order: 4
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Field collection
|
|
9
|
+
|
|
10
|
+
A field is one piece of data the conversation collects: a name, a company, a budget, a yes or no. You declare each field once, on the agent, with how to ask for it. Steps say which fields they collect. The model asks and extracts. Code decides what is still missing.
|
|
11
|
+
|
|
12
|
+
## Declared once
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { falai } from "@falai/agent";
|
|
16
|
+
|
|
17
|
+
const f = falai().fields({
|
|
18
|
+
nome: { type: "string", ask: "Pergunte o nome, sem tom de formulário." },
|
|
19
|
+
});
|
|
20
|
+
// `f` is the toolkit. `nome` is now a field any flow can collect.
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Declare the rest the same way:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { falai } from "@falai/agent";
|
|
27
|
+
import type { DataOf } from "@falai/agent";
|
|
28
|
+
|
|
29
|
+
const f = falai().fields({
|
|
30
|
+
nome: { type: "string", ask: "Pergunte o nome de um jeito leve, sem tom de formulário." },
|
|
31
|
+
tamanho: { type: "string", enum: ["1-10", "11-50", "51-200", "200+"], ask: "Pergunte quantas pessoas trabalham lá; ofereça as faixas." },
|
|
32
|
+
orcamento: { type: "number", ask: "Pergunte a faixa de investimento, dizendo que é só para orientar." },
|
|
33
|
+
confirmado: { type: "boolean", ask: "Resuma o que anotou e pergunte se está tudo certo." },
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
type Data = DataOf<typeof f>;
|
|
37
|
+
// { readonly nome: string; readonly tamanho: "1-10" | "11-50" | "51-200" | "200+"; readonly orcamento: number; readonly confirmado: boolean }
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
| Property | What it does |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `type` | `'string'`, `'number'`, `'integer'` or `'boolean'`. Values are coerced to it on the way in. |
|
|
43
|
+
| `enum` | The allowed values. A value outside the list is dropped. It becomes a literal union in `Data`. |
|
|
44
|
+
| `description` | What the field means, for the model. |
|
|
45
|
+
| `ask` | How the model should ask for it. A step may override it. |
|
|
46
|
+
| `extract` | Where a value may come from: `'anywhere'` or `'asked'`. The default depends on `type`, below. |
|
|
47
|
+
|
|
48
|
+
`f.fields()` binds the data type, so `collect`, `ask`, `clearOnStart`, `{ step, clear }`, `if: { equals }` and an action's `ctx.set()` are all checked against these field names at compile time. The collected values live in `session.data` as a `Partial<Data>`.
|
|
49
|
+
|
|
50
|
+
## Known and pending
|
|
51
|
+
|
|
52
|
+
A field is **known** when its value is not `undefined`, `null` or `''`. Anything else is unknown. There is no "asked but refused" state, only a count.
|
|
53
|
+
|
|
54
|
+
A talk step's **pending** fields are computed by code every time the step is reached or has spoken:
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
pending = step.collect − known fields − fields asked maxAsks times (in collect order)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Three things follow.
|
|
61
|
+
|
|
62
|
+
- Fields land in any order. When the first message says "sou a Ana da Zeta, somos 30", three fields become known at once, one of them belonging to a later step.
|
|
63
|
+
- A step with nothing pending is skipped with no model call: outcome `code: 'already-known'`. A run that was asking and finds its fields known on the next message logs `ok` and moves on.
|
|
64
|
+
- A step stays `asking` until its pending set is empty or a branch fires. There is no deadlock: `maxAsks` empties the set eventually.
|
|
65
|
+
|
|
66
|
+
## Where values come from
|
|
67
|
+
|
|
68
|
+
Four writers reach `session.data`. Two are the model, two are your code.
|
|
69
|
+
|
|
70
|
+
| Writer | Which fields | When |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| The understand call | Unknown fields with `extract: 'anywhere'` listed by any talk step of the floor's flow or of a candidate `message` flow | On a message, before runs move |
|
|
73
|
+
| The speak call | The speaking step's pending fields, whatever their `extract`, in the envelope `{ message, ...fields }` | When the step speaks |
|
|
74
|
+
| A tool's `data` | Whatever the tool returns | During a speak round, written as given |
|
|
75
|
+
| An action's `ctx.set(patch)` | Whatever the action writes | During a `do` step, written as given |
|
|
76
|
+
|
|
77
|
+
Values from the model are validated before they are written. Each dropped value leaves an outcome line instead of a write:
|
|
78
|
+
|
|
79
|
+
| Check | Outcome detail |
|
|
80
|
+
|---|---|
|
|
81
|
+
| The name is not one of the agent's fields | `code: 'unknown-field'` |
|
|
82
|
+
| The value does not fit the type | `code: 'bad-value'` |
|
|
83
|
+
| The value is not in `enum` | `code: 'not-in-enum'` |
|
|
84
|
+
|
|
85
|
+
Coercion is forgiving (`coerceField` in `src/utils/schema.ts`):
|
|
86
|
+
|
|
87
|
+
- `"30"` becomes the number 30; a comma is a decimal separator, so `"1,5"` is 1.5.
|
|
88
|
+
- An `integer` is truncated.
|
|
89
|
+
- A boolean reads `true`, `sim`, `yes`, `1` as true and `false`, `não`, `nao`, `no`, `0` as false.
|
|
90
|
+
- A number or boolean offered for a string is stringified.
|
|
91
|
+
|
|
92
|
+
## `extract`: anywhere or asked
|
|
93
|
+
|
|
94
|
+
`extract` says where a value may come from.
|
|
95
|
+
|
|
96
|
+
- `'anywhere'`: from any customer message, by the understand call, before the run moves. The default for `string`, `number` and `integer`.
|
|
97
|
+
- `'asked'`: only from the reply to the step that lists the field, by the speak envelope. The default for `boolean`, so a stray "sim" in an unrelated message never confirms anything.
|
|
98
|
+
|
|
99
|
+
The default is `extractMode` in `src/utils/schema.ts`: `def.extract ?? (def.type === 'boolean' ? 'asked' : 'anywhere')`. Set it when the default is wrong for you: a document number you want only when asked, or a boolean the customer often volunteers.
|
|
100
|
+
|
|
101
|
+
This split also decides which call spends tokens on what. On a message, the understand call lists every unknown `'anywhere'` field of the flows in play; the speak call lists only the current step's pending fields. A turn where everything the step needs is `'asked'` and no other flow is eligible skips the understand call entirely: one call for the whole turn (`tests/scenarios/s01-triagem.test.ts`, the correction test).
|
|
102
|
+
|
|
103
|
+
## `maxAsks`
|
|
104
|
+
|
|
105
|
+
`maxAsks` on a talk step is how many times a field may be asked before the step gives up on it. The default is 3 (`DEFAULT_MAX_ASKS` in `src/utils/schema.ts`).
|
|
106
|
+
|
|
107
|
+
`run.asked[field]` goes up by one each time the step speaks and the field is still unknown after that reply's own extraction. A field that reaches the ceiling drops out of the pending set. When the set is empty the step reports it and moves to `then`:
|
|
108
|
+
|
|
109
|
+
```text
|
|
110
|
+
{ kind: 'collect', status: 'skipped', code: 'max-asks', detail: 'orcamento' }
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
One line per field that ran out of asks, with the field's slug in `detail`. `maxAsks: 1` means "ask once, do not insist". The field stays unknown: a later step may still collect it, and a later run of the flow starts the count again, because `asked` lives on the run.
|
|
114
|
+
|
|
115
|
+
## Known fields are never re-extracted
|
|
116
|
+
|
|
117
|
+
Once a field is known it disappears from both calls: the understand call does not list it, the speak envelope does not carry it, and the prompt shows it under "Already known" with the instruction never to ask again. This keeps both calls small, and it means a correction cannot happen by itself. To let the customer change a value, clear it:
|
|
118
|
+
|
|
119
|
+
- `then: { step: 'quem', clear: ['confirmado', 'empresa'] }` clears the fields, then jumps. This is the idiom for a confirmation gate: a "no" clears the disputed field and re-asks it.
|
|
120
|
+
- `clearOnStart: ['confirmado']` on a flow clears the fields when a run starts, before this turn's extraction lands. This is the idiom for `repeat: 'always'` flows that must ask again.
|
|
121
|
+
- `ctx.set({ empresa: undefined })` from a `do` step.
|
|
122
|
+
|
|
123
|
+
`onEnd: 'reset'` keeps the data: the new run starts at step one with everything still known, so only the steps whose fields were cleared will ask.
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
import { falai } from "@falai/agent";
|
|
127
|
+
|
|
128
|
+
const f = falai().fields({
|
|
129
|
+
nome: { type: "string", ask: "Pergunte o nome." },
|
|
130
|
+
empresa: { type: "string", ask: "Pergunte de qual empresa a pessoa fala." },
|
|
131
|
+
orcamento: { type: "number", ask: "Pergunte a faixa de investimento." },
|
|
132
|
+
confirmado: { type: "boolean", ask: "Resuma o que anotou e pergunte se está tudo certo." },
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const triagem = f.flow({
|
|
136
|
+
id: "triagem",
|
|
137
|
+
name: "Triagem",
|
|
138
|
+
on: [{ message: ["quer saber como funciona"], repeat: "always" }],
|
|
139
|
+
clearOnStart: ["confirmado"],
|
|
140
|
+
steps: [
|
|
141
|
+
{ id: "quem", prompt: "Descubra quem é e de onde fala.", collect: ["nome", "empresa"] },
|
|
142
|
+
{ id: "grana", collect: ["orcamento"], ask: { orcamento: "Pergunte quanto {{data.empresa}} pensa em investir por mês." }, maxAsks: 2 },
|
|
143
|
+
{ id: "confirma", collect: ["confirmado"] },
|
|
144
|
+
{ id: "ok", if: { equals: { confirmado: true } }, else: { step: "quem", clear: ["confirmado", "empresa"] } },
|
|
145
|
+
{ id: "tchau", say: "Obrigada, {{data.nome}}. Um vendedor continua daqui." },
|
|
146
|
+
],
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
export { triagem };
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## The wording
|
|
153
|
+
|
|
154
|
+
Three layers of text shape the question, from general to specific.
|
|
155
|
+
|
|
156
|
+
1. The field's `ask`: the default wording for that field everywhere.
|
|
157
|
+
2. The step's `ask: { orcamento: '…' }`: wins over the field's, for that step only.
|
|
158
|
+
3. The step's `prompt`: the guideline for the whole reply. Without one, the default is "Collect what is still missing below, in the flow of the conversation, one or two things per message."
|
|
159
|
+
|
|
160
|
+
All three are templates: `{{data.x}}`, `{{context.x}}` and `{{input.x}}` are filled in before the model reads them. The model sees every pending field of the step with its wording, in collect order, and is told to ask at the pace the prompt sets and to take any value the customer's message already answers.
|
|
161
|
+
|
|
162
|
+
## What the provider sees
|
|
163
|
+
|
|
164
|
+
`toWireSchema` in `src/utils/schema.ts` is the only way a field definition reaches a provider. It keeps `type`, `description` and `enum` and strips `ask`, `extract` and `optional`: those are for the framework, not the model. The result is a closed JSON schema (`additionalProperties: false`). In both envelopes every property is required and nullable, so the model must answer each field with a value or `null`. A field name that is not a legal property name for the provider, or is spelled `message`, travels under an alias and is mapped back on the way out.
|
|
165
|
+
|
|
166
|
+
## Where next
|
|
167
|
+
|
|
168
|
+
- [Collect data](../start/03-collect-data.md): the same ideas as a tutorial.
|
|
169
|
+
- [Branching](../guides/branching.md): `when` and `if` branches on a talk step.
|
|
170
|
+
- [Fields](../reference/fields.md): `FieldDef`, `ScalarDef`, `DataOf`, `InferData`.
|