@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.
Files changed (145) hide show
  1. package/README.md +42 -34
  2. package/dist/cjs/src/core/Agent.d.ts +19 -5
  3. package/dist/cjs/src/core/Agent.d.ts.map +1 -1
  4. package/dist/cjs/src/core/Agent.js +79 -35
  5. package/dist/cjs/src/core/Agent.js.map +1 -1
  6. package/dist/cjs/src/core/ResponseModal.d.ts +9 -3
  7. package/dist/cjs/src/core/ResponseModal.d.ts.map +1 -1
  8. package/dist/cjs/src/core/ResponseModal.js +121 -55
  9. package/dist/cjs/src/core/ResponseModal.js.map +1 -1
  10. package/dist/cjs/src/core/ResponsePipeline.d.ts +8 -4
  11. package/dist/cjs/src/core/ResponsePipeline.d.ts.map +1 -1
  12. package/dist/cjs/src/core/ResponsePipeline.js +47 -19
  13. package/dist/cjs/src/core/ResponsePipeline.js.map +1 -1
  14. package/dist/cjs/src/core/Route.d.ts +12 -5
  15. package/dist/cjs/src/core/Route.d.ts.map +1 -1
  16. package/dist/cjs/src/core/Route.js +26 -5
  17. package/dist/cjs/src/core/Route.js.map +1 -1
  18. package/dist/cjs/src/core/RoutingEngine.d.ts +5 -0
  19. package/dist/cjs/src/core/RoutingEngine.d.ts.map +1 -1
  20. package/dist/cjs/src/core/RoutingEngine.js +37 -25
  21. package/dist/cjs/src/core/RoutingEngine.js.map +1 -1
  22. package/dist/cjs/src/core/SessionManager.d.ts +9 -1
  23. package/dist/cjs/src/core/SessionManager.d.ts.map +1 -1
  24. package/dist/cjs/src/core/SessionManager.js +27 -5
  25. package/dist/cjs/src/core/SessionManager.js.map +1 -1
  26. package/dist/cjs/src/core/Step.d.ts +60 -7
  27. package/dist/cjs/src/core/Step.d.ts.map +1 -1
  28. package/dist/cjs/src/core/Step.js +151 -4
  29. package/dist/cjs/src/core/Step.js.map +1 -1
  30. package/dist/cjs/src/core/ToolManager.d.ts +234 -0
  31. package/dist/cjs/src/core/ToolManager.d.ts.map +1 -0
  32. package/dist/cjs/src/core/ToolManager.js +1117 -0
  33. package/dist/cjs/src/core/ToolManager.js.map +1 -0
  34. package/dist/cjs/src/index.d.ts +2 -3
  35. package/dist/cjs/src/index.d.ts.map +1 -1
  36. package/dist/cjs/src/index.js +5 -3
  37. package/dist/cjs/src/index.js.map +1 -1
  38. package/dist/cjs/src/types/agent.d.ts +1 -1
  39. package/dist/cjs/src/types/agent.d.ts.map +1 -1
  40. package/dist/cjs/src/types/index.d.ts +3 -2
  41. package/dist/cjs/src/types/index.d.ts.map +1 -1
  42. package/dist/cjs/src/types/index.js +3 -1
  43. package/dist/cjs/src/types/index.js.map +1 -1
  44. package/dist/cjs/src/types/route.d.ts +6 -4
  45. package/dist/cjs/src/types/route.d.ts.map +1 -1
  46. package/dist/cjs/src/types/tool.d.ts +84 -14
  47. package/dist/cjs/src/types/tool.d.ts.map +1 -1
  48. package/dist/cjs/src/types/tool.js +13 -0
  49. package/dist/cjs/src/types/tool.js.map +1 -1
  50. package/dist/src/core/Agent.d.ts +19 -5
  51. package/dist/src/core/Agent.d.ts.map +1 -1
  52. package/dist/src/core/Agent.js +79 -35
  53. package/dist/src/core/Agent.js.map +1 -1
  54. package/dist/src/core/ResponseModal.d.ts +9 -3
  55. package/dist/src/core/ResponseModal.d.ts.map +1 -1
  56. package/dist/src/core/ResponseModal.js +121 -55
  57. package/dist/src/core/ResponseModal.js.map +1 -1
  58. package/dist/src/core/ResponsePipeline.d.ts +8 -4
  59. package/dist/src/core/ResponsePipeline.d.ts.map +1 -1
  60. package/dist/src/core/ResponsePipeline.js +47 -19
  61. package/dist/src/core/ResponsePipeline.js.map +1 -1
  62. package/dist/src/core/Route.d.ts +12 -5
  63. package/dist/src/core/Route.d.ts.map +1 -1
  64. package/dist/src/core/Route.js +26 -5
  65. package/dist/src/core/Route.js.map +1 -1
  66. package/dist/src/core/RoutingEngine.d.ts +5 -0
  67. package/dist/src/core/RoutingEngine.d.ts.map +1 -1
  68. package/dist/src/core/RoutingEngine.js +37 -25
  69. package/dist/src/core/RoutingEngine.js.map +1 -1
  70. package/dist/src/core/SessionManager.d.ts +9 -1
  71. package/dist/src/core/SessionManager.d.ts.map +1 -1
  72. package/dist/src/core/SessionManager.js +27 -5
  73. package/dist/src/core/SessionManager.js.map +1 -1
  74. package/dist/src/core/Step.d.ts +60 -7
  75. package/dist/src/core/Step.d.ts.map +1 -1
  76. package/dist/src/core/Step.js +151 -4
  77. package/dist/src/core/Step.js.map +1 -1
  78. package/dist/src/core/ToolManager.d.ts +234 -0
  79. package/dist/src/core/ToolManager.d.ts.map +1 -0
  80. package/dist/src/core/ToolManager.js +1111 -0
  81. package/dist/src/core/ToolManager.js.map +1 -0
  82. package/dist/src/index.d.ts +2 -3
  83. package/dist/src/index.d.ts.map +1 -1
  84. package/dist/src/index.js +1 -1
  85. package/dist/src/index.js.map +1 -1
  86. package/dist/src/types/agent.d.ts +1 -1
  87. package/dist/src/types/agent.d.ts.map +1 -1
  88. package/dist/src/types/index.d.ts +3 -2
  89. package/dist/src/types/index.d.ts.map +1 -1
  90. package/dist/src/types/index.js +1 -0
  91. package/dist/src/types/index.js.map +1 -1
  92. package/dist/src/types/route.d.ts +6 -4
  93. package/dist/src/types/route.d.ts.map +1 -1
  94. package/dist/src/types/tool.d.ts +84 -14
  95. package/dist/src/types/tool.d.ts.map +1 -1
  96. package/dist/src/types/tool.js +12 -1
  97. package/dist/src/types/tool.js.map +1 -1
  98. package/docs/CONTRIBUTING.md +40 -0
  99. package/docs/README.md +12 -5
  100. package/docs/api/README.md +75 -45
  101. package/docs/api/overview.md +74 -32
  102. package/docs/core/agent/session-management.md +152 -5
  103. package/docs/core/ai-integration/response-processing.md +115 -4
  104. package/docs/core/conversation-flows/routes.md +130 -0
  105. package/docs/core/error-handling.md +638 -0
  106. package/docs/core/tools/tool-definition.md +684 -60
  107. package/docs/core/tools/tool-scoping.md +244 -53
  108. package/docs/guides/error-handling-patterns.md +578 -0
  109. package/docs/guides/getting-started/README.md +139 -28
  110. package/examples/advanced-patterns/knowledge-based-agent.ts +6 -6
  111. package/examples/advanced-patterns/persistent-onboarding.ts +30 -43
  112. package/examples/ai-providers/anthropic-integration.ts +9 -5
  113. package/examples/ai-providers/openai-integration.ts +11 -7
  114. package/examples/core-concepts/basic-agent.ts +106 -67
  115. package/examples/core-concepts/schema-driven-extraction.ts +10 -7
  116. package/examples/core-concepts/session-management.ts +71 -18
  117. package/examples/integrations/healthcare-integration.ts +15 -29
  118. package/examples/integrations/server-session-management.ts +3 -3
  119. package/examples/persistence/memory-sessions.ts +3 -3
  120. package/examples/tools/basic-tools.ts +293 -89
  121. package/examples/tools/data-enrichment-tools.ts +185 -75
  122. package/package.json +1 -1
  123. package/src/core/Agent.ts +98 -44
  124. package/src/core/ResponseModal.ts +148 -72
  125. package/src/core/ResponsePipeline.ts +82 -56
  126. package/src/core/Route.ts +39 -12
  127. package/src/core/RoutingEngine.ts +46 -42
  128. package/src/core/SessionManager.ts +39 -7
  129. package/src/core/Step.ts +198 -20
  130. package/src/core/ToolManager.ts +1394 -0
  131. package/src/index.ts +8 -3
  132. package/src/types/agent.ts +1 -1
  133. package/src/types/index.ts +13 -2
  134. package/src/types/route.ts +6 -4
  135. package/src/types/tool.ts +116 -25
  136. package/dist/cjs/src/core/ToolExecutor.d.ts +0 -45
  137. package/dist/cjs/src/core/ToolExecutor.d.ts.map +0 -1
  138. package/dist/cjs/src/core/ToolExecutor.js +0 -84
  139. package/dist/cjs/src/core/ToolExecutor.js.map +0 -1
  140. package/dist/src/core/ToolExecutor.d.ts +0 -45
  141. package/dist/src/core/ToolExecutor.d.ts.map +0 -1
  142. package/dist/src/core/ToolExecutor.js +0 -80
  143. package/dist/src/core/ToolExecutor.js.map +0 -1
  144. package/docs/core/tools/tool-execution.md +0 -815
  145. package/src/core/ToolExecutor.ts +0 -126
