@andreprado/agentkit 0.1.0-alpha.17 → 0.1.0-alpha.19

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 (64) hide show
  1. package/README.md +3 -0
  2. package/docs/guides/add-channel.md +14 -8
  3. package/docs/guides/add-knowledge.md +10 -0
  4. package/docs/guides/add-managed-composio.md +43 -17
  5. package/docs/guides/channel-security.md +60 -39
  6. package/docs/guides/connect-discord.md +178 -0
  7. package/docs/guides/create-agent.md +13 -0
  8. package/docs/guides/debug-channel.md +147 -0
  9. package/docs/guides/improve-from-production.md +151 -0
  10. package/docs/guides/prepare-deploy.md +30 -14
  11. package/docs/guides/replay-production-traces.md +72 -0
  12. package/docs/guides/run-evals.md +18 -0
  13. package/docs/guides/security-rules.md +5 -5
  14. package/docs/guides/use-provider.md +11 -1
  15. package/docs/llms-full.txt +106 -15
  16. package/docs/llms.txt +22 -4
  17. package/package.json +1 -3
  18. package/src/cli/args.ts +23 -2
  19. package/src/cli/cloud-client.ts +75 -0
  20. package/src/cli/commands/channels.ts +139 -14
  21. package/src/cli/deploy-chat-ui.ts +146 -3
  22. package/src/cli/deploy-readiness.ts +57 -1
  23. package/src/cli/help.ts +32 -8
  24. package/src/cli/index.ts +447 -17
  25. package/src/create-project.ts +13 -2
  26. package/src/index.ts +46 -3
  27. package/src/providers/pi.ts +49 -15
  28. package/src/runtime/channel-test-harness.ts +4 -1
  29. package/src/runtime/channels/discord.ts +887 -0
  30. package/src/runtime/channels.ts +15 -0
  31. package/src/runtime/config.ts +39 -3
  32. package/src/runtime/core/manifest.ts +2 -0
  33. package/src/runtime/dev-server.ts +149 -8
  34. package/src/runtime/evals.ts +27 -6
  35. package/src/runtime/improve.ts +868 -0
  36. package/src/runtime/inspect.ts +1 -0
  37. package/src/runtime/integrations/composio.ts +168 -2
  38. package/src/runtime/knowledge/retrieve.ts +25 -5
  39. package/src/runtime/knowledge/schema.ts +45 -1
  40. package/src/runtime/runtime-contract.ts +54 -0
  41. package/src/runtime/targets/cloudflare/build.ts +479 -194
  42. package/src/runtime/targets/vps/deploy.ts +1 -1
  43. package/src/storage/sqlite.ts +7 -2
  44. package/src/templates/skills/agentkit-capsule/SKILL.md +8 -1
  45. package/src/templates/skills/agentkit-capsule/references/docs-router.md +1 -2
  46. package/src/templates/skills/agentkit-channels/SKILL.md +6 -1
  47. package/src/templates/skills/agentkit-channels/references/channel-debugging.md +2 -1
  48. package/src/templates/skills/agentkit-channels/references/discord.md +93 -0
  49. package/src/templates/skills/agentkit-deploy/SKILL.md +6 -0
  50. package/src/templates/skills/agentkit-evals/SKILL.md +12 -3
  51. package/src/templates/skills/agentkit-improve/SKILL.md +86 -0
  52. package/src/templates/skills/agentkit-improve/references/replay-side-effects.md +18 -0
  53. package/src/templates/skills/agentkit-improve/references/trace-packets.md +22 -0
  54. package/src/templates/skills/agentkit-improve/templates/regression.eval.md +18 -0
  55. package/src/templates/skills/agentkit-integrations/SKILL.md +12 -2
  56. package/src/templates/skills/agentkit-knowledge/SKILL.md +4 -1
  57. package/src/templates/skills/agentkit-provider/SKILL.md +4 -1
  58. package/src/templates/skills/agentkit-security/SKILL.md +3 -2
  59. package/src/templates/skills/agentkit-troubleshooting/SKILL.md +9 -0
  60. package/src/templates/support.ts +4 -2
  61. package/docs/guides/agentkit-skills-architecture.md +0 -472
  62. package/docs/guides/channels-implementation-map.md +0 -243
  63. package/docs/guides/channels-production-handoff.md +0 -118
  64. package/docs/portable-deploy-release-checklist.md +0 -41
