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.
Files changed (245) hide show
  1. package/CLAUDE.md +112 -0
  2. package/README.md +417 -0
  3. package/dist/AgentBase.d.ts +481 -0
  4. package/dist/AgentBase.js +1155 -0
  5. package/dist/AgentBase.js.map +1 -0
  6. package/dist/AgentServer.d.ts +60 -0
  7. package/dist/AgentServer.js +128 -0
  8. package/dist/AgentServer.js.map +1 -0
  9. package/dist/AuthHandler.d.ts +56 -0
  10. package/dist/AuthHandler.js +119 -0
  11. package/dist/AuthHandler.js.map +1 -0
  12. package/dist/ConfigLoader.d.ts +68 -0
  13. package/dist/ConfigLoader.js +150 -0
  14. package/dist/ConfigLoader.js.map +1 -0
  15. package/dist/ContextBuilder.d.ts +431 -0
  16. package/dist/ContextBuilder.js +751 -0
  17. package/dist/ContextBuilder.js.map +1 -0
  18. package/dist/DataMap.d.ts +179 -0
  19. package/dist/DataMap.js +321 -0
  20. package/dist/DataMap.js.map +1 -0
  21. package/dist/Logger.d.ts +91 -0
  22. package/dist/Logger.js +191 -0
  23. package/dist/Logger.js.map +1 -0
  24. package/dist/PomBuilder.d.ts +144 -0
  25. package/dist/PomBuilder.js +249 -0
  26. package/dist/PomBuilder.js.map +1 -0
  27. package/dist/PromptManager.d.ts +85 -0
  28. package/dist/PromptManager.js +108 -0
  29. package/dist/PromptManager.js.map +1 -0
  30. package/dist/SchemaUtils.d.ts +42 -0
  31. package/dist/SchemaUtils.js +148 -0
  32. package/dist/SchemaUtils.js.map +1 -0
  33. package/dist/ServerlessAdapter.d.ts +100 -0
  34. package/dist/ServerlessAdapter.js +166 -0
  35. package/dist/ServerlessAdapter.js.map +1 -0
  36. package/dist/SessionManager.d.ts +86 -0
  37. package/dist/SessionManager.js +155 -0
  38. package/dist/SessionManager.js.map +1 -0
  39. package/dist/SslConfig.d.ts +77 -0
  40. package/dist/SslConfig.js +100 -0
  41. package/dist/SslConfig.js.map +1 -0
  42. package/dist/SwaigFunction.d.ts +88 -0
  43. package/dist/SwaigFunction.js +125 -0
  44. package/dist/SwaigFunction.js.map +1 -0
  45. package/dist/SwaigFunctionResult.d.ts +442 -0
  46. package/dist/SwaigFunctionResult.js +735 -0
  47. package/dist/SwaigFunctionResult.js.map +1 -0
  48. package/dist/SwmlBuilder.d.ts +37 -0
  49. package/dist/SwmlBuilder.js +55 -0
  50. package/dist/SwmlBuilder.js.map +1 -0
  51. package/dist/cli/agent-loader.d.ts +22 -0
  52. package/dist/cli/agent-loader.js +106 -0
  53. package/dist/cli/agent-loader.js.map +1 -0
  54. package/dist/cli/mock-data.d.ts +37 -0
  55. package/dist/cli/mock-data.js +79 -0
  56. package/dist/cli/mock-data.js.map +1 -0
  57. package/dist/cli/swaig-test.d.ts +32 -0
  58. package/dist/cli/swaig-test.js +405 -0
  59. package/dist/cli/swaig-test.js.map +1 -0
  60. package/dist/index.d.ts +36 -0
  61. package/dist/index.js +44 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/prefabs/ConciergeAgent.d.ts +64 -0
  64. package/dist/prefabs/ConciergeAgent.js +188 -0
  65. package/dist/prefabs/ConciergeAgent.js.map +1 -0
  66. package/dist/prefabs/FAQBotAgent.d.ts +68 -0
  67. package/dist/prefabs/FAQBotAgent.js +206 -0
  68. package/dist/prefabs/FAQBotAgent.js.map +1 -0
  69. package/dist/prefabs/InfoGathererAgent.d.ts +73 -0
  70. package/dist/prefabs/InfoGathererAgent.js +202 -0
  71. package/dist/prefabs/InfoGathererAgent.js.map +1 -0
  72. package/dist/prefabs/ReceptionistAgent.d.ts +65 -0
  73. package/dist/prefabs/ReceptionistAgent.js +205 -0
  74. package/dist/prefabs/ReceptionistAgent.js.map +1 -0
  75. package/dist/prefabs/SurveyAgent.d.ts +84 -0
  76. package/dist/prefabs/SurveyAgent.js +324 -0
  77. package/dist/prefabs/SurveyAgent.js.map +1 -0
  78. package/dist/prefabs/index.d.ts +13 -0
  79. package/dist/prefabs/index.js +14 -0
  80. package/dist/prefabs/index.js.map +1 -0
  81. package/dist/skills/SkillBase.d.ts +134 -0
  82. package/dist/skills/SkillBase.js +105 -0
  83. package/dist/skills/SkillBase.js.map +1 -0
  84. package/dist/skills/SkillManager.d.ts +83 -0
  85. package/dist/skills/SkillManager.js +159 -0
  86. package/dist/skills/SkillManager.js.map +1 -0
  87. package/dist/skills/SkillRegistry.d.ts +105 -0
  88. package/dist/skills/SkillRegistry.js +195 -0
  89. package/dist/skills/SkillRegistry.js.map +1 -0
  90. package/dist/skills/builtin/api_ninjas_trivia.d.ts +35 -0
  91. package/dist/skills/builtin/api_ninjas_trivia.js +161 -0
  92. package/dist/skills/builtin/api_ninjas_trivia.js.map +1 -0
  93. package/dist/skills/builtin/claude_skills.d.ts +34 -0
  94. package/dist/skills/builtin/claude_skills.js +156 -0
  95. package/dist/skills/builtin/claude_skills.js.map +1 -0
  96. package/dist/skills/builtin/custom_skills.d.ts +59 -0
  97. package/dist/skills/builtin/custom_skills.js +231 -0
  98. package/dist/skills/builtin/custom_skills.js.map +1 -0
  99. package/dist/skills/builtin/datasphere.d.ts +34 -0
  100. package/dist/skills/builtin/datasphere.js +163 -0
  101. package/dist/skills/builtin/datasphere.js.map +1 -0
  102. package/dist/skills/builtin/datasphere_serverless.d.ts +54 -0
  103. package/dist/skills/builtin/datasphere_serverless.js +155 -0
  104. package/dist/skills/builtin/datasphere_serverless.js.map +1 -0
  105. package/dist/skills/builtin/datetime.d.ts +31 -0
  106. package/dist/skills/builtin/datetime.js +95 -0
  107. package/dist/skills/builtin/datetime.js.map +1 -0
  108. package/dist/skills/builtin/google_maps.d.ts +33 -0
  109. package/dist/skills/builtin/google_maps.js +233 -0
  110. package/dist/skills/builtin/google_maps.js.map +1 -0
  111. package/dist/skills/builtin/index.d.ts +28 -0
  112. package/dist/skills/builtin/index.js +75 -0
  113. package/dist/skills/builtin/index.js.map +1 -0
  114. package/dist/skills/builtin/info_gatherer.d.ts +52 -0
  115. package/dist/skills/builtin/info_gatherer.js +237 -0
  116. package/dist/skills/builtin/info_gatherer.js.map +1 -0
  117. package/dist/skills/builtin/joke.d.ts +32 -0
  118. package/dist/skills/builtin/joke.js +142 -0
  119. package/dist/skills/builtin/joke.js.map +1 -0
  120. package/dist/skills/builtin/math.d.ts +33 -0
  121. package/dist/skills/builtin/math.js +120 -0
  122. package/dist/skills/builtin/math.js.map +1 -0
  123. package/dist/skills/builtin/mcp_gateway.d.ts +35 -0
  124. package/dist/skills/builtin/mcp_gateway.js +85 -0
  125. package/dist/skills/builtin/mcp_gateway.js.map +1 -0
  126. package/dist/skills/builtin/native_vector_search.d.ts +44 -0
  127. package/dist/skills/builtin/native_vector_search.js +248 -0
  128. package/dist/skills/builtin/native_vector_search.js.map +1 -0
  129. package/dist/skills/builtin/play_background_file.d.ts +34 -0
  130. package/dist/skills/builtin/play_background_file.js +135 -0
  131. package/dist/skills/builtin/play_background_file.js.map +1 -0
  132. package/dist/skills/builtin/spider.d.ts +34 -0
  133. package/dist/skills/builtin/spider.js +164 -0
  134. package/dist/skills/builtin/spider.js.map +1 -0
  135. package/dist/skills/builtin/swml_transfer.d.ts +44 -0
  136. package/dist/skills/builtin/swml_transfer.js +204 -0
  137. package/dist/skills/builtin/swml_transfer.js.map +1 -0
  138. package/dist/skills/builtin/weather_api.d.ts +34 -0
  139. package/dist/skills/builtin/weather_api.js +136 -0
  140. package/dist/skills/builtin/weather_api.js.map +1 -0
  141. package/dist/skills/builtin/web_search.d.ts +34 -0
  142. package/dist/skills/builtin/web_search.js +141 -0
  143. package/dist/skills/builtin/web_search.js.map +1 -0
  144. package/dist/skills/builtin/wikipedia_search.d.ts +34 -0
  145. package/dist/skills/builtin/wikipedia_search.js +166 -0
  146. package/dist/skills/builtin/wikipedia_search.js.map +1 -0
  147. package/dist/skills/index.d.ts +11 -0
  148. package/dist/skills/index.js +10 -0
  149. package/dist/skills/index.js.map +1 -0
  150. package/dist/types.d.ts +85 -0
  151. package/dist/types.js +5 -0
  152. package/dist/types.js.map +1 -0
  153. package/docs/agent-guide.md +869 -0
  154. package/docs/api-reference.md +2419 -0
  155. package/docs/architecture.md +843 -0
  156. package/docs/cli-guide.md +579 -0
  157. package/docs/configuration.md +422 -0
  158. package/docs/contexts-guide.md +787 -0
  159. package/docs/datamap-guide.md +1141 -0
  160. package/docs/prefabs-guide.md +830 -0
  161. package/docs/security.md +436 -0
  162. package/docs/serverless-guide.md +513 -0
  163. package/docs/skills-guide.md +845 -0
  164. package/docs/swaig-reference.md +1627 -0
  165. package/examples/call-flow.ts +60 -0
  166. package/examples/contexts-steps.ts +62 -0
  167. package/examples/datamap-tools.ts +52 -0
  168. package/examples/dynamic-config.ts +51 -0
  169. package/examples/multi-agent.ts +67 -0
  170. package/examples/pom-prompt.ts +68 -0
  171. package/examples/simple-agent.ts +33 -0
  172. package/package.json +35 -0
  173. package/src/AgentBase.ts +1279 -0
  174. package/src/AgentServer.ts +149 -0
  175. package/src/AuthHandler.ts +141 -0
  176. package/src/ConfigLoader.ts +165 -0
  177. package/src/ContextBuilder.ts +796 -0
  178. package/src/DataMap.ts +365 -0
  179. package/src/Logger.ts +197 -0
  180. package/src/PomBuilder.ts +298 -0
  181. package/src/PromptManager.ts +133 -0
  182. package/src/SchemaUtils.ts +170 -0
  183. package/src/ServerlessAdapter.ts +218 -0
  184. package/src/SessionManager.ts +161 -0
  185. package/src/SslConfig.ts +118 -0
  186. package/src/SwaigFunction.ts +168 -0
  187. package/src/SwaigFunctionResult.ts +864 -0
  188. package/src/SwmlBuilder.ts +62 -0
  189. package/src/cli/agent-loader.ts +122 -0
  190. package/src/cli/mock-data.ts +110 -0
  191. package/src/cli/swaig-test.ts +440 -0
  192. package/src/index.ts +99 -0
  193. package/src/prefabs/ConciergeAgent.ts +251 -0
  194. package/src/prefabs/FAQBotAgent.ts +263 -0
  195. package/src/prefabs/InfoGathererAgent.ts +276 -0
  196. package/src/prefabs/ReceptionistAgent.ts +277 -0
  197. package/src/prefabs/SurveyAgent.ts +413 -0
  198. package/src/prefabs/index.ts +23 -0
  199. package/src/skills/SkillBase.ts +184 -0
  200. package/src/skills/SkillManager.ts +177 -0
  201. package/src/skills/SkillRegistry.ts +231 -0
  202. package/src/skills/builtin/api_ninjas_trivia.ts +230 -0
  203. package/src/skills/builtin/claude_skills.ts +239 -0
  204. package/src/skills/builtin/custom_skills.ts +326 -0
  205. package/src/skills/builtin/datasphere.ts +225 -0
  206. package/src/skills/builtin/datasphere_serverless.ts +194 -0
  207. package/src/skills/builtin/datetime.ts +115 -0
  208. package/src/skills/builtin/google_maps.ts +347 -0
  209. package/src/skills/builtin/index.ts +79 -0
  210. package/src/skills/builtin/info_gatherer.ts +331 -0
  211. package/src/skills/builtin/joke.ts +180 -0
  212. package/src/skills/builtin/math.ts +150 -0
  213. package/src/skills/builtin/mcp_gateway.ts +99 -0
  214. package/src/skills/builtin/native_vector_search.ts +327 -0
  215. package/src/skills/builtin/play_background_file.ts +189 -0
  216. package/src/skills/builtin/spider.ts +232 -0
  217. package/src/skills/builtin/swml_transfer.ts +285 -0
  218. package/src/skills/builtin/weather_api.ts +193 -0
  219. package/src/skills/builtin/web_search.ts +212 -0
  220. package/src/skills/builtin/wikipedia_search.ts +248 -0
  221. package/src/skills/index.ts +12 -0
  222. package/src/types.ts +99 -0
  223. package/tests/AgentBase.test.ts +693 -0
  224. package/tests/AgentServer.test.ts +102 -0
  225. package/tests/AuthHandler.test.ts +121 -0
  226. package/tests/ConfigLoader.test.ts +121 -0
  227. package/tests/DataMap.test.ts +286 -0
  228. package/tests/Logger.test.ts +218 -0
  229. package/tests/PomBuilder.test.ts +164 -0
  230. package/tests/ProxyDetection.test.ts +185 -0
  231. package/tests/SchemaUtils.test.ts +106 -0
  232. package/tests/ServerlessAdapter.test.ts +200 -0
  233. package/tests/SessionManager.test.ts +139 -0
  234. package/tests/SslConfig.test.ts +97 -0
  235. package/tests/SwaigFunctionResult.test.ts +298 -0
  236. package/tests/cli/mock-data.test.ts +94 -0
  237. package/tests/cli/swaig-test.test.ts +96 -0
  238. package/tests/prefabs/prefabs.test.ts +854 -0
  239. package/tests/setup.ts +6 -0
  240. package/tests/skills/SkillBase.test.ts +118 -0
  241. package/tests/skills/SkillManager.test.ts +164 -0
  242. package/tests/skills/SkillRegistry.test.ts +124 -0
  243. package/tests/skills/builtin.test.ts +924 -0
  244. package/tsconfig.json +18 -0
  245. package/vitest.config.ts +9 -0