@@ -1,26 +1,86 @@
1
- # Tool Definition
1
+ # Tool Definition with Unified Interface
2
2
 
3
- Tools in @falai/agent enable AI agents to execute custom logic, access external APIs, and perform actions during conversations. This document covers tool creation, configuration, and integration.
3
+ Tools in @falai/agent enable AI agents to execute custom logic, access external APIs, and perform actions during conversations. The unified Tool interface supports both simple return values and complex ToolResult patterns, providing maximum flexibility with minimal complexity.
4
4
 
5
5
  ## Overview
6
6
 
7
- Tools provide a way for agents to:
7
+ The unified Tool system provides:
8
8
 
9
- - Execute business logic and API calls
10
- - Access external services and databases
11
- - Perform calculations and data transformations
12
- - Update conversation context and session data
9
+ - **Single Interface**: One Tool interface that handles both simple and advanced patterns
10
+ - **Flexible Returns**: Return simple values (`return 'result'`) or complex objects (`return { data: 'result', success: true }`)
11
+ - **Multiple Creation Methods**: Direct addition, registry system, pattern helpers, and manual creation
12
+ - **Type Safety**: Full TypeScript support with automatic type inference
13
+ - **Helper Methods**: Built-in context and data update utilities
14
+ - **Intelligent Scoping**: Hierarchical tool resolution with registry fallback
13
15
 
