@andreprado/agentkit 0.1.0-alpha.9 → 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 (117) hide show
  1. package/README.md +18 -1
  2. package/docs/guides/add-channel.md +251 -7
  3. package/docs/guides/add-knowledge.md +10 -0
  4. package/docs/guides/add-managed-composio.md +165 -0
  5. package/docs/guides/add-tool.md +10 -3
  6. package/docs/guides/channel-security.md +162 -32
  7. package/docs/guides/connect-discord.md +178 -0
  8. package/docs/guides/connect-slack.md +126 -0
  9. package/docs/guides/connect-telegram.md +61 -1
  10. package/docs/guides/connect-whatsapp-evolution.md +121 -0
  11. package/docs/guides/connect-whatsapp-uazapi.md +139 -0
  12. package/docs/guides/connect-whatsapp-zapster.md +119 -16
  13. package/docs/guides/create-agent.md +31 -4
  14. package/docs/guides/debug-channel.md +159 -0
  15. package/docs/guides/improve-from-production.md +151 -0
  16. package/docs/guides/prepare-deploy.md +32 -14
  17. package/docs/guides/replay-production-traces.md +72 -0
  18. package/docs/guides/run-evals.md +95 -25
  19. package/docs/guides/security-rules.md +9 -5
  20. package/docs/guides/send-feedback.md +135 -0
  21. package/docs/guides/use-jev.md +67 -0
  22. package/docs/guides/use-provider.md +70 -3
  23. package/docs/llms-full.txt +295 -25
  24. package/docs/llms.txt +54 -7
  25. package/package.json +3 -7
  26. package/src/cli/args.ts +23 -2
  27. package/src/cli/cloud-client.ts +121 -9
  28. package/src/cli/commands/channels.ts +856 -36
  29. package/src/cli/commands/feedback.ts +438 -0
  30. package/src/cli/commands/provider.ts +47 -0
  31. package/src/cli/commands/transcribe.ts +171 -0
  32. package/src/cli/deploy-chat-ui.ts +232 -18
  33. package/src/cli/deploy-readiness.ts +227 -14
  34. package/src/cli/help.ts +67 -9
  35. package/src/cli/index.ts +740 -35
  36. package/src/cli/new-command.ts +41 -0
  37. package/src/cloud/client.ts +4 -3
  38. package/src/cloud/contracts.ts +1 -1
  39. package/src/create-project.ts +18 -35
  40. package/src/index.ts +565 -11
  41. package/src/providers/codex-auth.ts +111 -0
  42. package/src/providers/pi.ts +88 -19
  43. package/src/providers/test.ts +36 -0
  44. package/src/providers/types.ts +8 -0
  45. package/src/runtime/channel-test-harness.ts +21 -1
  46. package/src/runtime/channels/discord.ts +896 -0
  47. package/src/runtime/channels/generic-webhook.ts +974 -0
  48. package/src/runtime/channels/slack.ts +646 -0
  49. package/src/runtime/channels/telegram.ts +343 -12
  50. package/src/runtime/channels/whatsapp-evolution.ts +1357 -0
  51. package/src/runtime/channels/whatsapp-meta.ts +9 -0
  52. package/src/runtime/channels/whatsapp-uazapi.ts +1323 -0
  53. package/src/runtime/channels/whatsapp-zapster.ts +674 -40
  54. package/src/runtime/channels.ts +83 -3
  55. package/src/runtime/chat.ts +70 -44
  56. package/src/runtime/config.ts +489 -20
  57. package/src/runtime/core/manifest.ts +75 -5
  58. package/src/runtime/core/targets.ts +5 -5
  59. package/src/runtime/deploy-readiness.ts +34 -4
  60. package/src/runtime/dev-server.ts +639 -39
  61. package/src/runtime/env.ts +8 -3
  62. package/src/runtime/evals.ts +445 -74
  63. package/src/runtime/improve.ts +868 -0
  64. package/src/runtime/inspect.ts +173 -4
  65. package/src/runtime/integrations/composio.ts +425 -0
  66. package/src/runtime/knowledge/retrieve.ts +25 -5
  67. package/src/runtime/knowledge/schema.ts +45 -1
  68. package/src/runtime/prompt-context.ts +141 -0
  69. package/src/runtime/runtime-contract.ts +71 -7
  70. package/src/runtime/skills.ts +95 -0
  71. package/src/runtime/targets/cloudflare/build.ts +1010 -208
  72. package/src/runtime/targets/container/server.ts +1 -1
  73. package/src/runtime/targets/vps/deploy.ts +26 -9
  74. package/src/runtime/tool-runner.ts +9 -1
  75. package/src/runtime/tools.ts +26 -2
  76. package/src/runtime/transcription.ts +483 -0
  77. package/src/storage/sqlite.ts +7 -2
  78. package/src/templates/blank.ts +37 -9
  79. package/src/templates/dentista.ts +40 -14
  80. package/src/templates/skills/agentkit-build-agent/SKILL.md +34 -5
  81. package/src/templates/skills/agentkit-build-agent/templates/appointment-intake.instructions.md +2 -1
  82. package/src/templates/skills/agentkit-capsule/SKILL.md +32 -3
  83. package/src/templates/skills/agentkit-capsule/references/docs-router.md +2 -2
  84. package/src/templates/skills/agentkit-channels/SKILL.md +66 -1
  85. package/src/templates/skills/agentkit-channels/references/channel-buffering.md +8 -1
  86. package/src/templates/skills/agentkit-channels/references/channel-debugging.md +28 -3
  87. package/src/templates/skills/agentkit-channels/references/discord.md +93 -0
  88. package/src/templates/skills/agentkit-channels/references/slack.md +56 -0
  89. package/src/templates/skills/agentkit-channels/references/telegram.md +34 -0
  90. package/src/templates/skills/agentkit-channels/references/whatsapp-evolution.md +57 -0
  91. package/src/templates/skills/agentkit-channels/references/whatsapp-uazapi.md +54 -0
  92. package/src/templates/skills/agentkit-channels/references/whatsapp-zapster.md +42 -8
  93. package/src/templates/skills/agentkit-database/SKILL.md +11 -0
  94. package/src/templates/skills/agentkit-deploy/SKILL.md +9 -1
  95. package/src/templates/skills/agentkit-evals/SKILL.md +77 -13
  96. package/src/templates/skills/agentkit-evals/templates/multi-turn.eval.md +13 -6
  97. package/src/templates/skills/agentkit-evals/templates/no-leak.eval.md +8 -4
  98. package/src/templates/skills/agentkit-evals/templates/smoke.eval.md +8 -4
  99. package/src/templates/skills/agentkit-evals/templates/tool-call.eval.md +16 -7
  100. package/src/templates/skills/agentkit-improve/SKILL.md +96 -0
  101. package/src/templates/skills/agentkit-improve/references/replay-side-effects.md +18 -0
  102. package/src/templates/skills/agentkit-improve/references/trace-packets.md +22 -0
  103. package/src/templates/skills/agentkit-improve/templates/regression.eval.md +18 -0
  104. package/src/templates/skills/agentkit-integrations/SKILL.md +98 -0
  105. package/src/templates/skills/agentkit-knowledge/SKILL.md +4 -1
  106. package/src/templates/skills/agentkit-prompts/SKILL.md +3 -1
  107. package/src/templates/skills/agentkit-provider/SKILL.md +29 -4
  108. package/src/templates/skills/agentkit-security/SKILL.md +5 -2
  109. package/src/templates/skills/agentkit-tools/SKILL.md +8 -1
  110. package/src/templates/skills/agentkit-tools/examples/eval-safe-external-action.tool.md +8 -8
  111. package/src/templates/skills/agentkit-tools/examples/jev-service-fit.tool.md +110 -0
  112. package/src/templates/skills/agentkit-troubleshooting/SKILL.md +25 -1
  113. package/src/templates/support.ts +42 -12
  114. package/docs/guides/agentkit-skills-architecture.md +0 -471
  115. package/docs/guides/channels-implementation-map.md +0 -243
  116. package/docs/guides/channels-production-handoff.md +0 -101
  117. package/docs/portable-deploy-release-checklist.md +0 -41
