@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
|
@@ -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.
|
|
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
|
-
|
|
7
|
+
The unified Tool system provides:
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
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
|
|
16
|
+
## Unified Tool Interface
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
All tools use the same interface regardless of complexity:
|
|
17
19
|
|
|
18
20
|
```typescript
|
|
19
|
-
|
|
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
|
-
|
|
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",
|
|
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 ({
|
|
34
|
-
const weather = await weatherAPI.getForecast(location, date);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
110
|
+
### 2. Advanced ToolResult Pattern
|
|
47
111
|
|
|
48
|
-
|
|
112
|
+
For complex scenarios requiring detailed control:
|
|
49
113
|
|
|
50
114
|
```typescript
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
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
|
-
|
|
264
|
+
### 7. Pattern Helpers
|
|
60
265
|
|
|
61
|
-
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
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 ({
|
|
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
|
|
105
|
-
|
|
106
|
-
Tools receive execution context including:
|
|
364
|
+
## Simplified Tool Context
|
|
107
365
|
|
|
108
|
-
|
|
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
|
-
|
|
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 (
|
|
126
|
-
//
|
|
127
|
-
const currentUserId =
|
|
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
|
|
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
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
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
|
-
|
|
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
|
|
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
|