@@ -14,8 +14,9 @@ type DeployState = LocalDeployState;
14
14
  type CloudChannel = {
15
15
  id: string;
16
16
  name: string;
17
- type: "website" | "telegram" | "whatsapp";
18
- provider: "agentkit" | "telegram" | "zapster" | "meta";
17
+ type: "website" | "telegram" | "whatsapp" | "discord";
18
+ provider: "agentkit" | "telegram" | "zapster" | "meta" | "discord";
19
+ mode?: "interactions" | "bot";
19
20
  status: string;
20
21
  webhook_url: string;
21
22
  required_secrets: Array<{ name: string; status: string }>;
@@ -128,6 +129,7 @@ export async function handleChannelsCommand(args: ParsedArgs): Promise<void> {
128
129
  name: channel.name,
129
130
  type: channel.type,
130
131
  provider: channel.provider,
132
+ ...(channel.type === "discord" ? { mode: channel.mode } : {}),
131
133
  status: "local_config",
132
134
  webhook_url: "",
133
135
  required_secrets: channel.secrets.map((name) => ({ name, status: "missing" })),
@@ -140,11 +142,11 @@ export async function handleChannelsCommand(args: ParsedArgs): Promise<void> {
140
142
  const type = first;
141
143
  const name = second;
142
144
 
143
- if (!type || !name || (type !== "website" && type !== "telegram" && type !== "whatsapp")) {
144
- throw new Error("Usage: agentkit channels add <website|telegram|whatsapp> <name> [--provider zapster|meta]");
145
+ if (!type || !name || (type !== "website" && type !== "telegram" && type !== "whatsapp" && type !== "discord")) {
146
+ throw new Error("Usage: agentkit channels add <website|telegram|whatsapp|discord> <name> [--provider zapster|meta] [--mode interactions|bot]");
145
147
  }
146
148
 
147
- const response = await createHostedChannel(type, name, args.flags.provider, args.flags.api);
149
+ const response = await createHostedChannel(type, name, args.flags.provider, args.flags.mode, args.flags.api);
148
150
  printChannelStatus(response.channel);
149
151
  printSecretRepairHint(response.channel);
150
152
  return;
@@ -154,11 +156,11 @@ export async function handleChannelsCommand(args: ParsedArgs): Promise<void> {
154
156
  const type = first;
155
157
  const name = second;
156
158
 
157
- if (!type || !name || (type !== "website" && type !== "telegram" && type !== "whatsapp")) {
158
- throw new Error("Usage: agentkit channels connect <website|telegram|whatsapp> <name> [--provider zapster|meta]");
159
+ if (!type || !name || (type !== "website" && type !== "telegram" && type !== "whatsapp" && type !== "discord")) {
160
+ throw new Error("Usage: agentkit channels connect <website|telegram|whatsapp|discord> <name> [--provider zapster|meta] [--mode interactions|bot]");
159
161
  }
160
162
 
161
- const created = await createHostedChannel(type, name, args.flags.provider, args.flags.api);
163
+ const created = await createHostedChannel(type, name, args.flags.provider, args.flags.mode, args.flags.api);
162
164
  let channel = created.channel;
163
165
  printChannelStatus(channel);
164
166
  printSecretRepairHint(channel);
@@ -192,6 +194,15 @@ export async function handleChannelsCommand(args: ParsedArgs): Promise<void> {
192
194
  return;
193
195
  }
194
196
 
197
+ if (channel.type === "discord") {
198
+ const smoke = await runConnectSmoke(() => runChannelSmoke(channel, args.flags.api, args.flags.message));
199
+ printDiscordHumanNextStep(channel);
200
+ if (!smoke) {
201
+ process.exitCode = 1;
202
+ }
203
+ return;
204
+ }
205
+
195
206
  if (channel.type === "whatsapp" && channel.provider === "zapster") {
196
207
  const smoke = await runConnectSmoke(() => runChannelSmoke(channel, args.flags.api, args.flags.message));
197
208
  console.log(`Next human step: paste ${channel.webhook_url} into ${channel.provider}'s webhook settings.`);
@@ -230,6 +241,8 @@ export async function handleChannelsCommand(args: ParsedArgs): Promise<void> {
230
241
  }
231
242
  } else if (channel.type === "whatsapp") {
232
243
  console.log(`Next step: paste this URL into ${channel.provider}'s webhook settings.`);
244
+ } else if (channel.type === "discord") {
245
+ printDiscordHumanNextStep(channel);
233
246
  } else {
234
247
  console.log(`Website endpoint: ${channel.webhook_url}`);
235
248
  console.log("Use this endpoint from the AgentKit website client or a signed server-to-server test.");
@@ -402,19 +415,22 @@ export async function handleChannelsCommand(args: ParsedArgs): Promise<void> {
402
415
  }
403
416
 
404
417
  async function createHostedChannel(
405
- type: "website" | "telegram" | "whatsapp",
418
+ type: "website" | "telegram" | "whatsapp" | "discord",
406
419
  name: string,
407
420
  providerFlag: string | boolean | undefined,
421
+ modeFlag: string | boolean | undefined,
408
422
  apiFlag: string | boolean | undefined,
409
423
  ): Promise<{ channel: CloudChannel }> {
410
424
  const deployState = await readDeployStateRequired(process.cwd());
411
425
  const provider = channelProviderForCli(type, providerFlag);
412
426
  const localChannel = await readLocalChannelConfig(process.cwd(), type, provider, name);
427
+ const mode = discordModeForCli(type, modeFlag, localChannel);
413
428
  const payload = {
414
429
  name,
415
430
  type,
416
431
  provider,
417
- secrets: localChannel?.secrets ?? defaultChannelSecretsForCli(type, provider),
432
+ ...(mode ? { mode } : {}),
433
+ secrets: localChannel?.secrets ?? defaultChannelSecretsForCli(type, provider, mode),
418
434
  ...(localChannel?.limits ? { limits: channelLimitsForApi(localChannel.limits) } : {}),
419
435
  ...(localChannel?.buffer ? { buffer: localChannel.buffer } : {}),
420
436
  ...(localChannel?.audio ? { audio: localChannel.audio } : {}),
@@ -641,6 +657,26 @@ function printTelegramHumanNextStep(channelName: string, botUsername: string | u
641
657
  console.log(` Then run: npm run agentkit -- channels deliveries list ${channelName}`);
642
658
  }
643
659
 
660
+ function printDiscordHumanNextStep(channel: CloudChannel): void {
661
+ console.log("");
662
+ console.log("Next human step:");
663
+
664
+ if (channel.mode === "bot") {
665
+ console.log(" Open the Discord Developer Portal for your application");
666
+ console.log(" Bot page: enable Message Content Intent");
667
+ console.log(" Installation page: install the app into your server with bot permissions");
668
+ console.log(" Grant the bot View Channel, Read Message History, and Send Messages in the channels it should answer");
669
+ console.log(' Send "hello" in an allowed server channel');
670
+ console.log(` Then run: npm run agentkit -- channels deliveries list ${channel.name}`);
671
+ return;
672
+ }
673
+
674
+ console.log(" Open the Discord Developer Portal for your application");
675
+ console.log(` Paste ${channel.webhook_url} into Interactions Endpoint URL`);
676
+ console.log(" Register a slash command with a string option named message, text, prompt, question, query, or input");
677
+ console.log(` Then run: npm run agentkit -- channels deliveries list ${channel.name}`);
678
+ }
679
+
644
680
  function isRecord(value: unknown): value is Record<string, unknown> {
645
681
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
646
682
  }
@@ -682,12 +718,18 @@ function printChannelStatus(channel: CloudChannel): void {
682
718
  }
683
719
  console.log(`Type: ${channel.type}`);
684
720
  console.log(`Provider: ${channel.provider}`);
721
+ if (channel.type === "discord") {
722
+ console.log(`Mode: ${channel.mode ?? "interactions"}`);
723
+ }
685
724
  console.log(`Status: ${channel.status}`);
686
725
  if (channel.webhook_url) {
687
726
  console.log(`Webhook URL: ${channel.webhook_url}`);
688
727
  }
689
728
  console.log("Required secrets:");
690
- if (channel.required_secrets.length === 0 && defaultChannelSecretsForCli(channel.type, channel.provider).length > 0) {
729
+ if (
730
+ channel.required_secrets.length === 0 &&
731
+ defaultChannelSecretsForCli(channel.type, channel.provider, channel.mode).length > 0
732
+ ) {
691
733
  console.log(
692
734
  ` control-plane channel metadata bug: required_secrets is empty for ${channel.type}/${channel.provider}`,
693
735
  );
@@ -708,7 +750,10 @@ function printChannelStatus(channel: CloudChannel): void {
708
750
  }
709
751
 
710
752
  function printSecretRepairHint(channel: CloudChannel): void {
711
- if (channel.required_secrets.length > 0 || defaultChannelSecretsForCli(channel.type, channel.provider).length === 0) {
753
+ if (
754
+ channel.required_secrets.length > 0 ||
755
+ defaultChannelSecretsForCli(channel.type, channel.provider, channel.mode).length === 0
756
+ ) {
712
757
  return;
713
758
  }
714
759
 
@@ -718,7 +763,7 @@ function printSecretRepairHint(channel: CloudChannel): void {
718
763
  }
719
764
 
720
765
  function hasMissingRequiredSecrets(channel: CloudChannel): boolean {
721
- const expected = defaultChannelSecretsForCli(channel.type, channel.provider);
766
+ const expected = defaultChannelSecretsForCli(channel.type, channel.provider, channel.mode);
722
767
 
723
768
  if (channel.required_secrets.length === 0 && expected.length > 0) {
724
769
  return true;
@@ -923,6 +968,10 @@ function channelProviderForCli(type: string, providerFlag: string | boolean | un
923
968
  return "telegram";
924
969
  }
925
970
 
971
+ if (type === "discord") {
972
+ return "discord";
973
+ }
974
+
926
975
  const provider = providerFlag ?? "zapster";
927
976
 
928
977
  if (provider !== "zapster" && provider !== "meta") {
@@ -932,7 +981,31 @@ function channelProviderForCli(type: string, providerFlag: string | boolean | un
932
981
  return provider;
933
982
  }
934
983
 
935
- function defaultChannelSecretsForCli(type: string, provider: string): string[] {
984
+ function discordModeForCli(
985
+ type: string,
986
+ modeFlag: string | boolean | undefined,
987
+ localChannel: AgentChannel | null,
988
+ ): "interactions" | "bot" | undefined {
989
+ if (type !== "discord") {
990
+ if (modeFlag !== undefined) {
991
+ throw new Error("--mode is only supported for Discord channels.");
992
+ }
993
+
994
+ return undefined;
995
+ }
996
+
997
+ if (modeFlag !== undefined) {
998
+ if (modeFlag !== "interactions" && modeFlag !== "bot") {
999
+ throw new Error('Discord mode must be "interactions" or "bot".');
1000
+ }
1001
+
1002
+ return modeFlag;
1003
+ }
1004
+
1005
+ return localChannel?.type === "discord" ? localChannel.mode : "interactions";
1006
+ }
1007
+
1008
+ function defaultChannelSecretsForCli(type: string, provider: string, mode?: "interactions" | "bot"): string[] {
936
1009
  if (type === "website") {
937
1010
  return ["AGENTKIT_WEBSITE_CHANNEL_TOKEN"];
938
1011
  }
@@ -949,6 +1022,10 @@ function defaultChannelSecretsForCli(type: string, provider: string): string[] {
949
1022
  return ["META_WHATSAPP_ACCESS_TOKEN", "META_WHATSAPP_APP_SECRET", "META_WHATSAPP_VERIFY_TOKEN"];
950
1023
  }
951
1024
 
1025
+ if (type === "discord") {
1026
+ return mode === "bot" ? ["DISCORD_BOT_TOKEN"] : ["DISCORD_PUBLIC_KEY"];
1027
+ }
1028
+
952
1029
  return [];
953
1030
  }
954
1031
 
@@ -1012,6 +1089,54 @@ async function channelTestBody(
1012
1089
  });
1013
1090
  }
1014
1091
 
1092
+ if (channel.type === "discord") {
1093
+ if (channel.mode === "bot") {
1094
+ return JSON.stringify({
1095
+ id: `discord_message_${Date.now()}`,
1096
+ guild_id: "agentkit_guild",
1097
+ channel_id: "agentkit_channel",
1098
+ author: {
1099
+ id: "agentkit_user",
1100
+ username: "agentkit",
1101
+ },
1102
+ member: {
1103
+ nick: "AgentKit",
1104
+ },
1105
+ content: message,
1106
+ mentions: [],
1107
+ timestamp: new Date().toISOString(),
1108
+ });
1109
+ }
1110
+
1111
+ return JSON.stringify({
1112
+ id: `discord_interaction_${Date.now()}`,
1113
+ application_id: "agentkit_discord_app",
1114
+ type: 2,
1115
+ data: {
1116
+ id: "agentkit_command",
1117
+ name: "ask",
1118
+ type: 1,
1119
+ options: [
1120
+ {
1121
+ name: "message",
1122
+ type: 3,
1123
+ value: message,
1124
+ },
1125
+ ],
1126
+ },
1127
+ guild_id: "agentkit_guild",
1128
+ channel_id: "agentkit_channel",
1129
+ member: {
1130
+ user: {
1131
+ id: "agentkit_user",
1132
+ username: "agentkit",
1133
+ },
1134
+ },
1135
+ token: `agentkit_interaction_token_${Date.now()}`,
1136
+ version: 1,
1137
+ });
1138
+ }
1139
+
1015
1140
  return JSON.stringify({
1016
1141
  event_id: `web_${Date.now()}`,
1017
1142
  visitor_id: "visitor_test",
@@ -70,6 +70,27 @@ export async function startDeployChatUiServer(
70
70
  return;
71
71
  }
72
72
 
73
+ if (
74
+ request.method === "GET" &&
75
+ (requestUrl.pathname === "/v1/conversations" ||
76
+ /^\/v1\/conversations\/[^/]+(?:\/trace)?$/.test(requestUrl.pathname))
77
+ ) {
78
+ const token = await readDeployAccessTokenForUi(tokenPath);
79
+ const upstream = await fetch(new URL(requestUrl.pathname, deployUrl).href, {
80
+ method: "GET",
81
+ headers: {
82
+ Authorization: `Bearer ${token}`,
83
+ },
84
+ });
85
+ const text = await upstream.text();
86
+
87
+ response.writeHead(upstream.status, {
88
+ "content-type": upstream.headers.get("content-type") ?? "application/json",
89
+ });
90
+ response.end(text);
91
+ return;
92
+ }
93
+
73
94
  sendJson(response, 404, { error: { code: "not_found", message: "Route not found." } });
74
95
  } catch (error) {
75
96
  sendJson(response, 500, {
@@ -196,6 +217,8 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
196
217
  header {
197
218
  border-bottom: 1px solid var(--line);
198
219
  padding: 18px 22px;
220
+ display: grid;
221
+ gap: 10px;
199
222
  }
200
223
 
201
224
  h1 {
@@ -204,12 +227,27 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
204
227
  line-height: 1.2;
205
228
  }
206
229
 
230
+ .topline {
231
+ display: flex;
232
+ align-items: start;
233
+ justify-content: space-between;
234
+ gap: 12px;
235
+ }
236
+
207
237
  code {
208
238
  color: var(--muted);
209
239
  font-size: 12px;
210
240
  overflow-wrap: anywhere;
211
241
  }
212
242
 
243
+ .meta {
244
+ display: flex;
245
+ flex-wrap: wrap;
246
+ gap: 8px 14px;
247
+ color: var(--muted);
248
+ font-size: 12px;
249
+ }
250
+
213
251
  #messages {
214
252
  padding: 22px;
215
253
  overflow: auto;
@@ -255,6 +293,39 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
255
293
  background: #fff6f6;
256
294
  }
257
295
 
296
+ #trace {
297
+ border-top: 1px solid var(--line);
298
+ padding: 12px 22px;
299
+ display: grid;
300
+ gap: 8px;
301
+ background: #fbfbfa;
302
+ }
303
+
304
+ .tool-call {
305
+ border: 1px solid var(--line);
306
+ border-radius: 8px;
307
+ padding: 10px 12px;
308
+ display: grid;
309
+ gap: 6px;
310
+ font-size: 12px;
311
+ }
312
+
313
+ .tool-head {
314
+ display: flex;
315
+ flex-wrap: wrap;
316
+ gap: 8px;
317
+ align-items: center;
318
+ color: var(--muted);
319
+ font-weight: 700;
320
+ }
321
+
322
+ .tool-call pre {
323
+ margin: 0;
324
+ max-height: 180px;
325
+ overflow: auto;
326
+ white-space: pre-wrap;
327
+ }
328
+
258
329
  form {
259
330
  border-top: 1px solid var(--line);
260
331
  padding: 14px;
@@ -286,6 +357,13 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
286
357
  cursor: pointer;
287
358
  }
288
359
 
360
+ button.secondary {
361
+ min-height: 34px;
362
+ color: var(--ink);
363
+ background: #eef1ee;
364
+ border: 1px solid var(--line);
365
+ }
366
+
289
367
  button:disabled {
290
368
  cursor: wait;
291
369
  opacity: 0.65;
@@ -305,10 +383,20 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
305
383
  <body>
306
384
  <main>
307
385
  <header>
308
- <h1>AgentKit Hosted Chat</h1>
309
- <code>${deployUrl}</code>
386
+ <div class="topline">
387
+ <div>
388
+ <h1>AgentKit Hosted Chat</h1>
389
+ <code>${deployUrl}</code>
390
+ </div>
391
+ <button class="secondary" id="new-conversation" type="button">New conversation</button>
392
+ </div>
393
+ <div class="meta">
394
+ <span>Conversation: <code id="conversation-id">none</code></span>
395
+ <span>Tool calls: <code id="tool-count">0</code></span>
396
+ </div>
310
397
  </header>
311
398
  <section id="messages" aria-live="polite"></section>
399
+ <section id="trace" aria-live="polite"></section>
312
400
  <form id="form">
313
401
  <textarea id="message" name="message" placeholder="Type a message" required autofocus></textarea>
314
402
  <button id="send" type="submit">Send</button>
@@ -319,6 +407,10 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
319
407
  const textarea = document.querySelector("#message");
320
408
  const send = document.querySelector("#send");
321
409
  const messages = document.querySelector("#messages");
410
+ const trace = document.querySelector("#trace");
411
+ const conversationLabel = document.querySelector("#conversation-id");
412
+ const toolCount = document.querySelector("#tool-count");
413
+ const newConversation = document.querySelector("#new-conversation");
322
414
  let conversationId = null;
323
415
 
324
416
  function addMessage(role, content, className = "") {
@@ -335,6 +427,55 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
335
427
  messages.scrollTop = messages.scrollHeight;
336
428
  }
337
429
 
430
+ function setConversationId(value) {
431
+ conversationId = value || null;
432
+ conversationLabel.textContent = conversationId || "none";
433
+ }
434
+
435
+ function renderTrace(payload) {
436
+ const calls = [];
437
+ for (const run of payload.runs || []) {
438
+ for (const call of run.toolCalls || []) {
439
+ calls.push(call);
440
+ }
441
+ }
442
+
443
+ toolCount.textContent = String(calls.length);
444
+ trace.innerHTML = "";
445
+
446
+ for (const call of calls.slice(-8)) {
447
+ const item = document.createElement("article");
448
+ item.className = "tool-call";
449
+ const head = document.createElement("div");
450
+ head.className = "tool-head";
451
+ head.textContent = [call.name, call.status, call.errorMessage].filter(Boolean).join(" · ");
452
+ const input = document.createElement("pre");
453
+ input.textContent = JSON.stringify(call.input || {}, null, 2);
454
+ item.append(head, input);
455
+ trace.append(item);
456
+ }
457
+ }
458
+
459
+ async function refreshTrace() {
460
+ if (!conversationId) {
461
+ toolCount.textContent = "0";
462
+ trace.innerHTML = "";
463
+ return;
464
+ }
465
+
466
+ const response = await fetch("/v1/conversations/" + encodeURIComponent(conversationId) + "/trace");
467
+ const payload = await response.json();
468
+ if (response.ok) renderTrace(payload);
469
+ }
470
+
471
+ newConversation.addEventListener("click", () => {
472
+ setConversationId(null);
473
+ messages.innerHTML = "";
474
+ trace.innerHTML = "";
475
+ toolCount.textContent = "0";
476
+ textarea.focus();
477
+ });
478
+
338
479
  textarea.addEventListener("keydown", (event) => {
339
480
  if (event.key !== "Enter" || event.shiftKey || event.isComposing) return;
340
481
  event.preventDefault();
@@ -363,10 +504,12 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
363
504
  throw new Error(payload.error?.message || "Request failed");
364
505
  }
365
506
 
366
- conversationId = payload.conversationId || conversationId;
507
+ setConversationId(payload.conversationId || conversationId);
367
508
  addMessage("assistant", payload.message?.content || "");
509
+ await refreshTrace();
368
510
  } catch (error) {
369
511
  addMessage("error", error instanceof Error ? error.message : String(error), "error");
512
+ await refreshTrace().catch(() => {});
370
513
  } finally {
371
514
  send.disabled = false;
372
515
  textarea.focus();
@@ -2,13 +2,14 @@ import { findAgentCapsuleRoot, loadAgentCapsule } from "../runtime/config";
2
2
  import { loadDeployReadinessContext, type DeployReadinessContext } from "../runtime/deploy-readiness";
3
3
  import { loadCapsuleEnv } from "../runtime/env";
4
4
  import { isAgentKitError } from "../runtime/errors";
5
- import { MANAGED_COMPOSIO_ENTITLEMENT } from "../runtime/integrations/composio";
5
+ import { MANAGED_COMPOSIO_API_KEY_SECRET, MANAGED_COMPOSIO_ENTITLEMENT } from "../runtime/integrations/composio";
6
6
  import {
7
7
  cloudApiRequest,
8
8
  formatCloudAuthSource,
9
9
  readCloudAuthForApiUrl,
10
10
  type CloudCapabilitiesResponse,
11
11
  type CloudLimitsResponse,
12
+ type CloudManagedComposioResponse,
12
13
  type CloudMeResponse,
13
14
  type CloudProjectResolveResponse,
14
15
  type CloudSecretsResponse,
@@ -203,6 +204,61 @@ export async function checkDeployReadiness(options: {
203
204
  message: `Could not verify online deploy capacity. ${formatReadinessError(error)}`,
204
205
  });
205
206
  }
207
+
208
+ if (context.integrations.managedComposio.enabled) {
209
+ try {
210
+ const payload = (await cloudApiRequest(
211
+ options.apiUrl,
212
+ `/v1/me/managed-composio?toolkits=${encodeURIComponent(context.integrations.managedComposio.toolkits.join(","))}`,
213
+ {
214
+ method: "GET",
215
+ },
216
+ )) as CloudManagedComposioResponse;
217
+ const managed = payload.managed_composio;
218
+ const missingToolkits = (managed?.toolkits ?? []).filter((toolkit) => toolkit.auth_config !== "set");
219
+
220
+ if (managed?.api_key !== "set") {
221
+ checks.push({
222
+ status: "fail",
223
+ title: "Managed Composio API key",
224
+ message: `AgentKit Cloud is missing AGENTKIT_SECRET_${MANAGED_COMPOSIO_API_KEY_SECRET}.`,
225
+ action: "ask the AgentKit Cloud operator to configure managed Composio",
226
+ });
227
+ } else {
228
+ checks.push({
229
+ status: "pass",
230
+ title: "Managed Composio API key",
231
+ message: "AgentKit Cloud has the managed COMPOSIO_API_KEY.",
232
+ });
233
+ }
234
+
235
+ if (missingToolkits.length > 0) {
236
+ checks.push({
237
+ status: "fail",
238
+ title: "Managed Composio auth configs",
239
+ message: `Missing ${missingToolkits
240
+ .map((toolkit) => `${toolkit.auth_config_env ?? "auth config"} for ${toolkit.toolkit ?? "unknown"}`)
241
+ .join(", ")}.`,
242
+ action: "ask the AgentKit Cloud operator to configure the Composio auth config registry or fallback env",
243
+ });
244
+ } else {
245
+ const toolkitSources = (managed?.toolkits ?? []).map((toolkit) =>
246
+ `${toolkit.toolkit ?? "unknown"}${toolkit.auth_config_source ? ` via ${toolkit.auth_config_source}` : ""}`,
247
+ );
248
+ checks.push({
249
+ status: "pass",
250
+ title: "Managed Composio auth configs",
251
+ message: `Auth configs are available for ${toolkitSources.join(", ")}.`,
252
+ });
253
+ }
254
+ } catch (error) {
255
+ checks.push({
256
+ status: "warn",
257
+ title: "Managed Composio auth configs",
258
+ message: `Could not verify managed Composio auth configs. ${formatReadinessError(error)}`,
259
+ });
260
+ }
261
+ }
206
262
  }
207
263
 
208
264
  if (context.agentKitManagedSecrets.length > 0) {
package/src/cli/help.ts CHANGED
@@ -29,6 +29,8 @@ Build:
29
29
  agentkit db migrate
30
30
  agentkit eval run
31
31
  agentkit eval from-conversation <id>
32
+ agentkit improve collect --deploy --since 24h
33
+ agentkit replay <bundle-dir> --against local
32
34
  agentkit conversations list
33
35
 
34
36
  Deploy:
@@ -42,6 +44,8 @@ Deploy:
42
44
  More:
43
45
  agentkit channels ...
44
46
  agentkit integrations status
47
+ agentkit billing checkout --slots <count>
48
+ agentkit account token ...
45
49
  agentkit access token ...
46
50
  agentkit env ...
47
51
  agentkit docs full
@@ -73,12 +77,15 @@ Usage:
73
77
  agentkit db seed [--file <path>]
74
78
  agentkit eval run
75
79
  agentkit eval from-conversation <conversation-id> [--out <path>] [--force]
76
- agentkit conversations list
77
- agentkit conversations show <conversation-id>
78
- agentkit conversations trace <conversation-id>
80
+ agentkit improve collect [--deploy] [--since <duration|iso>] [--conversation-id <id>] [--out <directory>]
81
+ agentkit improve evals <bundle-dir-or-json> [--force]
82
+ agentkit replay <bundle-dir-or-json> --against local
83
+ agentkit conversations list [--deploy]
84
+ agentkit conversations show <conversation-id> [--deploy]
85
+ agentkit conversations trace <conversation-id> [--deploy]
79
86
  agentkit channels list
80
- agentkit channels add <website|telegram|whatsapp> <name> [--provider zapster|meta] [--api <url>]
81
- agentkit channels connect <website|telegram|whatsapp> <name> [--provider zapster|meta] [--api <url>]
87
+ agentkit channels add <website|telegram|whatsapp|discord> <name> [--provider zapster|meta] [--mode interactions|bot] [--api <url>]
88
+ agentkit channels connect <website|telegram|whatsapp|discord> <name> [--provider zapster|meta] [--mode interactions|bot] [--api <url>]
82
89
  agentkit channels setup <name> [--apply] [--api <url>]
83
90
  agentkit channels status <name> [--api <url>]
84
91
  agentkit channels doctor <name> [--api <url>]
@@ -91,7 +98,7 @@ Usage:
91
98
  agentkit channels buffers flush [<name>] <conversation-id> [--api <url>]
92
99
  agentkit channels buffers clear [<name>] <conversation-id> [--api <url>]
93
100
  agentkit channels buffers retry [<name>] <conversation-id> [--api <url>]
94
- agentkit integrations status [--api <url>]
101
+ agentkit integrations status [--toolkit <slug>] [--api <url>]
95
102
  agentkit integrations connect composio [--toolkit <slug>] [--callback-url <url>] [--api <url>]
96
103
  agentkit skills status
97
104
  agentkit skills sync
@@ -99,6 +106,13 @@ Usage:
99
106
  agentkit build [--target cloudflare|container]
100
107
  agentkit login --token <token> [--api <url>]
101
108
  agentkit logout
109
+ agentkit billing checkout --slots <count> [--email <email>] [--api <url>]
110
+ agentkit billing status <billing-intent-id> --secret <secret> [--api <url>]
111
+ agentkit billing claim <billing-intent-id> --secret <secret> [--token-name <name>] [--api <url>]
112
+ agentkit billing portal [--api <url>]
113
+ agentkit account token create <name> [--api <url>] [--use] [--out <path>]
114
+ agentkit account token list [--api <url>]
115
+ agentkit account token revoke <token-id> [--api <url>]
102
116
  agentkit deploy [--target cloudflare|vps] [--host <host>] [--api <url>] [--dry-run] [--anonymous] [--local-wrangler] [--smoke <message>]
103
117
  agentkit deploy doctor [--api <url>] [--anonymous]
104
118
  agentkit deploy smoke [--message <text>] [--api <url>]
@@ -140,6 +154,8 @@ Commands:
140
154
  sync Run or scaffold catalog/data synchronization
141
155
  db Manage the local SQLite database
142
156
  eval Run local eval files or create one from a conversation
157
+ improve Collect production or local traces and generate regression evals
158
+ replay Replay an improve bundle against the local Agent Capsule
143
159
  conversations List, inspect, and trace stored local conversations
144
160
  channels Manage hosted channel resources
145
161
  integrations Manage hosted AgentKit-managed integrations
@@ -149,6 +165,8 @@ Commands:
149
165
  build Build a hosted deploy artifact
150
166
  login Store an AgentKit Cloud alpha token outside the capsule
151
167
  logout Remove the stored AgentKit Cloud alpha token
168
+ billing Buy deploy slots, claim checkout tokens, and open the billing portal
169
+ account Manage AgentKit Cloud account tokens
152
170
  deploy Build and send a hosted artifact to AgentKit Cloud
153
171
  secret Manage hosted AgentKit Cloud secrets without readback
154
172
  access Manage hosted deploy access tokens
@@ -181,8 +199,11 @@ export function renderCommandHelp(command: string): string {
181
199
  spec: 'agentkit spec init --brief "owner request" | agentkit spec check',
182
200
  sync: "agentkit sync init [--force] | agentkit sync run [--file <path>]",
183
201
  eval: "agentkit eval run | agentkit eval from-conversation <conversation-id> [--out <path>] [--force]",
202
+ improve:
203
+ "agentkit improve collect [--deploy] [--since <duration|iso>] [--conversation-id <id>] [--out <directory>] | agentkit improve evals <bundle-dir-or-json> [--force]",
204
+ replay: "agentkit replay <bundle-dir-or-json> --against local",
184
205
  conversations:
185
- "agentkit conversations list | agentkit conversations show <conversation-id> | agentkit conversations trace <conversation-id>",
206
+ "agentkit conversations list [--deploy] | agentkit conversations show <conversation-id> [--deploy] | agentkit conversations trace <conversation-id> [--deploy]",
186
207
  channels:
187
208
  "agentkit channels list | add | connect | setup | status | doctor | test | test-audio | deliveries | buffers",
188
209
  skills: "agentkit skills status | agentkit skills sync",
@@ -192,7 +213,10 @@ export function renderCommandHelp(command: string): string {
192
213
  secret:
193
214
  "agentkit secret set <NAME> --stdin | --from-env [ENV_NAME] | --from-local-env | agentkit secret sync --from-local | list | unset <NAME>",
194
215
  access: "agentkit access token create <name> [--out <path>] | list | revoke <token-id>",
195
- integrations: "agentkit integrations status | agentkit integrations connect composio [--toolkit <slug>]",
216
+ account: "agentkit account token create <name> [--use] [--out <path>] | list | revoke <token-id>",
217
+ billing:
218
+ "agentkit billing checkout --slots <count> [--email <email>] | status <intent-id> --secret <secret> | claim <intent-id> --secret <secret> | portal",
219
+ integrations: "agentkit integrations status [--toolkit <slug>] | agentkit integrations connect composio [--toolkit <slug>]",
196
220
  env: "agentkit env set <NAME> --stdin | --from-env [ENV_NAME] | list | unset <NAME>",
197
221
  docs: "agentkit docs path | llms | full",
198
222
  handoff: "agentkit handoff codex [goal] | agentkit handoff claude [goal]",