package/src/index.ts CHANGED
@@ -1,11 +1,15 @@
1
1
  export type AgentRuntime = "local" | "edge";
2
- export type AgentProviderName = "test" | "openai" | "anthropic" | "openrouter" | "custom";
2
+ export type AgentProviderName = "test" | "openai" | "openai-codex" | "anthropic" | "openrouter" | "opencode" | "opencode-go" | "custom";
3
3
  export type AccessMode = "private" | "token" | "public";
4
4
  export type ToolVisibility = "user" | "internal";
5
- export type ChannelType = "website" | "telegram" | "whatsapp";
6
- export type ChannelProvider = "agentkit" | "telegram" | "zapster" | "meta";
7
- export type WhatsappChannelProvider = "zapster" | "meta";
5
+ export type ChannelType = "website" | "telegram" | "whatsapp" | "discord" | "slack" | "webhook";
6
+ export type ChannelProvider = "agentkit" | "telegram" | "zapster" | "meta" | "uazapi" | "evolution" | "discord" | "slack" | "generic";
7
+ export type WhatsappChannelProvider = "zapster" | "meta" | "uazapi" | "evolution";
8
+ export type DiscordChannelMode = "interactions" | "bot";
8
9
  export type TelegramAllowedUpdate = "message";
10
+ export type ChannelAudioMode = "off" | "reject" | "transcribe";
11
+ export type TranscriptionProviderName = "test" | "openai" | "groq";
12
+ export type GenericWebhookDirection = "inbound" | "outbound";
9
13
 
10
14
  export type AgentProvider = {
11
15
  name: AgentProviderName;
@@ -39,6 +43,76 @@ export type ChannelBufferConfig =
39
43
  maxChars: number;
40
44
  };
41
45
 
