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,422 @@
1
+ # Configuration
2
+
3
+ ## Table of Contents
4
+
5
+ - [Overview](#overview)
6
+ - [Constructor Options](#constructor-options)
7
+ - [Environment Variables](#environment-variables)
8
+ - [Config Files](#config-files)
9
+ - [Authentication](#authentication)
10
+ - [Logging](#logging)
11
+ - [Priority Order](#priority-order)
12
+
13
+ ---
14
+
15
+ ## Overview
16
+
17
+ The SignalWire AI Agents TypeScript SDK provides three layers of configuration:
18
+
19
+ 1. **Constructor options** -- passed directly when instantiating `AgentBase`.
20
+ 2. **Environment variables** -- read at startup for server, security, logging, and proxy settings.
21
+ 3. **Config files** -- JSON files loaded via `ConfigLoader` with environment variable interpolation.
22
+
23
+ These layers follow a well-defined priority order (see [Priority Order](#priority-order)) so that runtime overrides always take precedence over static defaults.
24
+
25
+ ---
26
+
27
+ ## Constructor Options
28
+
29
+ Pass an `AgentOptions` object to the `AgentBase` constructor to configure agent behavior. The interface is defined in `src/types.ts`.
30
+
31
+ ```typescript
32
+ import { AgentBase } from '@anthropic/signalwire-agents';
33
+
34
+ const agent = new AgentBase({
35
+ name: 'support-bot',
36
+ route: '/support',
37
+ port: 8080,
38
+ basicAuth: ['admin', 's3cret'],
39
+ autoAnswer: true,
40
+ recordCall: true,
41
+ tokenExpirySecs: 7200,
42
+ });
43
+ ```
44
+
45
+ ### AgentOptions Reference
46
+
47
+ | Property | Type | Default | Description |
48
+ |---|---|---|---|
49
+ | `name` | `string` | **(required)** | Display name of the agent. Also used as the default basic-auth username when credentials are auto-generated. |
50
+ | `route` | `string` | `"/"` | HTTP route path the agent listens on. Trailing slashes are stripped. |
51
+ | `host` | `string` | `"0.0.0.0"` | Hostname to bind the HTTP server to. |
52
+ | `port` | `number` | `PORT` env or `3000` | Port number for the HTTP server. |
53
+ | `basicAuth` | `[string, string]` | auto-generated | Explicit basic-auth credentials as `[username, password]`. If omitted, credentials are read from env vars or auto-generated. |
54
+ | `usePom` | `boolean` | `true` | Whether to use POM-based (Prompt Object Model) prompt rendering. |
55
+ | `tokenExpirySecs` | `number` | `3600` | Session token expiry in seconds for HMAC-signed SWAIG tokens. |
56
+ | `autoAnswer` | `boolean` | `true` | Whether to automatically insert an `answer` verb in the SWML call flow. |
57
+ | `recordCall` | `boolean` | `false` | Whether to record the call. |
58
+ | `recordFormat` | `string` | `"mp4"` | Recording format (e.g. `"mp4"`). |
59
+ | `recordStereo` | `boolean` | `true` | Whether to record in stereo. |
60
+ | `defaultWebhookUrl` | `string` | `null` | Default webhook URL for SWAIG function callbacks. |
61
+ | `nativeFunctions` | `string[]` | `[]` | List of native (platform-built-in) function names to include in the SWAIG configuration. |
62
+ | `agentId` | `string` | random hex (16 chars) | Unique identifier for this agent instance. Auto-generated via `randomBytes(8).toString('hex')` if omitted. |
63
+ | `suppressLogs` | `boolean` | `false` | When true, suppresses all log output from this agent. |
64
+
65
+ ---
66
+
67
+ ## Environment Variables
68
+
69
+ The SDK reads the following environment variables at startup. All are optional.
70
+
71
+ ### Server
72
+
73
+ | Variable | Type | Default | Description |
74
+ |---|---|---|---|
75
+ | `PORT` | `number` | `3000` | HTTP server port. Overridden by the constructor `port` option. |
76
+
77
+ ### Authentication
78
+
79
+ | Variable | Type | Default | Description |
80
+ |---|---|---|---|
81
+ | `SWML_BASIC_AUTH_USER` | `string` | -- | Basic-auth username. Used when no `basicAuth` constructor option is provided. |
82
+ | `SWML_BASIC_AUTH_PASSWORD` | `string` | -- | Basic-auth password. Both `_USER` and `_PASSWORD` must be set for env-based auth. |
83
+
84
+ ### Proxy Detection
85
+
86
+ | Variable | Type | Default | Description |
87
+ |---|---|---|---|
88
+ | `SWML_PROXY_URL_BASE` | `string` | -- | External-facing base URL for webhook URL generation (e.g. `https://my-agent.example.com`). When set, this takes priority over header-based proxy detection. |
89
+ | `SWML_PROXY_DEBUG` | `"true"` | -- | When `"true"`, logs proxy detection diagnostics at debug level. |
90
+
91
+ ### Logging
92
+
93
+ | Variable | Type | Default | Description |
94
+ |---|---|---|---|
95
+ | `SIGNALWIRE_LOG_LEVEL` | `"debug" \| "info" \| "warn" \| "error"` | `"info"` | Minimum log level. Messages below this level are suppressed. |
96
+ | `SIGNALWIRE_LOG_MODE` | `"off"` | -- | Set to `"off"` to suppress all log output globally. |
97
+ | `SIGNALWIRE_LOG_FORMAT` | `"text" \| "json"` | `"text"` | Log output format. `"text"` is human-readable; `"json"` emits structured JSON per line. |
98
+ | `SIGNALWIRE_LOG_COLOR` | `"true" \| "false"` | auto (TTY detection) | Enable or disable ANSI color codes in text-format output. Defaults to `true` when stdout is a TTY. |
99
+
100
+ ### Security
101
+
102
+ | Variable | Type | Default | Description |
103
+ |---|---|---|---|
104
+ | `SWML_CORS_ORIGINS` | `string` | `"*"` (all origins) | Comma-separated list of allowed CORS origins. Example: `"https://app.example.com,https://admin.example.com"`. |
105
+ | `SWML_ALLOWED_HOSTS` | `string` | -- (disabled) | Comma-separated allowlist of hostnames. Requests with a `Host` header not in this list receive a 403 response. |
106
+ | `SWML_MAX_REQUEST_SIZE` | `number` | `1048576` (1 MB) | Maximum allowed `Content-Length` in bytes. Requests exceeding this limit receive a 413 response. |
107
+ | `SWML_RATE_LIMIT` | `number` | -- (disabled) | Maximum requests per minute per IP address. When exceeded, the client receives a 429 response. |
108
+ | `SWML_REQUEST_TIMEOUT` | `number` | `30000` (30 sec) | Request timeout in milliseconds. |
109
+
110
+ ### SSL/TLS
111
+
112
+ | Variable | Type | Default | Description |
113
+ |---|---|---|---|
114
+ | `SWML_SSL_ENABLED` | `"true"` | `false` | Enable SSL/TLS for the HTTP server. |
115
+ | `SWML_SSL_CERT_PATH` | `string` | -- | Filesystem path to the PEM-encoded certificate file. |
116
+ | `SWML_SSL_KEY_PATH` | `string` | -- | Filesystem path to the PEM-encoded private key file. |
117
+ | `SWML_SSL_DOMAIN` | `string` | -- | Domain name used for HSTS (Strict-Transport-Security) headers. |
118
+
119
+ ### Skills
120
+
121
+ | Variable | Type | Default | Description |
122
+ |---|---|---|---|
123
+ | `SIGNALWIRE_SKILL_PATHS` | `string` | -- | Colon-separated list of directories to scan for skill modules. |
124
+
125
+ ### Schema Validation
126
+
127
+ | Variable | Type | Default | Description |
128
+ |---|---|---|---|
129
+ | `SWML_SKIP_SCHEMA_VALIDATION` | `"true"` | `false` | When `"true"`, skips JSON schema validation of SWML documents. |
130
+
131
+ ---
132
+
133
+ ## Config Files
134
+
135
+ The `ConfigLoader` class (`src/ConfigLoader.ts`) provides JSON configuration file loading with environment variable interpolation and dot-notation access.
136
+
137
+ ### Loading a Config File
138
+
139
+ ```typescript
140
+ import { ConfigLoader } from '@anthropic/signalwire-agents';
141
+
142
+ // Load by explicit path
143
+ const config = new ConfigLoader('./config/agent.json');
144
+
145
+ // Or load after construction
146
+ const config2 = new ConfigLoader();
147
+ config2.load('/etc/signalwire/agent.json');
148
+ ```
149
+
150
+ ### JSON Format with Environment Variable Interpolation
151
+
152
+ Config files are standard JSON with `${VAR|default}` interpolation syntax. Environment variables are resolved at load time.
153
+
154
+ ```json
155
+ {
156
+ "server": {
157
+ "port": "${PORT|3000}",
158
+ "host": "${HOST|0.0.0.0}"
159
+ },
160
+ "auth": {
161
+ "username": "${SWML_BASIC_AUTH_USER|admin}",
162
+ "password": "${SWML_BASIC_AUTH_PASSWORD}"
163
+ },
164
+ "agent": {
165
+ "name": "My Agent",
166
+ "model": "gpt-4"
167
+ }
168
+ }
169
+ ```
170
+
171
+ **Interpolation rules:**
172
+
173
+ - `${VAR}` -- replaced with the value of environment variable `VAR`, or an empty string if unset.
174
+ - `${VAR|default}` -- replaced with the value of `VAR`, or `"default"` if `VAR` is not set.
175
+
176
+ ### Search Paths
177
+
178
+ The static `ConfigLoader.search()` method looks for a config file in three standard locations, in order:
179
+
180
+ 1. Current working directory (`process.cwd()`)
181
+ 2. `./config/` subdirectory
182
+ 3. `$HOME/.signalwire/`
183
+
184
+ ```typescript
185
+ // Searches CWD, ./config/, and ~/.signalwire/ for "agent.json"
186
+ const config = ConfigLoader.search('agent.json');
187
+ if (config) {
188
+ console.log('Loaded from:', config.getFilePath());
189
+ }
190
+ ```
191
+
192
+ ### Dot-Notation Access
193
+
194
+ Use dot-separated paths to read and write nested values:
195
+
196
+ ```typescript
197
+ const config = new ConfigLoader('./config/agent.json');
198
+
199
+ // Read nested values with optional defaults
200
+ const port = config.get<number>('server.port', 3000);
201
+ const name = config.get<string>('agent.name', 'default-agent');
202
+
203
+ // Check existence
204
+ if (config.has('auth.password')) {
205
+ // ...
206
+ }
207
+
208
+ // Write nested values (intermediate objects created automatically)
209
+ config.set('agent.temperature', 0.7);
210
+
211
+ // Get entire config as a plain object
212
+ const all = config.getAll();
213
+ ```
214
+
215
+ ### Loading from Objects
216
+
217
+ For testing or programmatic configuration, load from a plain object:
218
+
219
+ ```typescript
220
+ const config = new ConfigLoader();
221
+ config.loadFromObject({
222
+ server: { port: 8080 },
223
+ agent: { name: 'test-agent' },
224
+ });
225
+ ```
226
+
227
+ ---
228
+
229
+ ## Authentication
230
+
231
+ ### Basic Auth in AgentBase
232
+
233
+ `AgentBase` uses Hono's built-in `basicAuth` middleware on all routes. Credentials are resolved in this order:
234
+
235
+ 1. **Constructor option** -- `basicAuth: ['user', 'pass']` in `AgentOptions` (source: `"provided"`).
236
+ 2. **Environment variables** -- `SWML_BASIC_AUTH_USER` and `SWML_BASIC_AUTH_PASSWORD` (source: `"environment"`).
237
+ 3. **Auto-generated** -- agent name as username with a random 16-character hex password (source: `"generated"`).
238
+
239
+ ```typescript
240
+ // 1. Explicit credentials
241
+ const agent = new AgentBase({
242
+ name: 'bot',
243
+ basicAuth: ['admin', 's3cret'],
244
+ });
245
+
246
+ // 2. Environment-based (set SWML_BASIC_AUTH_USER and SWML_BASIC_AUTH_PASSWORD)
247
+ const agent2 = new AgentBase({ name: 'bot' });
248
+
249
+ // Inspect the credentials and their source
250
+ const [user, pass, source] = agent.getBasicAuthCredentials(true);
251
+ // source: 'provided' | 'environment' | 'generated'
252
+ ```
253
+
254
+ ### Custom Basic Auth Validation
255
+
256
+ Override `validateBasicAuth()` in a subclass to add custom validation logic (e.g., database lookups). This hook runs after the standard credential check.
257
+
258
+ ```typescript
259
+ class MyAgent extends AgentBase {
260
+ validateBasicAuth(username: string, password: string): boolean {
261
+ // Add custom checks beyond credential matching
262
+ return username !== 'blocked-user';
263
+ }
264
+ }
265
+ ```
266
+
267
+ ### AuthHandler (Multi-Method Auth)
268
+
269
+ The `AuthHandler` class (`src/AuthHandler.ts`) supports multiple authentication methods with constant-time (timing-safe) credential comparison:
270
+
271
+ ```typescript
272
+ import { AuthHandler } from '@anthropic/signalwire-agents';
273
+
274
+ const auth = new AuthHandler({
275
+ bearerToken: 'my-secret-token', // Authorization: Bearer my-secret-token
276
+ apiKey: 'my-api-key-123', // X-Api-Key: my-api-key-123
277
+ basicAuth: ['admin', 'password'], // Authorization: Basic base64(admin:password)
278
+ customValidator: async (req) => { // Custom logic
279
+ return req.headers['x-custom'] === 'valid';
280
+ },
281
+ });
282
+
283
+ // Use as Hono middleware
284
+ app.use('/protected/*', auth.middleware());
285
+
286
+ // Or validate manually
287
+ const isValid = await auth.validate(requestHeaders);
288
+ ```
289
+
290
+ **Validation order:** Bearer token, API key, Basic auth, Custom validator. The first match succeeds. If no methods are configured, all requests are allowed (backwards compatibility).
291
+
292
+ **Introspection methods:**
293
+
294
+ | Method | Returns | Description |
295
+ |---|---|---|
296
+ | `hasBearerAuth()` | `boolean` | Whether a bearer token is configured |
297
+ | `hasApiKeyAuth()` | `boolean` | Whether an API key is configured |
298
+ | `hasBasicAuth()` | `boolean` | Whether basic auth credentials are configured |
299
+
300
+ ---
301
+
302
+ ## Logging
303
+
304
+ The `Logger` class (`src/Logger.ts`) provides structured logging with environment-variable-based configuration.
305
+
306
+ ### Log Levels
307
+
308
+ Four severity levels are supported, in ascending order:
309
+
310
+ | Level | Numeric | Description |
311
+ |---|---|---|
312
+ | `debug` | 0 | Verbose diagnostic information |
313
+ | `info` | 1 | General operational information (default) |
314
+ | `warn` | 2 | Potentially harmful situations |
315
+ | `error` | 3 | Error events that might still allow the application to continue |
316
+
317
+ ### Basic Usage
318
+
319
+ ```typescript
320
+ import { getLogger } from '@anthropic/signalwire-agents';
321
+
322
+ const log = getLogger('MyModule');
323
+
324
+ log.debug('Processing request', { requestId: '123' });
325
+ log.info('Agent started');
326
+ log.warn('Token expiring soon', { expiresIn: 300 });
327
+ log.error('Connection failed', { host: 'example.com' });
328
+ ```
329
+
330
+ ### Text Format (Default)
331
+
332
+ When `SIGNALWIRE_LOG_FORMAT` is `"text"` (the default):
333
+
334
+ ```
335
+ [INFO] [MyModule] Agent started
336
+ [WARN] [MyModule] Token expiring soon {"expiresIn":300}
337
+ ```
338
+
339
+ With color enabled (auto-detected when stdout is a TTY), level tags are color-coded:
340
+ - `debug` -- cyan
341
+ - `info` -- green
342
+ - `warn` -- yellow
343
+ - `error` -- red
344
+
345
+ ### JSON Format
346
+
347
+ Set `SIGNALWIRE_LOG_FORMAT=json` for structured output:
348
+
349
+ ```json
350
+ {"timestamp":"2025-01-15T10:30:00.000Z","level":"info","logger":"MyModule","message":"Agent started"}
351
+ ```
352
+
353
+ ### Context Binding with `bind()`
354
+
355
+ Create child loggers with additional context fields merged into every log entry:
356
+
357
+ ```typescript
358
+ const log = getLogger('Handler');
359
+
360
+ const requestLog = log.bind({ requestId: '456', callId: 'abc-123' });
361
+ requestLog.info('Handling request');
362
+ // Output includes requestId and callId in every entry
363
+ ```
364
+
365
+ ### Programmatic Configuration
366
+
367
+ ```typescript
368
+ import {
369
+ setGlobalLogLevel,
370
+ suppressAllLogs,
371
+ setGlobalLogFormat,
372
+ setGlobalLogColor,
373
+ resetLoggingConfiguration,
374
+ } from '@anthropic/signalwire-agents';
375
+
376
+ // Change log level at runtime
377
+ setGlobalLogLevel('debug');
378
+
379
+ // Suppress all output
380
+ suppressAllLogs(true);
381
+
382
+ // Switch to JSON format
383
+ setGlobalLogFormat('json');
384
+
385
+ // Force color on/off
386
+ setGlobalLogColor(false);
387
+
388
+ // Reset everything to env-var defaults
389
+ resetLoggingConfiguration();
390
+ ```
391
+
392
+ ### Environment Variable Summary
393
+
394
+ | Variable | Values | Default | Description |
395
+ |---|---|---|---|
396
+ | `SIGNALWIRE_LOG_LEVEL` | `debug`, `info`, `warn`, `error` | `info` | Minimum level to emit |
397
+ | `SIGNALWIRE_LOG_MODE` | `off` | -- | Set to `off` to suppress all output |
398
+ | `SIGNALWIRE_LOG_FORMAT` | `text`, `json` | `text` | Output format |
399
+ | `SIGNALWIRE_LOG_COLOR` | `true`, `false` | auto (TTY) | ANSI color codes in text mode |
400
+
401
+ ---
402
+
403
+ ## Priority Order
404
+
405
+ When the same setting can be configured in multiple places, the following priority order applies (highest to lowest):
406
+
407
+ ```
408
+ Environment Variables > Constructor Options > Config File > Defaults
409
+ ```
410
+
411
+ Specific resolution examples:
412
+
413
+ | Setting | Resolution |
414
+ |---|---|
415
+ | **Port** | `PORT` env var > `opts.port` > `3000` |
416
+ | **Basic auth** | `opts.basicAuth` > `SWML_BASIC_AUTH_USER`/`PASSWORD` env vars > auto-generated |
417
+ | **Log level** | `SIGNALWIRE_LOG_LEVEL` env var > programmatic `setGlobalLogLevel()` > `"info"` |
418
+ | **CORS origins** | `SWML_CORS_ORIGINS` env var > `"*"` (permissive default) |
419
+ | **Proxy URL** | `SWML_PROXY_URL_BASE` env var > `manualSetProxyUrl()` > header-based detection > local URL |
420
+ | **SSL** | `SslOptions` constructor > `SWML_SSL_*` env vars > disabled |
421
+
422
+ Note that basic auth is an exception: the constructor option takes precedence over environment variables. For most other settings, environment variables override constructor options to support container-based deployment patterns where env vars are the primary configuration mechanism.