@botpress/adk-cli 1.19.0-beta.3 → 1.19.0-beta.5

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 (81) hide show
  1. package/assets/ui-dist/assets/{index-CSTz-oTK.js → index-B3b7PPgV.js} +4 -4
  2. package/{dist/index-DNqXHLNi-27nvpkee.js → assets/ui-dist/assets/index-BESZeTO5.js} +2 -2
  3. package/{dist/index-DAztRXeA-vr85xnxs.css → assets/ui-dist/assets/index-DIFGtVmI.css} +1 -1
  4. package/{dist/index-DfjXY3Oo-szsanhnt.js → assets/ui-dist/assets/index-a3ZL0_Jr.js} +2 -2
  5. package/assets/ui-dist/index.html +2 -2
  6. package/dist/{README-wjb7z7f0.md → README-824wa4jj.md} +1 -1
  7. package/dist/SKILL-75ym6tcj.md +257 -0
  8. package/dist/SKILL-chnwzmt1.md +548 -0
  9. package/dist/SKILL-d4bs53y3.md +244 -0
  10. package/dist/SKILL-h4b2f1n9.md +114 -0
  11. package/dist/SKILL-hbw5nt95.md +111 -0
  12. package/dist/actions-h7hxxvxr.md +823 -0
  13. package/dist/adk-build-emhwd0tg.md +39 -0
  14. package/dist/adk-debug-yrrdtpmb.md +23 -0
  15. package/dist/adk-dev-console-7z9rtjpy.md +17 -0
  16. package/dist/adk-document-ras6zzzh.md +68 -0
  17. package/dist/adk-eval-vx76dwq0.md +17 -0
  18. package/dist/adk-explain-fcsaw852.md +22 -0
  19. package/dist/adk-init-9kmxmbbe.md +30 -0
  20. package/dist/adk-ship-dybzn884.md +29 -0
  21. package/dist/adk-test-xq67savs.md +27 -0
  22. package/dist/adk-validate-1p4skv4m.md +31 -0
  23. package/dist/advanced-patterns-z86m9h1a.md +669 -0
  24. package/dist/agent-config-1aqvkrgf.md +450 -0
  25. package/dist/agent-steps-zj4c1n9t.md +115 -0
  26. package/dist/agent0-assets/skills/adk/SKILL.md +5 -5
  27. package/dist/agent0-assets/skills/adk/references/cli.md +265 -24
  28. package/dist/agent0-assets/skills/adk-debugger/SKILL.md +5 -5
  29. package/dist/agent0-assets/skills/adk-debugger/references/common-failures.md +1 -1
  30. package/dist/agent0-assets/skills/adk-debugger/references/debug-workflow.md +3 -3
  31. package/dist/agent0-assets/skills/adk-debugger/references/traces-and-logs.md +15 -7
  32. package/dist/assets-q7jt8r2q.md +237 -0
  33. package/dist/autonomous-execution-fymc12e5.md +747 -0
  34. package/dist/cli-c31e06yr.md +1334 -0
  35. package/dist/cli.js +963 -548
  36. package/dist/commands.json +24 -3
  37. package/dist/common-failures-ht29w2db.md +231 -0
  38. package/dist/component-registry-bbpw0see.md +43 -0
  39. package/dist/context-api-760cvh0h.md +461 -0
  40. package/dist/conversation-analysis-8ka4nrm4.md +420 -0
  41. package/dist/conversation-lifecycle-4seqqjc1.md +311 -0
  42. package/dist/conversations-gwfvxaee.md +1111 -0
  43. package/dist/custom-components-y5wdgpey.md +167 -0
  44. package/dist/debug-workflow-vz84q80v.md +239 -0
  45. package/dist/desk-k54ktvsd.md +852 -0
  46. package/dist/doc-standards-ck6ax2jd.md +124 -0
  47. package/dist/eval-format-7n9brja4.md +354 -0
  48. package/dist/evals-y1zcr1mc.md +11 -0
  49. package/dist/explain-config-1yaq3zzd.md +424 -0
  50. package/dist/files-dzt0wxn3.md +918 -0
  51. package/dist/{index-gqxgqnyz.html → index-3t354nbw.html} +2 -2
  52. package/dist/{index-CSTz-oTK-mdfh47r8.js → index-B3b7PPgV-zetkb01w.js} +4 -4
  53. package/{assets/ui-dist/assets/index-DNqXHLNi.js → dist/index-BESZeTO5-2rpmcefa.js} +2 -2
  54. package/{assets/ui-dist/assets/index-DAztRXeA.css → dist/index-DIFGtVmI-d4dhjg97.css} +1 -1
  55. package/{assets/ui-dist/assets/index-DfjXY3Oo.js → dist/index-a3ZL0_Jr-q145h35p.js} +2 -2
  56. package/dist/integration-actions-xang7tma.md +659 -0
  57. package/dist/integrations-k5ss07f4.md +266 -0
  58. package/dist/interfaces-6t0bpxs4.md +97 -0
  59. package/dist/knowledge-bases-20rg8p5c.md +456 -0
  60. package/dist/llm-debugging-76ng8rzm.md +209 -0
  61. package/dist/mcp-server-n1asyzhv.md +112 -0
  62. package/dist/messages-gkkg0b54.md +769 -0
  63. package/dist/model-configuration-f273kgd0.md +201 -0
  64. package/dist/multi-agent-dashboard-1mdfjdts.md +70 -0
  65. package/dist/pages-xn18xn73.md +273 -0
  66. package/dist/patterns-mistakes-5vb99dhf.md +469 -0
  67. package/dist/plugins-ttnx8f49.md +280 -0
  68. package/dist/tables-x45t36dd.md +1136 -0
  69. package/dist/tags-46td3qrg.md +516 -0
  70. package/dist/test-patterns-hj47w4nc.md +355 -0
  71. package/dist/testing-workflow-2vkp932f.md +225 -0
  72. package/dist/tools-wk7bq24z.md +581 -0
  73. package/dist/trace-summarization-hdyx1c2e.md +313 -0
  74. package/dist/traces-and-logs-f2kjfh19.md +203 -0
  75. package/dist/triggers-4j2cc86x.md +719 -0
  76. package/dist/ui-server-entry.js +977 -162
  77. package/dist/workflow-steps-mrdrf1c5.md +851 -0
  78. package/dist/workflows-gadx3s69.md +1408 -0
  79. package/dist/zai-agent-reference-e6644aad.md +454 -0
  80. package/dist/zai-complete-guide-mnna5d6f.md +1408 -0
  81. package/package.json +4 -4
@@ -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