46
+ export type ChannelAudioInput = {
47
+ mode?: ChannelAudioMode;
48
+ fallbackMessage?: string;
49
+ maxDurationSeconds?: number;
50
+ maxBytes?: number;
51
+ };
52
+
53
+ export type ChannelAudioConfig =
54
+ | {
55
+ mode: "off";
56
+ }
57
+ | {
58
+ mode: "reject";
59
+ fallbackMessage: string;
60
+ maxDurationSeconds?: number;
61
+ maxBytes?: number;
62
+ }
63
+ | {
64
+ mode: "transcribe";
65
+ fallbackMessage: string;
66
+ maxDurationSeconds?: number;
67
+ maxBytes?: number;
68
+ };
69
+
70
+ export type ChannelReplyRouteInput = {
71
+ channel: string;
72
+ recipientFrom?: string;
73
+ };
74
+
75
+ export type ChannelReplyRouteConfig = {
76
+ channel: string;
77
+ recipientFrom?: string;
78
+ };
79
+
80
+ export type GenericWebhookOutputAuthInput =
81
+ | {
82
+ type: "none";
83
+ }
84
+ | {
85
+ type: "bearer";
86
+ tokenSecret: string;
87
+ }
88
+ | {
89
+ type: "header";
90
+ headerName: string;
91
+ valueSecret: string;
92
+ }
93
+ | {
94
+ type: "hmac";
95
+ secret: string;
96
+ headerName?: string;
97
+ };
98
+
99
+ export type GenericWebhookOutputAuthConfig = GenericWebhookOutputAuthInput;
100
+
101
+ export type AgentTranscriptionLimits = {
102
+ maxDurationSeconds?: number;
103
+ maxBytes?: number;
104
+ };
105
+
106
+ export type AgentTranscriptionConfig = {
107
+ provider: TranscriptionProviderName;
108
+ model: string;
109
+ secret?: string;
110
+ language?: string;
111
+ prompt?: string;
112
+ limits?: AgentTranscriptionLimits;
113
+ rawAudioTtlSeconds?: number;
114
+ };
115
+
42
116
  export type WebsiteChannelAccess = {
43
117
  mode: "token";
44
118
  };
@@ -49,6 +123,8 @@ export type WebsiteChannelInput = {
49
123
  secrets?: string[];
50
124
  limits?: ChannelLimits;
51
125
  buffer?: ChannelBufferInput;
126
+ audio?: ChannelAudioInput;
127
+ replyTo?: ChannelReplyRouteInput;
52
128
  };
53
129
 
