signalwire-agents 0.1.0
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/CLAUDE.md +112 -0
- package/README.md +417 -0
- package/dist/AgentBase.d.ts +481 -0
- package/dist/AgentBase.js +1155 -0
- package/dist/AgentBase.js.map +1 -0
- package/dist/AgentServer.d.ts +60 -0
- package/dist/AgentServer.js +128 -0
- package/dist/AgentServer.js.map +1 -0
- package/dist/AuthHandler.d.ts +56 -0
- package/dist/AuthHandler.js +119 -0
- package/dist/AuthHandler.js.map +1 -0
- package/dist/ConfigLoader.d.ts +68 -0
- package/dist/ConfigLoader.js +150 -0
- package/dist/ConfigLoader.js.map +1 -0
- package/dist/ContextBuilder.d.ts +431 -0
- package/dist/ContextBuilder.js +751 -0
- package/dist/ContextBuilder.js.map +1 -0
- package/dist/DataMap.d.ts +179 -0
- package/dist/DataMap.js +321 -0
- package/dist/DataMap.js.map +1 -0
- package/dist/Logger.d.ts +91 -0
- package/dist/Logger.js +191 -0
- package/dist/Logger.js.map +1 -0
- package/dist/PomBuilder.d.ts +144 -0
- package/dist/PomBuilder.js +249 -0
- package/dist/PomBuilder.js.map +1 -0
- package/dist/PromptManager.d.ts +85 -0
- package/dist/PromptManager.js +108 -0
- package/dist/PromptManager.js.map +1 -0
- package/dist/SchemaUtils.d.ts +42 -0
- package/dist/SchemaUtils.js +148 -0
- package/dist/SchemaUtils.js.map +1 -0
- package/dist/ServerlessAdapter.d.ts +100 -0
- package/dist/ServerlessAdapter.js +166 -0
- package/dist/ServerlessAdapter.js.map +1 -0
- package/dist/SessionManager.d.ts +86 -0
- package/dist/SessionManager.js +155 -0
- package/dist/SessionManager.js.map +1 -0
- package/dist/SslConfig.d.ts +77 -0
- package/dist/SslConfig.js +100 -0
- package/dist/SslConfig.js.map +1 -0
- package/dist/SwaigFunction.d.ts +88 -0
- package/dist/SwaigFunction.js +125 -0
- package/dist/SwaigFunction.js.map +1 -0
- package/dist/SwaigFunctionResult.d.ts +442 -0
- package/dist/SwaigFunctionResult.js +735 -0
- package/dist/SwaigFunctionResult.js.map +1 -0
- package/dist/SwmlBuilder.d.ts +37 -0
- package/dist/SwmlBuilder.js +55 -0
- package/dist/SwmlBuilder.js.map +1 -0
- package/dist/cli/agent-loader.d.ts +22 -0
- package/dist/cli/agent-loader.js +106 -0
- package/dist/cli/agent-loader.js.map +1 -0
- package/dist/cli/mock-data.d.ts +37 -0
- package/dist/cli/mock-data.js +79 -0
- package/dist/cli/mock-data.js.map +1 -0
- package/dist/cli/swaig-test.d.ts +32 -0
- package/dist/cli/swaig-test.js +405 -0
- package/dist/cli/swaig-test.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/prefabs/ConciergeAgent.d.ts +64 -0
- package/dist/prefabs/ConciergeAgent.js +188 -0
- package/dist/prefabs/ConciergeAgent.js.map +1 -0
- package/dist/prefabs/FAQBotAgent.d.ts +68 -0
- package/dist/prefabs/FAQBotAgent.js +206 -0
- package/dist/prefabs/FAQBotAgent.js.map +1 -0
- package/dist/prefabs/InfoGathererAgent.d.ts +73 -0
- package/dist/prefabs/InfoGathererAgent.js +202 -0
- package/dist/prefabs/InfoGathererAgent.js.map +1 -0
- package/dist/prefabs/ReceptionistAgent.d.ts +65 -0
- package/dist/prefabs/ReceptionistAgent.js +205 -0
- package/dist/prefabs/ReceptionistAgent.js.map +1 -0
- package/dist/prefabs/SurveyAgent.d.ts +84 -0
- package/dist/prefabs/SurveyAgent.js +324 -0
- package/dist/prefabs/SurveyAgent.js.map +1 -0
- package/dist/prefabs/index.d.ts +13 -0
- package/dist/prefabs/index.js +14 -0
- package/dist/prefabs/index.js.map +1 -0
- package/dist/skills/SkillBase.d.ts +134 -0
- package/dist/skills/SkillBase.js +105 -0
- package/dist/skills/SkillBase.js.map +1 -0
- package/dist/skills/SkillManager.d.ts +83 -0
- package/dist/skills/SkillManager.js +159 -0
- package/dist/skills/SkillManager.js.map +1 -0
- package/dist/skills/SkillRegistry.d.ts +105 -0
- package/dist/skills/SkillRegistry.js +195 -0
- package/dist/skills/SkillRegistry.js.map +1 -0
- package/dist/skills/builtin/api_ninjas_trivia.d.ts +35 -0
- package/dist/skills/builtin/api_ninjas_trivia.js +161 -0
- package/dist/skills/builtin/api_ninjas_trivia.js.map +1 -0
- package/dist/skills/builtin/claude_skills.d.ts +34 -0
- package/dist/skills/builtin/claude_skills.js +156 -0
- package/dist/skills/builtin/claude_skills.js.map +1 -0
- package/dist/skills/builtin/custom_skills.d.ts +59 -0
- package/dist/skills/builtin/custom_skills.js +231 -0
- package/dist/skills/builtin/custom_skills.js.map +1 -0
- package/dist/skills/builtin/datasphere.d.ts +34 -0
- package/dist/skills/builtin/datasphere.js +163 -0
- package/dist/skills/builtin/datasphere.js.map +1 -0
- package/dist/skills/builtin/datasphere_serverless.d.ts +54 -0
- package/dist/skills/builtin/datasphere_serverless.js +155 -0
- package/dist/skills/builtin/datasphere_serverless.js.map +1 -0
- package/dist/skills/builtin/datetime.d.ts +31 -0
- package/dist/skills/builtin/datetime.js +95 -0
- package/dist/skills/builtin/datetime.js.map +1 -0
- package/dist/skills/builtin/google_maps.d.ts +33 -0
- package/dist/skills/builtin/google_maps.js +233 -0
- package/dist/skills/builtin/google_maps.js.map +1 -0
- package/dist/skills/builtin/index.d.ts +28 -0
- package/dist/skills/builtin/index.js +75 -0
- package/dist/skills/builtin/index.js.map +1 -0
- package/dist/skills/builtin/info_gatherer.d.ts +52 -0
- package/dist/skills/builtin/info_gatherer.js +237 -0
- package/dist/skills/builtin/info_gatherer.js.map +1 -0
- package/dist/skills/builtin/joke.d.ts +32 -0
- package/dist/skills/builtin/joke.js +142 -0
- package/dist/skills/builtin/joke.js.map +1 -0
- package/dist/skills/builtin/math.d.ts +33 -0
- package/dist/skills/builtin/math.js +120 -0
- package/dist/skills/builtin/math.js.map +1 -0
- package/dist/skills/builtin/mcp_gateway.d.ts +35 -0
- package/dist/skills/builtin/mcp_gateway.js +85 -0
- package/dist/skills/builtin/mcp_gateway.js.map +1 -0
- package/dist/skills/builtin/native_vector_search.d.ts +44 -0
- package/dist/skills/builtin/native_vector_search.js +248 -0
- package/dist/skills/builtin/native_vector_search.js.map +1 -0
- package/dist/skills/builtin/play_background_file.d.ts +34 -0
- package/dist/skills/builtin/play_background_file.js +135 -0
- package/dist/skills/builtin/play_background_file.js.map +1 -0
- package/dist/skills/builtin/spider.d.ts +34 -0
- package/dist/skills/builtin/spider.js +164 -0
- package/dist/skills/builtin/spider.js.map +1 -0
- package/dist/skills/builtin/swml_transfer.d.ts +44 -0
- package/dist/skills/builtin/swml_transfer.js +204 -0
- package/dist/skills/builtin/swml_transfer.js.map +1 -0
- package/dist/skills/builtin/weather_api.d.ts +34 -0
- package/dist/skills/builtin/weather_api.js +136 -0
- package/dist/skills/builtin/weather_api.js.map +1 -0
- package/dist/skills/builtin/web_search.d.ts +34 -0
- package/dist/skills/builtin/web_search.js +141 -0
- package/dist/skills/builtin/web_search.js.map +1 -0
- package/dist/skills/builtin/wikipedia_search.d.ts +34 -0
- package/dist/skills/builtin/wikipedia_search.js +166 -0
- package/dist/skills/builtin/wikipedia_search.js.map +1 -0
- package/dist/skills/index.d.ts +11 -0
- package/dist/skills/index.js +10 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/types.d.ts +85 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/docs/agent-guide.md +869 -0
- package/docs/api-reference.md +2419 -0
- package/docs/architecture.md +843 -0
- package/docs/cli-guide.md +579 -0
- package/docs/configuration.md +422 -0
- package/docs/contexts-guide.md +787 -0
- package/docs/datamap-guide.md +1141 -0
- package/docs/prefabs-guide.md +830 -0
- package/docs/security.md +436 -0
- package/docs/serverless-guide.md +513 -0
- package/docs/skills-guide.md +845 -0
- package/docs/swaig-reference.md +1627 -0
- package/examples/call-flow.ts +60 -0
- package/examples/contexts-steps.ts +62 -0
- package/examples/datamap-tools.ts +52 -0
- package/examples/dynamic-config.ts +51 -0
- package/examples/multi-agent.ts +67 -0
- package/examples/pom-prompt.ts +68 -0
- package/examples/simple-agent.ts +33 -0
- package/package.json +35 -0
- package/src/AgentBase.ts +1279 -0
- package/src/AgentServer.ts +149 -0
- package/src/AuthHandler.ts +141 -0
- package/src/ConfigLoader.ts +165 -0
- package/src/ContextBuilder.ts +796 -0
- package/src/DataMap.ts +365 -0
- package/src/Logger.ts +197 -0
- package/src/PomBuilder.ts +298 -0
- package/src/PromptManager.ts +133 -0
- package/src/SchemaUtils.ts +170 -0
- package/src/ServerlessAdapter.ts +218 -0
- package/src/SessionManager.ts +161 -0
- package/src/SslConfig.ts +118 -0
- package/src/SwaigFunction.ts +168 -0
- package/src/SwaigFunctionResult.ts +864 -0
- package/src/SwmlBuilder.ts +62 -0
- package/src/cli/agent-loader.ts +122 -0
- package/src/cli/mock-data.ts +110 -0
- package/src/cli/swaig-test.ts +440 -0
- package/src/index.ts +99 -0
- package/src/prefabs/ConciergeAgent.ts +251 -0
- package/src/prefabs/FAQBotAgent.ts +263 -0
- package/src/prefabs/InfoGathererAgent.ts +276 -0
- package/src/prefabs/ReceptionistAgent.ts +277 -0
- package/src/prefabs/SurveyAgent.ts +413 -0
- package/src/prefabs/index.ts +23 -0
- package/src/skills/SkillBase.ts +184 -0
- package/src/skills/SkillManager.ts +177 -0
- package/src/skills/SkillRegistry.ts +231 -0
- package/src/skills/builtin/api_ninjas_trivia.ts +230 -0
- package/src/skills/builtin/claude_skills.ts +239 -0
- package/src/skills/builtin/custom_skills.ts +326 -0
- package/src/skills/builtin/datasphere.ts +225 -0
- package/src/skills/builtin/datasphere_serverless.ts +194 -0
- package/src/skills/builtin/datetime.ts +115 -0
- package/src/skills/builtin/google_maps.ts +347 -0
- package/src/skills/builtin/index.ts +79 -0
- package/src/skills/builtin/info_gatherer.ts +331 -0
- package/src/skills/builtin/joke.ts +180 -0
- package/src/skills/builtin/math.ts +150 -0
- package/src/skills/builtin/mcp_gateway.ts +99 -0
- package/src/skills/builtin/native_vector_search.ts +327 -0
- package/src/skills/builtin/play_background_file.ts +189 -0
- package/src/skills/builtin/spider.ts +232 -0
- package/src/skills/builtin/swml_transfer.ts +285 -0
- package/src/skills/builtin/weather_api.ts +193 -0
- package/src/skills/builtin/web_search.ts +212 -0
- package/src/skills/builtin/wikipedia_search.ts +248 -0
- package/src/skills/index.ts +12 -0
- package/src/types.ts +99 -0
- package/tests/AgentBase.test.ts +693 -0
- package/tests/AgentServer.test.ts +102 -0
- package/tests/AuthHandler.test.ts +121 -0
- package/tests/ConfigLoader.test.ts +121 -0
- package/tests/DataMap.test.ts +286 -0
- package/tests/Logger.test.ts +218 -0
- package/tests/PomBuilder.test.ts +164 -0
- package/tests/ProxyDetection.test.ts +185 -0
- package/tests/SchemaUtils.test.ts +106 -0
- package/tests/ServerlessAdapter.test.ts +200 -0
- package/tests/SessionManager.test.ts +139 -0
- package/tests/SslConfig.test.ts +97 -0
- package/tests/SwaigFunctionResult.test.ts +298 -0
- package/tests/cli/mock-data.test.ts +94 -0
- package/tests/cli/swaig-test.test.ts +96 -0
- package/tests/prefabs/prefabs.test.ts +854 -0
- package/tests/setup.ts +6 -0
- package/tests/skills/SkillBase.test.ts +118 -0
- package/tests/skills/SkillManager.test.ts +164 -0
- package/tests/skills/SkillRegistry.test.ts +124 -0
- package/tests/skills/builtin.test.ts +924 -0
- package/tsconfig.json +18 -0
- package/vitest.config.ts +9 -0
|
@@ -0,0 +1,1141 @@
|
|
|
1
|
+
# DataMap Guide
|
|
2
|
+
|
|
3
|
+
Comprehensive guide to the `DataMap` class in the SignalWire AI Agents TypeScript SDK.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Overview](#overview)
|
|
10
|
+
- [Creating a DataMap](#creating-a-datamap)
|
|
11
|
+
- [Configuration](#configuration)
|
|
12
|
+
- [purpose / description](#purpose--description)
|
|
13
|
+
- [parameter](#parameter)
|
|
14
|
+
- [Webhooks](#webhooks)
|
|
15
|
+
- [webhook](#webhook)
|
|
16
|
+
- [body](#body)
|
|
17
|
+
- [params](#params)
|
|
18
|
+
- [Webhook Headers](#webhook-headers)
|
|
19
|
+
- [Expressions](#expressions)
|
|
20
|
+
- [expression](#expression)
|
|
21
|
+
- [Response Processing](#response-processing)
|
|
22
|
+
- [output](#output)
|
|
23
|
+
- [webhookExpressions](#webhookexpressions)
|
|
24
|
+
- [Error Handling](#error-handling)
|
|
25
|
+
- [fallbackOutput](#fallbackoutput)
|
|
26
|
+
- [errorKeys](#errorkeys)
|
|
27
|
+
- [globalErrorKeys](#globalerrorkeys)
|
|
28
|
+
- [Iteration](#iteration)
|
|
29
|
+
- [foreach](#foreach)
|
|
30
|
+
- [Environment Variables](#environment-variables)
|
|
31
|
+
- [enableEnvExpansion](#enableenvexpansion)
|
|
32
|
+
- [Registration](#registration)
|
|
33
|
+
- [registerWithAgent](#registerwithagent)
|
|
34
|
+
- [toSwaigFunction](#toswaigfunction)
|
|
35
|
+
- [Helper Functions](#helper-functions)
|
|
36
|
+
- [createSimpleApiTool](#createsimpleapitool)
|
|
37
|
+
- [createExpressionTool](#createexpressiontool)
|
|
38
|
+
- [Template Variables Reference](#template-variables-reference)
|
|
39
|
+
- [Complete Examples](#complete-examples)
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Overview
|
|
44
|
+
|
|
45
|
+
`DataMap` creates server-side tool definitions that execute entirely on the SignalWire platform without requiring your own webhook endpoints for the tool handler. Instead of writing a handler function that runs on your server, you describe what HTTP call to make (or what expression to evaluate), how to process the response, and what to return to the AI -- all as configuration.
|
|
46
|
+
|
|
47
|
+
### When to use DataMap vs. defineTool
|
|
48
|
+
|
|
49
|
+
| Feature | `defineTool()` | `DataMap` |
|
|
50
|
+
|--------------------|--------------------------------------------|-------------------------------------------------|
|
|
51
|
+
| Execution location | Your server | SignalWire platform |
|
|
52
|
+
| Custom logic | Full TypeScript/JavaScript | Template variables and pattern matching |
|
|
53
|
+
| External API calls | You make them in your handler | SignalWire makes them for you |
|
|
54
|
+
| Webhook required | Yes (your agent server must be reachable) | No (the data_map config is embedded in SWML) |
|
|
55
|
+
| Best for | Complex logic, database access, auth flows | Simple API lookups, pattern matching, transforms |
|
|
56
|
+
|
|
57
|
+
### How it works
|
|
58
|
+
|
|
59
|
+
1. You define a `DataMap` with a name, parameters, and either webhooks or expressions.
|
|
60
|
+
2. You register it with an agent via `registerWithAgent()` or `toSwaigFunction()`.
|
|
61
|
+
3. When the AI decides to call this tool, SignalWire executes the data_map configuration directly:
|
|
62
|
+
- For **webhooks**: SignalWire makes the HTTP request, processes the response through your output template, and returns the result to the AI.
|
|
63
|
+
- For **expressions**: SignalWire evaluates the test value against the regex pattern and returns the matching output.
|
|
64
|
+
|
|
65
|
+
### Architecture
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
Caller <-> SignalWire AI <-> DataMap (runs on SignalWire)
|
|
69
|
+
|
|
|
70
|
+
+--> External API (optional webhook call)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
No traffic flows to your server for DataMap tool invocations. Your server only serves the initial SWML document that contains the data_map configuration.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Creating a DataMap
|
|
78
|
+
|
|
79
|
+
The `DataMap` constructor takes a single argument: the function name.
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { DataMap, SwaigFunctionResult } from '@anthropic/signalwire-agents';
|
|
83
|
+
|
|
84
|
+
const tool = new DataMap('get_weather');
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
| Parameter | Type | Description |
|
|
88
|
+
|----------------|----------|------------------------------------------|
|
|
89
|
+
| `functionName` | `string` | Unique name for this data map tool. |
|
|
90
|
+
|
|
91
|
+
All subsequent configuration is done via fluent method chaining:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const tool = new DataMap('get_weather')
|
|
95
|
+
.purpose('Get current weather for a city')
|
|
96
|
+
.parameter('city', 'string', 'The city name', { required: true })
|
|
97
|
+
.webhook('GET', 'https://wttr.in/${lc:args.city}?format=j1')
|
|
98
|
+
.output(new SwaigFunctionResult('Temperature: ${response.temp_F}F'))
|
|
99
|
+
.fallbackOutput(new SwaigFunctionResult('Weather data unavailable.'));
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Configuration
|
|
105
|
+
|
|
106
|
+
### purpose / description
|
|
107
|
+
|
|
108
|
+
Set the tool description that the AI sees. The AI uses this description to decide when to call the tool. `description()` is an alias for `purpose()`.
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
purpose(description: string): this
|
|
112
|
+
description(description: string): this
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
| Parameter | Type | Description |
|
|
116
|
+
|---------------|----------|----------------------------------------------------|
|
|
117
|
+
| `description` | `string` | Human-readable description of what the tool does. |
|
|
118
|
+
|
|
119
|
+
If not set, the description defaults to `"Execute <functionName>"`.
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
const tool = new DataMap('lookup_order')
|
|
123
|
+
.purpose('Look up an order by its ID and return the status');
|
|
124
|
+
|
|
125
|
+
// Equivalent:
|
|
126
|
+
const tool2 = new DataMap('lookup_order')
|
|
127
|
+
.description('Look up an order by its ID and return the status');
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### parameter
|
|
133
|
+
|
|
134
|
+
Define a parameter that the AI should extract from the conversation and pass to this tool.
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
parameter(
|
|
138
|
+
name: string,
|
|
139
|
+
paramType: string,
|
|
140
|
+
description: string,
|
|
141
|
+
opts?: { required?: boolean; enum?: string[] }
|
|
142
|
+
): this
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
| Parameter | Type | Description |
|
|
146
|
+
|-------------------|------------|----------------------------------------------------------|
|
|
147
|
+
| `name` | `string` | Parameter name (used in `${args.name}` templates). |
|
|
148
|
+
| `paramType` | `string` | JSON Schema type: `"string"`, `"number"`, `"boolean"`, `"integer"`, `"array"`, `"object"`. |
|
|
149
|
+
| `description` | `string` | Description shown to the AI to explain what this parameter is. |
|
|
150
|
+
| `opts.required` | `boolean` | If `true`, the AI must provide this parameter. |
|
|
151
|
+
| `opts.enum` | `string[]` | Restrict the parameter to a fixed set of allowed values. |
|
|
152
|
+
|
|
153
|
+
Multiple calls to `parameter()` define multiple parameters. Required parameters are tracked internally via a `_required` array in the parameter schema.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
const tool = new DataMap('search_products')
|
|
157
|
+
.purpose('Search for products in the catalog')
|
|
158
|
+
.parameter('query', 'string', 'Search query text', { required: true })
|
|
159
|
+
.parameter('category', 'string', 'Product category filter', {
|
|
160
|
+
enum: ['electronics', 'clothing', 'home', 'sports'],
|
|
161
|
+
})
|
|
162
|
+
.parameter('max_results', 'integer', 'Maximum number of results to return');
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The generated parameter schema:
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"type": "object",
|
|
170
|
+
"properties": {
|
|
171
|
+
"query": { "type": "string", "description": "Search query text" },
|
|
172
|
+
"category": {
|
|
173
|
+
"type": "string",
|
|
174
|
+
"description": "Product category filter",
|
|
175
|
+
"enum": ["electronics", "clothing", "home", "sports"]
|
|
176
|
+
},
|
|
177
|
+
"max_results": { "type": "integer", "description": "Maximum number of results to return" }
|
|
178
|
+
},
|
|
179
|
+
"required": ["query"]
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Webhooks
|
|
186
|
+
|
|
187
|
+
### webhook
|
|
188
|
+
|
|
189
|
+
Add a webhook that SignalWire calls when the tool is invoked. You can add multiple webhooks to a single DataMap.
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
webhook(
|
|
193
|
+
method: string,
|
|
194
|
+
url: string,
|
|
195
|
+
opts?: {
|
|
196
|
+
headers?: Record<string, string>;
|
|
197
|
+
formParam?: string;
|
|
198
|
+
inputArgsAsParams?: boolean;
|
|
199
|
+
requireArgs?: string[];
|
|
200
|
+
}
|
|
201
|
+
): this
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
| Parameter | Type | Description |
|
|
205
|
+
|------------------------|--------------------------|------------------------------------------------------------|
|
|
206
|
+
| `method` | `string` | HTTP method (`"GET"`, `"POST"`, `"PUT"`, etc.). Automatically uppercased. |
|
|
207
|
+
| `url` | `string` | The webhook URL. Supports template variables like `${args.city}`. |
|
|
208
|
+
| `opts.headers` | `Record<string, string>` | Custom HTTP headers for the request. |
|
|
209
|
+
| `opts.formParam` | `string` | Name of the form parameter to send the body as. |
|
|
210
|
+
| `opts.inputArgsAsParams` | `boolean` | If `true`, pass all input arguments as query/form parameters. |
|
|
211
|
+
| `opts.requireArgs` | `string[]` | Arguments that must be present for this webhook to fire. |
|
|
212
|
+
|
|
213
|
+
**Returns:** `this` for chaining.
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
// Simple GET request with URL template
|
|
217
|
+
const tool = new DataMap('get_stock_price')
|
|
218
|
+
.purpose('Get the current stock price')
|
|
219
|
+
.parameter('symbol', 'string', 'Stock ticker symbol', { required: true })
|
|
220
|
+
.webhook('GET', 'https://api.stocks.example.com/v1/price/${uc:args.symbol}');
|
|
221
|
+
|
|
222
|
+
// POST with authentication header
|
|
223
|
+
const tool2 = new DataMap('create_ticket')
|
|
224
|
+
.purpose('Create a support ticket')
|
|
225
|
+
.parameter('subject', 'string', 'Ticket subject', { required: true })
|
|
226
|
+
.parameter('description', 'string', 'Ticket description', { required: true })
|
|
227
|
+
.webhook('POST', 'https://api.helpdesk.example.com/tickets', {
|
|
228
|
+
headers: {
|
|
229
|
+
'Authorization': 'Bearer ${ENV.HELPDESK_API_KEY}',
|
|
230
|
+
'Content-Type': 'application/json',
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
### body
|
|
238
|
+
|
|
239
|
+
Set the JSON body for the most recently added webhook. Must be called after `webhook()`.
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
body(data: Record<string, unknown>): this
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
| Parameter | Type | Description |
|
|
246
|
+
|-----------|----------------------------|----------------------------|
|
|
247
|
+
| `data` | `Record<string, unknown>` | The request body object. |
|
|
248
|
+
|
|
249
|
+
**Throws:** `Error` if no webhook has been added yet.
|
|
250
|
+
|
|
251
|
+
**Returns:** `this` for chaining.
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
const tool = new DataMap('create_ticket')
|
|
255
|
+
.purpose('Create a support ticket')
|
|
256
|
+
.parameter('subject', 'string', 'Ticket subject', { required: true })
|
|
257
|
+
.parameter('priority', 'string', 'Priority level', { enum: ['low', 'medium', 'high'] })
|
|
258
|
+
.webhook('POST', 'https://api.helpdesk.example.com/tickets', {
|
|
259
|
+
headers: { 'Authorization': 'Bearer my-api-key' },
|
|
260
|
+
})
|
|
261
|
+
.body({
|
|
262
|
+
subject: '${args.subject}',
|
|
263
|
+
priority: '${args.priority}',
|
|
264
|
+
source: 'phone-call',
|
|
265
|
+
});
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
### params
|
|
271
|
+
|
|
272
|
+
Set query or form parameters for the most recently added webhook. Must be called after `webhook()`.
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
params(data: Record<string, unknown>): this
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
| Parameter | Type | Description |
|
|
279
|
+
|-----------|----------------------------|--------------------------|
|
|
280
|
+
| `data` | `Record<string, unknown>` | The parameters object. |
|
|
281
|
+
|
|
282
|
+
**Throws:** `Error` if no webhook has been added yet.
|
|
283
|
+
|
|
284
|
+
**Returns:** `this` for chaining.
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
const tool = new DataMap('search_kb')
|
|
288
|
+
.purpose('Search the knowledge base')
|
|
289
|
+
.parameter('query', 'string', 'Search query', { required: true })
|
|
290
|
+
.webhook('GET', 'https://api.kb.example.com/search')
|
|
291
|
+
.params({
|
|
292
|
+
q: '${args.query}',
|
|
293
|
+
limit: 5,
|
|
294
|
+
format: 'json',
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
### Webhook Headers
|
|
301
|
+
|
|
302
|
+
Headers are set via the `opts.headers` parameter of `webhook()`. Template variables are supported in header values.
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
const tool = new DataMap('authenticated_lookup')
|
|
306
|
+
.purpose('Look up data from an authenticated API')
|
|
307
|
+
.parameter('id', 'string', 'Record ID', { required: true })
|
|
308
|
+
.enableEnvExpansion()
|
|
309
|
+
.webhook('GET', 'https://api.example.com/records/${args.id}', {
|
|
310
|
+
headers: {
|
|
311
|
+
'Authorization': 'Bearer ${ENV.API_TOKEN}',
|
|
312
|
+
'X-Request-Source': 'signalwire-agent',
|
|
313
|
+
},
|
|
314
|
+
});
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## Expressions
|
|
320
|
+
|
|
321
|
+
### expression
|
|
322
|
+
|
|
323
|
+
Add a pattern-matching expression that evaluates a test value against a regex pattern. Expressions work without making any HTTP calls -- they are evaluated entirely on the SignalWire platform.
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
expression(
|
|
327
|
+
testValue: string,
|
|
328
|
+
pattern: string | RegExp,
|
|
329
|
+
output: SwaigFunctionResult,
|
|
330
|
+
nomatchOutput?: SwaigFunctionResult
|
|
331
|
+
): this
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
| Parameter | Type | Description |
|
|
335
|
+
|-----------------|----------------------------|----------------------------------------------------------|
|
|
336
|
+
| `testValue` | `string` | The string or template variable to test (e.g., `"${args.input}"`). |
|
|
337
|
+
| `pattern` | `string \| RegExp` | Regex pattern to match against. If a `RegExp`, the `.source` is used. |
|
|
338
|
+
| `output` | `SwaigFunctionResult` | Result returned when the pattern matches. |
|
|
339
|
+
| `nomatchOutput` | `SwaigFunctionResult` | Optional result returned when the pattern does not match.|
|
|
340
|
+
|
|
341
|
+
**Returns:** `this` for chaining.
|
|
342
|
+
|
|
343
|
+
You can add multiple expressions. They are evaluated in order; the first match wins.
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
const tool = new DataMap('validate_email')
|
|
347
|
+
.purpose('Validate an email address format')
|
|
348
|
+
.parameter('email', 'string', 'The email address to validate', { required: true })
|
|
349
|
+
.expression(
|
|
350
|
+
'${args.email}',
|
|
351
|
+
/^[^@]+@[^@]+\.[^@]+$/,
|
|
352
|
+
new SwaigFunctionResult('The email address ${args.email} is valid.'),
|
|
353
|
+
new SwaigFunctionResult('The email address ${args.email} is not valid. Please ask for a correct email.'),
|
|
354
|
+
);
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Multiple expressions for different test values:
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
const tool = new DataMap('classify_input')
|
|
361
|
+
.purpose('Classify user input as a question or command')
|
|
362
|
+
.parameter('input', 'string', 'The user input to classify', { required: true })
|
|
363
|
+
.expression(
|
|
364
|
+
'${args.input}',
|
|
365
|
+
'^(what|how|why|when|where|who|is|are|can|do|does)',
|
|
366
|
+
new SwaigFunctionResult('The input is a question.'),
|
|
367
|
+
)
|
|
368
|
+
.expression(
|
|
369
|
+
'${args.input}',
|
|
370
|
+
'^(please|set|change|update|delete|create|send)',
|
|
371
|
+
new SwaigFunctionResult('The input is a command.'),
|
|
372
|
+
new SwaigFunctionResult('The input type could not be determined.'),
|
|
373
|
+
);
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## Response Processing
|
|
379
|
+
|
|
380
|
+
### output
|
|
381
|
+
|
|
382
|
+
Set the output template for the most recently added webhook. The template uses `${response.*}` variables to reference fields in the webhook's JSON response and `${args.*}` to reference the tool's input arguments.
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
output(result: SwaigFunctionResult): this
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
| Parameter | Type | Description |
|
|
389
|
+
|-----------|-----------------------|------------------------------------------------------|
|
|
390
|
+
| `result` | `SwaigFunctionResult` | The result template. Use template variables in the response text. |
|
|
391
|
+
|
|
392
|
+
**Throws:** `Error` if no webhook has been added yet.
|
|
393
|
+
|
|
394
|
+
**Returns:** `this` for chaining.
|
|
395
|
+
|
|
396
|
+
```typescript
|
|
397
|
+
const tool = new DataMap('get_weather')
|
|
398
|
+
.purpose('Get current weather')
|
|
399
|
+
.parameter('city', 'string', 'City name', { required: true })
|
|
400
|
+
.webhook('GET', 'https://wttr.in/${lc:args.city}?format=j1')
|
|
401
|
+
.output(
|
|
402
|
+
new SwaigFunctionResult(
|
|
403
|
+
'Weather in ${args.city}: ' +
|
|
404
|
+
'Temperature: ${response.current_condition[0].temp_F}F, ' +
|
|
405
|
+
'Conditions: ${response.current_condition[0].weatherDesc[0].value}, ' +
|
|
406
|
+
'Humidity: ${response.current_condition[0].humidity}%'
|
|
407
|
+
),
|
|
408
|
+
);
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
The `output()` method calls `toDict()` on the `SwaigFunctionResult`, so you can also include actions:
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
const tool = new DataMap('urgent_alert')
|
|
415
|
+
.purpose('Send an urgent alert')
|
|
416
|
+
.parameter('message', 'string', 'Alert message', { required: true })
|
|
417
|
+
.webhook('POST', 'https://api.alerts.example.com/send')
|
|
418
|
+
.body({ message: '${args.message}' })
|
|
419
|
+
.output(
|
|
420
|
+
new SwaigFunctionResult('Alert sent: ${response.alert_id}')
|
|
421
|
+
.setMetadata({ alert_id: '${response.alert_id}' }),
|
|
422
|
+
);
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
### webhookExpressions
|
|
428
|
+
|
|
429
|
+
Set pattern-matching expressions on the most recently added webhook. These expressions are evaluated against the webhook's response, allowing conditional output based on the response content.
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
webhookExpressions(expressions: Record<string, unknown>[]): this
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
| Parameter | Type | Description |
|
|
436
|
+
|---------------|-----------------------------|----------------------------------------------------------------|
|
|
437
|
+
| `expressions` | `Record<string, unknown>[]` | Array of expression objects with `string`, `pattern`, and `output` fields. |
|
|
438
|
+
|
|
439
|
+
**Throws:** `Error` if no webhook has been added yet.
|
|
440
|
+
|
|
441
|
+
**Returns:** `this` for chaining.
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
const tool = new DataMap('check_order_status')
|
|
445
|
+
.purpose('Check the status of an order')
|
|
446
|
+
.parameter('order_id', 'string', 'Order ID', { required: true })
|
|
447
|
+
.webhook('GET', 'https://api.store.example.com/orders/${args.order_id}')
|
|
448
|
+
.webhookExpressions([
|
|
449
|
+
{
|
|
450
|
+
string: '${response.status}',
|
|
451
|
+
pattern: 'shipped',
|
|
452
|
+
output: new SwaigFunctionResult(
|
|
453
|
+
'Order ${args.order_id} has shipped! Tracking: ${response.tracking_number}'
|
|
454
|
+
).toDict(),
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
string: '${response.status}',
|
|
458
|
+
pattern: 'processing',
|
|
459
|
+
output: new SwaigFunctionResult(
|
|
460
|
+
'Order ${args.order_id} is being processed. Estimated ship date: ${response.est_ship_date}'
|
|
461
|
+
).toDict(),
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
string: '${response.status}',
|
|
465
|
+
pattern: 'delivered',
|
|
466
|
+
output: new SwaigFunctionResult(
|
|
467
|
+
'Order ${args.order_id} was delivered on ${response.delivery_date}.'
|
|
468
|
+
).toDict(),
|
|
469
|
+
},
|
|
470
|
+
])
|
|
471
|
+
.output(
|
|
472
|
+
new SwaigFunctionResult('Order ${args.order_id} status: ${response.status}'),
|
|
473
|
+
);
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
---
|
|
477
|
+
|
|
478
|
+
## Error Handling
|
|
479
|
+
|
|
480
|
+
### fallbackOutput
|
|
481
|
+
|
|
482
|
+
Set a fallback output used when no webhook succeeds or no expression matches. This ensures the AI always gets a response even when the tool encounters an error.
|
|
483
|
+
|
|
484
|
+
```typescript
|
|
485
|
+
fallbackOutput(result: SwaigFunctionResult): this
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
| Parameter | Type | Description |
|
|
489
|
+
|-----------|-----------------------|-----------------------------------------------|
|
|
490
|
+
| `result` | `SwaigFunctionResult` | The fallback result. |
|
|
491
|
+
|
|
492
|
+
**Returns:** `this` for chaining.
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
const tool = new DataMap('get_price')
|
|
496
|
+
.purpose('Get the price of a product')
|
|
497
|
+
.parameter('product', 'string', 'Product name', { required: true })
|
|
498
|
+
.webhook('GET', 'https://api.store.example.com/price/${args.product}')
|
|
499
|
+
.output(new SwaigFunctionResult('${args.product} costs $${response.price}'))
|
|
500
|
+
.fallbackOutput(
|
|
501
|
+
new SwaigFunctionResult('Sorry, I could not look up the price for ${args.product}. Please try again later.'),
|
|
502
|
+
);
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
### errorKeys
|
|
508
|
+
|
|
509
|
+
Set error keys on the most recently added webhook. If the webhook response contains any of these keys, the response is treated as an error and the fallback output is used instead.
|
|
510
|
+
|
|
511
|
+
If no webhook has been added, the error keys are set globally (same as `globalErrorKeys`).
|
|
512
|
+
|
|
513
|
+
```typescript
|
|
514
|
+
errorKeys(keys: string[]): this
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
| Parameter | Type | Description |
|
|
518
|
+
|-----------|------------|----------------------------------------------------|
|
|
519
|
+
| `keys` | `string[]` | Response keys that indicate an error occurred. |
|
|
520
|
+
|
|
521
|
+
**Returns:** `this` for chaining.
|
|
522
|
+
|
|
523
|
+
```typescript
|
|
524
|
+
const tool = new DataMap('api_lookup')
|
|
525
|
+
.purpose('Look up data from an API')
|
|
526
|
+
.parameter('id', 'string', 'Record ID', { required: true })
|
|
527
|
+
.webhook('GET', 'https://api.example.com/data/${args.id}')
|
|
528
|
+
.errorKeys(['error', 'error_message', 'fault'])
|
|
529
|
+
.output(new SwaigFunctionResult('Found: ${response.name}'))
|
|
530
|
+
.fallbackOutput(new SwaigFunctionResult('Lookup failed. Please try again.'));
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
---
|
|
534
|
+
|
|
535
|
+
### globalErrorKeys
|
|
536
|
+
|
|
537
|
+
Set error keys at the top-level data map scope, regardless of webhook context. These apply to all webhooks in the DataMap.
|
|
538
|
+
|
|
539
|
+
```typescript
|
|
540
|
+
globalErrorKeys(keys: string[]): this
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
| Parameter | Type | Description |
|
|
544
|
+
|-----------|------------|----------------------------------------------------|
|
|
545
|
+
| `keys` | `string[]` | Response keys that indicate an error occurred. |
|
|
546
|
+
|
|
547
|
+
**Returns:** `this` for chaining.
|
|
548
|
+
|
|
549
|
+
```typescript
|
|
550
|
+
const tool = new DataMap('multi_api')
|
|
551
|
+
.purpose('Call multiple APIs')
|
|
552
|
+
.globalErrorKeys(['error', 'err'])
|
|
553
|
+
.webhook('GET', 'https://api1.example.com/data')
|
|
554
|
+
.output(new SwaigFunctionResult('API 1: ${response.value}'))
|
|
555
|
+
.webhook('GET', 'https://api2.example.com/data')
|
|
556
|
+
.output(new SwaigFunctionResult('API 2: ${response.value}'))
|
|
557
|
+
.fallbackOutput(new SwaigFunctionResult('Both APIs failed.'));
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
---
|
|
561
|
+
|
|
562
|
+
## Iteration
|
|
563
|
+
|
|
564
|
+
### foreach
|
|
565
|
+
|
|
566
|
+
Configure iteration over an array in the webhook response. This allows you to loop over a list of items and build a composite response string.
|
|
567
|
+
|
|
568
|
+
```typescript
|
|
569
|
+
foreach(config: {
|
|
570
|
+
input_key: string;
|
|
571
|
+
output_key: string;
|
|
572
|
+
append: string;
|
|
573
|
+
max?: number;
|
|
574
|
+
}): this
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
| Parameter | Type | Description |
|
|
578
|
+
|--------------------|----------|--------------------------------------------------------------|
|
|
579
|
+
| `config.input_key` | `string` | Dot-path to the array in the response (e.g., `"results"`). |
|
|
580
|
+
| `config.output_key`| `string` | Variable name that holds the concatenated output. |
|
|
581
|
+
| `config.append` | `string` | Template string appended for each item in the array. |
|
|
582
|
+
| `config.max` | `number` | Optional maximum number of items to iterate over. |
|
|
583
|
+
|
|
584
|
+
**Throws:** `Error` if no webhook has been added yet.
|
|
585
|
+
|
|
586
|
+
**Returns:** `this` for chaining.
|
|
587
|
+
|
|
588
|
+
The `append` template has access to the current item's fields. After iteration, the concatenated result is available via `${output_key}` in the output template.
|
|
589
|
+
|
|
590
|
+
```typescript
|
|
591
|
+
const tool = new DataMap('list_orders')
|
|
592
|
+
.purpose('List recent orders for a customer')
|
|
593
|
+
.parameter('customer_id', 'string', 'Customer ID', { required: true })
|
|
594
|
+
.webhook('GET', 'https://api.store.example.com/customers/${args.customer_id}/orders')
|
|
595
|
+
.foreach({
|
|
596
|
+
input_key: 'orders',
|
|
597
|
+
output_key: 'order_list',
|
|
598
|
+
append: 'Order #${id}: ${status} - $${total}\n',
|
|
599
|
+
max: 5,
|
|
600
|
+
})
|
|
601
|
+
.output(
|
|
602
|
+
new SwaigFunctionResult('Recent orders for customer ${args.customer_id}:\n${order_list}'),
|
|
603
|
+
)
|
|
604
|
+
.fallbackOutput(
|
|
605
|
+
new SwaigFunctionResult('Could not retrieve orders for customer ${args.customer_id}.'),
|
|
606
|
+
);
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
In this example, if the API returns:
|
|
610
|
+
|
|
611
|
+
```json
|
|
612
|
+
{
|
|
613
|
+
"orders": [
|
|
614
|
+
{ "id": "1001", "status": "shipped", "total": "29.99" },
|
|
615
|
+
{ "id": "1002", "status": "processing", "total": "49.50" },
|
|
616
|
+
{ "id": "1003", "status": "delivered", "total": "15.00" }
|
|
617
|
+
]
|
|
618
|
+
}
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
The `${order_list}` variable becomes:
|
|
622
|
+
|
|
623
|
+
```
|
|
624
|
+
Order #1001: shipped - $29.99
|
|
625
|
+
Order #1002: processing - $49.50
|
|
626
|
+
Order #1003: delivered - $15.00
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
---
|
|
630
|
+
|
|
631
|
+
## Environment Variables
|
|
632
|
+
|
|
633
|
+
### enableEnvExpansion
|
|
634
|
+
|
|
635
|
+
Enable `${ENV.*}` variable expansion in URLs, bodies, headers, and outputs. When enabled, all `${ENV.VARIABLE_NAME}` references are replaced with the corresponding `process.env` values at the time `toSwaigFunction()` is called.
|
|
636
|
+
|
|
637
|
+
```typescript
|
|
638
|
+
enableEnvExpansion(enabled?: boolean): this
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
| Parameter | Type | Default | Description |
|
|
642
|
+
|-----------|-----------|---------|-----------------------------------------|
|
|
643
|
+
| `enabled` | `boolean` | `true` | Whether to enable environment expansion.|
|
|
644
|
+
|
|
645
|
+
**Returns:** `this` for chaining.
|
|
646
|
+
|
|
647
|
+
This is useful for embedding API keys or configuration values without hardcoding them:
|
|
648
|
+
|
|
649
|
+
```typescript
|
|
650
|
+
// Set environment variables (typically via .env file or deployment config)
|
|
651
|
+
// API_KEY=sk-abc123
|
|
652
|
+
// API_BASE_URL=https://api.example.com
|
|
653
|
+
|
|
654
|
+
const tool = new DataMap('secure_lookup')
|
|
655
|
+
.purpose('Look up data from a secure API')
|
|
656
|
+
.parameter('query', 'string', 'Search query', { required: true })
|
|
657
|
+
.enableEnvExpansion()
|
|
658
|
+
.webhook('GET', '${ENV.API_BASE_URL}/search?q=${args.query}', {
|
|
659
|
+
headers: {
|
|
660
|
+
'Authorization': 'Bearer ${ENV.API_KEY}',
|
|
661
|
+
},
|
|
662
|
+
})
|
|
663
|
+
.output(new SwaigFunctionResult('Result: ${response.data}'));
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
When `toSwaigFunction()` is called, `${ENV.API_KEY}` is replaced with the value of `process.env.API_KEY`. If the environment variable is not set, it is replaced with an empty string.
|
|
667
|
+
|
|
668
|
+
**Important:** The expansion happens at serialization time (when `toSwaigFunction()` is called), not at runtime. The resolved values are baked into the SWML document.
|
|
669
|
+
|
|
670
|
+
---
|
|
671
|
+
|
|
672
|
+
## Registration
|
|
673
|
+
|
|
674
|
+
### registerWithAgent
|
|
675
|
+
|
|
676
|
+
Register this DataMap tool with an `AgentBase` instance. This is a convenience method that calls `toSwaigFunction()` internally and passes the result to the agent's `registerSwaigFunction()` method.
|
|
677
|
+
|
|
678
|
+
```typescript
|
|
679
|
+
registerWithAgent(agent: {
|
|
680
|
+
registerSwaigFunction(fn: Record<string, unknown>): unknown
|
|
681
|
+
}): this
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
| Parameter | Type | Description |
|
|
685
|
+
|-----------|----------|----------------------------------------------------|
|
|
686
|
+
| `agent` | `object` | An object with a `registerSwaigFunction` method. |
|
|
687
|
+
|
|
688
|
+
**Returns:** `this` for chaining.
|
|
689
|
+
|
|
690
|
+
```typescript
|
|
691
|
+
import { AgentBase, DataMap, SwaigFunctionResult } from '@anthropic/signalwire-agents';
|
|
692
|
+
|
|
693
|
+
const agent = new AgentBase({ name: 'my-agent', basicAuth: ['user', 'pass'] });
|
|
694
|
+
|
|
695
|
+
new DataMap('get_time')
|
|
696
|
+
.purpose('Get the current time in a timezone')
|
|
697
|
+
.parameter('timezone', 'string', 'IANA timezone', { required: true })
|
|
698
|
+
.webhook('GET', 'https://worldtimeapi.org/api/timezone/${args.timezone}')
|
|
699
|
+
.output(new SwaigFunctionResult('Current time: ${response.datetime}'))
|
|
700
|
+
.fallbackOutput(new SwaigFunctionResult('Could not get time for that timezone.'))
|
|
701
|
+
.registerWithAgent(agent);
|
|
702
|
+
|
|
703
|
+
agent.run();
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
---
|
|
707
|
+
|
|
708
|
+
### toSwaigFunction
|
|
709
|
+
|
|
710
|
+
Serialize the DataMap to a SWAIG function definition object suitable for inclusion in a SWML document. This is the terminal method that produces the wire format.
|
|
711
|
+
|
|
712
|
+
```typescript
|
|
713
|
+
toSwaigFunction(): Record<string, unknown>
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
**Returns:** A plain object with `function`, `description`, `parameters`, and `data_map` fields.
|
|
717
|
+
|
|
718
|
+
```typescript
|
|
719
|
+
const tool = new DataMap('echo')
|
|
720
|
+
.purpose('Echo back the input')
|
|
721
|
+
.parameter('text', 'string', 'Text to echo', { required: true })
|
|
722
|
+
.expression(
|
|
723
|
+
'${args.text}',
|
|
724
|
+
'.*',
|
|
725
|
+
new SwaigFunctionResult('You said: ${args.text}'),
|
|
726
|
+
);
|
|
727
|
+
|
|
728
|
+
const swaigDef = tool.toSwaigFunction();
|
|
729
|
+
console.log(JSON.stringify(swaigDef, null, 2));
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
Output:
|
|
733
|
+
|
|
734
|
+
```json
|
|
735
|
+
{
|
|
736
|
+
"function": "echo",
|
|
737
|
+
"description": "Echo back the input",
|
|
738
|
+
"parameters": {
|
|
739
|
+
"type": "object",
|
|
740
|
+
"properties": {
|
|
741
|
+
"text": { "type": "string", "description": "Text to echo" }
|
|
742
|
+
},
|
|
743
|
+
"required": ["text"]
|
|
744
|
+
},
|
|
745
|
+
"data_map": {
|
|
746
|
+
"expressions": [
|
|
747
|
+
{
|
|
748
|
+
"string": "${args.text}",
|
|
749
|
+
"pattern": ".*",
|
|
750
|
+
"output": { "response": "You said: ${args.text}" }
|
|
751
|
+
}
|
|
752
|
+
]
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
You can then register this definition manually:
|
|
758
|
+
|
|
759
|
+
```typescript
|
|
760
|
+
agent.registerSwaigFunction(tool.toSwaigFunction());
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
---
|
|
764
|
+
|
|
765
|
+
## Helper Functions
|
|
766
|
+
|
|
767
|
+
### createSimpleApiTool
|
|
768
|
+
|
|
769
|
+
Create a DataMap tool that calls a single API endpoint and formats the response. This is a convenience function for the most common DataMap pattern: one GET/POST request with a response template.
|
|
770
|
+
|
|
771
|
+
```typescript
|
|
772
|
+
import { createSimpleApiTool } from '@anthropic/signalwire-agents';
|
|
773
|
+
|
|
774
|
+
createSimpleApiTool(opts: {
|
|
775
|
+
name: string;
|
|
776
|
+
url: string;
|
|
777
|
+
responseTemplate: string;
|
|
778
|
+
parameters?: Record<string, {
|
|
779
|
+
type?: string;
|
|
780
|
+
description?: string;
|
|
781
|
+
required?: boolean;
|
|
782
|
+
}>;
|
|
783
|
+
method?: string;
|
|
784
|
+
headers?: Record<string, string>;
|
|
785
|
+
body?: Record<string, unknown>;
|
|
786
|
+
errorKeys?: string[];
|
|
787
|
+
}): DataMap
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
| Parameter | Type | Default | Description |
|
|
791
|
+
|-------------------------|----------------------------|-----------|---------------------------------------------------|
|
|
792
|
+
| `opts.name` | `string` | -- | Tool name. |
|
|
793
|
+
| `opts.url` | `string` | -- | Webhook URL (supports template variables). |
|
|
794
|
+
| `opts.responseTemplate` | `string` | -- | Response template with `${response.*}` variables. |
|
|
795
|
+
| `opts.parameters` | `Record<string, {...}>` | -- | Parameter definitions. |
|
|
796
|
+
| `opts.method` | `string` | `'GET'` | HTTP method. |
|
|
797
|
+
| `opts.headers` | `Record<string, string>` | -- | Request headers. |
|
|
798
|
+
| `opts.body` | `Record<string, unknown>` | -- | Request body (for POST/PUT). |
|
|
799
|
+
| `opts.errorKeys` | `string[]` | -- | Response keys indicating errors. |
|
|
800
|
+
|
|
801
|
+
**Returns:** A configured `DataMap` instance ready for registration.
|
|
802
|
+
|
|
803
|
+
```typescript
|
|
804
|
+
import { createSimpleApiTool } from '@anthropic/signalwire-agents';
|
|
805
|
+
|
|
806
|
+
// Minimal: a single GET endpoint
|
|
807
|
+
const jokeTool = createSimpleApiTool({
|
|
808
|
+
name: 'get_joke',
|
|
809
|
+
url: 'https://official-joke-api.appspot.com/random_joke',
|
|
810
|
+
responseTemplate: 'Here is a joke: ${response.setup} ... ${response.punchline}',
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
agent.registerSwaigFunction(jokeTool.toSwaigFunction());
|
|
814
|
+
|
|
815
|
+
// With parameters and POST
|
|
816
|
+
const searchTool = createSimpleApiTool({
|
|
817
|
+
name: 'search_docs',
|
|
818
|
+
url: 'https://api.docs.example.com/search',
|
|
819
|
+
method: 'POST',
|
|
820
|
+
responseTemplate: 'Found ${response.total} results. Top result: ${response.results[0].title}',
|
|
821
|
+
parameters: {
|
|
822
|
+
query: { type: 'string', description: 'Search query', required: true },
|
|
823
|
+
limit: { type: 'integer', description: 'Max results' },
|
|
824
|
+
},
|
|
825
|
+
headers: {
|
|
826
|
+
'Authorization': 'Bearer my-token',
|
|
827
|
+
},
|
|
828
|
+
body: {
|
|
829
|
+
q: '${args.query}',
|
|
830
|
+
max: '${args.limit}',
|
|
831
|
+
},
|
|
832
|
+
errorKeys: ['error'],
|
|
833
|
+
});
|
|
834
|
+
|
|
835
|
+
agent.registerSwaigFunction(searchTool.toSwaigFunction());
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
---
|
|
839
|
+
|
|
840
|
+
### createExpressionTool
|
|
841
|
+
|
|
842
|
+
Create a DataMap tool that evaluates expressions against patterns without making any HTTP calls. Useful for validation, classification, and simple lookups.
|
|
843
|
+
|
|
844
|
+
```typescript
|
|
845
|
+
import { createExpressionTool } from '@anthropic/signalwire-agents';
|
|
846
|
+
|
|
847
|
+
createExpressionTool(opts: {
|
|
848
|
+
name: string;
|
|
849
|
+
patterns: Record<string, [string, SwaigFunctionResult]>;
|
|
850
|
+
parameters?: Record<string, {
|
|
851
|
+
type?: string;
|
|
852
|
+
description?: string;
|
|
853
|
+
required?: boolean;
|
|
854
|
+
}>;
|
|
855
|
+
}): DataMap
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
| Parameter | Type | Description |
|
|
859
|
+
|------------------|-------------------------------------------------------|--------------------------------------------------------|
|
|
860
|
+
| `opts.name` | `string` | Tool name. |
|
|
861
|
+
| `opts.patterns` | `Record<string, [string, SwaigFunctionResult]>` | Map of test values to `[pattern, output]` tuples. |
|
|
862
|
+
| `opts.parameters`| `Record<string, {...}>` | Parameter definitions. |
|
|
863
|
+
|
|
864
|
+
The `patterns` object maps test values (template strings) to tuples of `[regexPattern, result]`:
|
|
865
|
+
|
|
866
|
+
```typescript
|
|
867
|
+
import { createExpressionTool, SwaigFunctionResult } from '@anthropic/signalwire-agents';
|
|
868
|
+
|
|
869
|
+
const validator = createExpressionTool({
|
|
870
|
+
name: 'validate_phone',
|
|
871
|
+
patterns: {
|
|
872
|
+
'${args.phone}': [
|
|
873
|
+
'^\\+?1?\\d{10,15}$',
|
|
874
|
+
new SwaigFunctionResult('The phone number ${args.phone} is valid.'),
|
|
875
|
+
],
|
|
876
|
+
},
|
|
877
|
+
parameters: {
|
|
878
|
+
phone: { type: 'string', description: 'Phone number to validate', required: true },
|
|
879
|
+
},
|
|
880
|
+
});
|
|
881
|
+
|
|
882
|
+
agent.registerSwaigFunction(validator.toSwaigFunction());
|
|
883
|
+
```
|
|
884
|
+
|
|
885
|
+
---
|
|
886
|
+
|
|
887
|
+
## Template Variables Reference
|
|
888
|
+
|
|
889
|
+
Template variables are strings enclosed in `${}` that are evaluated by the SignalWire platform at runtime.
|
|
890
|
+
|
|
891
|
+
### Argument Variables
|
|
892
|
+
|
|
893
|
+
| Variable | Description | Example |
|
|
894
|
+
|-------------------|----------------------------------------------------------|------------------------|
|
|
895
|
+
| `${args.<name>}` | Value of an input argument passed by the AI. | `${args.city}` |
|
|
896
|
+
| `${lc:args.<name>}` | Argument value converted to lowercase. | `${lc:args.city}` |
|
|
897
|
+
| `${uc:args.<name>}` | Argument value converted to uppercase. | `${uc:args.symbol}` |
|
|
898
|
+
|
|
899
|
+
### Response Variables
|
|
900
|
+
|
|
901
|
+
| Variable | Description | Example |
|
|
902
|
+
|-----------------------------|-------------------------------------------------------|---------------------------------------------|
|
|
903
|
+
| `${response.<key>}` | Top-level field from the webhook JSON response. | `${response.name}` |
|
|
904
|
+
| `${response.<key>.<subkey>}` | Nested field from the response. | `${response.address.city}` |
|
|
905
|
+
| `${response.<key>[N]}` | Array element by index. | `${response.results[0].title}` |
|
|
906
|
+
| `${response.<key>[N].<sub>}` | Field within an array element. | `${response.current_condition[0].temp_F}` |
|
|
907
|
+
|
|
908
|
+
### Environment Variables
|
|
909
|
+
|
|
910
|
+
| Variable | Description | Example |
|
|
911
|
+
|-------------------|--------------------------------------------------------------------|------------------------|
|
|
912
|
+
| `${ENV.<name>}` | Value of `process.env.<name>`. Requires `enableEnvExpansion()`. | `${ENV.API_KEY}` |
|
|
913
|
+
|
|
914
|
+
### Foreach Variables
|
|
915
|
+
|
|
916
|
+
Inside a `foreach` `append` template, you can reference fields of the current item directly:
|
|
917
|
+
|
|
918
|
+
| Variable | Description | Example |
|
|
919
|
+
|------------|--------------------------------------------|----------------|
|
|
920
|
+
| `${<field>}` | Field of the current item in the array. | `${id}`, `${name}` |
|
|
921
|
+
|
|
922
|
+
### Case Transformation
|
|
923
|
+
|
|
924
|
+
The `${lc:...}` and `${uc:...}` prefixes can be applied to argument variables to transform them to lowercase or uppercase respectively. This is particularly useful in URL templates:
|
|
925
|
+
|
|
926
|
+
```typescript
|
|
927
|
+
// Lowercase city name for URL-friendly paths
|
|
928
|
+
.webhook('GET', 'https://api.example.com/cities/${lc:args.city_name}')
|
|
929
|
+
|
|
930
|
+
// Uppercase stock ticker symbol
|
|
931
|
+
.webhook('GET', 'https://api.example.com/stocks/${uc:args.symbol}')
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
---
|
|
935
|
+
|
|
936
|
+
## Complete Examples
|
|
937
|
+
|
|
938
|
+
### Example 1: Weather lookup with DataMap builder
|
|
939
|
+
|
|
940
|
+
```typescript
|
|
941
|
+
import { AgentBase, DataMap, SwaigFunctionResult } from '@anthropic/signalwire-agents';
|
|
942
|
+
|
|
943
|
+
const agent = new AgentBase({
|
|
944
|
+
name: 'weather-agent',
|
|
945
|
+
route: '/',
|
|
946
|
+
basicAuth: ['user', 'pass'],
|
|
947
|
+
});
|
|
948
|
+
|
|
949
|
+
agent.setPromptText('You are a weather assistant. Help users check the weather.');
|
|
950
|
+
|
|
951
|
+
const weatherTool = new DataMap('get_weather')
|
|
952
|
+
.purpose('Get current weather for a city')
|
|
953
|
+
.parameter('city', 'string', 'The city name', { required: true })
|
|
954
|
+
.webhook('GET', 'https://wttr.in/${lc:args.city}?format=j1')
|
|
955
|
+
.output(
|
|
956
|
+
new SwaigFunctionResult(
|
|
957
|
+
'Weather in ${args.city}: ${response.current_condition[0].temp_F}F, ' +
|
|
958
|
+
'${response.current_condition[0].weatherDesc[0].value}'
|
|
959
|
+
),
|
|
960
|
+
)
|
|
961
|
+
.fallbackOutput(
|
|
962
|
+
new SwaigFunctionResult('Sorry, could not fetch weather for that city.'),
|
|
963
|
+
);
|
|
964
|
+
|
|
965
|
+
agent.registerSwaigFunction(weatherTool.toSwaigFunction());
|
|
966
|
+
agent.run();
|
|
967
|
+
```
|
|
968
|
+
|
|
969
|
+
### Example 2: Expression-only tool (no HTTP)
|
|
970
|
+
|
|
971
|
+
```typescript
|
|
972
|
+
import { AgentBase, DataMap, SwaigFunctionResult } from '@anthropic/signalwire-agents';
|
|
973
|
+
|
|
974
|
+
const agent = new AgentBase({
|
|
975
|
+
name: 'validator-agent',
|
|
976
|
+
route: '/',
|
|
977
|
+
basicAuth: ['user', 'pass'],
|
|
978
|
+
});
|
|
979
|
+
|
|
980
|
+
agent.setPromptText('You help validate user data like emails and phone numbers.');
|
|
981
|
+
|
|
982
|
+
const emailValidator = new DataMap('validate_email')
|
|
983
|
+
.purpose('Check if an email address is valid')
|
|
984
|
+
.parameter('email', 'string', 'Email address to validate', { required: true })
|
|
985
|
+
.expression(
|
|
986
|
+
'${args.email}',
|
|
987
|
+
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
|
|
988
|
+
new SwaigFunctionResult('The email ${args.email} is valid.'),
|
|
989
|
+
new SwaigFunctionResult('The email ${args.email} is invalid. Please provide a correct email address.'),
|
|
990
|
+
);
|
|
991
|
+
|
|
992
|
+
emailValidator.registerWithAgent(agent);
|
|
993
|
+
agent.run();
|
|
994
|
+
```
|
|
995
|
+
|
|
996
|
+
### Example 3: API tool with POST body and error handling
|
|
997
|
+
|
|
998
|
+
```typescript
|
|
999
|
+
import { AgentBase, DataMap, SwaigFunctionResult } from '@anthropic/signalwire-agents';
|
|
1000
|
+
|
|
1001
|
+
const agent = new AgentBase({
|
|
1002
|
+
name: 'ticket-agent',
|
|
1003
|
+
route: '/',
|
|
1004
|
+
basicAuth: ['user', 'pass'],
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
agent.setPromptText('You are a support agent. Create tickets for customer issues.');
|
|
1008
|
+
|
|
1009
|
+
const ticketTool = new DataMap('create_ticket')
|
|
1010
|
+
.purpose('Create a support ticket for the customer')
|
|
1011
|
+
.parameter('subject', 'string', 'Brief description of the issue', { required: true })
|
|
1012
|
+
.parameter('priority', 'string', 'Urgency level', {
|
|
1013
|
+
required: true,
|
|
1014
|
+
enum: ['low', 'medium', 'high', 'critical'],
|
|
1015
|
+
})
|
|
1016
|
+
.parameter('description', 'string', 'Detailed description of the issue')
|
|
1017
|
+
.enableEnvExpansion()
|
|
1018
|
+
.webhook('POST', '${ENV.HELPDESK_URL}/api/tickets', {
|
|
1019
|
+
headers: {
|
|
1020
|
+
'Authorization': 'Bearer ${ENV.HELPDESK_TOKEN}',
|
|
1021
|
+
'Content-Type': 'application/json',
|
|
1022
|
+
},
|
|
1023
|
+
})
|
|
1024
|
+
.body({
|
|
1025
|
+
subject: '${args.subject}',
|
|
1026
|
+
priority: '${args.priority}',
|
|
1027
|
+
description: '${args.description}',
|
|
1028
|
+
source: 'phone',
|
|
1029
|
+
})
|
|
1030
|
+
.errorKeys(['error', 'message'])
|
|
1031
|
+
.output(
|
|
1032
|
+
new SwaigFunctionResult(
|
|
1033
|
+
'Ticket #${response.ticket_id} created successfully with ${args.priority} priority.'
|
|
1034
|
+
),
|
|
1035
|
+
)
|
|
1036
|
+
.fallbackOutput(
|
|
1037
|
+
new SwaigFunctionResult('Failed to create the ticket. Please try again or contact support via email.'),
|
|
1038
|
+
);
|
|
1039
|
+
|
|
1040
|
+
ticketTool.registerWithAgent(agent);
|
|
1041
|
+
agent.run();
|
|
1042
|
+
```
|
|
1043
|
+
|
|
1044
|
+
### Example 4: Iteration over array responses
|
|
1045
|
+
|
|
1046
|
+
```typescript
|
|
1047
|
+
import { AgentBase, DataMap, SwaigFunctionResult } from '@anthropic/signalwire-agents';
|
|
1048
|
+
|
|
1049
|
+
const agent = new AgentBase({
|
|
1050
|
+
name: 'store-agent',
|
|
1051
|
+
route: '/',
|
|
1052
|
+
basicAuth: ['user', 'pass'],
|
|
1053
|
+
});
|
|
1054
|
+
|
|
1055
|
+
agent.setPromptText('You help customers find products and check orders.');
|
|
1056
|
+
|
|
1057
|
+
const ordersTool = new DataMap('list_orders')
|
|
1058
|
+
.purpose('List recent orders for the caller')
|
|
1059
|
+
.parameter('email', 'string', 'Customer email address', { required: true })
|
|
1060
|
+
.webhook('GET', 'https://api.store.example.com/orders?email=${args.email}')
|
|
1061
|
+
.foreach({
|
|
1062
|
+
input_key: 'orders',
|
|
1063
|
+
output_key: 'order_summary',
|
|
1064
|
+
append: '- Order #${id}: ${status}, Total: $${total}\n',
|
|
1065
|
+
max: 10,
|
|
1066
|
+
})
|
|
1067
|
+
.output(
|
|
1068
|
+
new SwaigFunctionResult('Here are your recent orders:\n${order_summary}'),
|
|
1069
|
+
)
|
|
1070
|
+
.fallbackOutput(
|
|
1071
|
+
new SwaigFunctionResult('No orders found for ${args.email}.'),
|
|
1072
|
+
);
|
|
1073
|
+
|
|
1074
|
+
ordersTool.registerWithAgent(agent);
|
|
1075
|
+
agent.run();
|
|
1076
|
+
```
|
|
1077
|
+
|
|
1078
|
+
### Example 5: Quick setup with createSimpleApiTool
|
|
1079
|
+
|
|
1080
|
+
```typescript
|
|
1081
|
+
import { AgentBase, createSimpleApiTool } from '@anthropic/signalwire-agents';
|
|
1082
|
+
|
|
1083
|
+
const agent = new AgentBase({
|
|
1084
|
+
name: 'fun-agent',
|
|
1085
|
+
route: '/',
|
|
1086
|
+
basicAuth: ['user', 'pass'],
|
|
1087
|
+
});
|
|
1088
|
+
|
|
1089
|
+
agent.setPromptText('You tell jokes and fun facts.');
|
|
1090
|
+
|
|
1091
|
+
// One-liner API integration
|
|
1092
|
+
const jokeTool = createSimpleApiTool({
|
|
1093
|
+
name: 'get_joke',
|
|
1094
|
+
url: 'https://official-joke-api.appspot.com/random_joke',
|
|
1095
|
+
responseTemplate: '${response.setup} ... ${response.punchline}',
|
|
1096
|
+
});
|
|
1097
|
+
|
|
1098
|
+
const factTool = createSimpleApiTool({
|
|
1099
|
+
name: 'get_fact',
|
|
1100
|
+
url: 'https://uselessfacts.jsph.pl/random.json?language=en',
|
|
1101
|
+
responseTemplate: 'Fun fact: ${response.text}',
|
|
1102
|
+
});
|
|
1103
|
+
|
|
1104
|
+
agent.registerSwaigFunction(jokeTool.toSwaigFunction());
|
|
1105
|
+
agent.registerSwaigFunction(factTool.toSwaigFunction());
|
|
1106
|
+
agent.run();
|
|
1107
|
+
```
|
|
1108
|
+
|
|
1109
|
+
### Example 6: Expression tool with createExpressionTool
|
|
1110
|
+
|
|
1111
|
+
```typescript
|
|
1112
|
+
import {
|
|
1113
|
+
AgentBase,
|
|
1114
|
+
createExpressionTool,
|
|
1115
|
+
SwaigFunctionResult,
|
|
1116
|
+
} from '@anthropic/signalwire-agents';
|
|
1117
|
+
|
|
1118
|
+
const agent = new AgentBase({
|
|
1119
|
+
name: 'validator-agent',
|
|
1120
|
+
route: '/',
|
|
1121
|
+
basicAuth: ['user', 'pass'],
|
|
1122
|
+
});
|
|
1123
|
+
|
|
1124
|
+
agent.setPromptText('You validate user inputs like zip codes and phone numbers.');
|
|
1125
|
+
|
|
1126
|
+
const zipValidator = createExpressionTool({
|
|
1127
|
+
name: 'validate_zip',
|
|
1128
|
+
patterns: {
|
|
1129
|
+
'${args.zip}': [
|
|
1130
|
+
'^\\d{5}(-\\d{4})?$',
|
|
1131
|
+
new SwaigFunctionResult('${args.zip} is a valid US zip code.'),
|
|
1132
|
+
],
|
|
1133
|
+
},
|
|
1134
|
+
parameters: {
|
|
1135
|
+
zip: { type: 'string', description: 'Zip code to validate', required: true },
|
|
1136
|
+
},
|
|
1137
|
+
});
|
|
1138
|
+
|
|
1139
|
+
agent.registerSwaigFunction(zipValidator.toSwaigFunction());
|
|
1140
|
+
agent.run();
|
|
1141
|
+
```
|