14
- ## Tool Creation
16
+ ## Unified Tool Interface
15
17
 
16
- Tools are created as objects implementing the `Tool` interface:
18
+ All tools use the same interface regardless of complexity:
17
19
 
18
20
  ```typescript
19
- import { Tool } from "@falai/agent";
21
+ interface Tool<TContext = unknown, TData = unknown, TResult = unknown> {
22
+ id: string;
23
+ name?: string;
24
+ description?: string;
25
+ parameters?: unknown;
26
+ handler: (
27
+ context: ToolContext<TContext, TData>,
28
+ args?: Record<string, unknown>
29
+ ) => Promise<TResult | ToolResult<TResult, TContext, TData>> | TResult | ToolResult<TResult, TContext, TData>;
30
+ }
31
+ ```
32
+
33
+ The handler can return either:
34
+ - **Simple values**: `return 'result'` or `return { status: 'complete' }`
35
+ - **ToolResult objects**: `return { data: 'result', success: true, contextUpdate: {...} }`
36
+
37
+ ```typescript
38
+ import { Agent, GeminiProvider } from "@falai/agent";
39
+
40
+ const agent = new Agent({
41
+ name: "Assistant",
42
+ provider: new GeminiProvider({
43
+ apiKey: process.env.GEMINI_API_KEY!,
44
+ }),
45
+ });
46
+
47
+ // Access ToolManager for advanced operations
48
+ const toolManager = agent.tool;
49
+ ```
50
+
51
+ ## Tool Creation Methods
52
+
53
+ The unified Tool interface supports multiple creation approaches, each optimized for different use cases:
54
+
55
+ ### 1. Simple Return Values (Recommended for Most Cases)
56
+
57
+ The most straightforward approach - just return the result directly:
20
58
 