@@ -0,0 +1,513 @@
1
+ # Serverless Deployment Guide
2
+
3
+ ## Table of Contents
4
+
5
+ - [Overview](#overview)
6
+ - [ServerlessAdapter](#serverlessadapter)
7
+ - [AWS Lambda](#aws-lambda)
8
+ - [Google Cloud Functions](#google-cloud-functions)
9
+ - [Azure Functions](#azure-functions)
10
+ - [CGI Mode](#cgi-mode)
11
+ - [Platform Detection](#platform-detection)
12
+ - [URL Generation](#url-generation)
13
+ - [CLI Testing](#cli-testing)
14
+
15
+ ---
16
+
17
+ ## Overview
18
+
19
+ The SignalWire AI Agents TypeScript SDK can be deployed to serverless platforms using the `ServerlessAdapter` class (`src/ServerlessAdapter.ts`). The adapter converts platform-specific event formats into standard `Request` objects, routes them through the Hono application, and returns normalized responses.
20
+
21
+ Supported platforms:
22
+
23
+ | Platform | Identifier | Factory Method |
24
+ |---|---|---|
25
+ | AWS Lambda | `lambda` | `ServerlessAdapter.createLambdaHandler()` |
26
+ | Google Cloud Functions | `gcf` | `ServerlessAdapter.createGcfHandler()` |
27
+ | Azure Functions | `azure` | `ServerlessAdapter.createAzureHandler()` |
28
+ | CGI | `cgi` | Manual via `handleRequest()` |
29
+
30
+ ---
31
+
32
+ ## ServerlessAdapter
33
+
34
+ ### Constructor
35
+
36
+ ```typescript
37
+ import { ServerlessAdapter } from '@anthropic/signalwire-agents';
38
+
39
+ // Auto-detect platform from environment variables
40
+ const adapter = new ServerlessAdapter();
41
+ // or: new ServerlessAdapter('auto')
42
+
43
+ // Explicit platform selection
44
+ const lambdaAdapter = new ServerlessAdapter('lambda');
45
+ const gcfAdapter = new ServerlessAdapter('gcf');
46
+ const azureAdapter = new ServerlessAdapter('azure');
47
+ const cgiAdapter = new ServerlessAdapter('cgi');
48
+ ```
49
+
50
+ The `platform` parameter accepts `'lambda' | 'gcf' | 'azure' | 'cgi' | 'auto'`. When set to `'auto'` (the default), the platform is detected from environment variables (see [Platform Detection](#platform-detection)).
51
+
52
+ ### Core Types
53
+
54
+ **`ServerlessEvent`** -- Normalized incoming event:
55
+
56
+ ```typescript
57
+ interface ServerlessEvent {
58
+ httpMethod?: string; // HTTP method (AWS Lambda style)
59
+ method?: string; // HTTP method (GCF/Azure style)
60
+ headers?: Record<string, string>; // Request headers
61
+ body?: string | Record<string, unknown>; // Raw or parsed request body
62
+ path?: string; // Request path
63
+ rawPath?: string; // Raw path (AWS API Gateway v2)
64
+ queryStringParameters?: Record<string, string>; // Query parameters
65
+ requestContext?: Record<string, unknown>; // Platform-specific context
66
+ }
67
+ ```
68
+
69
+ **`ServerlessResponse`** -- Normalized outgoing response:
70
+
71
+ ```typescript
72
+ interface ServerlessResponse {
73
+ statusCode: number; // HTTP status code
74
+ headers: Record<string, string>; // Response headers
75
+ body: string; // Response body as string
76
+ }
77
+ ```
78
+
79
+ ### handleRequest()
80
+
81
+ The core method that processes any serverless event through a Hono app:
82
+
83
+ ```typescript
84
+ const adapter = new ServerlessAdapter('lambda');
85
+ const agent = new AgentBase({ name: 'my-agent' });
86
+ const app = agent.getApp();
87
+
88
+ const response = await adapter.handleRequest(app, event);
89
+ // response: { statusCode: 200, headers: {...}, body: '...' }
90
+ ```
91
+
92
+ **Processing steps:**
93
+
94
+ 1. Extract HTTP method from `event.httpMethod` (Lambda) or `event.method` (GCF/Azure), defaulting to `POST`.
95
+ 2. Extract path from `event.rawPath` (API Gateway v2) or `event.path`, defaulting to `/`.
96
+ 3. Build a full URL from the `host` and `x-forwarded-proto` headers.
97
+ 4. Append query string parameters if present.
98
+ 5. Create a standard `Request` object and route it through `app.fetch()`.
99
+ 6. Convert the `Response` back into a `ServerlessResponse`.
100
+
101
+ ---
102
+
103
+ ## AWS Lambda
104
+
105
+ Use `ServerlessAdapter.createLambdaHandler()` to create a Lambda-compatible handler function.
106
+
107
+ ### Example: Lambda Handler
108
+
109
+ ```typescript
110
+ // handler.ts
111
+ import { AgentBase, ServerlessAdapter } from '@anthropic/signalwire-agents';
112
+
113
+ const agent = new AgentBase({
114
+ name: 'lambda-agent',
115
+ basicAuth: ['admin', process.env.AGENT_PASSWORD!],
116
+ });
117
+
118
+ agent.setPromptText('You are a helpful assistant deployed on AWS Lambda.');
119
+
120
+ agent.defineTool({
121
+ name: 'get_status',
122
+ description: 'Get the current system status',
123
+ parameters: {
124
+ type: 'object',
125
+ properties: {
126
+ system: { type: 'string', description: 'System name' },
127
+ },
128
+ },
129
+ handler: async (args) => {
130
+ const { SwaigFunctionResult } = await import('@anthropic/signalwire-agents');
131
+ const result = new SwaigFunctionResult();
132
+ result.setResponse(`System ${args.system} is operational.`);
133
+ return result;
134
+ },
135
+ });
136
+
137
+ const app = agent.getApp();
138
+
139
+ // Export the Lambda handler
140
+ export const handler = ServerlessAdapter.createLambdaHandler(app);
141
+ ```
142
+
143
+ ### How It Works
144
+
145
+ `createLambdaHandler()` creates a new `ServerlessAdapter` instance with `platform: 'lambda'` and returns a function with the signature:
146
+
147
+ ```typescript
148
+ (event: ServerlessEvent) => Promise<ServerlessResponse>
149
+ ```
150
+
151
+ This matches the AWS Lambda handler contract. The event object maps directly to API Gateway proxy integration events (both v1 and v2):
152
+
153
+ - `event.httpMethod` -- HTTP method (v1)
154
+ - `event.rawPath` -- Request path (v2, preferred)
155
+ - `event.path` -- Request path (v1 fallback)
156
+ - `event.headers` -- Request headers
157
+ - `event.body` -- Request body (string)
158
+ - `event.queryStringParameters` -- Query parameters
159
+
160
+ ### Deployment
161
+
162
+ ```bash
163
+ # Build and package
164
+ npm run build
165
+ zip -r function.zip dist/ node_modules/ package.json
166
+
167
+ # Deploy via AWS CLI
168
+ aws lambda create-function \
169
+ --function-name my-agent \
170
+ --runtime nodejs20.x \
171
+ --handler dist/handler.handler \
172
+ --zip-file fileb://function.zip \
173
+ --environment "Variables={AGENT_PASSWORD=s3cret}"
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Google Cloud Functions
179
+
180
+ Use `ServerlessAdapter.createGcfHandler()` to create a GCF-compatible handler.
181
+
182
+ ### Example: Cloud Function Handler
183
+
184
+ ```typescript
185
+ // index.ts
186
+ import { AgentBase, ServerlessAdapter } from '@anthropic/signalwire-agents';
187
+
188
+ const agent = new AgentBase({
189
+ name: 'gcf-agent',
190
+ basicAuth: ['admin', process.env.AGENT_PASSWORD!],
191
+ });
192
+
193
+ agent.setPromptText('You are a helpful assistant on Google Cloud Functions.');
194
+
195
+ const app = agent.getApp();
196
+
197
+ // Export the GCF handler
198
+ export const agentHandler = ServerlessAdapter.createGcfHandler(app);
199
+ ```
200
+
201
+ ### How It Works
202
+
203
+ `createGcfHandler()` returns a function with the signature:
204
+
205
+ ```typescript
206
+ (req: any, res: any) => Promise<void>
207
+ ```
208
+
209
+ This matches the Google Cloud Functions HTTP function contract. The adapter:
210
+
211
+ 1. Constructs a `ServerlessEvent` from the GCF `req` object:
212
+ - `req.method` -- HTTP method
213
+ - `req.headers` -- Request headers
214
+ - `req.body` -- Request body (already parsed by GCF)
215
+ - `req.path` or `req.url` -- Request path
216
+ 2. Routes through the Hono app via `handleRequest()`.
217
+ 3. Writes the response to `res` using `res.status()`, `res.set()`, and `res.send()`.
218
+
219
+ ### Deployment
220
+
221
+ ```bash
222
+ # Deploy via gcloud CLI
223
+ gcloud functions deploy agentHandler \
224
+ --runtime nodejs20 \
225
+ --trigger-http \
226
+ --entry-point agentHandler \
227
+ --set-env-vars AGENT_PASSWORD=s3cret \
228
+ --allow-unauthenticated
229
+ ```
230
+
231
+ ---
232
+
233
+ ## Azure Functions
234
+
235
+ Use `ServerlessAdapter.createAzureHandler()` to create an Azure Functions-compatible handler.
236
+
237
+ ### Example: Azure Function Handler
238
+
239
+ ```typescript
240
+ // index.ts
241
+ import { AgentBase, ServerlessAdapter } from '@anthropic/signalwire-agents';
242
+
243
+ const agent = new AgentBase({
244
+ name: 'azure-agent',
245
+ basicAuth: ['admin', process.env.AGENT_PASSWORD!],
246
+ });
247
+
248
+ agent.setPromptText('You are a helpful assistant on Azure Functions.');
249
+
250
+ const app = agent.getApp();
251
+
252
+ // Export the Azure handler
253
+ const azureHandler = ServerlessAdapter.createAzureHandler(app);
254
+ export default azureHandler;
255
+ ```
256
+
257
+ ### How It Works
258
+
259
+ `createAzureHandler()` returns a function with the signature:
260
+
261
+ ```typescript
262
+ (context: any, req: any) => Promise<void>
263
+ ```
264
+
265
+ This matches the Azure Functions HTTP trigger contract. The adapter:
266
+
267
+ 1. Constructs a `ServerlessEvent` from the Azure `req` object:
268
+ - `req.method` -- HTTP method
269
+ - `req.headers` -- Request headers
270
+ - `req.body` -- Request body
271
+ - `req.url` -- Request path
272
+ 2. Routes through the Hono app via `handleRequest()`.
273
+ 3. Sets `context.res` with `status`, `headers`, and `body`.
274
+
275
+ ### Deployment
276
+
277
+ ```bash
278
+ # Deploy via Azure CLI
279
+ func azure functionapp publish my-agent-app \
280
+ --typescript
281
+ ```
282
+
283
+ ### function.json
284
+
285
+ ```json
286
+ {
287
+ "bindings": [
288
+ {
289
+ "authLevel": "anonymous",
290
+ "type": "httpTrigger",
291
+ "direction": "in",
292
+ "name": "req",
293
+ "methods": ["get", "post"]
294
+ },
295
+ {
296
+ "type": "http",
297
+ "direction": "out",
298
+ "name": "res"
299
+ }
300
+ ]
301
+ }
302
+ ```
303
+
304
+ ---
305
+
306
+ ## CGI Mode
307
+
308
+ For traditional CGI environments, use the `ServerlessAdapter` with `platform: 'cgi'`:
309
+
310
+ ```typescript
311
+ import { AgentBase, ServerlessAdapter } from '@anthropic/signalwire-agents';
312
+
313
+ const agent = new AgentBase({ name: 'cgi-agent' });
314
+ agent.setPromptText('You are a CGI-deployed assistant.');
315
+
316
+ const adapter = new ServerlessAdapter('cgi');
317
+ const app = agent.getApp();
318
+
319
+ // Read CGI environment and stdin to build a ServerlessEvent
320
+ const event = {
321
+ method: process.env.REQUEST_METHOD ?? 'GET',
322
+ headers: {
323
+ 'content-type': process.env.CONTENT_TYPE ?? 'application/json',
324
+ host: process.env.HTTP_HOST ?? 'localhost',
325
+ authorization: process.env.HTTP_AUTHORIZATION ?? '',
326
+ },
327
+ path: process.env.PATH_INFO ?? '/',
328
+ body: await readStdin(),
329
+ };
330
+
331
+ const response = await adapter.handleRequest(app, event);
332
+
333
+ // Write CGI response
334
+ process.stdout.write(`Status: ${response.statusCode}\r\n`);
335
+ for (const [key, value] of Object.entries(response.headers)) {
336
+ process.stdout.write(`${key}: ${value}\r\n`);
337
+ }
338
+ process.stdout.write('\r\n');
339
+ process.stdout.write(response.body);
340
+ ```
341
+
342
+ CGI mode is auto-detected when the `GATEWAY_INTERFACE` environment variable is present (e.g., `GATEWAY_INTERFACE=CGI/1.1`).
343
+
344
+ ---
345
+
346
+ ## Platform Detection
347
+
348
+ When the `ServerlessAdapter` is created with `platform: 'auto'` (the default), the platform is detected by checking for well-known environment variables in the following order:
349
+
350
+ | Order | Environment Variables Checked | Detected Platform |
351
+ |---|---|---|
352
+ | 1 | `AWS_LAMBDA_FUNCTION_NAME` or `_HANDLER` | `lambda` |
353
+ | 2 | `FUNCTION_TARGET` or `K_SERVICE` | `gcf` |
354
+ | 3 | `FUNCTIONS_WORKER_RUNTIME` or `AZURE_FUNCTIONS_ENVIRONMENT` | `azure` |
355
+ | 4 | `GATEWAY_INTERFACE` | `cgi` |
356
+ | 5 | *(none matched)* | `lambda` (default fallback) |
357
+
358
+ ```typescript
359
+ const adapter = new ServerlessAdapter('auto');
360
+ console.log(adapter.getPlatform());
361
+ // 'lambda', 'gcf', 'azure', or 'cgi'
362
+ ```
363
+
364
+ The `detectPlatform()` method can also be called explicitly:
365
+
366
+ ```typescript
367
+ const adapter = new ServerlessAdapter('auto');
368
+ const platform = adapter.detectPlatform();
369
+ ```
370
+
371
+ ---
372
+
373
+ ## URL Generation
374
+
375
+ The `generateUrl()` method constructs the expected invocation URL for a deployed function on each platform:
376
+
377
+ ```typescript
378
+ const adapter = new ServerlessAdapter('lambda');
379
+ const url = adapter.generateUrl({
380
+ region: 'us-west-2',
381
+ apiId: 'abc123xyz',
382
+ stage: 'prod',
383
+ });
384
+ // "https://abc123xyz.execute-api.us-west-2.amazonaws.com/prod"
385
+ ```
386
+
387
+ ### URL Formats by Platform
388
+
389
+ **AWS Lambda (API Gateway)**
390
+
391
+ ```typescript
392
+ const adapter = new ServerlessAdapter('lambda');
393
+ adapter.generateUrl({
394
+ region: 'us-east-1', // default: AWS_REGION env or 'us-east-1'
395
+ apiId: 'abc123', // default: 'API_ID'
396
+ stage: 'prod', // default: 'prod'
397
+ });
398
+ // "https://abc123.execute-api.us-east-1.amazonaws.com/prod"
399
+ ```
400
+
401
+ **Google Cloud Functions**
402
+
403
+ ```typescript
404
+ const adapter = new ServerlessAdapter('gcf');
405
+ adapter.generateUrl({
406
+ projectId: 'my-project', // default: GCLOUD_PROJECT env or 'PROJECT'
407
+ region: 'us-central1', // default: FUNCTION_REGION env or 'us-central1'
408
+ functionName: 'agent', // default: AWS_LAMBDA_FUNCTION_NAME env or 'agent'
409
+ });
410
+ // "https://us-central1-my-project.cloudfunctions.net/agent"
411
+ ```
412
+
413
+ **Azure Functions**
414
+
415
+ ```typescript
416
+ const adapter = new ServerlessAdapter('azure');
417
+ adapter.generateUrl({
418
+ functionName: 'my-agent', // default: 'agent'
419
+ });
420
+ // "https://my-agent.azurewebsites.net/api/my-agent"
421
+ ```
422
+
423
+ **CGI**
424
+
425
+ ```typescript
426
+ const adapter = new ServerlessAdapter('cgi');
427
+ adapter.generateUrl({
428
+ functionName: 'my-agent',
429
+ });
430
+ // "http://localhost/cgi-bin/my-agent"
431
+ ```
432
+
433
+ ### generateUrl() Options
434
+
435
+ | Option | Type | Default | Description |
436
+ |---|---|---|---|
437
+ | `region` | `string` | Platform-specific env var or default | Cloud region for the function. |
438
+ | `projectId` | `string` | `GCLOUD_PROJECT` env or `"PROJECT"` | GCP project ID (GCF only). |
439
+ | `functionName` | `string` | `AWS_LAMBDA_FUNCTION_NAME` env or `"agent"` | Name of the deployed function. |
440
+ | `stage` | `string` | `"prod"` | API Gateway stage (Lambda only). |
441
+ | `apiId` | `string` | `"API_ID"` | API Gateway ID (Lambda only). |
442
+
443
+ ---
444
+
445
+ ## CLI Testing
446
+
447
+ You can test serverless deployments locally using the `swaig-test` CLI tool. While there is no dedicated `--simulate-serverless` flag, you can test agent functionality locally before deploying:
448
+
449
+ ### Testing Tools Locally
450
+
451
+ ```bash
452
+ # List all registered tools
453
+ npx swaig-test --file handler.ts --list-tools
454
+
455
+ # Dump the SWML document the agent generates
456
+ npx swaig-test --file handler.ts --dump-swml
457
+
458
+ # Execute a specific tool with arguments
459
+ npx swaig-test --file handler.ts --exec get_status --args '{"system": "production"}'
460
+ ```
461
+
462
+ ### Local Development Pattern
463
+
464
+ For local development and testing before deploying to a serverless platform, run the agent as a standard HTTP server:
465
+
466
+ ```typescript
467
+ // local-dev.ts
468
+ import { AgentBase } from '@anthropic/signalwire-agents';
469
+
470
+ const agent = new AgentBase({
471
+ name: 'my-agent',
472
+ port: 3000,
473
+ });
474
+
475
+ agent.setPromptText('You are a helpful assistant.');
476
+
477
+ // In development, run as an HTTP server
478
+ if (process.env.NODE_ENV !== 'production') {
479
+ agent.serve();
480
+ }
481
+
482
+ // Export the app for serverless deployment
483
+ export const app = agent.getApp();
484
+ ```
485
+
486
+ ### Simulating Serverless Events
487
+
488
+ You can manually test the `ServerlessAdapter` with constructed events:
489
+
490
+ ```typescript
491
+ import { AgentBase, ServerlessAdapter } from '@anthropic/signalwire-agents';
492
+
493
+ const agent = new AgentBase({ name: 'test-agent', basicAuth: ['admin', 'test'] });
494
+ agent.setPromptText('Hello!');
495
+
496
+ const adapter = new ServerlessAdapter('lambda');
497
+ const app = agent.getApp();
498
+
499
+ // Simulate a Lambda event
500
+ const event = {
501
+ httpMethod: 'POST',
502
+ path: '/',
503
+ headers: {
504
+ 'content-type': 'application/json',
505
+ authorization: 'Basic ' + Buffer.from('admin:test').toString('base64'),
506
+ },
507
+ body: JSON.stringify({ call_id: 'test-call-123' }),
508
+ };
509
+
510
+ const response = await adapter.handleRequest(app, event);
511
+ console.log('Status:', response.statusCode);
512
+ console.log('Body:', response.body);
513
+ ```