@botpress/adk-cli 1.19.0-beta.4 → 1.19.0-beta.6
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/{dist/index-a3ZL0_Jr-q145h35p.js → assets/ui-dist/assets/index-BC_iUF2d.js} +2 -2
- package/assets/ui-dist/assets/index-BxpvDT_K.css +1 -0
- package/{dist/index-BESZeTO5-2rpmcefa.js → assets/ui-dist/assets/index-C7gAokRv.js} +2 -2
- package/assets/ui-dist/assets/{index-B3b7PPgV.js → index-exyr_Djl.js} +424 -424
- package/assets/ui-dist/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/assets/ui-dist/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/assets/ui-dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/assets/ui-dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/assets/ui-dist/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/assets/ui-dist/index.html +2 -2
- package/dist/{README-wjb7z7f0.md → README-824wa4jj.md} +1 -1
- package/dist/SKILL-75ym6tcj.md +257 -0
- package/dist/SKILL-chnwzmt1.md +548 -0
- package/dist/SKILL-d4bs53y3.md +244 -0
- package/dist/SKILL-h4b2f1n9.md +114 -0
- package/dist/SKILL-hbw5nt95.md +111 -0
- package/dist/actions-h7hxxvxr.md +823 -0
- package/dist/adk-build-emhwd0tg.md +39 -0
- package/dist/adk-debug-yrrdtpmb.md +23 -0
- package/dist/adk-dev-console-7z9rtjpy.md +17 -0
- package/dist/adk-document-ras6zzzh.md +68 -0
- package/dist/adk-eval-vx76dwq0.md +17 -0
- package/dist/adk-explain-fcsaw852.md +22 -0
- package/dist/adk-init-9kmxmbbe.md +30 -0
- package/dist/adk-ship-dybzn884.md +29 -0
- package/dist/adk-test-xq67savs.md +27 -0
- package/dist/adk-validate-1p4skv4m.md +31 -0
- package/dist/advanced-patterns-z86m9h1a.md +669 -0
- package/dist/agent-config-1aqvkrgf.md +450 -0
- package/dist/agent-steps-zj4c1n9t.md +115 -0
- package/dist/assets-q7jt8r2q.md +237 -0
- package/dist/autonomous-execution-fymc12e5.md +747 -0
- package/dist/cli-c31e06yr.md +1334 -0
- package/dist/cli.js +4241 -6449
- package/dist/commands.json +25 -4
- package/dist/common-failures-ht29w2db.md +231 -0
- package/dist/component-registry-bbpw0see.md +43 -0
- package/dist/context-api-760cvh0h.md +461 -0
- package/dist/conversation-analysis-8ka4nrm4.md +420 -0
- package/dist/conversation-lifecycle-4seqqjc1.md +311 -0
- package/dist/conversations-gwfvxaee.md +1111 -0
- package/dist/custom-components-y5wdgpey.md +167 -0
- package/dist/debug-workflow-vz84q80v.md +239 -0
- package/dist/desk-k54ktvsd.md +852 -0
- package/dist/doc-standards-ck6ax2jd.md +124 -0
- package/dist/eval-format-7n9brja4.md +354 -0
- package/dist/evals-y1zcr1mc.md +11 -0
- package/dist/explain-config-1yaq3zzd.md +424 -0
- package/dist/files-dzt0wxn3.md +918 -0
- package/dist/{index-3t354nbw.html → index-0qts7wfk.html} +2 -2
- package/{assets/ui-dist/assets/index-a3ZL0_Jr.js → dist/index-BC_iUF2d-3h9mqazs.js} +2 -2
- package/dist/index-BxpvDT_K-62864175.css +1 -0
- package/{assets/ui-dist/assets/index-BESZeTO5.js → dist/index-C7gAokRv-zr7dzkba.js} +2 -2
- package/dist/{index-B3b7PPgV-zetkb01w.js → index-exyr_Djl-ksys08wc.js} +424 -424
- package/dist/integration-actions-xang7tma.md +659 -0
- package/dist/integrations-k5ss07f4.md +266 -0
- package/dist/interfaces-6t0bpxs4.md +97 -0
- package/dist/jetbrains-mono-cyrillic-wght-normal-D73BlboJ-6vpq1jfh.woff2 +0 -0
- package/dist/jetbrains-mono-greek-wght-normal-Bw9x6K1M-jv5dqe09.woff2 +0 -0
- package/dist/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a-h2ysfc3f.woff2 +0 -0
- package/dist/jetbrains-mono-latin-wght-normal-B9CIFXIH-hj2e42wt.woff2 +0 -0
- package/dist/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq-wttk1pwp.woff2 +0 -0
- package/dist/knowledge-bases-20rg8p5c.md +456 -0
- package/dist/llm-debugging-76ng8rzm.md +209 -0
- package/dist/mcp-server-n1asyzhv.md +112 -0
- package/dist/messages-gkkg0b54.md +769 -0
- package/dist/model-configuration-f273kgd0.md +201 -0
- package/dist/multi-agent-dashboard-1mdfjdts.md +70 -0
- package/dist/pages-xn18xn73.md +273 -0
- package/dist/patterns-mistakes-5vb99dhf.md +469 -0
- package/dist/plugins-ttnx8f49.md +280 -0
- package/dist/tables-x45t36dd.md +1136 -0
- package/dist/tags-46td3qrg.md +516 -0
- package/dist/test-patterns-hj47w4nc.md +355 -0
- package/dist/testing-workflow-2vkp932f.md +225 -0
- package/dist/tools-wk7bq24z.md +581 -0
- package/dist/trace-summarization-hdyx1c2e.md +313 -0
- package/dist/traces-and-logs-f2kjfh19.md +203 -0
- package/dist/triggers-4j2cc86x.md +719 -0
- package/dist/ui-server-entry.js +1839 -791
- package/dist/workflow-steps-mrdrf1c5.md +851 -0
- package/dist/workflows-gadx3s69.md +1408 -0
- package/dist/zai-agent-reference-e6644aad.md +454 -0
- package/dist/zai-complete-guide-mnna5d6f.md +1408 -0
- package/package.json +4 -4
- package/assets/ui-dist/assets/index-DIFGtVmI.css +0 -1
- package/dist/index-DIFGtVmI-d4dhjg97.css +0 -1
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
# Tools
|
|
2
|
+
|
|
3
|
+
Tools are functions that AI models can call during conversations to perform actions, retrieve information, or interact with external systems based on user requests.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Tools enable you to:
|
|
8
|
+
- Give AI capabilities like searching, creating records, sending messages
|
|
9
|
+
- Perform actions autonomously based on conversation context
|
|
10
|
+
- Access external APIs and integrations
|
|
11
|
+
- Retrieve and process data for the AI to use
|
|
12
|
+
- Guide AI behavior with signals and structured outputs
|
|
13
|
+
|
|
14
|
+
## File Location
|
|
15
|
+
|
|
16
|
+
- **Location**: `src/tools/*.ts`
|
|
17
|
+
- **Auto-registration**: Available to AI via the `execute()` function
|
|
18
|
+
- **Export pattern**: Both `export const` and `export default` work
|
|
19
|
+
- **`export const`** (Recommended): Enables direct imports and passing to `execute()` as tools
|
|
20
|
+
- **`export default`**: Simpler for single-tool files
|
|
21
|
+
|
|
22
|
+
## Basic Tool Structure
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { Autonomous, z } from "@botpress/runtime";
|
|
26
|
+
|
|
27
|
+
// Option 1: Named export (recommended)
|
|
28
|
+
export const searchDocs = new Autonomous.Tool({
|
|
29
|
+
name: "searchDocs",
|
|
30
|
+
description: "Search documentation for answers to user questions",
|
|
31
|
+
|
|
32
|
+
input: z.object({
|
|
33
|
+
query: z.string().describe("The search query"),
|
|
34
|
+
maxResults: z.number().default(5).describe("Maximum results to return")
|
|
35
|
+
}),
|
|
36
|
+
|
|
37
|
+
output: z.string(),
|
|
38
|
+
|
|
39
|
+
handler: async ({ query, maxResults }) => {
|
|
40
|
+
const results = await searchDocumentation(query, maxResults);
|
|
41
|
+
return results.join("\n\n");
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Option 2: Default export (also valid)
|
|
46
|
+
export default new Autonomous.Tool({
|
|
47
|
+
name: "searchDocs",
|
|
48
|
+
// ... same configuration
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Why use `export const`?**
|
|
53
|
+
- Enables direct imports: `import { searchDocs } from "./tools/searchDocs"`
|
|
54
|
+
- Can pass directly to `execute()`: `tools: [searchDocs]`
|
|
55
|
+
- Better for tool composition and reusability
|
|
56
|
+
|
|
57
|
+
## Tool Properties
|
|
58
|
+
|
|
59
|
+
| Property | Type | Required | Description |
|
|
60
|
+
|----------|------|----------|-------------|
|
|
61
|
+
| **name** | `string` | Yes | Unique TypeScript-compatible identifier |
|
|
62
|
+
| **description** | `string` | Recommended | Helps AI understand when and how to use the tool |
|
|
63
|
+
| **input** | `z.ZodType` | No | Zod schema for input validation (defaults to `z.any()`) |
|
|
64
|
+
| **output** | `z.ZodType` | No | Zod schema for output validation (defaults to `z.any()`) |
|
|
65
|
+
| **handler** | `function` | Yes | Async function implementing tool logic |
|
|
66
|
+
| **aliases** | `string[]` | No | Alternative names the AI can use to call this tool |
|
|
67
|
+
| **metadata** | `Record<string, any>` | No | Custom information for tool categorization |
|
|
68
|
+
| **staticInputValues** | `object` | No | Pre-set parameter values |
|
|
69
|
+
| **retry** | `function` | No | Custom retry logic for failures |
|
|
70
|
+
|
|
71
|
+
## Tool Handler Syntax
|
|
72
|
+
|
|
73
|
+
Tools receive input directly (not wrapped in `{ input }`) and can use global runtime proxies such as `user`, `bot`, `adk`, and `actions`. For optional per-request values like `conversation` or `message`, use the Context API.
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { Autonomous, z, user, adk, context } from "@botpress/runtime";
|
|
77
|
+
|
|
78
|
+
// ✅ Tools can destructure input parameters directly
|
|
79
|
+
export default new Autonomous.Tool({
|
|
80
|
+
name: "createCharacter",
|
|
81
|
+
description: "Create a new character with name and race",
|
|
82
|
+
|
|
83
|
+
input: z.object({
|
|
84
|
+
name: z.string().describe("Character name"),
|
|
85
|
+
race: z.enum(["human", "elf", "dwarf"]),
|
|
86
|
+
background: z.enum(["warrior", "ranger"]).optional()
|
|
87
|
+
}),
|
|
88
|
+
|
|
89
|
+
output: z.string(),
|
|
90
|
+
|
|
91
|
+
// Handler destructures input directly
|
|
92
|
+
handler: async ({ name, race, background }) => {
|
|
93
|
+
// Direct access to user state
|
|
94
|
+
user.state.characterName = name;
|
|
95
|
+
user.state.race = race;
|
|
96
|
+
user.state.background = background;
|
|
97
|
+
|
|
98
|
+
// Use ADK utilities
|
|
99
|
+
const stats = await adk.zai.extract(
|
|
100
|
+
`Create character stats for ${name} the ${race}`,
|
|
101
|
+
z.object({
|
|
102
|
+
courage: z.number().min(0).max(100),
|
|
103
|
+
wisdom: z.number().min(0).max(100)
|
|
104
|
+
})
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
user.state.courage = stats.courage;
|
|
108
|
+
user.state.wisdom = stats.wisdom;
|
|
109
|
+
|
|
110
|
+
return `Created ${name} the ${race}!`;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// ✅ Can also receive input as single parameter
|
|
115
|
+
export const simpleSearch = new Autonomous.Tool({
|
|
116
|
+
name: "search",
|
|
117
|
+
description: "Search knowledge bases",
|
|
118
|
+
input: z.string().describe("The query to search for").min(1).max(1024),
|
|
119
|
+
output: z.string(),
|
|
120
|
+
|
|
121
|
+
handler: async (query) => {
|
|
122
|
+
const results = await performSearch(query);
|
|
123
|
+
return results;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// ✅ Method syntax with context parameter
|
|
128
|
+
export const anotherTool = new Autonomous.Tool({
|
|
129
|
+
name: "anotherTool",
|
|
130
|
+
input: z.object({ param: z.string() }),
|
|
131
|
+
output: z.string(),
|
|
132
|
+
|
|
133
|
+
async handler(input, ctx) {
|
|
134
|
+
// ctx.callId - unique identifier for this execution
|
|
135
|
+
console.log(`Processing call: ${ctx.callId}`);
|
|
136
|
+
return `Processed ${input.param}`;
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Key Differences from Actions:**
|
|
142
|
+
|
|
143
|
+
| Feature | Actions | Tools |
|
|
144
|
+
|---------|---------|-------|
|
|
145
|
+
| Input parameter | `{ input, client }` wrapper | Direct input or destructuring |
|
|
146
|
+
| Context access | Via imports or context API | Via imports (automatically available) |
|
|
147
|
+
| Typical use | Internal functions, any context | AI-callable, conversation context |
|
|
148
|
+
| Handler signature | `handler({ input, client })` | `handler(input, ctx?)` or `handler({ ...fields }, ctx?)` |
|
|
149
|
+
|
|
150
|
+
## Accessing Context in Tools
|
|
151
|
+
|
|
152
|
+
Tools can use global runtime proxies directly, but conversation-specific values should be loaded through `context.get(...)`:
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
import { Autonomous, z, user, bot, adk, actions, context } from "@botpress/runtime";
|
|
156
|
+
|
|
157
|
+
export default new Autonomous.Tool({
|
|
158
|
+
name: "upgradeUser",
|
|
159
|
+
description: "Upgrade user to pro tier",
|
|
160
|
+
input: z.object({}),
|
|
161
|
+
output: z.string(),
|
|
162
|
+
|
|
163
|
+
handler: async (input) => {
|
|
164
|
+
// Direct access to context
|
|
165
|
+
const userName = user.state.name;
|
|
166
|
+
const currentTier = user.tags.tier;
|
|
167
|
+
const conversation = context.get("conversation", { optional: true });
|
|
168
|
+
|
|
169
|
+
// Update user state and tags
|
|
170
|
+
user.tags.tier = "pro";
|
|
171
|
+
bot.state.totalUpgrades += 1;
|
|
172
|
+
|
|
173
|
+
// Call integration actions
|
|
174
|
+
await actions.slack.sendMessage({
|
|
175
|
+
channel: "upgrades",
|
|
176
|
+
text: `${userName} upgraded from ${currentTier} to pro`
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
return `Upgraded ${userName} to pro tier`;
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Commonly used in tools:**
|
|
185
|
+
- `user` - Current user (`.state`, `.tags`)
|
|
186
|
+
- `bot` - Bot object (always available)
|
|
187
|
+
- `adk` - ADK utilities (`adk.zai.extract()`, etc.)
|
|
188
|
+
- `actions` - All available actions
|
|
189
|
+
|
|
190
|
+
Use `context.get("conversation", { optional: true })` or `context.get("message", { optional: true })` when you need those per-request values.
|
|
191
|
+
|
|
192
|
+
For complete context access details including `client`, `citations`, availability rules, and all context keys, see **[Context API](./context-api.md)**.
|
|
193
|
+
|
|
194
|
+
## Using ThinkSignal
|
|
195
|
+
|
|
196
|
+
`ThinkSignal` allows tools to return results with additional instructions for the AI. When thrown, it provides context that guides how the AI should use the information.
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
import { Autonomous, z } from "@botpress/runtime";
|
|
200
|
+
|
|
201
|
+
export default new Autonomous.Tool({
|
|
202
|
+
name: "searchKnowledge",
|
|
203
|
+
description: "Search the knowledge base",
|
|
204
|
+
input: z.string().describe("Search query"),
|
|
205
|
+
output: z.string(),
|
|
206
|
+
|
|
207
|
+
handler: async (query) => {
|
|
208
|
+
const results = await knowledgeBase.search(query);
|
|
209
|
+
|
|
210
|
+
// Handle no results case
|
|
211
|
+
if (!results.length) {
|
|
212
|
+
throw new Autonomous.ThinkSignal(
|
|
213
|
+
"No results found",
|
|
214
|
+
"No results were found. Try rephrasing or ask something else. Do NOT make up an answer."
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Format results for AI consumption
|
|
219
|
+
const formatted = results
|
|
220
|
+
.map((r, i) => `[${i + 1}] ${r.title}\n${r.content}`)
|
|
221
|
+
.join("\n\n");
|
|
222
|
+
|
|
223
|
+
// Return results with instructions for the AI
|
|
224
|
+
throw new Autonomous.ThinkSignal(
|
|
225
|
+
"Search complete - use these results to answer",
|
|
226
|
+
formatted
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**ThinkSignal parameters:**
|
|
233
|
+
- **First argument**: Brief status message for logs
|
|
234
|
+
- **Second argument**: Detailed content/instructions for the AI
|
|
235
|
+
|
|
236
|
+
**When to use ThinkSignal:**
|
|
237
|
+
- Providing search results with guidance
|
|
238
|
+
- Handling edge cases (no results, errors)
|
|
239
|
+
- Guiding AI behavior based on outcomes
|
|
240
|
+
- Passing contextual information to the AI
|
|
241
|
+
|
|
242
|
+
## Advanced Tool Properties
|
|
243
|
+
|
|
244
|
+
### Aliases
|
|
245
|
+
|
|
246
|
+
Provide alternative names for the tool:
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
export default new Autonomous.Tool({
|
|
250
|
+
name: "searchDocumentation",
|
|
251
|
+
aliases: ["search_docs", "findDocs", "lookupDocs"],
|
|
252
|
+
description: "Search documentation",
|
|
253
|
+
handler: async (query) => { /* ... */ }
|
|
254
|
+
});
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Static Input Values
|
|
258
|
+
|
|
259
|
+
Pre-set parameter values for specialized tool variants:
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
const baseSearchTool = new Autonomous.Tool({
|
|
263
|
+
name: "search",
|
|
264
|
+
input: z.object({
|
|
265
|
+
query: z.string(),
|
|
266
|
+
category: z.string()
|
|
267
|
+
}),
|
|
268
|
+
handler: async ({ query, category }) => { /* ... */ }
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// Create specialized version with pre-set category
|
|
272
|
+
const productSearchTool = baseSearchTool.with({
|
|
273
|
+
staticInputValues: { category: "products" }
|
|
274
|
+
});
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Custom Retry Logic
|
|
278
|
+
|
|
279
|
+
Handle failures with custom retry behavior:
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
export default new Autonomous.Tool({
|
|
283
|
+
name: "externalAPI",
|
|
284
|
+
description: "Call external API",
|
|
285
|
+
input: z.object({ endpoint: z.string() }),
|
|
286
|
+
output: z.any(),
|
|
287
|
+
|
|
288
|
+
retry: async ({ input, attempt, error }) => {
|
|
289
|
+
if (attempt < 3 && error?.code === 'RATE_LIMIT') {
|
|
290
|
+
await new Promise(r => setTimeout(r, 1000 * attempt));
|
|
291
|
+
return true; // Retry
|
|
292
|
+
}
|
|
293
|
+
return false; // Don't retry
|
|
294
|
+
},
|
|
295
|
+
|
|
296
|
+
handler: async ({ endpoint }) => {
|
|
297
|
+
const response = await fetch(endpoint);
|
|
298
|
+
return await response.json();
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Autonomous Namespace
|
|
304
|
+
|
|
305
|
+
The `Autonomous` namespace provides types and utilities for AI-powered autonomous execution.
|
|
306
|
+
|
|
307
|
+
### Autonomous.Tool
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
export const Tool = LlmzTool;
|
|
311
|
+
export type Tool = InstanceType<typeof Tool>;
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Autonomous.Model Type
|
|
315
|
+
|
|
316
|
+
Type for specifying AI models:
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
import { defineConfig } from "@botpress/runtime";
|
|
320
|
+
|
|
321
|
+
export default defineConfig({
|
|
322
|
+
name: "my-agent",
|
|
323
|
+
defaultModels: {
|
|
324
|
+
autonomous: "openai:gpt-4o",
|
|
325
|
+
zai: "openai:gpt-4o-mini"
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// With fallback chain
|
|
330
|
+
export default defineConfig({
|
|
331
|
+
defaultModels: {
|
|
332
|
+
autonomous: ["openai:gpt-4o", "anthropic:claude-3-5-sonnet"],
|
|
333
|
+
zai: "openai:gpt-4o-mini"
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**Model format:** `"provider:model-name"`
|
|
339
|
+
|
|
340
|
+
**Common providers:**
|
|
341
|
+
- `openai:gpt-4o`, `openai:gpt-4o-mini`
|
|
342
|
+
- `anthropic:claude-3-5-sonnet`
|
|
343
|
+
- `cerebras:gpt-oss-120b`
|
|
344
|
+
|
|
345
|
+
### Autonomous.Hooks Interface
|
|
346
|
+
|
|
347
|
+
Advanced hooks for controlling AI execution behavior:
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
export type Hooks = {
|
|
351
|
+
onBeforeTool?: (event: {
|
|
352
|
+
iteration: Iteration;
|
|
353
|
+
tool: Autonomous.Tool;
|
|
354
|
+
input: any;
|
|
355
|
+
controller: AbortController;
|
|
356
|
+
}) => Promise<{ input?: any; } | void>;
|
|
357
|
+
|
|
358
|
+
onAfterTool?: (event: {
|
|
359
|
+
iteration: Iteration;
|
|
360
|
+
tool: Autonomous.Tool;
|
|
361
|
+
input: any;
|
|
362
|
+
output: any;
|
|
363
|
+
controller: AbortController;
|
|
364
|
+
}) => Promise<{ output?: any; } | void>;
|
|
365
|
+
|
|
366
|
+
onBeforeExecution?: (
|
|
367
|
+
iteration: Iteration,
|
|
368
|
+
controller: AbortController
|
|
369
|
+
) => Promise<{ code?: string; } | void>;
|
|
370
|
+
|
|
371
|
+
onExit?: <T = unknown>(result: ExitResult<T>) => Promise<void> | void;
|
|
372
|
+
|
|
373
|
+
onTrace?: (props: { trace: Trace; iteration: number }) => void;
|
|
374
|
+
|
|
375
|
+
onIterationEnd?: (
|
|
376
|
+
iteration: Iteration,
|
|
377
|
+
controller: IterationController
|
|
378
|
+
) => void | Promise<void>;
|
|
379
|
+
};
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
**Example - Logging tool calls:**
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
await execute({
|
|
386
|
+
instructions: "Help the user",
|
|
387
|
+
tools: [searchTool, createTicketTool],
|
|
388
|
+
hooks: {
|
|
389
|
+
onBeforeTool: async ({ tool, input }) => {
|
|
390
|
+
console.log(`Calling tool: ${tool.name}`, input);
|
|
391
|
+
},
|
|
392
|
+
onAfterTool: async ({ tool, output }) => {
|
|
393
|
+
console.log(`Tool ${tool.name} returned:`, output);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
**Example - Modifying tool inputs:**
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
await execute({
|
|
403
|
+
instructions: "Search for information",
|
|
404
|
+
tools: [searchTool],
|
|
405
|
+
hooks: {
|
|
406
|
+
onBeforeTool: async ({ tool, input }) => {
|
|
407
|
+
if (tool.name === "search") {
|
|
408
|
+
return {
|
|
409
|
+
input: {
|
|
410
|
+
...input,
|
|
411
|
+
query: `${input.query} site:docs.example.com`
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### Autonomous.Exit - Structured AI Exits
|
|
421
|
+
|
|
422
|
+
Exits provide type-safe, structured ways for AI to return different outcomes:
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
import { Autonomous, z } from "@botpress/runtime";
|
|
426
|
+
|
|
427
|
+
const SearchExit = new Autonomous.Exit({
|
|
428
|
+
name: "search_complete",
|
|
429
|
+
description: "Search completed successfully",
|
|
430
|
+
schema: z.object({
|
|
431
|
+
results: z.array(z.string()),
|
|
432
|
+
count: z.number()
|
|
433
|
+
})
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
const NoResultsExit = new Autonomous.Exit({
|
|
437
|
+
name: "no_results",
|
|
438
|
+
description: "No results found for the query"
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
// Use exits in execute()
|
|
442
|
+
const result = await execute({
|
|
443
|
+
instructions: "Search and return appropriate exit",
|
|
444
|
+
exits: [SearchExit, NoResultsExit]
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
// Type-safe handling
|
|
448
|
+
if (result.is(SearchExit)) {
|
|
449
|
+
console.log(`Found ${result.output.count} results`);
|
|
450
|
+
} else if (result.is(NoResultsExit)) {
|
|
451
|
+
console.log("No results found");
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Other Autonomous Exports
|
|
456
|
+
|
|
457
|
+
**Signal Classes:**
|
|
458
|
+
```typescript
|
|
459
|
+
export const ThinkSignal = _ThinkSignal;
|
|
460
|
+
export const SnapshotSignal = _SnapshotSignal;
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
**Type Exports:**
|
|
464
|
+
```typescript
|
|
465
|
+
export type Iteration = InstanceType<typeof LlmzIteration>;
|
|
466
|
+
export type ExecuteResult = Awaited<ReturnType<Execute>>;
|
|
467
|
+
export type Trace = /* various trace types */;
|
|
468
|
+
export type IterationController = /* controller interface */;
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
> **Note:** See [Using ThinkSignal](#using-thinksignal) section for detailed usage examples.
|
|
472
|
+
|
|
473
|
+
## Best Practices
|
|
474
|
+
|
|
475
|
+
1. **Clear descriptions**: Help AI understand when to use the tool
|
|
476
|
+
2. **Use `.describe()` on inputs**: Clarify parameter purposes for AI
|
|
477
|
+
3. **Provide context in output**: Return informative strings or objects
|
|
478
|
+
4. **Handle edge cases**: Use ThinkSignal for no-result or error scenarios
|
|
479
|
+
5. **Keep handlers focused**: One tool = one capability
|
|
480
|
+
6. **Test independently**: Tools can be tested outside of conversations
|
|
481
|
+
|
|
482
|
+
**Example - Production-Ready Tool:**
|
|
483
|
+
|
|
484
|
+
```typescript
|
|
485
|
+
export default new Autonomous.Tool({
|
|
486
|
+
name: "createSupportTicket",
|
|
487
|
+
description: "Create a support ticket for user issues or requests",
|
|
488
|
+
|
|
489
|
+
input: z.object({
|
|
490
|
+
title: z.string()
|
|
491
|
+
.min(5)
|
|
492
|
+
.max(100)
|
|
493
|
+
.describe("Brief ticket title"),
|
|
494
|
+
description: z.string()
|
|
495
|
+
.min(10)
|
|
496
|
+
.max(2000)
|
|
497
|
+
.describe("Detailed issue description"),
|
|
498
|
+
priority: z.enum(["low", "medium", "high", "urgent"])
|
|
499
|
+
.default("medium")
|
|
500
|
+
.describe("Ticket priority level"),
|
|
501
|
+
category: z.enum(["bug", "feature", "question", "other"])
|
|
502
|
+
.describe("Issue category")
|
|
503
|
+
}),
|
|
504
|
+
|
|
505
|
+
output: z.object({
|
|
506
|
+
ticketId: z.string(),
|
|
507
|
+
url: z.string()
|
|
508
|
+
}),
|
|
509
|
+
|
|
510
|
+
handler: async ({ title, description, priority, category }) => {
|
|
511
|
+
// Validate user has permission
|
|
512
|
+
if (user.tags.tier === "free" && priority === "urgent") {
|
|
513
|
+
throw new ThinkSignal(
|
|
514
|
+
"Priority upgrade needed",
|
|
515
|
+
"Urgent priority is only available for premium users. Would you like to upgrade?"
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// Create ticket with context
|
|
520
|
+
const ticket = await actions.helpdesk.createTicket({
|
|
521
|
+
title,
|
|
522
|
+
description: `User: ${user.id}\nCategory: ${category}\n\n${description}`,
|
|
523
|
+
priority,
|
|
524
|
+
metadata: {
|
|
525
|
+
userId: user.id,
|
|
526
|
+
conversationId: conversation?.id
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
// Update user state
|
|
531
|
+
user.state.lastTicketId = ticket.id;
|
|
532
|
+
user.state.lastTicketCreated = new Date().toISOString();
|
|
533
|
+
|
|
534
|
+
return {
|
|
535
|
+
ticketId: ticket.id,
|
|
536
|
+
url: `https://support.example.com/ticket/${ticket.id}`
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
## Troubleshooting
|
|
543
|
+
|
|
544
|
+
### Common Issues
|
|
545
|
+
|
|
546
|
+
1. **Tool not available to AI**
|
|
547
|
+
- Check file is in `src/tools/` directory
|
|
548
|
+
- Ensure tool is exported as default or named export
|
|
549
|
+
- Verify tool is included in `execute()` tools array
|
|
550
|
+
|
|
551
|
+
2. **"user is not defined" or context errors**
|
|
552
|
+
- **Cause**: Trying to access conversation context outside of conversation
|
|
553
|
+
- **Solution**: Use optional chaining (`user?.state`) or `context.get("user", { optional: true })`
|
|
554
|
+
- **Note**: Tools are typically called from conversations, so context is usually available
|
|
555
|
+
|
|
556
|
+
3. **Type errors with inputs/outputs**
|
|
557
|
+
- Verify Zod schemas match actual data
|
|
558
|
+
- Use `.optional()` for optional fields
|
|
559
|
+
- Check for typos in property names
|
|
560
|
+
|
|
561
|
+
4. **State properties undefined**
|
|
562
|
+
- **Cause**: State properties must be defined in `agent.config.ts` schemas
|
|
563
|
+
- **Solution**: Add properties to `user.state` or `bot.state` schema in config
|
|
564
|
+
|
|
565
|
+
5. **AI not calling tool correctly**
|
|
566
|
+
- Improve tool `description` to clarify when it should be used
|
|
567
|
+
- Add detailed `.describe()` to all input parameters
|
|
568
|
+
- Use clear, descriptive parameter names
|
|
569
|
+
- Consider using ThinkSignal to guide AI behavior
|
|
570
|
+
|
|
571
|
+
6. **ThinkSignal not working as expected**
|
|
572
|
+
- **Issue**: ThinkSignal must be thrown, not returned
|
|
573
|
+
- **Wrong**: `return new ThinkSignal(...)`
|
|
574
|
+
- **Correct**: `throw new ThinkSignal(...)`
|
|
575
|
+
|
|
576
|
+
## See Also
|
|
577
|
+
|
|
578
|
+
- [Actions](./actions.md) - Strongly-typed internal functions
|
|
579
|
+
- [Conversations](./conversations.md) - Using tools in conversation handlers
|
|
580
|
+
- [Autonomous Execution](./autonomous-execution.md) - Objects, Exits, hooks, and full `execute()` API
|
|
581
|
+
- [Context API](./context-api.md) - Access runtime context and services
|