21
- const weatherTool: Tool<unknown, WeatherData, [], string> = {
59
+ ```typescript
60
+ import { Agent, GeminiProvider } from "@falai/agent";
61
+
62
+ interface UserContext {
63
+ userId: string;
64
+ preferences: Record<string, any>;
65
+ }
66
+
67
+ interface WeatherData {
68
+ location?: string;
69
+ temperature?: number;
70
+ condition?: string;
71
+ }
72
+
73
+ const agent = new Agent<UserContext, WeatherData>({
74
+ name: "Weather Assistant",
75
+ provider: new GeminiProvider({
76
+ apiKey: process.env.GEMINI_API_KEY!,
77
+ }),
78
+ });
79
+
80
+ // Simple return value - most common pattern
81
+ agent.addTool({
22
82
  id: "get_weather",
23
- name: "Weather Forecast", // Human-readable name shown to AI models
83
+ name: "Weather Forecast",
24
84
  description: "Get current weather and forecast for a location",
25
85
  parameters: {
26
86
  type: "object",
@@ -30,45 +90,244 @@ const weatherTool: Tool<unknown, WeatherData, [], string> = {
30
90
  },
31
91
  required: ["location"],
32
92
  },
33
- handler: async ({ location, date }) => {
34
- const weather = await weatherAPI.getForecast(location, date);
35
- return {
36
- data: `The weather in ${location} on ${date} is ${weather.condition}`,
37
- contextUpdate: {
38
- currentWeather: weather,
39
- lastWeatherCheck: new Date().toISOString(),
40
- },
41
- };
93
+ handler: async ({ context, data, updateContext, updateData }, args) => {
94
+ const weather = await weatherAPI.getForecast(args.location, args.date);
95
+
96
+ // Use helper methods for updates
97
+ await updateContext({ lastWeatherCheck: new Date().toISOString() });
98
+ await updateData({
99
+ location: args.location,
100
+ temperature: weather.temperature,
101
+ condition: weather.condition,
102
+ });
103
+
104
+ // Return simple string - unified interface handles the rest
105
+ return `The weather in ${args.location} on ${args.date} is ${weather.condition}`;
42
106
  },
43
- };
107
+ });
44
108
  ```
45
109
 
46
- ## Tool Name
110
+ ### 2. Advanced ToolResult Pattern
47
111
 
48
- The optional `name` field provides a human-readable name for the tool that is displayed to AI models. When provided, this name takes precedence over the `id` field in AI provider interactions:
112
+ For complex scenarios requiring detailed control:
49
113
 
50
114
  ```typescript
51
- const calculatorTool: Tool<unknown, CalcData, [], string> = {
52
- id: "math_calculator", // Internal identifier
53
- name: "Math Calculator", // Display name for AI models
115
+ // Advanced ToolResult pattern for complex scenarios
116
+ agent.addTool({
117
+ id: "process_payment",
118
+ name: "Payment Processor",
119
+ description: "Process payment with detailed result tracking",
120
+ parameters: {
121
+ type: "object",
122
+ properties: {
123
+ amount: { type: "number", description: "Payment amount" },
124
+ currency: { type: "string", description: "Currency code" },
125
+ },
126
+ required: ["amount", "currency"],
127
+ },
128
+ handler: async ({ context, data }, args) => {
129
+ try {
130
+ const result = await paymentAPI.process(args.amount, args.currency);
131
+
132
+ // Return detailed ToolResult object
133
+ return {
134
+ data: `Payment of ${args.amount} ${args.currency} processed successfully`,
135
+ success: true,
136
+ contextUpdate: {
137
+ lastPaymentId: result.transactionId,
138
+ paymentHistory: [...(context.paymentHistory || []), result]
139
+ },
140
+ dataUpdate: {
141
+ paymentStatus: 'completed',
142
+ transactionId: result.transactionId
143
+ }
144
+ };
145
+ } catch (error) {
146
+ return {
147
+ data: `Payment failed: ${error.message}`,
148
+ success: false,
149
+ contextUpdate: {
150
+ lastPaymentError: error.message
151
+ }
152
+ };
153
+ }
154
+ },
155
+ });
156
+ ```
157
+
158
+ ## Multiple Creation Approaches
159
+
160
+ Choose the approach that best fits your use case:
161
+
162
+ ### 3. Direct Addition (`agent.addTool`)
163
+
164
+ Add tools directly to agent scope - available to all routes and steps:
165
+
166
+ ```typescript
167
+ // Creates and adds tool to agent scope in one operation
168
+ agent.addTool({
169
+ id: "math_calculator",
170
+ name: "Math Calculator",
54
171
  description: "Perform mathematical calculations",
55
- // ... rest of tool definition
56
- };
172
+ parameters: {
173
+ type: "object",
174
+ properties: {
175
+ expression: { type: "string", description: "Mathematical expression to evaluate" },
176
+ },
177
+ required: ["expression"],
178
+ },
179
+ handler: async ({ context, data, updateData }, args) => {
180
+ const result = performCalculation(args.expression);
181
+
182
+ // Update collected data with calculation result
183
+ await updateData({ lastCalculation: result });
184
+
185
+ // Simple return value
186
+ return `Result: ${result}`;
187
+ },
188
+ });
189
+ ```
190
+
191
+ ### 4. Registry System (`agent.tool.register`)
192
+
193
+ Register tools for reuse across multiple contexts:
194
+
195
+ ```typescript
196
+ // Register tool without adding to any scope
197
+ agent.tool.register({
198
+ id: "reusable_search",
199
+ name: "Universal Search",
200
+ description: "Search across multiple data sources",
201
+ parameters: {
202
+ type: "object",
203
+ properties: {
204
+ query: { type: "string", description: "Search query" },
205
+ sources: { type: "array", items: { type: "string" }, description: "Data sources to search" },
206
+ },
207
+ required: ["query"],
208
+ },
209
+ handler: async ({ context, data }, args) => {
210
+ const results = await searchMultipleSources(args.query, args.sources);
211
+ return `Found ${results.length} results`; // Simple return
212
+ },
213
+ });
214
+
215
+ // Reference registered tool by ID in steps
216
+ route.initialStep.nextStep({
217
+ prompt: "What would you like to search for?",
218
+ tools: ['reusable_search'] // Reference by ID
219
+ });
220
+
221
+ // Or add registered tool to specific scopes
222
+ const searchTool = agent.tool.find('reusable_search');
223
+ route.addTool(searchTool);
224
+ ```
225
+
226
+ ### 5. Manual Creation (`agent.tool.create`)
227
+
228
+ Create tool instances without registering or adding to any scope:
229
+
230
+ ```typescript
231
+ // Create tool instance for manual management
232
+ const customTool = agent.tool.create({
233
+ id: "standalone_processor",
234
+ description: "Process data independently",
235
+ handler: async ({ context, data }) => {
236
+ return "Processing complete"; // Simple return
237
+ },
238
+ });
239
+
240
+ // Manually add to specific contexts as needed
241
+ someStep.tools = [customTool];
242
+ ```
243
+
244
+ ### 6. Bulk Operations (`registerMany`)
245
+
246
+ Register multiple tools at once:
247
+
248
+ ```typescript
249
+ agent.tool.registerMany([
250
+ {
251
+ id: "system_status",
252
+ description: "Check system health",
253
+ handler: async () => "System OK", // Simple return
254
+ },
255
+ {
256
+ id: "audit_log",
257
+ description: "Create audit log entry",
258
+ handler: async ({ context }) => `Audit logged for ${context.userId}`,
259
+ },
260
+ existingToolInstance, // Can mix definitions and instances
261
+ ]);
57
262
  ```
58
263
 
59
- **Benefits:**
264
+ ### 7. Pattern Helpers
60
265
 
61
- - **Better AI Understanding**: Clear, descriptive names help AI models choose appropriate tools
62
- - **User-Friendly**: More readable than cryptic IDs in AI responses and logs
63
- - **Backward Compatible**: Falls back to `id` if `name` is not provided
64
- - **Flexible**: Allows separation of internal IDs from user-facing names
266
+ Use built-in helpers for common tool patterns - these return tool instances that can be registered or added as needed:
267
+
268
+ ```typescript
269
+ // Data enrichment tool - returns Tool instance
270
+ const enrichmentTool = agent.tool.createDataEnrichment({
271
+ id: "enrich_user_profile",
272
+ fields: ['name', 'email'] as const, // Type-safe field selection
273
+ enricher: async (context, data) => ({
274
+ fullName: `${data.name} (${context.userRole})`,
275
+ emailDomain: data.email?.split('@')[1],
276
+ })
277
+ });
278
+
279
+ // Validation tool - returns Tool instance
280
+ const validationTool = agent.tool.createValidation({
281
+ id: "validate_booking",
282
+ fields: ['date', 'guests'] as const,
283
+ validator: async (context, data) => {
284
+ const errors = [];
285
+ if (!data.date) errors.push({ field: 'date', message: 'Date is required' });
286
+ if (!data.guests || data.guests < 1) errors.push({ field: 'guests', message: 'At least 1 guest required' });
287
+
288
+ return { valid: errors.length === 0, errors };
289
+ }
290
+ });
291
+
292
+ // API call tool - returns Tool instance
293
+ const apiTool = agent.tool.createApiCall({
294
+ id: "fetch_weather_data",
295
+ endpoint: "https://api.weather.com/v1/current",
296
+ method: "GET",
297
+ headers: { "API-Key": process.env.WEATHER_API_KEY! },
298
+ transform: (response: any) => response.data.current,
299
+ });
300
+
301
+ // Computation tool - returns Tool instance
302
+ const computeTool = agent.tool.createComputation({
303
+ id: "calculate_total_cost",
304
+ inputs: ['basePrice', 'taxRate', 'discountPercent'] as const,
305
+ compute: async (context, inputs) => {
306
+ const subtotal = inputs.basePrice * (1 - (inputs.discountPercent || 0) / 100);
307
+ return subtotal * (1 + (inputs.taxRate || 0));
308
+ }
309
+ });
310
+
311
+ // Register or add pattern helpers as needed
312
+ agent.tool.registerMany([enrichmentTool, validationTool, apiTool, computeTool]);
313
+ ```
314
+
315
+ ## When to Use Each Approach
316
+
317
+ - **Simple Return Values**: Most common cases, straightforward results
318
+ - **ToolResult Pattern**: Complex scenarios requiring context/data updates
319
+ - **Direct Addition**: Tools specific to one agent
320
+ - **Registry System**: Reusable tools across multiple contexts
321
+ - **Manual Creation**: Custom tool management scenarios
322
+ - **Bulk Operations**: Efficient registration of multiple tools
323
+ - **Pattern Helpers**: Common patterns with built-in logic
65
324
 
66
325
  ## Tool Parameters
67
326
 
68
327
  Tool parameters are defined using JSON Schema:
69
328
 
70
329
  ```typescript
71
- const searchTool: Tool<unknown, SearchData, [], string> = {
330
+ agent.addTool({
72
331
  id: "web_search",
73
332
  name: "Web Search Engine",
74
333
  description: "Search the web for information",
@@ -91,26 +350,23 @@ const searchTool: Tool<unknown, SearchData, [], string> = {
91
350
  },
92
351
  required: ["query"],
93
352
  },
94
- handler: async ({ query, limit = 10 }) => {
353
+ handler: async ({ context, data }, args) => {
354
+ const { query, limit = 10 } = args;
95
355
  const results = await searchAPI.query(query, limit);
96
356
  return {
97
357
  data: `Found ${results.length} results for "${query}"`,
98
358
  contextUpdate: { searchResults: results },
99
359
  };
100
360
  },
101
- };
361
+ });
102
362
  ```
103
363
 
104
- ## Tool Execution Context
105
-
106
- Tools receive execution context including:
364
+ ## Simplified Tool Context
107
365
 
108
- - **Current context** - Agent and route context
109
- - **Session data** - Collected conversation data
110
- - **Route information** - Current route and step details
366
+ Tools receive a simplified context with direct access to agent data and helper methods:
111
367
 
112
368
  ```typescript
113
- const userProfileTool: Tool<unknown, UserData, [], string> = {
369
+ agent.addTool({
114
370
  id: "get_user_profile",
115
371
  description: "Retrieve user profile information",
116
372
  parameters: {
@@ -122,20 +378,43 @@ const userProfileTool: Tool<unknown, UserData, [], string> = {
122
378
  },
123
379
  },
124
380
  },
125
- handler: async (toolContext, args) => {
126
- // Access current context
127
- const currentUserId = toolContext.context.userId || args.userId;
128
-
129
- // Access collected data
130
- const preferences = toolContext.data.userPreferences;
381
+ handler: async ({ context, data, updateContext, updateData }, args) => {
382
+ // Direct access to current context and data
383
+ const currentUserId = context.userId || args.userId;
384
+ const preferences = data.userPreferences;
131
385
 
132
386
  const profile = await userAPI.getProfile(currentUserId);
387
+
388
+ // Use helper methods for updates
389
+ await updateData({ userProfile: profile });
390
+
133
391
  return {
134
392
  data: `Retrieved profile for ${profile.name}`,
135
- dataUpdate: { userProfile: profile },
136
393
  };
137
394
  },
138
- };
395
+ });
396
+ ```
397
+
398
+ ### Context Helper Methods
399
+
400
+ The simplified context provides convenient helper methods:
401
+
402
+ ```typescript
403
+ agent.addTool({
404
+ id: "user_preferences",
405
+ handler: async ({ context, data, getField, setField, hasField }) => {
406
+ // Check if field exists
407
+ if (hasField('preferences')) {
408
+ const prefs = getField('preferences');
409
+ console.log('Current preferences:', prefs);
410
+ }
411
+
412
+ // Set field value
413
+ await setField('lastLogin', new Date().toISOString());
414
+
415
+ return { data: "Preferences updated" };
416
+ },
417
+ });
139
418
  ```
140
419
 
141
420
  ## Tool Response Format
@@ -253,17 +532,30 @@ const apiTool: Tool<unknown, ApiData, [], string> = {
253
532
 
254
533
  ## Tool Scoping
255
534
 
256
- Tools can be registered at different levels:
535
+ Tools can be added at different scopes using the new ToolManager API:
257
536
 
258
537
  ### Agent-Level Tools
259
538
 
260
539
  Available to all routes and steps:
261
540
 
262
541
  ```typescript
263
- const agent = new Agent({
264
- name: "Assistant",
265
- provider: openaiProvider,
266
- tools: [globalSearchTool, userManagementTool],
542
+ // Add tools directly to agent scope
543
+ agent.addTool({
544
+ id: "global_search",
545
+ description: "Search across all data sources",
546
+ handler: async ({ context, data }) => {
547
+ // Tool logic here
548
+ return { data: "Search completed" };
549
+ },
550
+ });
551
+
552
+ // Or register for later use
553
+ agent.tool.register({
554
+ id: "user_management",
555
+ description: "Manage user accounts",
556
+ handler: async ({ context, data }) => {
557
+ return { data: "User managed" };
558
+ },
267
559
  });
268
560
  ```
269
561
 
@@ -274,7 +566,15 @@ Available only within specific routes:
274
566
  ```typescript
275
567
  const supportRoute = agent.createRoute({
276
568
  title: "Customer Support",
277
- tools: [ticketCreationTool, knowledgeBaseTool],
569
+ });
570
+
571
+ // Add tools to route scope
572
+ supportRoute.addTool({
573
+ id: "create_ticket",
574
+ description: "Create support ticket",
575
+ handler: async ({ context, data }) => {
576
+ return { data: "Ticket created" };
577
+ },
278
578
  });
279
579
  ```
280
580
 
@@ -283,10 +583,22 @@ const supportRoute = agent.createRoute({
283
583
  Available only in specific steps:
284
584
 
285
585
  ```typescript
586
+ // Add tool directly to step
286
587
  const bookingStep = route.initialStep.nextStep({
287
588
  prompt: "Ready to book?",
288
- tools: [paymentProcessingTool],
289
589
  requires: ["bookingDetails"],
590
+ }).addTool({
591
+ id: "process_payment",
592
+ description: "Process payment for booking",
593
+ handler: async ({ context, data }) => {
594
+ return { data: "Payment processed" };
595
+ },
596
+ });
597
+
598
+ // Or reference registered tools by ID
599
+ const step = route.initialStep.nextStep({
600
+ prompt: "Processing...",
601
+ tools: ['registered_tool_id'], // Reference by ID
290
602
  });
291
603
  ```
292
604
 
@@ -335,12 +647,324 @@ Tools are validated at registration time:
335
647
  - **Type checking** - TypeScript types must match schemas
336
648
  - **Name uniqueness** - Tool names must be unique within scope
337
649
 
650
+ ## Pattern Helpers
651
+
652
+ ToolManager provides built-in helpers for common tool patterns:
653
+
654
+ ### Data Enrichment Tools
655
+
656
+ For tools that modify collected data:
657
+
658
+ ```typescript
659
+ const enrichmentTool = agent.tool.createDataEnrichment({
660
+ id: "enrich_user_data",
661
+ fields: ['name', 'email'],
662
+ enricher: async (context, data) => ({
663
+ fullName: `${data.name} (${context.userRole})`,
664
+ emailDomain: data.email.split('@')[1]
665
+ })
666
+ });
667
+
668
+ // Register or add to scope
669
+ agent.tool.register(enrichmentTool);
670
+ ```
671
+
672
+ ### Validation Tools
673
+
674
+ For tools that validate data fields:
675
+
676
+ ```typescript
677
+ const validationTool = agent.tool.createValidation({
678
+ id: "validate_booking",
679
+ fields: ['bookingDate', 'guestCount'],
680
+ validator: async (context, data) => {
681
+ const errors = [];
682
+ if (!data.bookingDate) errors.push({ field: 'bookingDate', message: 'Required' });
683
+ if (data.guestCount < 1) errors.push({ field: 'guestCount', message: 'Must be positive' });
684
+
685
+ return {
686
+ valid: errors.length === 0,
687
+ errors
688
+ };
689
+ }
690
+ });
691
+
692
+ agent.addTool(validationTool);
693
+ ```
694
+
695
+ ### API Call Tools
696
+
697
+ For tools that make external API calls:
698
+
699
+ ```typescript
700
+ const apiTool = agent.tool.createApiCall({
701
+ id: "fetch_weather",
702
+ endpoint: "https://api.weather.com/forecast",
703
+ method: "GET",
704
+ headers: { "API-Key": process.env.WEATHER_API_KEY },
705
+ transform: (response) => response.data.forecast
706
+ });
707
+
708
+ agent.tool.register(apiTool);
709
+ ```
710
+
711
+ ### Computation Tools
712
+
713
+ For tools that perform calculations:
714
+
715
+ ```typescript
716
+ const computeTool = agent.tool.createComputation({
717
+ id: "calculate_total",
718
+ inputs: ['price', 'quantity', 'taxRate'],
719
+ compute: async (context, inputs) => {
720
+ const subtotal = inputs.price * inputs.quantity;
721
+ const tax = subtotal * inputs.taxRate;
722
+ return subtotal + tax;
723
+ }
724
+ });
725
+
726
+ agent.addTool(computeTool);
727
+ ```
728
+
729
+ ## Tool Registry and Resolution
730
+
731
+ ### Registry Management
732
+
733
+ ```typescript
734
+ // Register multiple tools at once
735
+ agent.tool.registerMany([
736
+ { id: 'tool1', handler: () => {} },
737
+ { id: 'tool2', handler: () => {} },
738
+ existingToolInstance
739
+ ]);
740
+
741
+ // Check if tool is registered
742
+ if (agent.tool.isRegistered('my_tool')) {
743
+ console.log('Tool is available');
744
+ }
745
+
746
+ // Get all registered tools
747
+ const registeredTools = agent.tool.getRegistered();
748
+ ```
749
+
750
+ ### Tool Resolution
751
+
752
+ Tools are resolved with the following priority:
753
+
754
+ 1. **Step-level inline tools** (highest priority)
755
+ 2. **Step-level tool references** (by ID) → Registry lookup
756
+ 3. **Route-level tools**
757
+ 4. **Agent-level tools**
758
+ 5. **Registered tools** (fallback for unresolved IDs)
759
+
760
+ ```typescript
761
+ // Find tool across all scopes
762
+ const tool = agent.tool.find('my_tool');
763
+
764
+ // Get available tools for current context
765
+ const availableTools = agent.tool.getAvailable();
766
+ ```
767
+
768
+ ## Tools as Step Lifecycle Hooks
769
+
770
+ Tools can be used as `prepare` and `finalize` functions in step lifecycle, enabling powerful data processing and side effects before and after AI responses:
771
+
772
+ ### Using Tools for Step Preparation
773
+
774
+ ```typescript
775
+ // Create a preparation tool
776
+ agent.addTool({
777
+ id: "validate_user_data",
778
+ name: "User Data Validator",
779
+ description: "Validate user data before processing",
780
+ parameters: { type: "object", properties: {} },
781
+ handler: async ({ context, data, updateData }) => {
782
+ // Validation logic with helper methods
783
+ if (!data.email?.includes("@")) {
784
+ throw new Error("Invalid email address");
785
+ }
786
+
787
+ // Mark as validated using helper method
788
+ await updateData({ emailValidated: true });
789
+
790
+ return "User validation completed successfully";
791
+ },
792
+ });
793
+
794
+ // Use tool as prepare hook
795
+ const step = route.initialStep.nextStep({
796
+ id: "collect_info",
797
+ description: "Collect user information",
798
+ collect: ["name", "email"],
799
+ prompt: "Please provide your name and email.",
800
+ prepare: "validate_user_data", // Tool ID string - executes before AI response
801
+ });
802
+ ```
803
+
804
+ ### Using Tools for Step Finalization
805
+
806
+ ```typescript
807
+ // Create a finalization tool with ToolResult pattern
808
+ agent.addTool({
809
+ id: "send_welcome_email",
810
+ name: "Welcome Email Sender",
811
+ description: "Send welcome email after data collection",
812
+ parameters: { type: "object", properties: {} },
813
+ handler: async ({ context, data }) => {
814
+ const emailResult = await emailService.sendWelcome(data.email, data.name);
815
+
816
+ return {
817
+ data: `Welcome email sent to ${data.email}`,
818
+ success: emailResult.success,
819
+ contextUpdate: {
820
+ lastEmailSent: new Date().toISOString(),
821
+ emailsSent: (context.emailsSent || 0) + 1
822
+ }
823
+ };
824
+ },
825
+ });
826
+
827
+ // Use tool as finalize hook
828
+ const welcomeStep = route.initialStep.nextStep({
829
+ id: "send_welcome",
830
+ description: "Send welcome email",
831
+ prompt: "Welcome! Check your email for confirmation.",
832
+ finalize: "send_welcome_email", // Tool ID string - executes after AI response
833
+ });
834
+ ```
835
+
836
+ ### Multiple Lifecycle Approaches
837
+
838
+ Tools can be used in step lifecycle in several ways:
839
+
840
+ ```typescript
841
+ // Method 1: Tool ID reference (most common)
842
+ const step1 = route.initialStep.nextStep({
843
+ prompt: "Processing your request...",
844
+ prepare: "setup_processing", // References registered tool by ID
845
+ finalize: "cleanup_processing", // References registered tool by ID
846
+ });
847
+
848
+ // Method 2: Inline tool definition
849
+ const step2 = route.initialStep.nextStep({
850
+ prompt: "Validating your information...",
851
+ prepare: {
852
+ id: "inline_validator",
853
+ description: "Validate data inline",
854
+ handler: async ({ context, data }) => {
855
+ // Inline validation logic
856
+ return data.isValid ? "Validation passed" : "Validation failed";
857
+ }
858
+ }
859
+ });
860
+
861
+ // Method 3: Function reference (traditional approach)
862
+ const step3 = route.initialStep.nextStep({
863
+ prompt: "Setting up your account...",
864
+ prepare: async (context, data) => {
865
+ // Traditional function approach
866
+ console.log("Preparing account setup...");
867
+ },
868
+ finalize: async (context, data) => {
869
+ // Traditional function approach
870
+ console.log("Account setup complete");
871
+ }
872
+ });
873
+ ```
874
+
875
+ ### Advanced Lifecycle Tool Patterns
876
+
877
+ ```typescript
878
+ // Data enrichment during preparation
879
+ agent.addTool({
880
+ id: "enrich_user_context",
881
+ description: "Enrich user context before processing",
882
+ handler: async ({ context, data, updateContext, updateData }) => {
883
+ // Fetch additional user data
884
+ const userProfile = await userService.getProfile(context.userId);
885
+ const preferences = await userService.getPreferences(context.userId);
886
+
887
+ // Update context with enriched data
888
+ await updateContext({
889
+ userProfile,
890
+ preferences,
891
+ lastEnrichment: new Date().toISOString()
892
+ });
893
+
894
+ // Update collected data
895
+ await updateData({
896
+ userTier: userProfile.tier,
897
+ preferredLanguage: preferences.language
898
+ });
899
+
900
+ return {
901
+ data: "User context enriched successfully",
902
+ contextUpdate: { enrichmentComplete: true }
903
+ };
904
+ }
905
+ });
906
+
907
+ // Audit logging during finalization
908
+ agent.addTool({
909
+ id: "audit_step_completion",
910
+ description: "Log step completion for audit trail",
911
+ handler: async ({ context, data }) => {
912
+ await auditService.logStepCompletion({
913
+ userId: context.userId,
914
+ stepId: context.currentStep,
915
+ timestamp: new Date(),
916
+ collectedData: data
917
+ });
918
+
919
+ return "Step completion logged";
920
+ }
921
+ });
922
+
923
+ // Use in step with both prepare and finalize
924
+ const auditedStep = route.initialStep.nextStep({
925
+ prompt: "Processing your secure transaction...",
926
+ prepare: "enrich_user_context",
927
+ finalize: "audit_step_completion",
928
+ collect: ["transactionAmount", "recipientAccount"]
929
+ });
930
+ ```
931
+
932
+ ### Benefits of Tool-Based Lifecycle Hooks
933
+
934
+ - ✅ **Reusable Logic** - Tools can be shared across steps and routes
935
+ - ✅ **Error Handling** - Tool execution includes automatic error handling
936
+ - ✅ **Context Access** - Tools receive full context and collected data
937
+ - ✅ **Data Updates** - Tools can modify collected data or agent context
938
+ - ✅ **Flexible Returns** - Support both simple returns and complex ToolResult objects
939
+ - ✅ **Type Safety** - Full TypeScript support with automatic inference
940
+ - ✅ **Registry Integration** - Reference tools by ID for consistency
941
+
942
+ ### Lifecycle Execution Order
943
+
944
+ When using tools in step lifecycle:
945
+
946
+ 1. **Prepare Phase**: Tool executes before AI response generation
947
+ 2. **AI Response**: Agent generates response based on enriched context/data
948
+ 3. **Finalize Phase**: Tool executes after AI response, can process results
949
+
950
+ ```typescript
951
+ const lifecycleStep = route.initialStep.nextStep({
952
+ prompt: "Let me process your request...",
953
+ prepare: "setup_processing", // 1. Executes first
954
+ // 2. AI generates response using enriched context
955
+ finalize: "complete_processing", // 3. Executes last
956
+ });
957
+ ```
958
+
338
959
  ## Best Practices
339
960
 
961
+ - **Use pattern helpers** - Leverage built-in helpers for common patterns
962
+ - **Register reusable tools** - Use registry for tools referenced across multiple steps
340
963
  - **Keep tools focused** - Each tool should do one thing well
341
964
  - **Use descriptive names** - Tool names should be clear and specific
342
965
  - **Handle errors gracefully** - Provide meaningful error messages
343
- - **Leverage context updates** - Use context to maintain conversation state
966
+ - **Leverage helper methods** - Use `updateContext`, `updateData`, `getField`, etc.
344
967
  - **Validate parameters** - Use JSON Schema constraints effectively
345
968
  - **Consider performance** - Avoid long-running operations when possible
346
969
  - **Document thoroughly** - Provide clear descriptions for AI usage
970
+ - **Use lifecycle hooks** - Leverage prepare/finalize for setup and cleanup logic