@falai/agent 1.2.8 → 2.0.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 +40 -886
- package/dist/adapters/MemoryAdapter.js +2 -2
- package/dist/adapters/MemoryAdapter.js.map +1 -1
- package/dist/adapters/MongoAdapter.js +2 -2
- package/dist/adapters/MongoAdapter.js.map +1 -1
- package/dist/adapters/OpenSearchAdapter.d.ts.map +1 -1
- package/dist/adapters/OpenSearchAdapter.js +9 -7
- package/dist/adapters/OpenSearchAdapter.js.map +1 -1
- package/dist/adapters/PostgreSQLAdapter.d.ts +14 -0
- package/dist/adapters/PostgreSQLAdapter.d.ts.map +1 -1
- package/dist/adapters/PostgreSQLAdapter.js +25 -9
- package/dist/adapters/PostgreSQLAdapter.js.map +1 -1
- package/dist/adapters/PrismaAdapter.js +5 -5
- package/dist/adapters/PrismaAdapter.js.map +1 -1
- package/dist/adapters/RedisAdapter.js +2 -2
- package/dist/adapters/RedisAdapter.js.map +1 -1
- package/dist/adapters/SQLiteAdapter.d.ts +17 -0
- package/dist/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/dist/adapters/SQLiteAdapter.js +30 -11
- package/dist/adapters/SQLiteAdapter.js.map +1 -1
- package/dist/cjs/adapters/MemoryAdapter.js +2 -2
- package/dist/cjs/adapters/MemoryAdapter.js.map +1 -1
- package/dist/cjs/adapters/MongoAdapter.js +2 -2
- package/dist/cjs/adapters/MongoAdapter.js.map +1 -1
- package/dist/cjs/adapters/OpenSearchAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/OpenSearchAdapter.js +9 -7
- package/dist/cjs/adapters/OpenSearchAdapter.js.map +1 -1
- package/dist/cjs/adapters/PostgreSQLAdapter.d.ts +14 -0
- package/dist/cjs/adapters/PostgreSQLAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/PostgreSQLAdapter.js +25 -9
- package/dist/cjs/adapters/PostgreSQLAdapter.js.map +1 -1
- package/dist/cjs/adapters/PrismaAdapter.js +5 -5
- package/dist/cjs/adapters/PrismaAdapter.js.map +1 -1
- package/dist/cjs/adapters/RedisAdapter.js +2 -2
- package/dist/cjs/adapters/RedisAdapter.js.map +1 -1
- package/dist/cjs/adapters/SQLiteAdapter.d.ts +17 -0
- package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/SQLiteAdapter.js +30 -11
- package/dist/cjs/adapters/SQLiteAdapter.js.map +1 -1
- package/dist/cjs/constants/index.d.ts +0 -9
- package/dist/cjs/constants/index.d.ts.map +1 -1
- package/dist/cjs/constants/index.js +2 -11
- package/dist/cjs/constants/index.js.map +1 -1
- package/dist/cjs/core/Agent.d.ts +119 -153
- package/dist/cjs/core/Agent.d.ts.map +1 -1
- package/dist/cjs/core/Agent.js +471 -324
- package/dist/cjs/core/Agent.js.map +1 -1
- package/dist/cjs/core/AutoChainExecutor.d.ts +107 -0
- package/dist/cjs/core/AutoChainExecutor.d.ts.map +1 -0
- package/dist/cjs/core/AutoChainExecutor.js +297 -0
- package/dist/cjs/core/AutoChainExecutor.js.map +1 -0
- package/dist/cjs/core/BranchEvaluator.d.ts +54 -0
- package/dist/cjs/core/BranchEvaluator.d.ts.map +1 -0
- package/dist/cjs/core/BranchEvaluator.js +130 -0
- package/dist/cjs/core/BranchEvaluator.js.map +1 -0
- package/dist/cjs/core/DirectiveBus.d.ts +88 -0
- package/dist/cjs/core/DirectiveBus.d.ts.map +1 -0
- package/dist/cjs/core/DirectiveBus.js +196 -0
- package/dist/cjs/core/DirectiveBus.js.map +1 -0
- package/dist/cjs/core/DirectiveChainTracker.d.ts +49 -0
- package/dist/cjs/core/DirectiveChainTracker.d.ts.map +1 -0
- package/dist/cjs/core/DirectiveChainTracker.js +121 -0
- package/dist/cjs/core/DirectiveChainTracker.js.map +1 -0
- package/dist/cjs/core/Flow.d.ts +186 -0
- package/dist/cjs/core/Flow.d.ts.map +1 -0
- package/dist/cjs/core/Flow.js +550 -0
- package/dist/cjs/core/Flow.js.map +1 -0
- package/dist/cjs/core/FlowRouter.d.ts +182 -0
- package/dist/cjs/core/FlowRouter.d.ts.map +1 -0
- package/dist/cjs/core/{RoutingEngine.js → FlowRouter.js} +323 -306
- package/dist/cjs/core/FlowRouter.js.map +1 -0
- package/dist/cjs/core/PersistenceManager.d.ts +2 -2
- package/dist/cjs/core/PersistenceManager.d.ts.map +1 -1
- package/dist/cjs/core/PersistenceManager.js +7 -7
- package/dist/cjs/core/PersistenceManager.js.map +1 -1
- package/dist/cjs/core/PromptComposer.d.ts +21 -8
- package/dist/cjs/core/PromptComposer.d.ts.map +1 -1
- package/dist/cjs/core/PromptComposer.js +182 -105
- package/dist/cjs/core/PromptComposer.js.map +1 -1
- package/dist/cjs/core/PromptSectionCache.d.ts +1 -1
- package/dist/cjs/core/PromptSectionCache.js +1 -1
- package/dist/cjs/core/ResponseEngine.d.ts +18 -8
- package/dist/cjs/core/ResponseEngine.d.ts.map +1 -1
- package/dist/cjs/core/ResponseEngine.js +38 -36
- package/dist/cjs/core/ResponseEngine.js.map +1 -1
- package/dist/cjs/core/ResponseModal.d.ts +73 -56
- package/dist/cjs/core/ResponseModal.d.ts.map +1 -1
- package/dist/cjs/core/ResponseModal.js +1191 -1014
- package/dist/cjs/core/ResponseModal.js.map +1 -1
- package/dist/cjs/core/ResponsePipeline.d.ts +124 -26
- package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/cjs/core/ResponsePipeline.js +509 -136
- package/dist/cjs/core/ResponsePipeline.js.map +1 -1
- package/dist/cjs/core/SignalEvaluator.d.ts +86 -0
- package/dist/cjs/core/SignalEvaluator.d.ts.map +1 -0
- package/dist/cjs/core/SignalEvaluator.js +333 -0
- package/dist/cjs/core/SignalEvaluator.js.map +1 -0
- package/dist/cjs/core/SignalProcessor.d.ts +152 -0
- package/dist/cjs/core/SignalProcessor.d.ts.map +1 -0
- package/dist/cjs/core/SignalProcessor.js +562 -0
- package/dist/cjs/core/SignalProcessor.js.map +1 -0
- package/dist/cjs/core/Step.d.ts +43 -32
- package/dist/cjs/core/Step.d.ts.map +1 -1
- package/dist/cjs/core/Step.js +221 -126
- package/dist/cjs/core/Step.js.map +1 -1
- package/dist/cjs/core/StreamingToolExecutor.d.ts +2 -2
- package/dist/cjs/core/StreamingToolExecutor.d.ts.map +1 -1
- package/dist/cjs/core/StreamingToolExecutor.js.map +1 -1
- package/dist/cjs/core/ToolManager.d.ts +44 -13
- package/dist/cjs/core/ToolManager.d.ts.map +1 -1
- package/dist/cjs/core/ToolManager.js +174 -91
- package/dist/cjs/core/ToolManager.js.map +1 -1
- package/dist/cjs/core/createAgent.d.ts +35 -0
- package/dist/cjs/core/createAgent.d.ts.map +1 -0
- package/dist/cjs/core/createAgent.js +39 -0
- package/dist/cjs/core/createAgent.js.map +1 -0
- package/dist/cjs/core/flow-namespace.d.ts +49 -0
- package/dist/cjs/core/flow-namespace.d.ts.map +1 -0
- package/dist/cjs/core/flow-namespace.js +171 -0
- package/dist/cjs/core/flow-namespace.js.map +1 -0
- package/dist/cjs/index.d.ts +11 -14
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +18 -22
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/providers/AnthropicProvider.d.ts +1 -1
- package/dist/cjs/providers/AnthropicProvider.js +1 -1
- package/dist/cjs/providers/GeminiProvider.d.ts +1 -1
- package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/cjs/providers/GeminiProvider.js +1 -1
- package/dist/cjs/providers/GeminiProvider.js.map +1 -1
- package/dist/cjs/providers/OpenAIProvider.d.ts +1 -1
- package/dist/cjs/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenAIProvider.js +1 -1
- package/dist/cjs/providers/OpenAIProvider.js.map +1 -1
- package/dist/cjs/types/agent.d.ts +183 -54
- package/dist/cjs/types/agent.d.ts.map +1 -1
- package/dist/cjs/types/agent.js +0 -6
- package/dist/cjs/types/agent.js.map +1 -1
- package/dist/cjs/types/ai.d.ts +3 -3
- package/dist/cjs/types/ai.d.ts.map +1 -1
- package/dist/cjs/types/errors.d.ts +15 -0
- package/dist/cjs/types/errors.d.ts.map +1 -0
- package/dist/cjs/types/errors.js +22 -0
- package/dist/cjs/types/errors.js.map +1 -0
- package/dist/cjs/types/flow.d.ts +513 -0
- package/dist/cjs/types/flow.d.ts.map +1 -0
- package/dist/cjs/types/{route.js → flow.js} +2 -2
- package/dist/cjs/types/flow.js.map +1 -0
- package/dist/cjs/types/index.d.ts +7 -6
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/types/index.js +6 -2
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/cjs/types/persistence.d.ts +11 -7
- package/dist/cjs/types/persistence.d.ts.map +1 -1
- package/dist/cjs/types/routing.d.ts +1 -1
- package/dist/cjs/types/routing.d.ts.map +1 -1
- package/dist/cjs/types/session.d.ts +24 -23
- package/dist/cjs/types/session.d.ts.map +1 -1
- package/dist/cjs/types/signals.d.ts +248 -0
- package/dist/cjs/types/signals.d.ts.map +1 -0
- package/dist/cjs/types/signals.js +11 -0
- package/dist/cjs/types/signals.js.map +1 -0
- package/dist/cjs/types/template.d.ts +2 -8
- package/dist/cjs/types/template.d.ts.map +1 -1
- package/dist/cjs/types/tool.d.ts +36 -29
- package/dist/cjs/types/tool.d.ts.map +1 -1
- package/dist/cjs/types/tool.js +1 -1
- package/dist/cjs/types/tool.js.map +1 -1
- package/dist/cjs/utils/condition.d.ts +7 -1
- package/dist/cjs/utils/condition.d.ts.map +1 -1
- package/dist/cjs/utils/condition.js.map +1 -1
- package/dist/cjs/utils/id.d.ts +13 -5
- package/dist/cjs/utils/id.d.ts.map +1 -1
- package/dist/cjs/utils/id.js +24 -10
- package/dist/cjs/utils/id.js.map +1 -1
- package/dist/cjs/utils/index.d.ts +2 -2
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +7 -3
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/session.d.ts +44 -5
- package/dist/cjs/utils/session.d.ts.map +1 -1
- package/dist/cjs/utils/session.js +197 -38
- package/dist/cjs/utils/session.js.map +1 -1
- package/dist/constants/index.d.ts +0 -9
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/index.js +3 -9
- package/dist/constants/index.js.map +1 -1
- package/dist/core/Agent.d.ts +119 -153
- package/dist/core/Agent.d.ts.map +1 -1
- package/dist/core/Agent.js +472 -325
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/AutoChainExecutor.d.ts +107 -0
- package/dist/core/AutoChainExecutor.d.ts.map +1 -0
- package/dist/core/AutoChainExecutor.js +293 -0
- package/dist/core/AutoChainExecutor.js.map +1 -0
- package/dist/core/BranchEvaluator.d.ts +54 -0
- package/dist/core/BranchEvaluator.d.ts.map +1 -0
- package/dist/core/BranchEvaluator.js +126 -0
- package/dist/core/BranchEvaluator.js.map +1 -0
- package/dist/core/DirectiveBus.d.ts +88 -0
- package/dist/core/DirectiveBus.d.ts.map +1 -0
- package/dist/core/DirectiveBus.js +192 -0
- package/dist/core/DirectiveBus.js.map +1 -0
- package/dist/core/DirectiveChainTracker.d.ts +49 -0
- package/dist/core/DirectiveChainTracker.d.ts.map +1 -0
- package/dist/core/DirectiveChainTracker.js +117 -0
- package/dist/core/DirectiveChainTracker.js.map +1 -0
- package/dist/core/Flow.d.ts +186 -0
- package/dist/core/Flow.d.ts.map +1 -0
- package/dist/core/Flow.js +546 -0
- package/dist/core/Flow.js.map +1 -0
- package/dist/core/FlowRouter.d.ts +182 -0
- package/dist/core/FlowRouter.d.ts.map +1 -0
- package/dist/core/{RoutingEngine.js → FlowRouter.js} +322 -305
- package/dist/core/FlowRouter.js.map +1 -0
- package/dist/core/PersistenceManager.d.ts +2 -2
- package/dist/core/PersistenceManager.d.ts.map +1 -1
- package/dist/core/PersistenceManager.js +7 -7
- package/dist/core/PersistenceManager.js.map +1 -1
- package/dist/core/PromptComposer.d.ts +21 -8
- package/dist/core/PromptComposer.d.ts.map +1 -1
- package/dist/core/PromptComposer.js +183 -106
- package/dist/core/PromptComposer.js.map +1 -1
- package/dist/core/PromptSectionCache.d.ts +1 -1
- package/dist/core/PromptSectionCache.js +1 -1
- package/dist/core/ResponseEngine.d.ts +18 -8
- package/dist/core/ResponseEngine.d.ts.map +1 -1
- package/dist/core/ResponseEngine.js +38 -36
- package/dist/core/ResponseEngine.js.map +1 -1
- package/dist/core/ResponseModal.d.ts +73 -56
- package/dist/core/ResponseModal.d.ts.map +1 -1
- package/dist/core/ResponseModal.js +1193 -1016
- package/dist/core/ResponseModal.js.map +1 -1
- package/dist/core/ResponsePipeline.d.ts +124 -26
- package/dist/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/core/ResponsePipeline.js +509 -137
- package/dist/core/ResponsePipeline.js.map +1 -1
- package/dist/core/SignalEvaluator.d.ts +86 -0
- package/dist/core/SignalEvaluator.d.ts.map +1 -0
- package/dist/core/SignalEvaluator.js +326 -0
- package/dist/core/SignalEvaluator.js.map +1 -0
- package/dist/core/SignalProcessor.d.ts +152 -0
- package/dist/core/SignalProcessor.d.ts.map +1 -0
- package/dist/core/SignalProcessor.js +555 -0
- package/dist/core/SignalProcessor.js.map +1 -0
- package/dist/core/Step.d.ts +43 -32
- package/dist/core/Step.d.ts.map +1 -1
- package/dist/core/Step.js +220 -126
- package/dist/core/Step.js.map +1 -1
- package/dist/core/StreamingToolExecutor.d.ts +2 -2
- package/dist/core/StreamingToolExecutor.d.ts.map +1 -1
- package/dist/core/StreamingToolExecutor.js.map +1 -1
- package/dist/core/ToolManager.d.ts +44 -13
- package/dist/core/ToolManager.d.ts.map +1 -1
- package/dist/core/ToolManager.js +174 -91
- package/dist/core/ToolManager.js.map +1 -1
- package/dist/core/createAgent.d.ts +35 -0
- package/dist/core/createAgent.d.ts.map +1 -0
- package/dist/core/createAgent.js +36 -0
- package/dist/core/createAgent.js.map +1 -0
- package/dist/core/flow-namespace.d.ts +49 -0
- package/dist/core/flow-namespace.d.ts.map +1 -0
- package/dist/core/flow-namespace.js +168 -0
- package/dist/core/flow-namespace.js.map +1 -0
- package/dist/index.d.ts +11 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -12
- package/dist/index.js.map +1 -1
- package/dist/providers/AnthropicProvider.d.ts +1 -1
- package/dist/providers/AnthropicProvider.js +1 -1
- package/dist/providers/GeminiProvider.d.ts +1 -1
- package/dist/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/providers/GeminiProvider.js +1 -1
- package/dist/providers/GeminiProvider.js.map +1 -1
- package/dist/providers/OpenAIProvider.d.ts +1 -1
- package/dist/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/providers/OpenAIProvider.js +1 -1
- package/dist/providers/OpenAIProvider.js.map +1 -1
- package/dist/types/agent.d.ts +183 -54
- package/dist/types/agent.d.ts.map +1 -1
- package/dist/types/agent.js +0 -6
- package/dist/types/agent.js.map +1 -1
- package/dist/types/ai.d.ts +3 -3
- package/dist/types/ai.d.ts.map +1 -1
- package/dist/types/errors.d.ts +15 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +18 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/flow.d.ts +513 -0
- package/dist/types/flow.d.ts.map +1 -0
- package/dist/types/flow.js +5 -0
- package/dist/types/flow.js.map +1 -0
- package/dist/types/index.d.ts +7 -6
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +4 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/persistence.d.ts +11 -7
- package/dist/types/persistence.d.ts.map +1 -1
- package/dist/types/routing.d.ts +1 -1
- package/dist/types/routing.d.ts.map +1 -1
- package/dist/types/session.d.ts +24 -23
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/signals.d.ts +248 -0
- package/dist/types/signals.d.ts.map +1 -0
- package/dist/types/signals.js +10 -0
- package/dist/types/signals.js.map +1 -0
- package/dist/types/template.d.ts +2 -8
- package/dist/types/template.d.ts.map +1 -1
- package/dist/types/tool.d.ts +36 -29
- package/dist/types/tool.d.ts.map +1 -1
- package/dist/types/tool.js +1 -1
- package/dist/types/tool.js.map +1 -1
- package/dist/utils/condition.d.ts +7 -1
- package/dist/utils/condition.d.ts.map +1 -1
- package/dist/utils/condition.js.map +1 -1
- package/dist/utils/id.d.ts +13 -5
- package/dist/utils/id.d.ts.map +1 -1
- package/dist/utils/id.js +22 -9
- package/dist/utils/id.js.map +1 -1
- package/dist/utils/index.d.ts +2 -2
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -2
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/session.d.ts +44 -5
- package/dist/utils/session.d.ts.map +1 -1
- package/dist/utils/session.js +193 -37
- package/dist/utils/session.js.map +1 -1
- package/docs/README.md +22 -200
- package/docs/concepts/architecture.md +281 -0
- package/docs/concepts/directives.md +400 -0
- package/docs/concepts/pipeline.md +399 -0
- package/docs/guides/branching.md +263 -0
- package/docs/guides/compaction.md +163 -0
- package/docs/guides/conditions.md +167 -0
- package/docs/guides/error-handling.md +176 -0
- package/docs/guides/flow-control.md +409 -0
- package/docs/guides/instructions.md +210 -0
- package/docs/guides/persistence.md +182 -0
- package/docs/guides/streaming.md +137 -0
- package/docs/migration/README.md +14 -0
- package/docs/migration/route-to-flow.md +561 -0
- package/docs/migration/v1-to-v2.md +909 -0
- package/docs/reference/adapters.md +481 -0
- package/docs/reference/branches.md +241 -0
- package/docs/reference/create-agent.md +186 -0
- package/docs/reference/directive.md +243 -0
- package/docs/reference/errors.md +122 -0
- package/docs/reference/flow.md +238 -0
- package/docs/reference/instruction.md +177 -0
- package/docs/reference/pre-directive.md +131 -0
- package/docs/reference/providers.md +227 -0
- package/docs/reference/signals.md +356 -0
- package/docs/reference/step.md +339 -0
- package/docs/reference/tool.md +269 -0
- package/docs/start/01-install.md +81 -0
- package/docs/start/02-first-agent.md +196 -0
- package/docs/start/03-collect-data.md +222 -0
- package/docs/start/04-add-tools.md +276 -0
- package/docs/start/05-go-to-production.md +216 -0
- package/examples/01-quickstart.ts +20 -0
- package/examples/02-data-extraction.ts +90 -0
- package/examples/03-tools.ts +136 -0
- package/examples/04-instructions.ts +100 -0
- package/examples/05-branching.ts +140 -0
- package/examples/06-flow-control.ts +103 -0
- package/examples/07-streaming.ts +69 -0
- package/examples/08-persistence.ts +98 -0
- package/examples/09-signals.ts +144 -0
- package/examples/tsconfig.json +30 -0
- package/package.json +2 -1
- package/src/adapters/MemoryAdapter.ts +3 -3
- package/src/adapters/MongoAdapter.ts +3 -3
- package/src/adapters/OpenSearchAdapter.ts +10 -8
- package/src/adapters/PostgreSQLAdapter.ts +26 -10
- package/src/adapters/PrismaAdapter.ts +6 -6
- package/src/adapters/RedisAdapter.ts +3 -3
- package/src/adapters/SQLiteAdapter.ts +31 -12
- package/src/constants/index.ts +2 -10
- package/src/core/Agent.ts +585 -374
- package/src/core/AutoChainExecutor.ts +440 -0
- package/src/core/BranchEvaluator.ts +167 -0
- package/src/core/DirectiveBus.ts +248 -0
- package/src/core/DirectiveChainTracker.ts +144 -0
- package/src/core/Flow.ts +666 -0
- package/src/core/{RoutingEngine.ts → FlowRouter.ts} +385 -365
- package/src/core/PersistenceManager.ts +8 -8
- package/src/core/PromptComposer.ts +209 -140
- package/src/core/PromptSectionCache.ts +1 -1
- package/src/core/ResponseEngine.ts +61 -46
- package/src/core/ResponseModal.ts +1453 -1240
- package/src/core/ResponsePipeline.ts +655 -175
- package/src/core/SignalEvaluator.ts +420 -0
- package/src/core/SignalProcessor.ts +723 -0
- package/src/core/Step.ts +279 -176
- package/src/core/StreamingToolExecutor.ts +4 -4
- package/src/core/ToolManager.ts +200 -97
- package/src/core/createAgent.ts +40 -0
- package/src/core/flow-namespace.ts +219 -0
- package/src/index.ts +42 -36
- package/src/providers/AnthropicProvider.ts +2 -2
- package/src/providers/GeminiProvider.ts +2 -2
- package/src/providers/OpenAIProvider.ts +2 -2
- package/src/types/agent.ts +182 -53
- package/src/types/ai.ts +3 -3
- package/src/types/errors.ts +18 -0
- package/src/types/flow.ts +590 -0
- package/src/types/index.ts +43 -16
- package/src/types/persistence.ts +12 -8
- package/src/types/routing.ts +1 -1
- package/src/types/session.ts +26 -23
- package/src/types/signals.ts +321 -0
- package/src/types/template.ts +3 -11
- package/src/types/tool.ts +50 -42
- package/src/utils/condition.ts +13 -4
- package/src/utils/id.ts +27 -9
- package/src/utils/index.ts +6 -2
- package/src/utils/session.ts +238 -42
- package/dist/cjs/core/BatchExecutor.d.ts +0 -359
- package/dist/cjs/core/BatchExecutor.d.ts.map +0 -1
- package/dist/cjs/core/BatchExecutor.js +0 -861
- package/dist/cjs/core/BatchExecutor.js.map +0 -1
- package/dist/cjs/core/BatchPromptBuilder.d.ts +0 -89
- package/dist/cjs/core/BatchPromptBuilder.d.ts.map +0 -1
- package/dist/cjs/core/BatchPromptBuilder.js +0 -223
- package/dist/cjs/core/BatchPromptBuilder.js.map +0 -1
- package/dist/cjs/core/Route.d.ts +0 -180
- package/dist/cjs/core/Route.d.ts.map +0 -1
- package/dist/cjs/core/Route.js +0 -542
- package/dist/cjs/core/Route.js.map +0 -1
- package/dist/cjs/core/RoutingEngine.d.ts +0 -185
- package/dist/cjs/core/RoutingEngine.d.ts.map +0 -1
- package/dist/cjs/core/RoutingEngine.js.map +0 -1
- package/dist/cjs/types/route.d.ts +0 -336
- package/dist/cjs/types/route.d.ts.map +0 -1
- package/dist/cjs/types/route.js.map +0 -1
- package/dist/core/BatchExecutor.d.ts +0 -359
- package/dist/core/BatchExecutor.d.ts.map +0 -1
- package/dist/core/BatchExecutor.js +0 -856
- package/dist/core/BatchExecutor.js.map +0 -1
- package/dist/core/BatchPromptBuilder.d.ts +0 -89
- package/dist/core/BatchPromptBuilder.d.ts.map +0 -1
- package/dist/core/BatchPromptBuilder.js +0 -219
- package/dist/core/BatchPromptBuilder.js.map +0 -1
- package/dist/core/Route.d.ts +0 -180
- package/dist/core/Route.d.ts.map +0 -1
- package/dist/core/Route.js +0 -538
- package/dist/core/Route.js.map +0 -1
- package/dist/core/RoutingEngine.d.ts +0 -185
- package/dist/core/RoutingEngine.d.ts.map +0 -1
- package/dist/core/RoutingEngine.js.map +0 -1
- package/dist/types/route.d.ts +0 -336
- package/dist/types/route.d.ts.map +0 -1
- package/dist/types/route.js +0 -5
- package/dist/types/route.js.map +0 -1
- package/docs/CONTRIBUTING.md +0 -521
- package/docs/api/README.md +0 -3299
- package/docs/api/overview.md +0 -1410
- package/docs/architecture/data-extraction-flow.md +0 -360
- package/docs/architecture/multi-step-execution.md +0 -277
- package/docs/core/agent/README.md +0 -938
- package/docs/core/agent/context-management.md +0 -796
- package/docs/core/agent/rules-and-prohibitions.md +0 -113
- package/docs/core/agent/session-management.md +0 -693
- package/docs/core/ai-integration/prompt-composition.md +0 -355
- package/docs/core/ai-integration/providers.md +0 -515
- package/docs/core/ai-integration/response-processing.md +0 -433
- package/docs/core/conversation-flows/data-collection.md +0 -772
- package/docs/core/conversation-flows/route-dsl.md +0 -509
- package/docs/core/conversation-flows/routes.md +0 -249
- package/docs/core/conversation-flows/step-transitions.md +0 -731
- package/docs/core/conversation-flows/steps.md +0 -268
- package/docs/core/error-handling.md +0 -830
- package/docs/core/persistence/adapters.md +0 -255
- package/docs/core/persistence/session-storage.md +0 -656
- package/docs/core/routing/intelligent-routing.md +0 -470
- package/docs/core/tools/enhanced-tool.md +0 -186
- package/docs/core/tools/streaming-execution.md +0 -161
- package/docs/core/tools/tool-definition.md +0 -970
- package/docs/core/tools/tool-scoping.md +0 -819
- package/docs/guides/advanced-patterns/publishing.md +0 -186
- package/docs/guides/context-compaction.md +0 -96
- package/docs/guides/error-handling-patterns.md +0 -578
- package/docs/guides/getting-started/README.md +0 -795
- package/docs/guides/migration/README.md +0 -101
- package/docs/guides/migration/flexible-routing-conditions.md +0 -375
- package/docs/guides/migration/multi-step-execution.md +0 -393
- package/docs/guides/migration/response-modal-refactor.md +0 -518
- package/docs/guides/prompt-optimization.md +0 -164
- package/examples/advanced-patterns/context-compaction.ts +0 -223
- package/examples/advanced-patterns/knowledge-based-agent.ts +0 -735
- package/examples/advanced-patterns/persistent-onboarding.ts +0 -728
- package/examples/advanced-patterns/route-lifecycle-hooks.ts +0 -556
- package/examples/advanced-patterns/streaming-responses.ts +0 -656
- package/examples/ai-providers/anthropic-integration.ts +0 -388
- package/examples/ai-providers/openai-integration.ts +0 -228
- package/examples/condition-patterns/function-only-conditions.ts +0 -365
- package/examples/condition-patterns/mixed-array-conditions.ts +0 -477
- package/examples/condition-patterns/route-skipif-patterns.ts +0 -468
- package/examples/condition-patterns/step-skipif-patterns.ts +0 -0
- package/examples/condition-patterns/string-only-conditions.ts +0 -296
- package/examples/conversation-flows/completion-transitions.ts +0 -318
- package/examples/core-concepts/basic-agent.ts +0 -503
- package/examples/core-concepts/modern-streaming-api.ts +0 -309
- package/examples/core-concepts/schema-driven-extraction.ts +0 -332
- package/examples/core-concepts/session-management.ts +0 -494
- package/examples/integrations/database-integration.ts +0 -631
- package/examples/integrations/healthcare-integration.ts +0 -595
- package/examples/integrations/search-integration.ts +0 -530
- package/examples/integrations/server-session-management.ts +0 -307
- package/examples/persistence/custom-adapter.ts +0 -526
- package/examples/persistence/database-persistence.ts +0 -583
- package/examples/persistence/memory-sessions.ts +0 -495
- package/examples/persistence/prisma-schema.example.prisma +0 -74
- package/examples/persistence/redis-persistence.ts +0 -488
- package/examples/tools/basic-tools.ts +0 -765
- package/examples/tools/data-enrichment-tools.ts +0 -593
- package/examples/tools/enhanced-tool-metadata.ts +0 -268
- package/examples/tools/streaming-tool-execution.ts +0 -283
- package/src/core/BatchExecutor.ts +0 -1187
- package/src/core/BatchPromptBuilder.ts +0 -299
- package/src/core/Route.ts +0 -678
- package/src/types/route.ts +0 -392
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Errors"
|
|
3
|
+
description: "Typed error classes the framework throws, and the message format contract every thrown error follows."
|
|
4
|
+
type: reference
|
|
5
|
+
order: 12
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Errors
|
|
9
|
+
|
|
10
|
+
> **Where this is introduced:** [Errors](../guides/error-handling.md)
|
|
11
|
+
|
|
12
|
+
`@falai/agent` throws typed `Error` subclasses for every failure mode the framework owns. Catch them by class to discriminate construction errors from runtime errors, and by `error.name` when classes that are not exported (e.g. `DataValidationError`, `ResponseGenerationError`) need to be matched.
|
|
13
|
+
|
|
14
|
+
Every thrown message follows the same format contract:
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
[<ErrorClass>] <what>: <why>. <how to fix>.
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The bracketed prefix matches the class name. The "what / why / how to fix" triplet is mandatory — the framework never throws a bare message.
|
|
21
|
+
|
|
22
|
+
## Signature
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
// Exported from "@falai/agent"
|
|
26
|
+
class FlowConfigurationError extends Error { /* name = "FlowConfigurationError" */ }
|
|
27
|
+
class ToolCreationError extends Error { toolId: string; cause?: Error }
|
|
28
|
+
class ToolExecutionError extends Error {
|
|
29
|
+
toolId: string;
|
|
30
|
+
executionContext?: Record<string, unknown>;
|
|
31
|
+
cause?: Error;
|
|
32
|
+
}
|
|
33
|
+
class NotImplementedError extends Error { /* name = "NotImplementedError" */ }
|
|
34
|
+
|
|
35
|
+
// Internal — match by `error.name` (not exported from the package barrel)
|
|
36
|
+
class DataValidationError extends Error { errors: ValidationError[] }
|
|
37
|
+
class ResponseGenerationError extends Error {
|
|
38
|
+
details?: {
|
|
39
|
+
originalError?: unknown;
|
|
40
|
+
params?: Record<string, unknown>;
|
|
41
|
+
phase?: string;
|
|
42
|
+
context?: Record<string, unknown>;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Fields
|
|
48
|
+
|
|
49
|
+
| Class | Thrown when | Notable fields | Recover by |
|
|
50
|
+
|-------|-------------|----------------|------------|
|
|
51
|
+
| `FlowConfigurationError` | Construction- or run-time misconfiguration: duplicate ids, unknown `collect` keys, malformed `Directive`, auto-step cycles, branch targets that do not resolve, function on `when`. | `message` | Fix the offending agent/flow/step/branch/directive at the source. Not a runtime-recoverable error. |
|
|
52
|
+
| `ToolCreationError` | A `Tool` fails registration (invalid schema, duplicate id, builder threw). | `toolId`, `cause` | Repair the tool definition. Not user-facing. |
|
|
53
|
+
| `ToolExecutionError` | A handler throws, all retries fail, or `validateInput` cannot correct invalid args. | `toolId`, `executionContext`, `cause` | Surface a user-friendly message; optionally `agent.dispatch({ goTo: '<recovery-flow>' })`. |
|
|
54
|
+
| `DataValidationError` | `agent.respond(...)` collects values that violate the declared `schema`. | `errors: ValidationError[]` | Re-prompt for the offending fields, then retry. |
|
|
55
|
+
| `ResponseGenerationError` | The provider call fails or the response cannot be parsed. | `details.phase`, `details.originalError` | Retry with backoff, fall back to a different provider, or surface a soft failure to the user. |
|
|
56
|
+
| `NotImplementedError` | A reserved option is set to a value this version does not support (e.g. `routerMode: 'embedding'` in v2.0). | `message` | Use a supported value. |
|
|
57
|
+
|
|
58
|
+
## Examples
|
|
59
|
+
|
|
60
|
+
### 1. Narrowing by class and `name`
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import {
|
|
64
|
+
FlowConfigurationError,
|
|
65
|
+
ToolExecutionError,
|
|
66
|
+
NotImplementedError,
|
|
67
|
+
} from "@falai/agent";
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const response = await agent.respond(message);
|
|
71
|
+
return response.message;
|
|
72
|
+
} catch (err) {
|
|
73
|
+
if (err instanceof FlowConfigurationError) throw err; // bug — bubble up
|
|
74
|
+
if (err instanceof NotImplementedError) throw err; // config bug
|
|
75
|
+
if (err instanceof ToolExecutionError) {
|
|
76
|
+
log.warn({ toolId: err.toolId, cause: err.cause }, err.message);
|
|
77
|
+
return "Sorry, that action failed. Try again in a moment.";
|
|
78
|
+
}
|
|
79
|
+
// Not exported — match by name.
|
|
80
|
+
if (err instanceof Error && err.name === "DataValidationError") {
|
|
81
|
+
return "I need you to clarify a few details — let's try that again.";
|
|
82
|
+
}
|
|
83
|
+
if (err instanceof Error && err.name === "ResponseGenerationError") {
|
|
84
|
+
return "I'm having trouble reaching the model. Please retry.";
|
|
85
|
+
}
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 2. The format contract in practice
|
|
91
|
+
|
|
92
|
+
Every thrown message is parseable. The leading `[<ErrorClass>]` token mirrors the class name, the colon separates `<what>` from `<why>`, and the trailing sentence is `<how to fix>`.
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
[FlowConfigurationError] Invalid directive: multiple position fields set (goTo, complete). A directive may have at most one position field. Remove the extras.
|
|
96
|
+
|
|
97
|
+
[ToolExecutionError] Tool "book_hotel" execution failed: all 3 attempts exhausted. Check the tool handler for errors or increase maxRetries. Last error: ECONNRESET.
|
|
98
|
+
|
|
99
|
+
[DataValidationError] Data validation failed: fields [checkIn must be a date] did not pass schema validation. Fix the offending values to match the declared schema.
|
|
100
|
+
|
|
101
|
+
[NotImplementedError] routerMode "embedding" is not implemented: only "ai" is supported in v2.0. Set routerMode to "ai" or omit the option.
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Errors
|
|
105
|
+
|
|
106
|
+
The format contract itself has zero runtime enforcement — it is a contract on framework code, not on user code. If you write a custom `Tool` or hook that throws, follow the same shape so downstream `try/catch` blocks parse uniformly:
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
throw new ToolExecutionError(
|
|
110
|
+
`[ToolExecutionError] Tool "${tool.id}" booking failed: provider returned 503. Retry the call or fall back to manual booking.`,
|
|
111
|
+
tool.id,
|
|
112
|
+
);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Tool input validation, permission denials, and missing-tool warnings are reported as `ToolResult { success: false, error }` rather than thrown — this keeps the AI's reasoning loop intact while preserving the same `[<ErrorClass>] <what>: <why>. <how to fix>.` shape in the `error` string.
|
|
116
|
+
|
|
117
|
+
## Related
|
|
118
|
+
|
|
119
|
+
- [Errors](../guides/error-handling.md) — recipe-shaped guide that introduces this surface.
|
|
120
|
+
- [createAgent](./create-agent.md) — construction-time errors thrown from `new Agent(...)`.
|
|
121
|
+
- [Tool](./tool.md) — handler return shape and the `ToolExecutionError` triggers.
|
|
122
|
+
- [Directive](./directive.md) — the validation rules that surface as `FlowConfigurationError`.
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Flow
|
|
3
|
+
description: A goal-shaped sequence of steps with shared schema, conditions, and completion semantics.
|
|
4
|
+
type: reference
|
|
5
|
+
order: 2
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Flow
|
|
9
|
+
|
|
10
|
+
> **Where this is introduced:** [Architecture](../concepts/architecture.md)
|
|
11
|
+
|
|
12
|
+
A `Flow` is one of the seven primitives in `@falai/agent`. It models a single conversational goal — booking a hotel, escalating a complaint, onboarding a teammate — as an ordered set of steps that share the agent's typed `TData` schema. Flows declare what data they need (`requiredFields`), what extra data they can use (`optionalFields`), when they should activate (`when` for AI strings, `if` for code), and what happens when they finish (`onComplete` or `hooks.onComplete`). The router selects exactly one flow per turn; once the active flow's required fields are satisfied, the engine fires its completion path.
|
|
13
|
+
|
|
14
|
+
## Signature
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
interface FlowOptions<TContext = unknown, TData = unknown> {
|
|
18
|
+
id?: string;
|
|
19
|
+
title: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
|
|
22
|
+
when?: ConditionWhen; // string | string[]
|
|
23
|
+
if?: ConditionIf<TContext, TData>; // predicate | predicate[]
|
|
24
|
+
|
|
25
|
+
instructions?: Instruction<TContext, TData>[];
|
|
26
|
+
tools?: (string | Tool<TContext, TData>)[];
|
|
27
|
+
|
|
28
|
+
routingExtrasSchema?: StructuredSchema;
|
|
29
|
+
responseOutputSchema?: StructuredSchema;
|
|
30
|
+
|
|
31
|
+
requiredFields?: (keyof TData)[];
|
|
32
|
+
optionalFields?: (keyof TData)[];
|
|
33
|
+
initialData?: Partial<TData>;
|
|
34
|
+
|
|
35
|
+
steps?: StepOptions<TContext, TData>[];
|
|
36
|
+
|
|
37
|
+
onComplete?: string; // top-level: string sugar only
|
|
38
|
+
reentrant?: boolean; // default false
|
|
39
|
+
|
|
40
|
+
hooks?: FlowLifecycleHooks<TContext, TData>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
class Flow<TContext = unknown, TData = unknown> {
|
|
44
|
+
readonly id: string;
|
|
45
|
+
readonly title: string;
|
|
46
|
+
readonly description?: string;
|
|
47
|
+
readonly when?: ConditionWhen;
|
|
48
|
+
readonly if?: ConditionIf<TContext, TData>;
|
|
49
|
+
readonly initialStep: Step<TContext, TData>;
|
|
50
|
+
readonly requiredFields?: (keyof TData)[];
|
|
51
|
+
readonly optionalFields?: (keyof TData)[];
|
|
52
|
+
readonly initialData?: Partial<TData>;
|
|
53
|
+
readonly onComplete?: string;
|
|
54
|
+
readonly reentrant: boolean;
|
|
55
|
+
readonly hooks?: FlowLifecycleHooks<TContext, TData>;
|
|
56
|
+
|
|
57
|
+
constructor(options: FlowOptions<TContext, TData>, parentAgent?: Agent<TContext, TData>);
|
|
58
|
+
|
|
59
|
+
addStep(options: StepOptions<TContext, TData>): Step<TContext, TData>;
|
|
60
|
+
getSteps(): Step<TContext, TData>[];
|
|
61
|
+
getStep(stepId: string): Step<TContext, TData> | undefined;
|
|
62
|
+
getInstructions(): Instruction<TContext, TData>[];
|
|
63
|
+
getTools(): Tool<TContext, TData>[];
|
|
64
|
+
|
|
65
|
+
isComplete(data: Partial<TData>): boolean;
|
|
66
|
+
getMissingRequiredFields(data: Partial<TData>): (keyof TData)[];
|
|
67
|
+
getCompletionProgress(data: Partial<TData>): number;
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Fields
|
|
72
|
+
|
|
73
|
+
### `FlowOptions`
|
|
74
|
+
|
|
75
|
+
| Field | Type | Required | Default | Notes |
|
|
76
|
+
| --------------------- | ------------------------------------------------- | -------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
77
|
+
| `id` | `string` | no | derived from `title` | Stable identifier. Auto-generated deterministically from the title when omitted. |
|
|
78
|
+
| `title` | `string` | yes | — | Human-readable name. Shown to the router and used as the default flow id. |
|
|
79
|
+
| `description` | `string` | no | — | One-line summary surfaced to the router prompt. |
|
|
80
|
+
| `when` | `string \| string[]` | no | — | AI-evaluated activation condition(s). Strings only — functions belong on `if`. Multiple strings combine with AND semantics. |
|
|
81
|
+
| `if` | `(ctx) => boolean \| Promise<boolean>` or array | no | — | Code-evaluated activation condition(s). Free to evaluate. When both are set, `if` runs first; `when` only evaluates if `if` passes. |
|
|
82
|
+
| `instructions` | `Instruction<TContext, TData>[]` | no | `[]` | Flow-scoped instructions. Apply only while this flow is active. See [Instruction](./instruction.md). |
|
|
83
|
+
| `tools` | `(string \| Tool)[]` | no | `[]` | Tool ids (resolved via the agent's tool registry) or inline `Tool` objects. Available only while this flow is active. |
|
|
84
|
+
| `routingExtrasSchema` | `StructuredSchema` | no | — | Optional extra fields the router may extract during routing. |
|
|
85
|
+
| `responseOutputSchema`| `StructuredSchema` | no | — | Optional structured response shape for this flow's assistant messages. |
|
|
86
|
+
| `requiredFields` | `(keyof TData)[]` | no | — | Fields that must be present in `session.data` for the flow to complete. Drives `isComplete` and progress calculation. |
|
|
87
|
+
| `optionalFields` | `(keyof TData)[]` | no | — | Fields the flow uses but doesn't require. Tracked for re-entry resets and progress visibility only. |
|
|
88
|
+
| `initialData` | `Partial<TData>` | no | — | Pre-populated values applied when the flow is entered. Merged into `session.data`. |
|
|
89
|
+
| `steps` | `StepOptions<TContext, TData>[]` | no | — | Sequential steps. The first becomes the initial step; the rest are chained as linear successors. The last step is the implicit terminus. |
|
|
90
|
+
| `onComplete` | `string` | no | — | **String only.** Sugar for `hooks.onComplete = () => ({ goTo: '<id>' })`. For dynamic completion logic, use `hooks.onComplete`. |
|
|
91
|
+
| `reentrant` | `boolean` | no | `false` | If `true`, the router may select this flow again after it has completed in the current session. On re-entry, declared `requiredFields` and `optionalFields` are cleared. |
|
|
92
|
+
| `hooks` | `FlowLifecycleHooks<TContext, TData>` | no | — | Lifecycle hooks: `onEnter`, `onExit`, `onComplete`, `onDataUpdate`, `onContextUpdate`. See below. |
|
|
93
|
+
|
|
94
|
+
### `FlowLifecycleHooks`
|
|
95
|
+
|
|
96
|
+
| Hook | Returns | Phase | Notes |
|
|
97
|
+
| ----------------- | -------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
98
|
+
| `onEnter` | `void \| PreDirective` | pre-LLM | Fires when the flow is entered. May augment the prompt, inject tools, or `halt`. See [PreDirective](./pre-directive.md).|
|
|
99
|
+
| `onExit` | `void` | post | Informational. Receives an `ExitReason`; cannot influence flow control. |
|
|
100
|
+
| `onComplete` | `void \| Directive` | post-LLM | Handler form of completion. Mutually exclusive with top-level `onComplete: string` — setting both throws. |
|
|
101
|
+
| `onDataUpdate` | `Partial<TData>` | post | Mutate or enrich the data update before it is committed to `session.data`. |
|
|
102
|
+
| `onContextUpdate` | `void` | post | Informational reaction to context updates while this flow is active. |
|
|
103
|
+
|
|
104
|
+
### `Flow` instance methods
|
|
105
|
+
|
|
106
|
+
| Method | Returns | Notes |
|
|
107
|
+
| -------------------------------------------- | -------------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
108
|
+
| `addStep(options)` | `Step<TContext, TData>` | Imperatively append a step as the successor of the current last step. Same validations as `steps[]`. |
|
|
109
|
+
| `getSteps()` | `Step<TContext, TData>[]` | All steps reachable from the initial step via BFS traversal. |
|
|
110
|
+
| `getStep(stepId)` | `Step \| undefined` | Look up a step by id. |
|
|
111
|
+
| `getInstructions()` | `Instruction[]` | Flow-scoped instructions (a copy). |
|
|
112
|
+
| `getTools()` | `Tool[]` | Flow-scoped tools (a copy). |
|
|
113
|
+
| `isComplete(data)` | `boolean` | `true` when all `requiredFields` are populated. Optional-only flows complete on terminus, not data. |
|
|
114
|
+
| `getMissingRequiredFields(data)` | `(keyof TData)[]` | Fields from `requiredFields` not yet present in `data`. |
|
|
115
|
+
| `getCompletionProgress(data)` | `number` (0–1) | Fraction of `requiredFields` satisfied. `0` when only `optionalFields` are declared. |
|
|
116
|
+
|
|
117
|
+
### Completion semantics
|
|
118
|
+
|
|
119
|
+
A flow finishes in one of three ways:
|
|
120
|
+
|
|
121
|
+
1. **All `requiredFields` are satisfied.** The engine marks the flow complete, fires `hooks.onComplete` (or the desugared `onComplete: string` transition), and applies the returned `Directive`.
|
|
122
|
+
2. **The last step in `steps[]` runs and `requiredFields` is empty.** The terminus rule applies — the flow is implicitly complete, and the same completion path runs.
|
|
123
|
+
3. **A `Directive` with `complete: true` is returned** from a tool, hook, or branch while the flow is active. Completion fires immediately regardless of field state.
|
|
124
|
+
|
|
125
|
+
`requiredFields` is the contract for "this flow is done." `optionalFields` is descriptive metadata — it never gates completion, but it's tracked for two reasons:
|
|
126
|
+
|
|
127
|
+
- **Re-entry resets.** When `reentrant: true` and the router re-selects this flow after it has completed, every field listed in `requiredFields` and `optionalFields` is cleared so the flow starts fresh.
|
|
128
|
+
- **Progress visibility.** `getCompletionProgress` ignores optional fields by design — progress reflects what the flow is *blocked on*, not what it has *touched*.
|
|
129
|
+
|
|
130
|
+
### `reentrant` behavior
|
|
131
|
+
|
|
132
|
+
By default (`reentrant: false`), once a flow completes the router excludes it from candidate selection for the rest of the session. Set `reentrant: true` to support patterns like "book another?", "file another ticket?", or "search again". On re-entry:
|
|
133
|
+
|
|
134
|
+
- All `requiredFields` and `optionalFields` are cleared from `session.data`.
|
|
135
|
+
- Other fields in `session.data` are preserved.
|
|
136
|
+
- The flow restarts from its initial step.
|
|
137
|
+
|
|
138
|
+
`onComplete` always wins over `reentrant`. If `onComplete` (or `hooks.onComplete`) returns a target, the session transitions there. `reentrant` is consulted only when the completion handler is absent or returns `undefined`.
|
|
139
|
+
|
|
140
|
+
### Top-level `onComplete` vs `hooks.onComplete`
|
|
141
|
+
|
|
142
|
+
The top-level `onComplete` is **string-only** sugar. Internally, the constructor desugars `onComplete: 'targetFlow'` into `hooks.onComplete = () => ({ goTo: 'targetFlow' })`. Use the handler form when you need conditional transitions, data writes, or any logic beyond a static target id.
|
|
143
|
+
|
|
144
|
+
| Use this | When |
|
|
145
|
+
| ------------------ | ----------------------------------------------------------------------------------- |
|
|
146
|
+
| `onComplete: 'id'` | You always want to chain into the same next flow when this one finishes. |
|
|
147
|
+
| `hooks.onComplete` | The next flow depends on collected data, or you want to write state on completion. |
|
|
148
|
+
|
|
149
|
+
> Setting **both** the top-level `onComplete` and `hooks.onComplete` on the same flow throws `FlowConfigurationError` at construction time. Pick one.
|
|
150
|
+
|
|
151
|
+
## Examples
|
|
152
|
+
|
|
153
|
+
### Basic linear flow
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { createAgent, Flow, GeminiProvider } from "@falai/agent";
|
|
157
|
+
|
|
158
|
+
interface BookingData {
|
|
159
|
+
destination: string;
|
|
160
|
+
checkIn: string;
|
|
161
|
+
guests: number;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const bookHotel = new Flow<unknown, BookingData>({
|
|
165
|
+
title: "Book Hotel",
|
|
166
|
+
description: "Collect destination, check-in date, and party size, then book.",
|
|
167
|
+
when: "the user wants to book a hotel",
|
|
168
|
+
requiredFields: ["destination", "checkIn", "guests"],
|
|
169
|
+
steps: [
|
|
170
|
+
{ description: "Greet and ask destination", collect: ["destination"] },
|
|
171
|
+
{ description: "Ask check-in date", collect: ["checkIn"] },
|
|
172
|
+
{ description: "Ask guest count", collect: ["guests"] },
|
|
173
|
+
],
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const agent = createAgent<unknown, BookingData>({
|
|
177
|
+
schema: { /* ... */ },
|
|
178
|
+
provider: new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY! }),
|
|
179
|
+
flows: [bookHotel],
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Completion handler with state writes and chained transition
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import { Flow } from "@falai/agent";
|
|
187
|
+
|
|
188
|
+
const bookHotel = new Flow<AppContext, BookingData>({
|
|
189
|
+
title: "Book Hotel",
|
|
190
|
+
requiredFields: ["destination", "checkIn", "guests"],
|
|
191
|
+
reentrant: true, // allow "book another?" loops
|
|
192
|
+
steps: [/* ... */],
|
|
193
|
+
hooks: {
|
|
194
|
+
onComplete: ({ data }) => ({
|
|
195
|
+
dataUpdate: { lastBookedAt: new Date().toISOString() },
|
|
196
|
+
goTo: data.guests > 4 ? "Group Coordination" : "Confirmation",
|
|
197
|
+
reason: "booking finalized",
|
|
198
|
+
}),
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Imperative `addStep` after construction
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
const supportFlow = new Flow({
|
|
207
|
+
title: "Support",
|
|
208
|
+
steps: [{ description: "Capture issue summary", collect: ["issue"] }],
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// Later — extend the flow programmatically.
|
|
212
|
+
supportFlow.addStep({
|
|
213
|
+
description: "Triage severity",
|
|
214
|
+
collect: ["severity"],
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
> Calling `addStep` after the agent has handled a turn emits a debug-level warning that the flow graph is being mutated mid-session. The new step is still registered and connected as the successor of the current last step.
|
|
219
|
+
|
|
220
|
+
## Errors
|
|
221
|
+
|
|
222
|
+
| Error | When it's thrown |
|
|
223
|
+
| --------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
224
|
+
| `FlowConfigurationError` | Both top-level `onComplete` and `hooks.onComplete` are set on the same flow. |
|
|
225
|
+
| `FlowConfigurationError` | A function appears in `when` (functions belong on `if`). |
|
|
226
|
+
| `FlowConfigurationError` | A step inside `steps[]` violates auto-step or reply-step shape rules (raised from the underlying `Step` constructor). |
|
|
227
|
+
|
|
228
|
+
All `FlowConfigurationError` messages follow the format `[FlowConfigurationError] <what>: <why>. <how to fix>.` See [Errors](./errors.md).
|
|
229
|
+
|
|
230
|
+
## Related
|
|
231
|
+
|
|
232
|
+
- [Architecture](../concepts/architecture.md) — where Flow fits among the seven primitives
|
|
233
|
+
- [Turn pipeline](../concepts/pipeline.md) — when flows are selected, entered, and completed
|
|
234
|
+
- [Step](./step.md) — the inner DSL primitive flows are composed of
|
|
235
|
+
- [Directive](./directive.md) — what `hooks.onComplete` returns
|
|
236
|
+
- [Instruction](./instruction.md) — flow-scoped behavioral nudges
|
|
237
|
+
- [Branching](../guides/branching.md) — explicit forks inside a flow
|
|
238
|
+
- [Flow control](../guides/flow-control.md) — completion, dispatch, and verbatim replies
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Instruction"
|
|
3
|
+
description: "Unified behavioral primitive that shapes how the agent responds, with a kind discriminator (must / never / should) and agent / flow / step scoping."
|
|
4
|
+
type: reference
|
|
5
|
+
order: 5
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Instruction
|
|
9
|
+
|
|
10
|
+
> **Where this is introduced:** [Instructions](../guides/instructions.md)
|
|
11
|
+
|
|
12
|
+
An `Instruction` is a single statement of behavior the agent should follow. v2 collapses three v1 types into one — every instruction now carries a `kind` discriminator (`'must'`, `'never'`, or `'should'`) and a `prompt` that is rendered into the system prompt with a scope caption. The same shape works at agent, flow, and step scope; only its position in the configuration changes.
|
|
13
|
+
|
|
14
|
+
The set of instructions actually rendered into a given turn's prompt is reported back on the response as `appliedInstructions` — observability is deterministic, derived from rendering, not self-reported by the model.
|
|
15
|
+
|
|
16
|
+
## Signature
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
interface Instruction<TContext = unknown, TData = unknown> {
|
|
20
|
+
id?: string;
|
|
21
|
+
kind?: 'must' | 'never' | 'should'; // default: 'should'
|
|
22
|
+
when?: ConditionWhen; // AI-evaluated string(s), AND semantics
|
|
23
|
+
if?: ConditionIf<TContext, TData>; // code-evaluated function(s), AND semantics
|
|
24
|
+
prompt: Template<TContext, TData>;
|
|
25
|
+
enabled?: boolean; // default: true
|
|
26
|
+
tags?: string[];
|
|
27
|
+
metadata?: Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface ScopedInstructions<TContext = unknown, TData = unknown> {
|
|
31
|
+
global: Instruction<TContext, TData>[];
|
|
32
|
+
flow?: { flowTitle: string; items: Instruction<TContext, TData>[] };
|
|
33
|
+
step?: { stepId: string; items: Instruction<TContext, TData>[] };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface AppliedInstruction {
|
|
37
|
+
id: string;
|
|
38
|
+
scope: 'global' | 'flow' | 'step';
|
|
39
|
+
scopeRef?: string; // flowTitle for flow, stepId for step
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Fields
|
|
44
|
+
|
|
45
|
+
### `Instruction`
|
|
46
|
+
|
|
47
|
+
| Field | Type | Required | Default | Notes |
|
|
48
|
+
|-------|------|----------|---------|-------|
|
|
49
|
+
| `prompt` | `Template<TContext, TData>` | yes | — | Behavioral text rendered into the prompt under the `## Instructions` section. |
|
|
50
|
+
| `kind` | `'must' \| 'never' \| 'should'` | no | `'should'` | Severity. `'must'` = absolute do, `'never'` = absolute don't, `'should'` = conditional nudge. |
|
|
51
|
+
| `when` | `ConditionWhen` | no | — | AI-evaluated activation string (or array, AND semantics). Functions are not allowed here; use `if`. |
|
|
52
|
+
| `if` | `ConditionIf<TContext, TData>` | no | — | Code-evaluated activation function (or array). Free to evaluate. When both `when` and `if` are set, `if` runs first; `when` is only evaluated if `if` passes. |
|
|
53
|
+
| `id` | `string` | no | auto | Stable identifier used in `AppliedInstruction.id`. Auto-generated when omitted. |
|
|
54
|
+
| `enabled` | `boolean` | no | `true` | Set `false` to skip the instruction without removing it from configuration. |
|
|
55
|
+
| `tags` | `string[]` | no | — | Free-form tags for filtering and grouping. |
|
|
56
|
+
| `metadata` | `Record<string, unknown>` | no | — | Free-form per-instruction metadata. |
|
|
57
|
+
|
|
58
|
+
### `AppliedInstruction`
|
|
59
|
+
|
|
60
|
+
| Field | Type | Notes |
|
|
61
|
+
|-------|------|-------|
|
|
62
|
+
| `id` | `string` | The `Instruction.id` that fired. |
|
|
63
|
+
| `scope` | `'global' \| 'flow' \| 'step'` | Where the instruction was declared. |
|
|
64
|
+
| `scopeRef` | `string \| undefined` | `flowTitle` for `flow`, `stepId` for `step`, `undefined` for `global`. |
|
|
65
|
+
|
|
66
|
+
## Scoping
|
|
67
|
+
|
|
68
|
+
The same `Instruction` shape attaches at three positions:
|
|
69
|
+
|
|
70
|
+
- **Agent (global):** `AgentOptions.instructions` — always considered, on every turn, for every flow.
|
|
71
|
+
- **Flow:** `FlowOptions.instructions` — considered when the active flow matches.
|
|
72
|
+
- **Step:** `StepOptions.instructions` — considered when the active step matches.
|
|
73
|
+
|
|
74
|
+
At prompt-build time the composer renders each active instruction as a single bullet:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
- [<kind>] [<scope-caption>] <prompt>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Scope captions are fixed by where the instruction was declared:
|
|
81
|
+
|
|
82
|
+
| Scope | Caption |
|
|
83
|
+
|-------|---------|
|
|
84
|
+
| Agent | `[Always]` |
|
|
85
|
+
| Flow | `[In: <FlowTitle>]` |
|
|
86
|
+
| Step | `[Step: <stepId>]` |
|
|
87
|
+
|
|
88
|
+
Example block in the rendered prompt:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
## Instructions
|
|
92
|
+
|
|
93
|
+
- [must] [Always] Always greet by name
|
|
94
|
+
- [never] [Always] Promise delivery dates you cannot guarantee
|
|
95
|
+
- [should] [In: Booking] Confirm dates before calling book_hotel
|
|
96
|
+
- [should] [Step: payment] If the card is declined, never retry without confirmation
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Examples
|
|
100
|
+
|
|
101
|
+
### 1. Agent-level absolutes plus a step-level nudge
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { createAgent, GeminiProvider } from '@falai/agent';
|
|
105
|
+
|
|
106
|
+
const agent = createAgent({
|
|
107
|
+
name: 'BookingBot',
|
|
108
|
+
provider: new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY! }),
|
|
109
|
+
instructions: [
|
|
110
|
+
{ kind: 'must', prompt: 'Validate dates are in the future before booking.' },
|
|
111
|
+
{ kind: 'never', prompt: 'Promise rates you have not looked up.' },
|
|
112
|
+
],
|
|
113
|
+
flows: [
|
|
114
|
+
{
|
|
115
|
+
title: 'Booking',
|
|
116
|
+
instructions: [
|
|
117
|
+
{ kind: 'should', prompt: 'Offer to compare two options before committing.' },
|
|
118
|
+
],
|
|
119
|
+
steps: [
|
|
120
|
+
{
|
|
121
|
+
id: 'payment',
|
|
122
|
+
prompt: 'Take payment.',
|
|
123
|
+
instructions: [
|
|
124
|
+
{ kind: 'must', prompt: 'If the card is declined, never retry without confirmation.' },
|
|
125
|
+
],
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 2. Conditional activation with `when` and `if`
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import type { Instruction } from '@falai/agent';
|
|
137
|
+
|
|
138
|
+
type Ctx = { tier: 'free' | 'pro' };
|
|
139
|
+
type Data = { hasQuoted: boolean };
|
|
140
|
+
|
|
141
|
+
const concise: Instruction<Ctx, Data> = {
|
|
142
|
+
kind: 'should',
|
|
143
|
+
when: 'User asks a simple yes/no question',
|
|
144
|
+
prompt: 'Answer in one sentence.',
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const proOnly: Instruction<Ctx, Data> = {
|
|
148
|
+
kind: 'must',
|
|
149
|
+
if: (ctx) => ctx.context.tier === 'pro',
|
|
150
|
+
prompt: 'Offer to export the conversation as PDF.',
|
|
151
|
+
};
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 3. Reading `appliedInstructions` from a response
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
const response = await agent.respond('Hi, I want to book a room.');
|
|
158
|
+
|
|
159
|
+
for (const a of response.appliedInstructions ?? []) {
|
|
160
|
+
console.log(`${a.scope}${a.scopeRef ? `:${a.scopeRef}` : ''} → ${a.id}`);
|
|
161
|
+
}
|
|
162
|
+
// global → ins_validate_dates
|
|
163
|
+
// flow:Booking → ins_offer_two_options
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Errors
|
|
167
|
+
|
|
168
|
+
- `FlowConfigurationError` — duplicate `id` across instructions in the same scope, or `kind` set to a value other than `'must' | 'never' | 'should'`.
|
|
169
|
+
- `DataValidationError` — a `Template` `prompt` references a `data` field not declared in the agent `schema`.
|
|
170
|
+
|
|
171
|
+
## Related
|
|
172
|
+
|
|
173
|
+
- [Instructions](../guides/instructions.md) — recipe for shaping behavior with `must` / `never` / `should`
|
|
174
|
+
- [Architecture](../concepts/architecture.md) — where Instruction fits among the seven primitives
|
|
175
|
+
- [createAgent](./create-agent.md) — `AgentOptions.instructions`
|
|
176
|
+
- [Flow](./flow.md) — `FlowOptions.instructions`
|
|
177
|
+
- [Step](./step.md) — `StepOptions.instructions`
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "PreDirective"
|
|
3
|
+
description: "Directive variant returned by pre-LLM hooks; adds prompt and tool shaping for the current turn."
|
|
4
|
+
type: reference
|
|
5
|
+
order: 7
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# PreDirective
|
|
9
|
+
|
|
10
|
+
> **Where this is introduced:** [Directives](../concepts/directives.md)
|
|
11
|
+
|
|
12
|
+
`PreDirective<TContext, TData>` is the variant of [`Directive`](./directive.md)
|
|
13
|
+
that pre-LLM hooks return. It inherits every Directive field — position writes
|
|
14
|
+
(`goTo`, `goToStep`, `complete`, `abort`, `reset`), the verbatim `reply`, and
|
|
15
|
+
state writes (`dataUpdate`, `contextUpdate`) — and adds three fields that only
|
|
16
|
+
make sense before this turn's LLM call: `appendPrompt`, `injectTools`, and
|
|
17
|
+
`halt`.
|
|
18
|
+
|
|
19
|
+
Lifetime is one turn. PreDirective fields are stripped before
|
|
20
|
+
`session.pendingDirective` is written, so they cannot persist across turns and
|
|
21
|
+
cannot be assigned to `pendingDirective` directly.
|
|
22
|
+
|
|
23
|
+
PreDirective is the return type of:
|
|
24
|
+
|
|
25
|
+
- `flow.hooks.onEnter`
|
|
26
|
+
- `step.hooks.onEnter`
|
|
27
|
+
- `step.hooks.prepare`
|
|
28
|
+
- the merged pre-LLM phase of the directive bus
|
|
29
|
+
- a [`Signal`](./signals.md) firing in the pre-phase (via `SignalDirective`,
|
|
30
|
+
which extends PreDirective)
|
|
31
|
+
|
|
32
|
+
Post-LLM hooks (`step.hooks.finalize`, `flow.hooks.onComplete`) return plain
|
|
33
|
+
`Directive` — the three PreDirective-only fields have no effect post-LLM and
|
|
34
|
+
are dropped with a debug log if present.
|
|
35
|
+
|
|
36
|
+
## Signature
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
interface PreDirective<TContext = unknown, TData = unknown>
|
|
40
|
+
extends Directive<TContext, TData> {
|
|
41
|
+
appendPrompt?: string[];
|
|
42
|
+
injectTools?: Array<Tool<TContext, TData>>;
|
|
43
|
+
halt?: boolean;
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Fields
|
|
48
|
+
|
|
49
|
+
| Field | Type | Required | Default | Notes |
|
|
50
|
+
|-------|------|----------|---------|-------|
|
|
51
|
+
| `appendPrompt` | `string[]` | no | — | Sentences appended to the system prompt for THIS turn only via `PromptComposer`'s transient appendage slot. Merged across hooks by array-concat (Algorithm 4). Never cached, never persisted. |
|
|
52
|
+
| `injectTools` | `Tool<TContext, TData>[]` | no | — | Tools added to the available tool list for THIS turn only via `ToolManager`'s transient layer. Merged across hooks by concat-then-dedupe by `Tool.id` (last definition wins). Tool references are not serializable, so this field never persists. |
|
|
53
|
+
| `halt` | `boolean` | no | `false` | When `true`, skip the LLM call entirely this turn. Merged by logical-OR. Co-validates with `reply`: if both are set the `reply` is emitted and the turn ends with `stoppedReason: 'reply'`; if `halt` is set without `reply` the turn ends with `stoppedReason: 'halt'` and an empty assistant message. |
|
|
54
|
+
| *…all `Directive` fields* | — | — | — | See [Directive](./directive.md) for `goTo`, `goToStep`, `complete`, `abort`, `reset`, `reply`, `dataUpdate`, `contextUpdate`. Mutually-exclusive position rules apply identically. |
|
|
55
|
+
|
|
56
|
+
## Examples
|
|
57
|
+
|
|
58
|
+
### Append a sentence to the prompt for this turn
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import type { PreDirective } from '@falai/agent';
|
|
62
|
+
|
|
63
|
+
const flow = {
|
|
64
|
+
title: 'Booking',
|
|
65
|
+
hooks: {
|
|
66
|
+
onEnter: (ctx): PreDirective => {
|
|
67
|
+
if (ctx.context.user.tier === 'vip') {
|
|
68
|
+
return {
|
|
69
|
+
appendPrompt: ['This caller is a VIP — confirm preferences before suggesting options.'],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
steps: [/* ... */],
|
|
75
|
+
};
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Inject a one-shot tool, then halt the LLM call
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import type { PreDirective, Tool } from '@falai/agent';
|
|
82
|
+
|
|
83
|
+
const lookupAccount: Tool = {
|
|
84
|
+
id: 'lookup_account',
|
|
85
|
+
description: 'Fetch the caller\'s account record.',
|
|
86
|
+
parameters: { type: 'object', properties: {} },
|
|
87
|
+
handler: async (ctx) => ({ content: JSON.stringify(await fetchAccount(ctx.context.user.id)) }),
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const step = {
|
|
91
|
+
id: 'verify',
|
|
92
|
+
prompt: 'Verify the caller before proceeding.',
|
|
93
|
+
hooks: {
|
|
94
|
+
prepare: async (ctx): Promise<PreDirective> => {
|
|
95
|
+
if (!ctx.data.verified) {
|
|
96
|
+
// Make the tool available for THIS turn only and let the model call it.
|
|
97
|
+
return { injectTools: [lookupAccount] };
|
|
98
|
+
}
|
|
99
|
+
// Already verified — skip the LLM, emit a deterministic reply.
|
|
100
|
+
return { halt: true, reply: 'Verified. How can I help?' };
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Errors
|
|
107
|
+
|
|
108
|
+
`PreDirective` shares Directive's construction-time validation. The following
|
|
109
|
+
typed errors may be thrown by `flow.validate(...)` or by the directive bus
|
|
110
|
+
when an invalid PreDirective is emitted:
|
|
111
|
+
|
|
112
|
+
- `FlowConfigurationError` — multiple position fields set (`goTo`, `goToStep`, `complete`, `abort`, `reset`); `reply` co-existing with `abort`; `goTo` set as an empty object.
|
|
113
|
+
|
|
114
|
+
PreDirective-only fields surface no extra construction errors. Two runtime
|
|
115
|
+
behaviors are notable rather than thrown:
|
|
116
|
+
|
|
117
|
+
- Assigning a PreDirective with `appendPrompt`, `injectTools`, or `halt` to
|
|
118
|
+
`session.pendingDirective` causes those fields to be stripped before the
|
|
119
|
+
write (with a debug log). The remaining Directive fields persist normally.
|
|
120
|
+
- Returning a PreDirective from a post-LLM hook (`finalize`, `onComplete`)
|
|
121
|
+
causes the three PreDirective-only fields to be dropped with a debug log;
|
|
122
|
+
the Directive fields are honored.
|
|
123
|
+
|
|
124
|
+
## Related
|
|
125
|
+
|
|
126
|
+
- [Directives](../concepts/directives.md) — the mental model for the Directive → PreDirective → SignalDirective inheritance chain
|
|
127
|
+
- [Directive](./directive.md) — the parent interface and field semantics for position writes, `reply`, and state writes
|
|
128
|
+
- [Step](./step.md) — `hooks.onEnter` and `hooks.prepare` return `PreDirective`
|
|
129
|
+
- [Flow](./flow.md) — `hooks.onEnter` returns `PreDirective`
|
|
130
|
+
- [Signals](./signals.md) — `SignalDirective` extends `PreDirective` for pre-phase signal firings
|
|
131
|
+
- [Tool](./tool.md) — the type of values in `injectTools[]`
|