@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,400 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Directives"
|
|
3
|
+
description: "The flat object shape any tool, hook, or branch returns to write state, redirect the conversation, or speak verbatim."
|
|
4
|
+
type: concept
|
|
5
|
+
order: 3
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Directives
|
|
9
|
+
|
|
10
|
+
> **Where this is introduced:** [Turn pipeline](./pipeline.md)
|
|
11
|
+
|
|
12
|
+
A directive is the single language `@falai/agent` speaks for control
|
|
13
|
+
flow. When a tool decides "this user is ineligible," it returns
|
|
14
|
+
`{ goTo: "Denial", reply: "Sorry — you don't qualify." }`. When a
|
|
15
|
+
finalize hook closes a booking, it returns
|
|
16
|
+
`{ complete: true, dataUpdate: { bookingId } }`. When a pre-phase
|
|
17
|
+
signal detects a frustrated user, it dispatches
|
|
18
|
+
`{ appendPrompt: ["Lead with empathy."] }`. Different jobs, different
|
|
19
|
+
emitters, one shape.
|
|
20
|
+
|
|
21
|
+
This page explains why the shape is flat, what each field does, how
|
|
22
|
+
they merge when more than one handler emits during the same turn, and
|
|
23
|
+
how `Directive`, `PreDirective`, and `SignalDirective` form the
|
|
24
|
+
inheritance chain that lets pre-LLM hooks and signals add capability
|
|
25
|
+
without adding a parallel type system. The page is conceptual — the
|
|
26
|
+
[directive reference](../reference/directive.md) carries the
|
|
27
|
+
field-by-field contract.
|
|
28
|
+
|
|
29
|
+
## Why a flat shape
|
|
30
|
+
|
|
31
|
+
An earlier draft of v2 modeled directives as a discriminated union:
|
|
32
|
+
`{ type: 'goto_flow', flow: 'X' }`, `{ type: 'complete', next: ... }`,
|
|
33
|
+
`{ type: 'abort', reason: ... }`, and so on. The shape that ships is
|
|
34
|
+
flat — a single interface with optional fields, no `type`
|
|
35
|
+
discriminator, no builder, no factory functions. Four reasons drove
|
|
36
|
+
the decision, and each one is visible at the call site once you know
|
|
37
|
+
to look for it.
|
|
38
|
+
|
|
39
|
+
**Single shape.** Every emitter returns the same object literal. A
|
|
40
|
+
finalize hook does not have to choose between `Directive.goto({...})`
|
|
41
|
+
and `Directive.complete({...})` and `Directive.reply({...})` — it
|
|
42
|
+
returns `{}` with whichever fields it needs. Authors learn one shape
|
|
43
|
+
and reach for it from tools, from prepare hooks, from finalize hooks,
|
|
44
|
+
from signal handlers, from branch `then` targets. The framework's
|
|
45
|
+
control-flow vocabulary is one type wide. The same object literal is
|
|
46
|
+
also persistable verbatim as `session.pendingDirective`, so the shape
|
|
47
|
+
that sits in source code is the same shape that crosses the
|
|
48
|
+
persistence boundary.
|
|
49
|
+
|
|
50
|
+
**Trivially mergeable.** Algorithm 4 — the per-turn merge that the
|
|
51
|
+
pipeline runs over the directive bus — works on a flat object: pick
|
|
52
|
+
the winning position field by precedence, last-wins for `reply`,
|
|
53
|
+
shallow-merge state writes, concatenate the pre-LLM arrays. A nested
|
|
54
|
+
discriminated union would force a per-variant merge case at every
|
|
55
|
+
combinator: how do you merge a `goto_flow` with a `complete`? With a
|
|
56
|
+
`reply`? With a `dataUpdate`? Every cross-variant combination becomes
|
|
57
|
+
its own special case. With a flat object, "merge" is one function
|
|
58
|
+
that does not branch on shape.
|
|
59
|
+
|
|
60
|
+
**Validates statically.** TypeScript narrowing on field presence is
|
|
61
|
+
clean. `if (d.goTo) { /* d.goTo is string | object */ }` is the
|
|
62
|
+
entire pattern. A discriminated union adds one extra branching level
|
|
63
|
+
at every call site — `if (d.type === 'goto_flow') { /* d is the
|
|
64
|
+
goto_flow variant */ }` — and the variant types repeat the same
|
|
65
|
+
optional-fields prose for state writes and `reply`. The flat shape
|
|
66
|
+
moves "is this a position directive or a state directive or a reply"
|
|
67
|
+
from a type-level question to a runtime question that the merge
|
|
68
|
+
algorithm answers once.
|
|
69
|
+
|
|
70
|
+
**Composable.** A directive carries up to four orthogonal payloads
|
|
71
|
+
without forcing them into a hierarchy: at most one position field,
|
|
72
|
+
optional state writes (`dataUpdate` / `contextUpdate`), an optional
|
|
73
|
+
verbatim `reply`, and on `PreDirective` an optional set of pre-LLM
|
|
74
|
+
augmentations. `dataUpdate` works alongside `goTo`. `reply` works
|
|
75
|
+
alongside `complete`. A booking tool's success result writes the
|
|
76
|
+
booking id and finishes the flow in one return value:
|
|
77
|
+
`{ complete: true, dataUpdate: { bookingId } }`. A bridge utterance
|
|
78
|
+
at a flow boundary writes nothing and only speaks: `{ reply: "Let me
|
|
79
|
+
transfer you." }`. The same primitive covers both because the fields
|
|
80
|
+
do not exclude each other by shape — only by validation.
|
|
81
|
+
|
|
82
|
+
The trade-off is that exhaustive `case` checking on a `type`
|
|
83
|
+
discriminator is gone. The pipeline replaces it with structural
|
|
84
|
+
validation (`flow.validate`) — one position field at most, no empty
|
|
85
|
+
`goTo: {}`, no `reply` alongside `abort` — that runs at apply time
|
|
86
|
+
anyway, since flow and step lookups are runtime checks regardless. The
|
|
87
|
+
exchange is one less compile-time check for a far cleaner authoring
|
|
88
|
+
surface and a merge algorithm that does not branch on shape.
|
|
89
|
+
|
|
90
|
+
## Position fields and their precedence
|
|
91
|
+
|
|
92
|
+
A directive carries at most one **position field**. Position fields
|
|
93
|
+
answer the question "where does the conversation go next?" The five
|
|
94
|
+
options span every form of position control the framework offers:
|
|
95
|
+
|
|
96
|
+
| Field | What it means |
|
|
97
|
+
|-------|---------------|
|
|
98
|
+
| `goTo` | Jump to another flow. |
|
|
99
|
+
| `goToStep` | Jump to a step (within the current flow, or — in the object form — within another flow). |
|
|
100
|
+
| `complete` | Mark the current flow done. The flow's completion logic runs. |
|
|
101
|
+
| `abort` | End the conversation. Optionally clear the session. |
|
|
102
|
+
| `reset` | Restart the current flow. Optionally clear its declared fields. |
|
|
103
|
+
|
|
104
|
+
Each of `goTo`, `goToStep`, `complete`, `abort`, and `reset` accepts
|
|
105
|
+
both a shorthand and an object form. The shorthand expresses the
|
|
106
|
+
common case (`goTo: "Booking"`, `complete: true`, `abort: "denied"`).
|
|
107
|
+
The object form exposes the optional knobs — `reason` strings for
|
|
108
|
+
observability, `data` for pre-entry state writes, `clearSession` /
|
|
109
|
+
`clearData` flags for the destructive variants. The fields are
|
|
110
|
+
mutually exclusive: setting two at once throws
|
|
111
|
+
`FlowConfigurationError` at validation. There is no "go to *and*
|
|
112
|
+
abort" — only one position can win per directive.
|
|
113
|
+
|
|
114
|
+
When more than one emitter writes a position field during the same
|
|
115
|
+
turn — a tool returns `goTo` and a finalize hook returns `complete` —
|
|
116
|
+
the merge algorithm picks one winner by precedence:
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
abort > complete > goTo / goToStep > reset
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The order encodes intent. **`abort` always wins.** A handler that
|
|
123
|
+
ended the conversation cannot be overridden by a later "go somewhere
|
|
124
|
+
else" — there is no somewhere else. **`complete` beats `goTo` and
|
|
125
|
+
`goToStep`.** The flow is ending; any follow-up jump belongs in
|
|
126
|
+
`complete.next` (which chains another directive after completion),
|
|
127
|
+
not as a competing position field. **`goTo` and `goToStep` share a
|
|
128
|
+
tier.** Both express "next position is here" — the difference is
|
|
129
|
+
flow-level vs step-level granularity, and within the tier last
|
|
130
|
+
emission wins. **`reset` is lowest.** Any explicit jump out of the
|
|
131
|
+
current flow beats a "restart this flow" emitted earlier in the
|
|
132
|
+
phase.
|
|
133
|
+
|
|
134
|
+
Within the same tier, the most recent emission wins, with a debug
|
|
135
|
+
log naming all losers so a noisy turn is diagnosable from the trace.
|
|
136
|
+
The precedence ordering does not change between phases: it applies to
|
|
137
|
+
the pre-LLM bus, the post-LLM bus, and the signal phases identically.
|
|
138
|
+
|
|
139
|
+
## State writes
|
|
140
|
+
|
|
141
|
+
Two fields — `dataUpdate` and `contextUpdate` — write to session
|
|
142
|
+
state. Both are `Partial<>` slices of their respective surfaces:
|
|
143
|
+
`dataUpdate?: Partial<TData>` writes into `session.data`,
|
|
144
|
+
`contextUpdate?: Partial<TContext>` writes into `session.context`.
|
|
145
|
+
Both fire their respective hooks (`flow.hooks.onDataUpdate`,
|
|
146
|
+
`flow.hooks.onContextUpdate`) after the merge applies, and both run
|
|
147
|
+
through schema validation atomically — every field across every
|
|
148
|
+
emitter on this turn is checked together, and the session is not
|
|
149
|
+
mutated unless the whole set passes.
|
|
150
|
+
|
|
151
|
+
State writes are **additive** and shallow-merged across emitters in
|
|
152
|
+
emission order. If a flow-level `onEnter` writes
|
|
153
|
+
`{ dataUpdate: { tier: "vip" } }` and a step-level `prepare` writes
|
|
154
|
+
`{ dataUpdate: { lastSeen: now } }`, the merged result is
|
|
155
|
+
`{ tier: "vip", lastSeen: now }` — neither hook needs to know about
|
|
156
|
+
the other. On key collision, last write wins. The merge is shallow —
|
|
157
|
+
top-level keys are replaced wholesale, nested objects are not
|
|
158
|
+
deep-merged. To update a nested object, read it from `data`, merge
|
|
159
|
+
in code, write back the full sub-object. Deep merge is intentionally
|
|
160
|
+
absent because it would silently disagree with TypeScript's
|
|
161
|
+
`Partial<>` shape: the type says "I'm overwriting this key," and the
|
|
162
|
+
runtime should agree.
|
|
163
|
+
|
|
164
|
+
State writes always apply, regardless of what the position fields do.
|
|
165
|
+
A directive with `{ goTo: "Denial", dataUpdate: { reason: "expired" }
|
|
166
|
+
}` jumps flows *and* writes the reason. A directive with only
|
|
167
|
+
`{ dataUpdate: {...} }` writes state and stays where it is. Position
|
|
168
|
+
fields and state writes are orthogonal payloads; they don't compete
|
|
169
|
+
for the same slot.
|
|
170
|
+
|
|
171
|
+
## Reply as a verbatim utterance
|
|
172
|
+
|
|
173
|
+
The `reply: string` field is the framework's way of letting code
|
|
174
|
+
speak. When a directive sets `reply`, the LLM call for the entered
|
|
175
|
+
step is skipped this turn and the literal string becomes the
|
|
176
|
+
assistant's message. The text is taken verbatim — no templating, no
|
|
177
|
+
post-processing, no "the model rephrased it" surprise.
|
|
178
|
+
|
|
179
|
+
`reply` is the right tool for utterances that should be exact:
|
|
180
|
+
confirmations ("Booking confirmed."), bridges ("Connecting you with a
|
|
181
|
+
specialist now."), refusals ("Sorry — you don't qualify."), and
|
|
182
|
+
boilerplate at flow boundaries. It is the wrong tool for anything
|
|
183
|
+
that should adapt to context — that's what the model is for. The two
|
|
184
|
+
shapes coexist on the same step boundary: `reply` for the line, the
|
|
185
|
+
LLM for the conversation.
|
|
186
|
+
|
|
187
|
+
`reply` co-validates with two other fields. With **`abort`**, it is
|
|
188
|
+
rejected at validation — an aborted conversation cannot deliver a
|
|
189
|
+
reply. With **`halt: true`** (a `PreDirective` field, see below), it
|
|
190
|
+
is the assistant message and the turn ends with
|
|
191
|
+
`stoppedReason: 'reply'`; if `halt` is set without `reply`, the turn
|
|
192
|
+
ends with `stoppedReason: 'halt'` and an empty body. Across multiple
|
|
193
|
+
emitters in the same turn, `reply` is **last-wins** — the most
|
|
194
|
+
recent emission overrides earlier ones, with a debug log so the
|
|
195
|
+
override is visible in the trace.
|
|
196
|
+
|
|
197
|
+
`reply` is the same shape on `Directive` and on `PreDirective` —
|
|
198
|
+
there is no separate "speak before the LLM" vs "speak after the
|
|
199
|
+
LLM" type. The phase the directive runs in determines whether the
|
|
200
|
+
reply replaces a message that would have been generated (pre-LLM) or
|
|
201
|
+
replaces one that just was (post-LLM). The field stays the same.
|
|
202
|
+
|
|
203
|
+
## PreDirective fields
|
|
204
|
+
|
|
205
|
+
`PreDirective` is the `Directive` variant that pre-LLM hooks return.
|
|
206
|
+
It inherits every base field — position writes, state writes,
|
|
207
|
+
`reply` — and adds three more that only make sense before this turn's
|
|
208
|
+
LLM call: `appendPrompt`, `injectTools`, and `halt`.
|
|
209
|
+
|
|
210
|
+
**`appendPrompt: string[]`** is the prompt nudge slot. Each string is
|
|
211
|
+
a sentence the prompt composer appends to the system prompt for this
|
|
212
|
+
turn only. A flow-level `onEnter` that detects a VIP caller can add
|
|
213
|
+
"This caller is a VIP — confirm preferences before suggesting
|
|
214
|
+
options." A step-level `prepare` that detects a returning customer
|
|
215
|
+
can add "The user is a returning customer; skip introductions." Both
|
|
216
|
+
fire on the same turn, and both sentences land in the prompt's
|
|
217
|
+
per-turn appendage slot in emission order. The slot is never cached
|
|
218
|
+
(the prompt section cache memoizes static sections only) and never
|
|
219
|
+
persisted — `appendPrompt` lives for one turn and is gone.
|
|
220
|
+
|
|
221
|
+
**`injectTools: Tool[]`** is the per-turn tool slot. Tools listed
|
|
222
|
+
here are added to the available tool list for this turn only,
|
|
223
|
+
stacked on top of the agent → flow → step → transient resolution
|
|
224
|
+
chain. A `prepare` hook that detects an ambiguous request can inject
|
|
225
|
+
a `lookup_account` tool for a single LLM call without registering it
|
|
226
|
+
on the step or the flow. The slot is never persisted — tool
|
|
227
|
+
references are functions, and functions are not JSON-serializable —
|
|
228
|
+
so the field is structurally one-turn-only.
|
|
229
|
+
|
|
230
|
+
**`halt: boolean`** is the kill switch. When any pre-phase emitter
|
|
231
|
+
sets `halt: true`, the LLM call is skipped entirely. If `reply` is
|
|
232
|
+
also set, the verbatim string becomes the assistant message. If not,
|
|
233
|
+
the turn ends with `stoppedReason: 'halt'` and an empty body. `halt`
|
|
234
|
+
merges by **logical-OR** — a single emitter setting it is enough to
|
|
235
|
+
halt the turn. The field is the framework's circuit breaker: a hook
|
|
236
|
+
that detects an unresolvable state can stop the turn outright
|
|
237
|
+
without competing with other emitters.
|
|
238
|
+
|
|
239
|
+
The three `PreDirective`-only fields are stripped from
|
|
240
|
+
`session.pendingDirective` before persistence — `pendingDirective`
|
|
241
|
+
holds a plain `Directive`, and the augmentation fields cannot survive
|
|
242
|
+
across turns by design. If a post-LLM hook returns a `PreDirective`
|
|
243
|
+
with these fields set, they are dropped with a debug warning: an
|
|
244
|
+
`appendPrompt` after the fact has no prompt to append to, an
|
|
245
|
+
`injectTools` after the fact has no LLM call to inject into, and a
|
|
246
|
+
`halt` after the fact has no LLM call to halt. The remaining base
|
|
247
|
+
`Directive` portion is honored.
|
|
248
|
+
|
|
249
|
+
`appendPrompt` is concatenated across emitters in emission order
|
|
250
|
+
without deduplication — duplicate sentences from different sources
|
|
251
|
+
are preserved (a flow-level "be polite" plus a step-level "be polite"
|
|
252
|
+
is acceptable redundancy). `injectTools` is concatenated and then
|
|
253
|
+
deduped by `Tool.id`, with the later definition winning — typically a
|
|
254
|
+
step-level injection overriding a flow-level default. `halt` is
|
|
255
|
+
logical-OR. The merge rules for the inherited base fields stay
|
|
256
|
+
identical: position fields by precedence, `reply` last-wins, state
|
|
257
|
+
writes shallow-merged.
|
|
258
|
+
|
|
259
|
+
## The inheritance chain
|
|
260
|
+
|
|
261
|
+
`Directive` is the base. `PreDirective` extends it with the three
|
|
262
|
+
pre-LLM-only fields. `SignalDirective` extends `PreDirective` further
|
|
263
|
+
with two signal-specific fields. The chain is one direction —
|
|
264
|
+
capabilities accumulate as you go down — and each level is the return
|
|
265
|
+
type of a specific class of emitter:
|
|
266
|
+
|
|
267
|
+
```mermaid
|
|
268
|
+
classDiagram
|
|
269
|
+
Directive <|-- PreDirective
|
|
270
|
+
PreDirective <|-- SignalDirective
|
|
271
|
+
|
|
272
|
+
class Directive {
|
|
273
|
+
+goTo? string | object
|
|
274
|
+
+goToStep? string | object
|
|
275
|
+
+complete? true | object
|
|
276
|
+
+abort? string | object
|
|
277
|
+
+reset? true | object
|
|
278
|
+
+reply? string
|
|
279
|
+
+dataUpdate? Partial~TData~
|
|
280
|
+
+contextUpdate? Partial~TContext~
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
class PreDirective {
|
|
284
|
+
+appendPrompt? string[]
|
|
285
|
+
+injectTools? Tool[]
|
|
286
|
+
+halt? boolean
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
class SignalDirective {
|
|
290
|
+
+stopOtherSignals? boolean
|
|
291
|
+
+replyWith? string | function
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
note for Directive "Returned by tools, finalize hooks, branches.\nPersistable as session.pendingDirective."
|
|
295
|
+
note for PreDirective "Returned by prepare hooks, onEnter hooks.\nTransient — one-turn lifetime."
|
|
296
|
+
note for SignalDirective "Returned by signals (pre / post / both phases)."
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
`Directive` is what tools (return value or `ctx.dispatch`), `finalize`
|
|
300
|
+
hooks, `flow.hooks.onComplete`, and branch `then` targets return. It
|
|
301
|
+
is plain JSON-serializable data — the same shape that sits on the
|
|
302
|
+
session as `pendingDirective` and crosses the persistence boundary.
|
|
303
|
+
|
|
304
|
+
`PreDirective` is what `flow.hooks.onEnter`, `step.hooks.onEnter`,
|
|
305
|
+
and `step.hooks.prepare` return. The three augmentation fields and a
|
|
306
|
+
live `Tool[]` reference make it non-serializable; the type system
|
|
307
|
+
encodes the one-turn lifetime by being a structurally separate type
|
|
308
|
+
that the engine strips before persistence.
|
|
309
|
+
|
|
310
|
+
`SignalDirective` is what signal handlers return — pre-phase
|
|
311
|
+
handlers, post-phase handlers, and `both`-phase handlers all use the
|
|
312
|
+
same type. The two added fields are signal-pipeline-specific:
|
|
313
|
+
`stopOtherSignals` skips remaining handlers in the same phase (it is
|
|
314
|
+
consumed inside the signal pipeline, not the directive bus), and
|
|
315
|
+
`replyWith` is a late-binding `reply` that accepts a function form
|
|
316
|
+
evaluated at emit time. Phase semantics still apply: when a
|
|
317
|
+
`SignalDirective` runs in the post-phase, the inherited `appendPrompt`
|
|
318
|
+
/ `injectTools` / `halt` fields are dropped (they have no meaning
|
|
319
|
+
after the LLM call) and inherited position fields set
|
|
320
|
+
`pendingDirective` for the *next* turn rather than redirecting this
|
|
321
|
+
one.
|
|
322
|
+
|
|
323
|
+
The three types share one merge algorithm and one validation pass.
|
|
324
|
+
A pre-phase signal can dispatch a `SignalDirective`, a `prepare` hook
|
|
325
|
+
can return a `PreDirective`, and the engine merges them through the
|
|
326
|
+
same `flow.merge` that handles tool directives — the inheritance
|
|
327
|
+
chain exists to widen the type at the call site without splitting the
|
|
328
|
+
runtime.
|
|
329
|
+
|
|
330
|
+
## The `flow` namespace
|
|
331
|
+
|
|
332
|
+
There are no constructor builders for directives. Directives are
|
|
333
|
+
plain object literals — that is the whole point of the flat shape.
|
|
334
|
+
What the framework does export is a small runtime helper namespace
|
|
335
|
+
for working with directives in code: validating shapes that arrived
|
|
336
|
+
from outside the framework, merging two directives by hand, and
|
|
337
|
+
narrowing `unknown` values in type guards.
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
import { flow } from "@falai/agent";
|
|
341
|
+
|
|
342
|
+
flow.isDirective(x); // structural type guard
|
|
343
|
+
flow.merge(a, b); // Algorithm 4 merge of two directives
|
|
344
|
+
flow.validate(d); // throws FlowConfigurationError on invalid shape
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
`flow.isDirective(x)` is a structural type guard. It returns `true`
|
|
348
|
+
for any non-null, non-array object — primitives, `null`, `undefined`,
|
|
349
|
+
arrays, and functions are filtered out. Use it to narrow an `unknown`
|
|
350
|
+
value coming off an RPC payload or a queue message before passing it
|
|
351
|
+
to `applyDirective` or `agent.dispatch`.
|
|
352
|
+
|
|
353
|
+
`flow.merge(a, b)` is the same Algorithm 4 the engine runs internally
|
|
354
|
+
on the per-turn directive bus, exposed for callers that need to
|
|
355
|
+
compose results before dispatching them. Position fields merge by
|
|
356
|
+
precedence (`abort > complete > goTo / goToStep > reset`, last-wins
|
|
357
|
+
within the same tier), `reply` is last-wins, `dataUpdate` and
|
|
358
|
+
`contextUpdate` shallow-merge in emission order, `appendPrompt`
|
|
359
|
+
concatenates without deduplication, `injectTools` concatenates and
|
|
360
|
+
then dedupes by `Tool.id` (later definition wins), and `halt` is
|
|
361
|
+
logical-OR. The function is generic in the shared subtype: merging
|
|
362
|
+
two `PreDirective`s yields a `PreDirective`, merging two plain
|
|
363
|
+
`Directive`s yields a `Directive`.
|
|
364
|
+
|
|
365
|
+
`flow.validate(d)` enforces three structural invariants and throws
|
|
366
|
+
`FlowConfigurationError` when any fails: at most one position field
|
|
367
|
+
per directive, no empty `goTo: {}` (the object form requires a flow
|
|
368
|
+
id), no `reply` alongside `abort`. The pipeline calls it eagerly on
|
|
369
|
+
every emitted directive, so downstream code can rely on shape. It
|
|
370
|
+
does **not** validate that referenced flows or steps exist — that
|
|
371
|
+
check happens at apply time, against the agent's flow registry, which
|
|
372
|
+
the validator does not have a handle on.
|
|
373
|
+
|
|
374
|
+
The namespace's design intent is "runtime helpers, not authoring
|
|
375
|
+
sugar." If you're constructing a directive in source, write the
|
|
376
|
+
object literal. If you're handling a directive that came from
|
|
377
|
+
elsewhere, narrow it with `flow.isDirective`, validate it with
|
|
378
|
+
`flow.validate`, and merge it with `flow.merge`. The seam between
|
|
379
|
+
"control flow as code" and "control flow as data" is exactly that
|
|
380
|
+
small.
|
|
381
|
+
|
|
382
|
+
## Where to go next
|
|
383
|
+
|
|
384
|
+
The directive's mental model is in this page; the field-by-field
|
|
385
|
+
contract — every position field's shorthand and object form, every
|
|
386
|
+
state-write rule, every typed error the validator can throw — is in
|
|
387
|
+
the [Directive reference](../reference/directive.md). The pre-LLM
|
|
388
|
+
extras have their own [PreDirective reference](../reference/pre-directive.md).
|
|
389
|
+
The signal-specific additions live in [Signals](../reference/signals.md).
|
|
390
|
+
|
|
391
|
+
When the goal is to *use* directives in handlers, the
|
|
392
|
+
[Flow control guide](../guides/flow-control.md) walks through the
|
|
393
|
+
recipes: redirecting from a tool, completing a flow with a chained
|
|
394
|
+
follow-up, aborting on a permission failure, replying verbatim from a
|
|
395
|
+
finalize hook, dispatching a directive from outside a turn. When the
|
|
396
|
+
goal is to *understand* where directives sit in the per-turn
|
|
397
|
+
sequence, [Turn pipeline](./pipeline.md) covers the bus, the merge
|
|
398
|
+
phases, and the resolution precedence around the directive surface.
|
|
399
|
+
|
|
400
|
+
**Next:** [createAgent reference](../reference/create-agent.md)
|