@falai/agent 0.9.0 → 0.9.2
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 +42 -34
- package/dist/cjs/src/core/Agent.d.ts +19 -5
- package/dist/cjs/src/core/Agent.d.ts.map +1 -1
- package/dist/cjs/src/core/Agent.js +79 -35
- package/dist/cjs/src/core/Agent.js.map +1 -1
- package/dist/cjs/src/core/ResponseModal.d.ts +9 -3
- package/dist/cjs/src/core/ResponseModal.d.ts.map +1 -1
- package/dist/cjs/src/core/ResponseModal.js +121 -55
- package/dist/cjs/src/core/ResponseModal.js.map +1 -1
- package/dist/cjs/src/core/ResponsePipeline.d.ts +8 -4
- package/dist/cjs/src/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/cjs/src/core/ResponsePipeline.js +47 -19
- package/dist/cjs/src/core/ResponsePipeline.js.map +1 -1
- package/dist/cjs/src/core/Route.d.ts +12 -5
- package/dist/cjs/src/core/Route.d.ts.map +1 -1
- package/dist/cjs/src/core/Route.js +26 -5
- package/dist/cjs/src/core/Route.js.map +1 -1
- package/dist/cjs/src/core/RoutingEngine.d.ts +5 -0
- package/dist/cjs/src/core/RoutingEngine.d.ts.map +1 -1
- package/dist/cjs/src/core/RoutingEngine.js +37 -25
- package/dist/cjs/src/core/RoutingEngine.js.map +1 -1
- package/dist/cjs/src/core/SessionManager.d.ts +9 -1
- package/dist/cjs/src/core/SessionManager.d.ts.map +1 -1
- package/dist/cjs/src/core/SessionManager.js +27 -5
- package/dist/cjs/src/core/SessionManager.js.map +1 -1
- package/dist/cjs/src/core/Step.d.ts +60 -7
- package/dist/cjs/src/core/Step.d.ts.map +1 -1
- package/dist/cjs/src/core/Step.js +151 -4
- package/dist/cjs/src/core/Step.js.map +1 -1
- package/dist/cjs/src/core/ToolManager.d.ts +234 -0
- package/dist/cjs/src/core/ToolManager.d.ts.map +1 -0
- package/dist/cjs/src/core/ToolManager.js +1117 -0
- package/dist/cjs/src/core/ToolManager.js.map +1 -0
- package/dist/cjs/src/index.d.ts +2 -3
- package/dist/cjs/src/index.d.ts.map +1 -1
- package/dist/cjs/src/index.js +5 -3
- package/dist/cjs/src/index.js.map +1 -1
- package/dist/cjs/src/types/agent.d.ts +1 -1
- package/dist/cjs/src/types/agent.d.ts.map +1 -1
- package/dist/cjs/src/types/index.d.ts +3 -2
- package/dist/cjs/src/types/index.d.ts.map +1 -1
- package/dist/cjs/src/types/index.js +3 -1
- package/dist/cjs/src/types/index.js.map +1 -1
- package/dist/cjs/src/types/route.d.ts +6 -4
- package/dist/cjs/src/types/route.d.ts.map +1 -1
- package/dist/cjs/src/types/tool.d.ts +84 -14
- package/dist/cjs/src/types/tool.d.ts.map +1 -1
- package/dist/cjs/src/types/tool.js +13 -0
- package/dist/cjs/src/types/tool.js.map +1 -1
- package/dist/src/core/Agent.d.ts +19 -5
- package/dist/src/core/Agent.d.ts.map +1 -1
- package/dist/src/core/Agent.js +79 -35
- package/dist/src/core/Agent.js.map +1 -1
- package/dist/src/core/ResponseModal.d.ts +9 -3
- package/dist/src/core/ResponseModal.d.ts.map +1 -1
- package/dist/src/core/ResponseModal.js +121 -55
- package/dist/src/core/ResponseModal.js.map +1 -1
- package/dist/src/core/ResponsePipeline.d.ts +8 -4
- package/dist/src/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/src/core/ResponsePipeline.js +47 -19
- package/dist/src/core/ResponsePipeline.js.map +1 -1
- package/dist/src/core/Route.d.ts +12 -5
- package/dist/src/core/Route.d.ts.map +1 -1
- package/dist/src/core/Route.js +26 -5
- package/dist/src/core/Route.js.map +1 -1
- package/dist/src/core/RoutingEngine.d.ts +5 -0
- package/dist/src/core/RoutingEngine.d.ts.map +1 -1
- package/dist/src/core/RoutingEngine.js +37 -25
- package/dist/src/core/RoutingEngine.js.map +1 -1
- package/dist/src/core/SessionManager.d.ts +9 -1
- package/dist/src/core/SessionManager.d.ts.map +1 -1
- package/dist/src/core/SessionManager.js +27 -5
- package/dist/src/core/SessionManager.js.map +1 -1
- package/dist/src/core/Step.d.ts +60 -7
- package/dist/src/core/Step.d.ts.map +1 -1
- package/dist/src/core/Step.js +151 -4
- package/dist/src/core/Step.js.map +1 -1
- package/dist/src/core/ToolManager.d.ts +234 -0
- package/dist/src/core/ToolManager.d.ts.map +1 -0
- package/dist/src/core/ToolManager.js +1111 -0
- package/dist/src/core/ToolManager.js.map +1 -0
- package/dist/src/index.d.ts +2 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/types/agent.d.ts +1 -1
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/index.d.ts +3 -2
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/index.js +1 -0
- package/dist/src/types/index.js.map +1 -1
- package/dist/src/types/route.d.ts +6 -4
- package/dist/src/types/route.d.ts.map +1 -1
- package/dist/src/types/tool.d.ts +84 -14
- package/dist/src/types/tool.d.ts.map +1 -1
- package/dist/src/types/tool.js +12 -1
- package/dist/src/types/tool.js.map +1 -1
- package/docs/CONTRIBUTING.md +40 -0
- package/docs/README.md +12 -5
- package/docs/api/README.md +75 -45
- package/docs/api/overview.md +74 -32
- package/docs/core/agent/session-management.md +152 -5
- package/docs/core/ai-integration/response-processing.md +115 -4
- package/docs/core/conversation-flows/routes.md +130 -0
- package/docs/core/error-handling.md +638 -0
- package/docs/core/tools/tool-definition.md +684 -60
- package/docs/core/tools/tool-scoping.md +244 -53
- package/docs/guides/error-handling-patterns.md +578 -0
- package/docs/guides/getting-started/README.md +139 -28
- package/examples/advanced-patterns/knowledge-based-agent.ts +6 -6
- package/examples/advanced-patterns/persistent-onboarding.ts +30 -43
- package/examples/ai-providers/anthropic-integration.ts +9 -5
- package/examples/ai-providers/openai-integration.ts +11 -7
- package/examples/core-concepts/basic-agent.ts +106 -67
- package/examples/core-concepts/schema-driven-extraction.ts +10 -7
- package/examples/core-concepts/session-management.ts +71 -18
- package/examples/integrations/healthcare-integration.ts +15 -29
- package/examples/integrations/server-session-management.ts +3 -3
- package/examples/persistence/memory-sessions.ts +3 -3
- package/examples/tools/basic-tools.ts +293 -89
- package/examples/tools/data-enrichment-tools.ts +185 -75
- package/package.json +1 -1
- package/src/core/Agent.ts +98 -44
- package/src/core/ResponseModal.ts +148 -72
- package/src/core/ResponsePipeline.ts +82 -56
- package/src/core/Route.ts +39 -12
- package/src/core/RoutingEngine.ts +46 -42
- package/src/core/SessionManager.ts +39 -7
- package/src/core/Step.ts +198 -20
- package/src/core/ToolManager.ts +1394 -0
- package/src/index.ts +8 -3
- package/src/types/agent.ts +1 -1
- package/src/types/index.ts +13 -2
- package/src/types/route.ts +6 -4
- package/src/types/tool.ts +116 -25
- package/dist/cjs/src/core/ToolExecutor.d.ts +0 -45
- package/dist/cjs/src/core/ToolExecutor.d.ts.map +0 -1
- package/dist/cjs/src/core/ToolExecutor.js +0 -84
- package/dist/cjs/src/core/ToolExecutor.js.map +0 -1
- package/dist/src/core/ToolExecutor.d.ts +0 -45
- package/dist/src/core/ToolExecutor.d.ts.map +0 -1
- package/dist/src/core/ToolExecutor.js +0 -80
- package/dist/src/core/ToolExecutor.js.map +0 -1
- package/docs/core/tools/tool-execution.md +0 -815
- package/src/core/ToolExecutor.ts +0 -126
package/docs/api/README.md
CHANGED
|
@@ -74,6 +74,72 @@ Adds a domain glossary term. Returns `this` for chaining.
|
|
|
74
74
|
|
|
75
75
|
Adds a behavioral guideline. Returns `this` for chaining.
|
|
76
76
|
|
|
77
|
+
##### `addTool(definition: Tool<TContext, TData, TResult>): this`
|
|
78
|
+
|
|
79
|
+
Creates and adds a tool to agent scope using the unified Tool interface. Returns `this` for chaining.
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// Simple return value approach
|
|
83
|
+
agent.addTool({
|
|
84
|
+
id: "weather_check",
|
|
85
|
+
description: "Get current weather",
|
|
86
|
+
parameters: {
|
|
87
|
+
type: "object",
|
|
88
|
+
properties: {
|
|
89
|
+
location: { type: "string", description: "City name" }
|
|
90
|
+
},
|
|
91
|
+
required: ["location"]
|
|
92
|
+
},
|
|
93
|
+
handler: async ({ context, data }, args) => {
|
|
94
|
+
const weather = await weatherAPI.get(args.location);
|
|
95
|
+
return `Weather in ${args.location}: ${weather.condition}`;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Advanced ToolResult pattern
|
|
100
|
+
agent.addTool({
|
|
101
|
+
id: "user_lookup",
|
|
102
|
+
description: "Look up user information",
|
|
103
|
+
handler: async ({ context, data }, args) => {
|
|
104
|
+
const user = await userAPI.find(args.userId);
|
|
105
|
+
return {
|
|
106
|
+
data: `Found user: ${user.name}`,
|
|
107
|
+
success: true,
|
|
108
|
+
contextUpdate: { currentUser: user },
|
|
109
|
+
dataUpdate: { userName: user.name }
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
##### `tool: ToolManager<TContext, TData>`
|
|
116
|
+
|
|
117
|
+
Access to the ToolManager instance for advanced tool operations.
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
// Register tools for ID-based reference
|
|
121
|
+
agent.tool.register({
|
|
122
|
+
id: "reusable_search",
|
|
123
|
+
description: "Search across data sources",
|
|
124
|
+
handler: async ({ context, data }, args) => "Search results"
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Create tools without adding to scope
|
|
128
|
+
const customTool = agent.tool.create({
|
|
129
|
+
id: "standalone_tool",
|
|
130
|
+
handler: async () => "Custom result"
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Use pattern helpers
|
|
134
|
+
const enrichmentTool = agent.tool.createDataEnrichment({
|
|
135
|
+
id: "enrich_profile",
|
|
136
|
+
fields: ['name', 'email'],
|
|
137
|
+
enricher: async (context, data) => ({
|
|
138
|
+
displayName: `${data.name} <${data.email}>`
|
|
139
|
+
})
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
77
143
|
##### `respond(input: RespondInput<TContext>): Promise<RespondOutput>`
|
|
78
144
|
|
|
79
145
|
Generates an AI response with session step management, tool execution, data extraction, and intelligent routing.
|
|
@@ -957,7 +1023,7 @@ Represents a step within a conversation route.
|
|
|
957
1023
|
|
|
958
1024
|
#### Methods
|
|
959
1025
|
|
|
960
|
-
##### `nextStep(spec: StepOptions):
|
|
1026
|
+
##### `nextStep(spec: StepOptions): Step`
|
|
961
1027
|
|
|
962
1028
|
Creates a transition from this step and returns a chainable result.
|
|
963
1029
|
|
|
@@ -982,10 +1048,14 @@ interface StepOptions<TData = unknown> {
|
|
|
982
1048
|
condition?: string;
|
|
983
1049
|
}
|
|
984
1050
|
|
|
985
|
-
interface
|
|
1051
|
+
interface Step<TContext = unknown, TData = unknown> {
|
|
986
1052
|
id: string; // Step identifier
|
|
987
1053
|
routeId: string; // Route identifier
|
|
988
|
-
nextStep: (spec: StepOptions<TData>) =>
|
|
1054
|
+
nextStep: (spec: StepOptions<TContext, TData>) => Step<TContext, TData>;
|
|
1055
|
+
description?: string; // Step description
|
|
1056
|
+
collect?: (keyof TData)[]; // Fields to collect in this step
|
|
1057
|
+
skipIf?: (data: Partial<TData>) => boolean; // Skip condition function
|
|
1058
|
+
requires?: (keyof TData)[]; // Required data prerequisites
|
|
989
1059
|
}
|
|
990
1060
|
```
|
|
991
1061
|
|
|
@@ -993,7 +1063,7 @@ interface StepResult<TData = unknown> {
|
|
|
993
1063
|
|
|
994
1064
|
- `spec`: The transition specification (see `StepOptions` above). Can include an optional `condition` property for AI-evaluated step selection guidance.
|
|
995
1065
|
|
|
996
|
-
**Returns:** A `
|
|
1066
|
+
**Returns:** A `Step` that includes the target step's reference (`id`, `routeId`) and a `nextStep` method for chaining additional transitions.
|
|
997
1067
|
|
|
998
1068
|
**Example:**
|
|
999
1069
|
|
|
@@ -1110,14 +1180,7 @@ if (step.hasRequires(session.data)) {
|
|
|
1110
1180
|
}
|
|
1111
1181
|
```
|
|
1112
1182
|
|
|
1113
|
-
##### `asStepResult(): StepResult<TContext, TData>`
|
|
1114
1183
|
|
|
1115
|
-
Creates a transition result for this step that supports chaining.
|
|
1116
|
-
|
|
1117
|
-
```typescript
|
|
1118
|
-
const result = step.asStepResult();
|
|
1119
|
-
// Returns StepResult with nextStep method for chaining
|
|
1120
|
-
```
|
|
1121
1184
|
|
|
1122
1185
|
##### `configure(config): this`
|
|
1123
1186
|
|
|
@@ -1566,39 +1629,6 @@ Builds a fallback prompt when no routes are configured.
|
|
|
1566
1629
|
|
|
1567
1630
|
---
|
|
1568
1631
|
|
|
1569
|
-
### `ToolExecutor<TContext, TData>`
|
|
1570
|
-
|
|
1571
|
-
Executes tools with context and security enforcement.
|
|
1572
|
-
|
|
1573
|
-
#### Constructor
|
|
1574
|
-
|
|
1575
|
-
```typescript
|
|
1576
|
-
new ToolExecutor<TContext, TData>();
|
|
1577
|
-
```
|
|
1578
|
-
|
|
1579
|
-
#### Methods
|
|
1580
|
-
|
|
1581
|
-
##### `executeTool(params): Promise<ToolExecutionResult>`
|
|
1582
|
-
|
|
1583
|
-
Executes a single tool with domain security enforcement.
|
|
1584
|
-
|
|
1585
|
-
**Parameters:**
|
|
1586
|
-
|
|
1587
|
-
- `tool`: Tool reference to execute
|
|
1588
|
-
- `context`: Agent context
|
|
1589
|
-
- `updateContext`: Function to update context
|
|
1590
|
-
- `history`: Conversation history
|
|
1591
|
-
- `data`: Collected session data
|
|
1592
|
-
- `allowedDomains`: Array of allowed domain names
|
|
1593
|
-
|
|
1594
|
-
**Returns:** Tool execution result with success status and data
|
|
1595
|
-
|
|
1596
|
-
##### `executeTools(params): Promise<ToolExecutionResult[]>`
|
|
1597
|
-
|
|
1598
|
-
Executes multiple tools in sequence, stopping on first failure.
|
|
1599
|
-
|
|
1600
|
-
---
|
|
1601
|
-
|
|
1602
1632
|
### `Events`
|
|
1603
1633
|
|
|
1604
1634
|
Utility functions for creating and adapting conversation events.
|
|
@@ -3016,4 +3046,4 @@ agent.createGuideline({
|
|
|
3016
3046
|
|
|
3017
3047
|
---
|
|
3018
3048
|
|
|
3019
|
-
**Made with ❤️ for the community**
|
|
3049
|
+
**Made with ❤️ for the community**
|
package/docs/api/overview.md
CHANGED
|
@@ -12,7 +12,7 @@ Complete API documentation for `@falai/agent`. This framework provides a strongl
|
|
|
12
12
|
- [RoutingEngine](#routingengine)
|
|
13
13
|
- [ResponseEngine](#responseengine)
|
|
14
14
|
- [PromptComposer](#promptcomposer)
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
- [AI Providers](#ai-providers)
|
|
17
17
|
- [Persistence Adapters](#persistence-adapters)
|
|
18
18
|
- [Types & Interfaces](#types--interfaces)
|
|
@@ -136,9 +136,58 @@ for await (const chunk of agent.stream("Hello")) {
|
|
|
136
136
|
##### Tool Management
|
|
137
137
|
|
|
138
138
|
```typescript
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
addTool(definition: Tool<TContext, TData, TResult>): this
|
|
140
|
+
tool: ToolManager<TContext, TData> // Access to ToolManager instance
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Comprehensive Tool Examples:**
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
// 1. Simple return value (most common)
|
|
147
|
+
agent.addTool({
|
|
148
|
+
id: "calculate_tip",
|
|
149
|
+
description: "Calculate tip amount",
|
|
150
|
+
handler: async ({ context, data }, args) => {
|
|
151
|
+
const tip = args.amount * args.percentage;
|
|
152
|
+
return `Tip: $${tip.toFixed(2)}`; // Simple string return
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// 2. Complex ToolResult pattern
|
|
157
|
+
agent.addTool({
|
|
158
|
+
id: "process_order",
|
|
159
|
+
description: "Process customer order",
|
|
160
|
+
handler: async ({ context, data }, args) => {
|
|
161
|
+
const order = await orderService.process(args.items);
|
|
162
|
+
return {
|
|
163
|
+
data: `Order ${order.id} processed successfully`,
|
|
164
|
+
success: true,
|
|
165
|
+
contextUpdate: { lastOrderId: order.id },
|
|
166
|
+
dataUpdate: { orderStatus: 'processed' }
|
|
167
|
+
}; // Detailed ToolResult object
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// 3. Registry for reuse
|
|
172
|
+
agent.tool.register({
|
|
173
|
+
id: "send_notification",
|
|
174
|
+
description: "Send notification to user",
|
|
175
|
+
handler: async ({ context }, args) => {
|
|
176
|
+
await notificationService.send(context.userId, args.message);
|
|
177
|
+
return "Notification sent"; // Simple return
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// 4. Pattern helper
|
|
182
|
+
const validationTool = agent.tool.createValidation({
|
|
183
|
+
id: "validate_email",
|
|
184
|
+
fields: ['email'],
|
|
185
|
+
validator: async (context, data) => ({
|
|
186
|
+
valid: /\S+@\S+\.\S+/.test(data.email),
|
|
187
|
+
errors: []
|
|
188
|
+
})
|
|
189
|
+
});
|
|
190
|
+
agent.tool.register(validationTool);
|
|
142
191
|
```
|
|
143
192
|
|
|
144
193
|
##### Domain Knowledge
|
|
@@ -301,9 +350,7 @@ getRoutingExtrasSchema(): StructuredSchema | undefined
|
|
|
301
350
|
##### Tool Management
|
|
302
351
|
|
|
303
352
|
```typescript
|
|
304
|
-
|
|
305
|
-
registerTools(tools: Tool<TContext, unknown[], unknown, TData>[]): this
|
|
306
|
-
getTools(): Tool<TContext, unknown[], unknown, TData>[]
|
|
353
|
+
addTool(definition: Tool<TContext, TData, TResult>): this
|
|
307
354
|
```
|
|
308
355
|
|
|
309
356
|
##### Lifecycle Hooks
|
|
@@ -347,9 +394,9 @@ configure(config: Partial<StepOptions<TContext, TData>>): this
|
|
|
347
394
|
##### Transitions
|
|
348
395
|
|
|
349
396
|
```typescript
|
|
350
|
-
nextStep(spec: StepOptions<TContext, TData>):
|
|
397
|
+
nextStep(spec: StepOptions<TContext, TData>): Step<TContext, TData>
|
|
351
398
|
branch(branches: BranchSpec<TContext, TData>[]): BranchResult<TContext, TData>
|
|
352
|
-
endRoute(options?: Omit<StepOptions<TContext, TData>, 'step'>):
|
|
399
|
+
endRoute(options?: Omit<StepOptions<TContext, TData>, 'step'>): Step<TContext, TData>
|
|
353
400
|
```
|
|
354
401
|
|
|
355
402
|
##### Validation
|
|
@@ -371,7 +418,6 @@ getTransitions(): Step<TContext, TData>[]
|
|
|
371
418
|
|
|
372
419
|
```typescript
|
|
373
420
|
getRef(): StepRef
|
|
374
|
-
asStepResult(): StepResult<TContext, TData>
|
|
375
421
|
```
|
|
376
422
|
|
|
377
423
|
---
|
|
@@ -505,23 +551,7 @@ addDirectives(directives?: string[]): Promise<this>
|
|
|
505
551
|
build(): Promise<string>
|
|
506
552
|
```
|
|
507
553
|
|
|
508
|
-
---
|
|
509
|
-
|
|
510
|
-
### ToolExecutor
|
|
511
|
-
|
|
512
|
-
Handles tool execution with context updates and data collection.
|
|
513
554
|
|
|
514
|
-
#### Methods
|
|
515
|
-
|
|
516
|
-
```typescript
|
|
517
|
-
executeTool(params: {
|
|
518
|
-
tool: Tool;
|
|
519
|
-
context: unknown;
|
|
520
|
-
updateContext: (updates: Partial<unknown>) => Promise<void>;
|
|
521
|
-
history: Event[];
|
|
522
|
-
data: unknown;
|
|
523
|
-
}): Promise<ToolExecutionResult>
|
|
524
|
-
```
|
|
525
555
|
|
|
526
556
|
---
|
|
527
557
|
|
|
@@ -756,21 +786,33 @@ interface StepOptions<TContext = unknown, TData = unknown> {
|
|
|
756
786
|
}
|
|
757
787
|
}
|
|
758
788
|
|
|
759
|
-
// Example: Using existing tools (
|
|
789
|
+
// Example: Using existing tools (unified Tool interface)
|
|
760
790
|
{
|
|
761
|
-
prepare: "validate_user_data", // Tool ID string
|
|
762
|
-
finalize:
|
|
791
|
+
prepare: "validate_user_data", // Tool ID string - simple return value
|
|
792
|
+
finalize: "send_notification", // Tool ID string - ToolResult pattern
|
|
763
793
|
}
|
|
764
794
|
|
|
765
|
-
// Example: Inline tool definition
|
|
795
|
+
// Example: Inline tool definition with flexible returns
|
|
766
796
|
{
|
|
767
797
|
prepare: {
|
|
768
798
|
id: "setup_step_context",
|
|
769
799
|
description: "Prepare context for this step",
|
|
770
800
|
parameters: { type: "object", properties: {} },
|
|
771
801
|
handler: ({ context, data }) => {
|
|
772
|
-
//
|
|
773
|
-
return
|
|
802
|
+
// Simple return value
|
|
803
|
+
return "Setup complete";
|
|
804
|
+
}
|
|
805
|
+
},
|
|
806
|
+
finalize: {
|
|
807
|
+
id: "cleanup_step_context",
|
|
808
|
+
description: "Clean up after step completion",
|
|
809
|
+
handler: ({ context, data }) => {
|
|
810
|
+
// Complex ToolResult pattern
|
|
811
|
+
return {
|
|
812
|
+
data: "Cleanup complete",
|
|
813
|
+
success: true,
|
|
814
|
+
contextUpdate: { lastCleanup: new Date() }
|
|
815
|
+
};
|
|
774
816
|
}
|
|
775
817
|
}
|
|
776
818
|
}
|
|
@@ -104,7 +104,7 @@ const response3 = await agent.respond("Also book me a hotel in Tokyo");
|
|
|
104
104
|
|
|
105
105
|
**SessionManager API:**
|
|
106
106
|
|
|
107
|
-
The `SessionManager` provides a clean API for session operations:
|
|
107
|
+
The `SessionManager` provides a clean API for session operations with comprehensive error handling:
|
|
108
108
|
|
|
109
109
|
```typescript
|
|
110
110
|
// Access the session manager
|
|
@@ -114,13 +114,19 @@ const sessionManager = agent.session;
|
|
|
114
114
|
await sessionManager.getOrCreate("user-123");
|
|
115
115
|
await sessionManager.getOrCreate(); // Auto-generates ID
|
|
116
116
|
|
|
117
|
-
// History management
|
|
118
|
-
|
|
119
|
-
await sessionManager.addMessage("
|
|
117
|
+
// History management with error handling
|
|
118
|
+
try {
|
|
119
|
+
await sessionManager.addMessage("user", "Hello");
|
|
120
|
+
await sessionManager.addMessage("assistant", "Hi there!");
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.error("Failed to add message to history:", error);
|
|
123
|
+
// Message will be rolled back automatically
|
|
124
|
+
}
|
|
125
|
+
|
|
120
126
|
const history = sessionManager.getHistory();
|
|
121
127
|
sessionManager.clearHistory();
|
|
122
128
|
|
|
123
|
-
// Data access
|
|
129
|
+
// Data access with synchronization
|
|
124
130
|
const data = sessionManager.getData<FlightData>();
|
|
125
131
|
await sessionManager.setData({ destination: "Paris" });
|
|
126
132
|
|
|
@@ -130,6 +136,147 @@ await sessionManager.delete();
|
|
|
130
136
|
const newSession = await sessionManager.reset(true); // Preserve history
|
|
131
137
|
```
|
|
132
138
|
|
|
139
|
+
### Agent-Session Data Synchronization
|
|
140
|
+
|
|
141
|
+
The framework ensures bidirectional synchronization between agent collected data and session data:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
// Agent data updates automatically sync with session
|
|
145
|
+
const agent = new Agent<{}, BookingData>({
|
|
146
|
+
sessionId: "user-123",
|
|
147
|
+
// ... other config
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
// Update agent data - automatically syncs with session
|
|
152
|
+
await agent.updateCollectedData({
|
|
153
|
+
destination: "Tokyo",
|
|
154
|
+
passengers: 2
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Session data is automatically updated
|
|
158
|
+
const sessionData = agent.session.getData<BookingData>();
|
|
159
|
+
console.log(sessionData.destination); // "Tokyo"
|
|
160
|
+
|
|
161
|
+
// Update session data - automatically syncs with agent
|
|
162
|
+
await agent.session.setData({
|
|
163
|
+
checkInDate: "2025-03-15"
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Agent data is automatically updated
|
|
167
|
+
const agentData = agent.getCollectedData();
|
|
168
|
+
console.log(agentData.checkInDate); // "2025-03-15"
|
|
169
|
+
|
|
170
|
+
} catch (error) {
|
|
171
|
+
console.error("Data synchronization failed:", error);
|
|
172
|
+
// Both agent and session data remain in consistent state
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Error Handling in Data Synchronization
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
class SessionManager<TData> {
|
|
180
|
+
async setData(data: Partial<TData>): Promise<void> {
|
|
181
|
+
const previousData = { ...this.session.data };
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
// Validate data if schema is available
|
|
185
|
+
if (this.schema) {
|
|
186
|
+
this.validateData(data);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Update session data
|
|
190
|
+
this.session.data = { ...this.session.data, ...data };
|
|
191
|
+
|
|
192
|
+
// Sync with agent collected data
|
|
193
|
+
if (this.agent) {
|
|
194
|
+
await this.agent.updateCollectedData(data);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Persist changes
|
|
198
|
+
await this.save();
|
|
199
|
+
|
|
200
|
+
} catch (error) {
|
|
201
|
+
// Rollback session data on any failure
|
|
202
|
+
this.session.data = previousData;
|
|
203
|
+
|
|
204
|
+
console.error("Session data update failed, rolled back:", error);
|
|
205
|
+
throw new Error(`Data synchronization failed: ${error.message}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async addMessage(role: "user" | "assistant", content: string): Promise<void> {
|
|
210
|
+
const message: HistoryItem = {
|
|
211
|
+
role,
|
|
212
|
+
content,
|
|
213
|
+
timestamp: new Date().toISOString()
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
// Add to session history
|
|
218
|
+
this.session.history.push(message);
|
|
219
|
+
|
|
220
|
+
// Persist immediately for reliability
|
|
221
|
+
await this.save();
|
|
222
|
+
|
|
223
|
+
} catch (error) {
|
|
224
|
+
// Remove message from history on persistence failure
|
|
225
|
+
this.session.history.pop();
|
|
226
|
+
|
|
227
|
+
console.error("Failed to persist message:", error);
|
|
228
|
+
throw new Error(`Message persistence failed: ${error.message}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Chat Method with Proper Error Handling
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
class Agent<TContext, TData> {
|
|
238
|
+
async chat(message: string, sessionId?: string): Promise<AgentResponse<TData>> {
|
|
239
|
+
try {
|
|
240
|
+
// Ensure session is loaded
|
|
241
|
+
if (!this.session || this.session.id !== sessionId) {
|
|
242
|
+
await this.loadSession(sessionId);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Add user message to history BEFORE processing
|
|
246
|
+
await this.session.addMessage("user", message);
|
|
247
|
+
|
|
248
|
+
// Process the message
|
|
249
|
+
const response = await this.respond({
|
|
250
|
+
message,
|
|
251
|
+
sessionId: this.session.id
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// Add assistant response to history
|
|
255
|
+
if (response.message) {
|
|
256
|
+
await this.session.addMessage("assistant", response.message);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return response;
|
|
260
|
+
|
|
261
|
+
} catch (error) {
|
|
262
|
+
console.error("Chat method failed:", error);
|
|
263
|
+
|
|
264
|
+
// Try to remove the user message if response failed
|
|
265
|
+
try {
|
|
266
|
+
const history = this.session.getHistory();
|
|
267
|
+
if (history.length > 0 && history[history.length - 1].role === "user") {
|
|
268
|
+
await this.session.removeLastMessage();
|
|
269
|
+
}
|
|
270
|
+
} catch (rollbackError) {
|
|
271
|
+
console.error("Failed to rollback user message:", rollbackError);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
throw new Error(`Chat failed: ${error.message}`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
133
280
|
**Why?** Automatic session management provides:
|
|
134
281
|
|
|
135
282
|
- **Zero Boilerplate** - No manual session creation or persistence code
|
|
@@ -118,10 +118,121 @@ agentContext.lastResponseTime = Date.now();
|
|
|
118
118
|
|
|
119
119
|
Robust error handling for various failure scenarios:
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
121
|
+
### Schema Validation Failures
|
|
122
|
+
|
|
123
|
+
When AI responses don't match expected schemas, the system gracefully falls back:
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
const processResponse = async (response: string, schema: JSONSchema) => {
|
|
127
|
+
try {
|
|
128
|
+
// Try schema-based extraction first
|
|
129
|
+
const extracted = await extractWithSchema(response, schema);
|
|
130
|
+
return { success: true, data: extracted };
|
|
131
|
+
} catch (schemaError) {
|
|
132
|
+
console.warn("Schema extraction failed, falling back to manual parsing:", schemaError.message);
|
|
133
|
+
|
|
134
|
+
// Fallback to manual extraction
|
|
135
|
+
try {
|
|
136
|
+
const manualData = await manualExtraction(response);
|
|
137
|
+
return { success: true, data: manualData, fallback: true };
|
|
138
|
+
} catch (fallbackError) {
|
|
139
|
+
return {
|
|
140
|
+
success: false,
|
|
141
|
+
error: `Both schema and manual extraction failed: ${fallbackError.message}`
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Tool Execution Errors
|
|
149
|
+
|
|
150
|
+
Tool failures are handled gracefully with proper error propagation:
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
const executeTool = async (tool: Tool, params: any) => {
|
|
154
|
+
try {
|
|
155
|
+
const result = await tool.handler(params);
|
|
156
|
+
return { success: true, result };
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error(`Tool ${tool.id} execution failed:`, error);
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
success: false,
|
|
162
|
+
error: error.message,
|
|
163
|
+
fallbackMessage: "I encountered an issue while processing your request. Please try again."
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Context Update Failures
|
|
170
|
+
|
|
171
|
+
Context updates include rollback mechanisms:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
const updateContext = async (newContext: any, previousContext: any) => {
|
|
175
|
+
try {
|
|
176
|
+
await persistContext(newContext);
|
|
177
|
+
return { success: true };
|
|
178
|
+
} catch (error) {
|
|
179
|
+
console.error("Context update failed, rolling back:", error);
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
await persistContext(previousContext);
|
|
183
|
+
return { success: false, rolledBack: true, error: error.message };
|
|
184
|
+
} catch (rollbackError) {
|
|
185
|
+
return {
|
|
186
|
+
success: false,
|
|
187
|
+
rolledBack: false,
|
|
188
|
+
error: `Update and rollback both failed: ${rollbackError.message}`
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Streaming Error Propagation
|
|
196
|
+
|
|
197
|
+
Streaming responses properly propagate provider errors:
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
async function* processStreamingResponse(provider: AIProvider, prompt: string) {
|
|
201
|
+
try {
|
|
202
|
+
for await (const chunk of provider.generateMessageStream(prompt)) {
|
|
203
|
+
yield { success: true, chunk };
|
|
204
|
+
}
|
|
205
|
+
} catch (error) {
|
|
206
|
+
// Ensure streaming errors are properly propagated
|
|
207
|
+
yield { success: false, error: error.message };
|
|
208
|
+
throw error; // Re-throw to stop the stream
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Routing Errors
|
|
214
|
+
|
|
215
|
+
Safe fallback to default behavior when routing fails:
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
const selectRoute = async (routes: Route[], context: any) => {
|
|
219
|
+
try {
|
|
220
|
+
const selectedRoute = await aiRouting.selectBestRoute(routes, context);
|
|
221
|
+
return { success: true, route: selectedRoute };
|
|
222
|
+
} catch (routingError) {
|
|
223
|
+
console.warn("AI routing failed, using default route:", routingError.message);
|
|
224
|
+
|
|
225
|
+
// Fallback to first available route or default
|
|
226
|
+
const fallbackRoute = routes.find(r => r.isDefault) || routes[0];
|
|
227
|
+
return {
|
|
228
|
+
success: true,
|
|
229
|
+
route: fallbackRoute,
|
|
230
|
+
fallback: true,
|
|
231
|
+
error: routingError.message
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
```
|
|
125
236
|
|
|
126
237
|
## Streaming Response Processing
|
|
127
238
|
|