54
130
  export type WebsiteChannelConfig = {
@@ -59,6 +135,8 @@ export type WebsiteChannelConfig = {
59
135
  secrets: string[];
60
136
  limits?: ChannelLimits;
61
137
  buffer?: ChannelBufferConfig;
138
+ audio?: ChannelAudioConfig;
139
+ replyTo?: ChannelReplyRouteConfig;
62
140
  };
63
141
 
64
142
  export type TelegramChannelInput = {
@@ -67,6 +145,8 @@ export type TelegramChannelInput = {
67
145
  allowedUpdates?: TelegramAllowedUpdate[];
68
146
  limits?: ChannelLimits;
69
147
  buffer?: ChannelBufferInput;
148
+ audio?: ChannelAudioInput;
149
+ replyTo?: ChannelReplyRouteInput;
70
150
  };
71
151
 
72
152
  export type TelegramChannelConfig = {
@@ -77,6 +157,8 @@ export type TelegramChannelConfig = {
77
157
  allowedUpdates: TelegramAllowedUpdate[];
78
158
  limits?: ChannelLimits;
79
159
  buffer?: ChannelBufferConfig;
160
+ audio?: ChannelAudioConfig;
161
+ replyTo?: ChannelReplyRouteConfig;
80
162
  };
81
163
 
82
164
  export type WhatsappChannelInput = {
@@ -85,6 +167,8 @@ export type WhatsappChannelInput = {
85
167
  secrets?: string[];
86
168
  limits?: ChannelLimits;
87
169
  buffer?: ChannelBufferInput;
170
+ audio?: ChannelAudioInput;
171
+ replyTo?: ChannelReplyRouteInput;
88
172
  };
89
173
 
90
174
  export type WhatsappChannelConfig = {
@@ -94,9 +178,128 @@ export type WhatsappChannelConfig = {
94
178
  secrets: string[];
95
179
  limits?: ChannelLimits;
96
180
  buffer?: ChannelBufferConfig;
181
+ audio?: ChannelAudioConfig;
182
+ replyTo?: ChannelReplyRouteConfig;
183
+ };
184
+
185
+ export type DiscordChannelInput = {
186
+ name: string;
187
+ mode?: DiscordChannelMode;
188
+ secrets?: string[];
189
+ limits?: ChannelLimits;
190
+ buffer?: ChannelBufferInput;
191
+ replyTo?: ChannelReplyRouteInput;
192
+ };
193
+
194
+ export type DiscordChannelConfig = {
195
+ type: "discord";
196
+ provider: "discord";
197
+ name: string;
198
+ mode: DiscordChannelMode;
199
+ secrets: string[];
200
+ limits?: ChannelLimits;
201
+ buffer?: ChannelBufferConfig;
202
+ replyTo?: ChannelReplyRouteConfig;
203
+ audio?: never;
204
+ };
205
+
206
+ export type SlackChannelInput = {
207
+ name: string;
208
+ secrets?: string[];
209
+ limits?: ChannelLimits;
210
+ buffer?: ChannelBufferInput;
211
+ replyTo?: ChannelReplyRouteInput;
212
+ };
213
+
214
+ export type SlackChannelConfig = {
215
+ type: "slack";
216
+ provider: "slack";
217
+ name: string;
218
+ secrets: string[];
219
+ limits?: ChannelLimits;
220
+ buffer?: ChannelBufferConfig;
221
+ replyTo?: ChannelReplyRouteConfig;
222
+ audio?: never;
223
+ };
224
+
225
+ export type GenericWebhookChannelInput = {
226
+ name: string;
227
+ secrets?: string[];
228
+ limits?: ChannelLimits;
229
+ buffer?: ChannelBufferInput;
230
+ replyTo?: ChannelReplyRouteInput;
231
+ };
232
+
233
+ export type GenericWebhookChannelConfig = {
234
+ type: "webhook";
235
+ provider: "generic";
236
+ direction: "inbound";
237
+ name: string;
238
+ secrets: string[];
239
+ limits?: ChannelLimits;
240
+ buffer?: ChannelBufferConfig;
241
+ replyTo?: ChannelReplyRouteConfig;
242
+ urlSecret?: never;
243
+ auth?: never;
244
+ audio?: never;
97
245
  };
98
246
 
99
- export type AgentChannel = WebsiteChannelConfig | TelegramChannelConfig | WhatsappChannelConfig;
247
+ export type GenericWebhookOutputChannelInput = {
248
+ name: string;
249
+ urlSecret: string;
250
+ auth?: GenericWebhookOutputAuthInput;
251
+ secrets?: string[];
252
+ limits?: ChannelLimits;
253
+ };
254
+
255
+ export type GenericWebhookOutputChannelConfig = {
256
+ type: "webhook";
257
+ provider: "generic";
258
+ direction: "outbound";
259
+ name: string;
260
+ urlSecret: string;
261
+ auth: GenericWebhookOutputAuthConfig;
262
+ secrets: string[];
263
+ limits?: ChannelLimits;
264
+ buffer?: never;
265
+ replyTo?: never;
266
+ audio?: never;
267
+ };
268
+
269
+ export type AgentChannel =
270
+ | WebsiteChannelConfig
271
+ | TelegramChannelConfig
272
+ | WhatsappChannelConfig
273
+ | DiscordChannelConfig
274
+ | SlackChannelConfig
275
+ | GenericWebhookChannelConfig
276
+ | GenericWebhookOutputChannelConfig;
277
+
278
+ export type IntegrationTagsConfig = {
279
+ enable?: string[];
280
+ disable?: string[];
281
+ };
282
+
283
+ export type ComposioManagedIntegrationInput = {
284
+ name?: string;
285
+ toolkits: string[];
286
+ tools?: Record<string, string[]>;
287
+ tags?: IntegrationTagsConfig;
288
+ confirmExternalWrites?: boolean;
289
+ };
290
+
291
+ export type ComposioManagedIntegration = {
292
+ type: "composio";
293
+ provider: "composio";
294
+ mode: "managed";
295
+ name: string;
296
+ toolkits: string[];
297
+ tools?: Record<string, string[]>;
298
+ tags?: IntegrationTagsConfig;
299
+ confirmExternalWrites?: boolean;
300
+ };
301
+
302
+ export type AgentIntegration = ComposioManagedIntegration;
100
303
 
101
304
  export type AgentDatabaseConfig =
102
305
  | {
@@ -210,6 +413,7 @@ export type ToolRenderResult = {
210
413
  export type ToolRenderContext<Input = unknown> = {
211
414
  input: Input;
212
415
  runtime: ToolRuntimeContext;
416
+ clock: ToolClockContext;
213
417
  };
214
418
 
215
419
  export type ToolRuntimeContext = {
@@ -219,10 +423,20 @@ export type ToolRuntimeContext = {
219
423
  database: "sqlite" | "turso" | "none";
220
424
  };
221
425
 
426
+ export type ToolClockContext = {
427
+ now: Date;
428
+ isoTimestamp: string;
429
+ timeZone: string;
430
+ localDate: string;
431
+ localWeekday: string;
432
+ localDateTime: string;
433
+ };
434
+
222
435
  export type ToolContext = {
223
436
  secrets: Record<string, string>;
224
437
  signal: AbortSignal;
225
438
  runtime: ToolRuntimeContext;
439
+ clock: ToolClockContext;
226
440
  database: DatabaseRunner;
227
441
  db: DatabaseRunner;
228
442
  storage: {
@@ -254,10 +468,13 @@ export type AgentConfig = {
254
468
  name: string;
255
469
  runtime: AgentRuntime;
256
470
  provider: AgentProvider;
471
+ timeZone?: string;
257
472
  instructions: string;
258
473
  secrets: string[];
259
474
  tools?: AgentTool[];
475
+ integrations?: AgentIntegration[];
260
476
  channels?: AgentChannel[];
477
+ transcription?: AgentTranscriptionConfig;
261
478
  knowledge?: AgentKnowledgeConfig;
262
479
  access: {
263
480
  mode: AccessMode;
@@ -278,6 +495,25 @@ export function defineTool<Input = unknown, Output = unknown>(tool: AgentTool<In
278
495
  return tool;
279
496
  }
280
497
 
498
+ export function composioManaged(input: ComposioManagedIntegrationInput): ComposioManagedIntegration {
499
+ const name = normalizeIntegrationName(input.name ?? "composio", "composio integration name");
500
+ const toolkits = normalizeToolkitList(input.toolkits, "composioManaged.toolkits");
501
+ const tools = input.tools ? normalizeComposioToolMap(input.tools, toolkits) : undefined;
502
+ const tags = input.tags ? normalizeIntegrationTags(input.tags) : undefined;
503
+ const confirmExternalWrites = input.confirmExternalWrites;
504
+
505
+ return {
506
+ type: "composio",
507
+ provider: "composio",
508
+ mode: "managed",
509
+ name,
510
+ toolkits,
511
+ ...(tools ? { tools } : {}),
512
+ ...(tags ? { tags } : {}),
513
+ ...(confirmExternalWrites === undefined ? {} : { confirmExternalWrites }),
514
+ };
515
+ }
516
+
281
517
  export function websiteChannel(input: WebsiteChannelInput): WebsiteChannelConfig {
282
518
  return {
283
519
  type: "website",
@@ -287,6 +523,8 @@ export function websiteChannel(input: WebsiteChannelInput): WebsiteChannelConfig
287
523
  secrets: normalizeChannelSecrets(input.secrets ?? ["AGENTKIT_WEBSITE_CHANNEL_TOKEN"], "website channel"),
288
524
  ...(input.limits ? { limits: input.limits } : {}),
289
525
  ...(input.buffer ? { buffer: normalizeChannelBuffer(input.buffer, "website channel") } : {}),
526
+ ...(input.audio ? { audio: normalizeChannelAudio(input.audio, "website channel") } : {}),
527
+ ...(input.replyTo ? { replyTo: normalizeChannelReplyRoute(input.replyTo, "website channel") } : {}),
290
528
  };
291
529
  }
292
530
 
@@ -302,6 +540,8 @@ export function telegramChannel(input: TelegramChannelInput): TelegramChannelCon
302
540
  allowedUpdates: input.allowedUpdates ?? ["message"],
303
541
  ...(input.limits ? { limits: input.limits } : {}),
304
542
  ...(input.buffer ? { buffer: normalizeChannelBuffer(input.buffer, "telegram channel") } : {}),
543
+ ...(input.audio ? { audio: normalizeChannelAudio(input.audio, "telegram channel") } : {}),
544
+ ...(input.replyTo ? { replyTo: normalizeChannelReplyRoute(input.replyTo, "telegram channel") } : {}),
305
545
  };
306
546
  }
307
547
 
@@ -316,12 +556,86 @@ export function whatsappChannel(input: WhatsappChannelInput): WhatsappChannelCon
316
556
  ),
317
557
  ...(input.limits ? { limits: input.limits } : {}),
318
558
  ...(input.buffer ? { buffer: normalizeChannelBuffer(input.buffer, `${input.provider} whatsapp channel`) } : {}),
559
+ ...(input.audio ? { audio: normalizeChannelAudio(input.audio, `${input.provider} whatsapp channel`) } : {}),
560
+ ...(input.replyTo ? { replyTo: normalizeChannelReplyRoute(input.replyTo, `${input.provider} whatsapp channel`) } : {}),
561
+ };
562
+ }
563
+
564
+ export function discordChannel(input: DiscordChannelInput): DiscordChannelConfig {
565
+ const mode = input.mode ?? "interactions";
566
+
567
+ return {
568
+ type: "discord",
569
+ provider: "discord",
570
+ name: input.name,
571
+ mode,
572
+ secrets: normalizeChannelSecrets(input.secrets ?? defaultDiscordChannelSecrets(mode), "discord channel"),
573
+ ...(input.limits ? { limits: input.limits } : {}),
574
+ ...(input.buffer ? { buffer: normalizeChannelBuffer(input.buffer, "discord channel") } : {}),
575
+ ...(input.replyTo ? { replyTo: normalizeChannelReplyRoute(input.replyTo, "discord channel") } : {}),
576
+ };
577
+ }
578
+
579
+ export function slackChannel(input: SlackChannelInput): SlackChannelConfig {
580
+ return {
581
+ type: "slack",
582
+ provider: "slack",
583
+ name: input.name,
584
+ secrets: normalizeChannelSecrets(input.secrets ?? ["SLACK_BOT_TOKEN", "SLACK_SIGNING_SECRET"], "slack channel"),
585
+ ...(input.limits ? { limits: input.limits } : {}),
586
+ ...(input.buffer ? { buffer: normalizeChannelBuffer(input.buffer, "slack channel") } : {}),
587
+ ...(input.replyTo ? { replyTo: normalizeChannelReplyRoute(input.replyTo, "slack channel") } : {}),
588
+ };
589
+ }
590
+
591
+ export function webhookChannel(input: GenericWebhookChannelInput): GenericWebhookChannelConfig {
592
+ return {
593
+ type: "webhook",
594
+ provider: "generic",
595
+ direction: "inbound",
596
+ name: input.name,
597
+ secrets: normalizeChannelSecrets(input.secrets ?? ["AGENTKIT_WEBHOOK_SECRET"], "generic webhook channel"),
598
+ ...(input.limits ? { limits: input.limits } : {}),
599
+ ...(input.buffer ? { buffer: normalizeChannelBuffer(input.buffer, "generic webhook channel") } : {}),
600
+ ...(input.replyTo ? { replyTo: normalizeChannelReplyRoute(input.replyTo, "generic webhook channel") } : {}),
319
601
  };
320
602
  }
321
603
 
604
+ export function webhookOutputChannel(input: GenericWebhookOutputChannelInput): GenericWebhookOutputChannelConfig {
605
+ const auth = normalizeGenericWebhookOutputAuth(input.auth ?? { type: "none" }, "generic webhook output channel");
606
+ const requiredSecrets = [
607
+ input.urlSecret,
608
+ ...genericWebhookOutputAuthSecrets(auth),
609
+ ...(input.secrets ?? []),
610
+ ];
611
+
612
+ return {
613
+ type: "webhook",
614
+ provider: "generic",
615
+ direction: "outbound",
616
+ name: input.name,
617
+ urlSecret: normalizeSecretName(input.urlSecret, "generic webhook output channel urlSecret"),
618
+ auth,
619
+ secrets: normalizeChannelSecrets(requiredSecrets, "generic webhook output channel"),
620
+ ...(input.limits ? { limits: input.limits } : {}),
621
+ };
622
+ }
623
+
624
+ function defaultDiscordChannelSecrets(mode: DiscordChannelMode): string[] {
625
+ return mode === "bot" ? ["DISCORD_BOT_TOKEN"] : ["DISCORD_PUBLIC_KEY"];
626
+ }
627
+
322
628
  function defaultWhatsappChannelSecrets(provider: WhatsappChannelProvider): string[] {
323
629
  if (provider === "zapster") {
324
- return ["ZAPSTER_API_KEY", "ZAPSTER_WEBHOOK_SECRET"];
630
+ return ["ZAPSTER_API_KEY", "ZAPSTER_INSTANCE_ID", "ZAPSTER_WEBHOOK_ID", "ZAPSTER_WEBHOOK_TOKEN"];
631
+ }
632
+
633
+ if (provider === "uazapi") {
634
+ return ["UAZAPI_BASE_URL", "UAZAPI_TOKEN", "UAZAPI_WEBHOOK_TOKEN"];
635
+ }
636
+
637
+ if (provider === "evolution") {
638
+ return ["EVOLUTION_API_BASE_URL", "EVOLUTION_API_KEY", "EVOLUTION_INSTANCE_NAME", "EVOLUTION_WEBHOOK_TOKEN"];
325
639
  }
326
640
 
327
641
  return ["META_WHATSAPP_ACCESS_TOKEN", "META_WHATSAPP_APP_SECRET", "META_WHATSAPP_VERIFY_TOKEN"];
@@ -331,14 +645,125 @@ function normalizeChannelSecrets(secrets: string[], context: string): string[] {
331
645
  const uniqueSecrets = new Set<string>();
332
646
 
333
647
  for (const secret of secrets) {
334
- if (!/^[A-Z_][A-Z0-9_]*$/.test(secret)) {
335
- throw new Error(`${context} secrets must be environment variable names, not secret values.`);
648
+ uniqueSecrets.add(normalizeSecretName(secret, `${context} secrets`));
649
+ }
650
+
651
+ return Array.from(uniqueSecrets).sort();
652
+ }
653
+
654
+ function normalizeSecretName(secret: string, context: string): string {
655
+ if (!/^[A-Z_][A-Z0-9_]*$/.test(secret)) {
656
+ if (context.endsWith("secrets")) {
657
+ throw new Error(`${context} must be environment variable names, not secret values.`);
336
658
  }
337
659
 
338
- uniqueSecrets.add(secret);
660
+ throw new Error(`${context} must be an environment variable name, not a secret value.`);
339
661
  }
340
662
 
341
- return Array.from(uniqueSecrets).sort();
663
+ return secret;
664
+ }
665
+
666
+ function normalizeIntegrationName(value: string, context: string): string {
667
+ const name = value.trim();
668
+
669
+ if (!/^[a-z][a-z0-9-]*$/.test(name)) {
670
+ throw new Error(`${context} must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`);
671
+ }
672
+
673
+ return name;
674
+ }
675
+
676
+ function normalizeToolkitList(values: string[], context: string): string[] {
677
+ if (!Array.isArray(values) || values.length === 0) {
678
+ throw new Error(`${context} must include at least one toolkit slug.`);
679
+ }
680
+
681
+ const toolkits = new Set<string>();
682
+
683
+ for (const value of values) {
684
+ if (typeof value !== "string") {
685
+ throw new Error(`${context} entries must be toolkit slug strings.`);
686
+ }
687
+
688
+ const toolkit = value.trim().toLowerCase();
689
+
690
+ if (!/^[a-z][a-z0-9_-]*$/.test(toolkit)) {
691
+ throw new Error(`${context} entries must start with a letter and contain only letters, numbers, underscores, and hyphens.`);
692
+ }
693
+
694
+ toolkits.add(toolkit);
695
+ }
696
+
697
+ return Array.from(toolkits).sort();
698
+ }
699
+
700
+ function normalizeComposioToolMap(values: Record<string, string[]>, toolkits: string[]): Record<string, string[]> | undefined {
701
+ const toolkitSet = new Set(toolkits);
702
+ const normalized: Record<string, string[]> = {};
703
+
704
+ for (const [rawToolkit, rawTools] of Object.entries(values)) {
705
+ const toolkit = rawToolkit.trim().toLowerCase();
706
+
707
+ if (!toolkitSet.has(toolkit)) {
708
+ throw new Error(`composioManaged.tools.${rawToolkit} must reference a toolkit listed in composioManaged.toolkits.`);
709
+ }
710
+
711
+ if (!Array.isArray(rawTools) || rawTools.length === 0) {
712
+ throw new Error(`composioManaged.tools.${rawToolkit} must include at least one Composio action slug.`);
713
+ }
714
+
715
+ const tools = new Set<string>();
716
+
717
+ for (const rawTool of rawTools) {
718
+ if (typeof rawTool !== "string") {
719
+ throw new Error(`composioManaged.tools.${rawToolkit} entries must be Composio action slug strings.`);
720
+ }
721
+
722
+ const tool = rawTool.trim().toUpperCase();
723
+
724
+ if (!/^[A-Z][A-Z0-9_]*$/.test(tool)) {
725
+ throw new Error(`composioManaged.tools.${rawToolkit} entries must be uppercase Composio action slugs.`);
726
+ }
727
+
728
+ tools.add(tool);
729
+ }
730
+
731
+ normalized[toolkit] = Array.from(tools).sort();
732
+ }
733
+
734
+ return Object.keys(normalized).length > 0 ? normalized : undefined;
735
+ }
736
+
737
+ function normalizeIntegrationTags(tags: IntegrationTagsConfig): IntegrationTagsConfig {
738
+ const normalized: IntegrationTagsConfig = {};
739
+
740
+ if (tags.enable !== undefined) {
741
+ normalized.enable = normalizeTagList(tags.enable, "composioManaged.tags.enable");
742
+ }
743
+
744
+ if (tags.disable !== undefined) {
745
+ normalized.disable = normalizeTagList(tags.disable, "composioManaged.tags.disable");
746
+ }
747
+
748
+ return normalized;
749
+ }
750
+
751
+ function normalizeTagList(values: string[], context: string): string[] {
752
+ if (!Array.isArray(values)) {
753
+ throw new Error(`${context} must be an array of tag strings.`);
754
+ }
755
+
756
+ return Array.from(
757
+ new Set(
758
+ values.map((value) => {
759
+ if (typeof value !== "string" || value.trim().length === 0) {
760
+ throw new Error(`${context} entries must be non-empty strings.`);
761
+ }
762
+
763
+ return value.trim();
764
+ }),
765
+ ),
766
+ ).sort();
342
767
  }
343
768
 
344
769
  function normalizeChannelBuffer(input: ChannelBufferInput, context: string): ChannelBufferConfig {
@@ -370,6 +795,114 @@ function normalizeChannelBuffer(input: ChannelBufferInput, context: string): Cha
370
795
  return buffer;
371
796
  }
372
797
 
798
+ function normalizeChannelAudio(input: ChannelAudioInput, context: string): ChannelAudioConfig {
799
+ const mode = input.mode ?? "transcribe";
800
+
801
+ if (mode !== "off" && mode !== "reject" && mode !== "transcribe") {
802
+ throw new Error(`${context} audio.mode must be "off", "reject", or "transcribe".`);
803
+ }
804
+
805
+ if (mode === "off") {
806
+ return { mode: "off" };
807
+ }
808
+
809
+ if (input.maxDurationSeconds !== undefined) {
810
+ validatePositiveInteger(input.maxDurationSeconds, `${context} audio.maxDurationSeconds`);
811
+ }
812
+
813
+ if (input.maxBytes !== undefined) {
814
+ validatePositiveInteger(input.maxBytes, `${context} audio.maxBytes`);
815
+ }
816
+
817
+ return {
818
+ mode,
819
+ fallbackMessage: input.fallbackMessage ?? "I received an audio message, but I could not transcribe it. Please send the message as text.",
820
+ ...(input.maxDurationSeconds !== undefined ? { maxDurationSeconds: input.maxDurationSeconds } : {}),
821
+ ...(input.maxBytes !== undefined ? { maxBytes: input.maxBytes } : {}),
822
+ };
823
+ }
824
+
825
+ function normalizeChannelReplyRoute(input: ChannelReplyRouteInput, context: string): ChannelReplyRouteConfig {
826
+ const channel = input.channel.trim();
827
+
828
+ if (!/^[a-z][a-z0-9-]*$/.test(channel)) {
829
+ throw new Error(`${context} replyTo.channel must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`);
830
+ }
831
+
832
+ return {
833
+ channel,
834
+ ...(input.recipientFrom ? { recipientFrom: normalizeJsonPath(input.recipientFrom, `${context} replyTo.recipientFrom`) } : {}),
835
+ };
836
+ }
837
+
838
+ function normalizeJsonPath(value: string, context: string): string {
839
+ const path = value.trim().replace(/^payload\./, "");
840
+
841
+ if (!/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(path)) {
842
+ throw new Error(`${context} must be a dotted JSON field path such as "phone" or "customer.phone".`);
843
+ }
844
+
845
+ return path;
846
+ }
847
+
848
+ function normalizeGenericWebhookOutputAuth(
849
+ auth: GenericWebhookOutputAuthInput,
850
+ context: string,
851
+ ): GenericWebhookOutputAuthConfig {
852
+ if (auth.type === "none") {
853
+ return { type: "none" };
854
+ }
855
+
856
+ if (auth.type === "bearer") {
857
+ return {
858
+ type: "bearer",
859
+ tokenSecret: normalizeSecretName(auth.tokenSecret, `${context} auth.tokenSecret`),
860
+ };
861
+ }
862
+
863
+ if (auth.type === "header") {
864
+ if (!/^[A-Za-z][A-Za-z0-9-]*$/.test(auth.headerName)) {
865
+ throw new Error(`${context} auth.headerName must be an HTTP header name.`);
866
+ }
867
+
868
+ return {
869
+ type: "header",
870
+ headerName: auth.headerName,
871
+ valueSecret: normalizeSecretName(auth.valueSecret, `${context} auth.valueSecret`),
872
+ };
873
+ }
874
+
875
+ if (auth.type === "hmac") {
876
+ if (auth.headerName !== undefined && !/^[A-Za-z][A-Za-z0-9-]*$/.test(auth.headerName)) {
877
+ throw new Error(`${context} auth.headerName must be an HTTP header name.`);
878
+ }
879
+
880
+ return {
881
+ type: "hmac",
882
+ secret: normalizeSecretName(auth.secret, `${context} auth.secret`),
883
+ ...(auth.headerName ? { headerName: auth.headerName } : {}),
884
+ };
885
+ }
886
+
887
+ throw new Error(`${context} auth.type must be "none", "bearer", "header", or "hmac".`);
888
+ }
889
+
890
+ function genericWebhookOutputAuthSecrets(auth: GenericWebhookOutputAuthConfig): string[] {
891
+ if (auth.type === "bearer") {
892
+ return [auth.tokenSecret];
893
+ }
894
+
895
+ if (auth.type === "header") {
896
+ return [auth.valueSecret];
897
+ }
898
+
899
+ if (auth.type === "hmac") {
900
+ return [auth.secret];
901
+ }
902
+
903
+ return [];
904
+ }
905
+
373
906
  function validatePositiveInteger(value: number, field: string): void {
374
907
  if (!Number.isInteger(value) || value <= 0) {
375
908
  throw new Error(`${field} must be a positive integer.`);
@@ -379,7 +912,18 @@ function validatePositiveInteger(value: number, field: string): void {
379
912
  export { loadAgentCapsule, findAgentCapsuleRoot } from "./runtime/config";
380
913
  export { runAgentMessage, runAgentMessageFromCwd } from "./runtime/chat";
381
914
  export { listConversationsFromCwd, getConversationFromCwd } from "./runtime/conversations";
382
- export { runEvalsFromCwd } from "./runtime/evals";
915
+ export { defineEval, runEvalsFromCwd } from "./runtime/evals";
916
+ export type {
917
+ EvalCase,
918
+ EvalExpect,
919
+ EvalResponseExpectation,
920
+ EvalRunSummary,
921
+ EvalResult,
922
+ EvalToolsContainerExpectation,
923
+ EvalToolsExpectation,
924
+ EvalTurn,
925
+ ToolExpectation,
926
+ } from "./runtime/evals";
383
927
  export { getConversationTraceFromCwd } from "./runtime/traces";
384
928
  export { runToolFromCwd } from "./runtime/tool-runner";
385
929
  export { startAgentDevServer } from "./runtime/dev-server";
@@ -390,19 +934,29 @@ export { AgentKitError } from "./runtime/errors";
390
934
  export type {
391
935
  ChannelAdapter,
392
936
  ChannelAdapterId,
937
+ ChannelAudioAttachment,
393
938
  ChannelDeliveryDirection,
394
939
  ChannelDeliveryState,
395
940
  ChannelEventKind,
396
941
  ChannelExternalIdentity,
942
+ ChannelMediaDownloadInput,
943
+ ChannelMediaDownloadResult,
397
944
  ChannelMessageContentType,
398
945
  ChannelMessageRole,
946
+ ChannelReplyTarget,
399
947
  ChannelSendInput,
400
948
  ChannelSendResult,
401
949
  ChannelStatusInput,
402
950
  ChannelStatusResult,
951
+ ChannelWebhookResponse,
403
952
  NormalizedChannelEvent,
404
953
  NormalizedChannelMessage,
405
954
  RawWebhookEvent,
406
955
  WebhookVerificationInput,
407
956
  WebhookVerificationResult,
408
957
  } from "./runtime/channels";
958
+ export type {
959
+ TranscriptionAdapter,
960
+ TranscriptionInput,
961
+ TranscriptionResult,
962
+ } from "./runtime/transcription";