@andreprado/agentkit 0.1.1 → 0.2.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 (95) hide show
  1. package/README.md +8 -77
  2. package/docs/guides/add-channel.md +14 -92
  3. package/docs/guides/add-knowledge.md +0 -21
  4. package/docs/guides/add-tool.md +5 -11
  5. package/docs/guides/channel-security.md +3 -207
  6. package/docs/guides/connect-discord.md +7 -172
  7. package/docs/guides/connect-slack.md +6 -121
  8. package/docs/guides/connect-telegram.md +6 -165
  9. package/docs/guides/connect-whatsapp-evolution.md +6 -116
  10. package/docs/guides/connect-whatsapp-uazapi.md +6 -134
  11. package/docs/guides/connect-whatsapp-zapster.md +6 -202
  12. package/docs/guides/create-agent.md +5 -14
  13. package/docs/guides/debug-channel.md +4 -156
  14. package/docs/guides/improve-local.md +13 -0
  15. package/docs/guides/local-only-migration.md +35 -0
  16. package/docs/guides/replay-local-traces.md +11 -0
  17. package/docs/guides/run-evals.md +2 -4
  18. package/docs/guides/security-rules.md +5 -154
  19. package/docs/guides/use-jev.md +3 -6
  20. package/docs/guides/use-provider.md +0 -3
  21. package/docs/guides/write-feedback.md +10 -0
  22. package/docs/llms-full.txt +27 -448
  23. package/docs/llms.txt +8 -44
  24. package/package.json +2 -4
  25. package/src/cli/commands/channels.ts +8 -1613
  26. package/src/cli/commands/feedback.ts +8 -86
  27. package/src/cli/constants.ts +0 -3
  28. package/src/cli/flags.ts +0 -28
  29. package/src/cli/help.ts +16 -92
  30. package/src/cli/index.ts +15 -1091
  31. package/src/index.ts +6 -158
  32. package/src/providers/pi.ts +2 -0
  33. package/src/runtime/channels/discord.ts +2 -2
  34. package/src/runtime/chat.ts +5 -3
  35. package/src/runtime/config.ts +14 -148
  36. package/src/runtime/database.ts +2 -2
  37. package/src/runtime/dev-server.ts +8 -8
  38. package/src/runtime/env.ts +11 -0
  39. package/src/runtime/improve.ts +2 -262
  40. package/src/runtime/inspect.ts +13 -73
  41. package/src/runtime/knowledge/ingest.ts +1 -1
  42. package/src/runtime/knowledge/tool.ts +16 -2
  43. package/src/runtime/knowledge/vector.ts +1 -1
  44. package/src/runtime/tool-runner.ts +5 -3
  45. package/src/runtime/tools.ts +10 -14
  46. package/src/storage/sqlite.ts +11 -32
  47. package/src/templates/blank.ts +15 -102
  48. package/src/templates/common.ts +60 -0
  49. package/src/templates/dentista.ts +7 -74
  50. package/src/templates/skills/agentkit-capsule/SKILL.md +5 -7
  51. package/src/templates/skills/agentkit-capsule/references/docs-router.md +2 -3
  52. package/src/templates/skills/agentkit-channels/SKILL.md +6 -119
  53. package/src/templates/skills/agentkit-channels/references/channel-buffering.md +0 -9
  54. package/src/templates/skills/agentkit-channels/references/channel-debugging.md +1 -64
  55. package/src/templates/skills/agentkit-channels/references/discord.md +2 -92
  56. package/src/templates/skills/agentkit-channels/references/slack.md +2 -55
  57. package/src/templates/skills/agentkit-channels/references/telegram.md +2 -71
  58. package/src/templates/skills/agentkit-channels/references/whatsapp-evolution.md +2 -56
  59. package/src/templates/skills/agentkit-channels/references/whatsapp-uazapi.md +2 -53
  60. package/src/templates/skills/agentkit-channels/references/whatsapp-zapster.md +2 -70
  61. package/src/templates/skills/agentkit-database/SKILL.md +2 -4
  62. package/src/templates/skills/agentkit-evals/SKILL.md +1 -1
  63. package/src/templates/skills/agentkit-improve/SKILL.md +6 -85
  64. package/src/templates/skills/agentkit-improve/references/trace-packets.md +1 -1
  65. package/src/templates/skills/agentkit-provider/SKILL.md +0 -1
  66. package/src/templates/skills/agentkit-security/SKILL.md +1 -3
  67. package/src/templates/skills/agentkit-tools/SKILL.md +1 -1
  68. package/src/templates/skills/agentkit-tools/examples/database-write.tool.md +1 -2
  69. package/src/templates/skills/agentkit-troubleshooting/SKILL.md +5 -11
  70. package/src/templates/support.ts +8 -92
  71. package/docs/guides/add-managed-composio.md +0 -165
  72. package/docs/guides/improve-from-production.md +0 -151
  73. package/docs/guides/prepare-deploy.md +0 -227
  74. package/docs/guides/replay-production-traces.md +0 -72
  75. package/docs/guides/send-feedback.md +0 -135
  76. package/src/cli/cloud-client.ts +0 -377
  77. package/src/cli/deploy-chat-ui.ts +0 -606
  78. package/src/cli/deploy-readiness.ts +0 -561
  79. package/src/cloud/artifact.ts +0 -139
  80. package/src/cloud/client.ts +0 -80
  81. package/src/cloud/contracts.ts +0 -63
  82. package/src/cloud/index.ts +0 -3
  83. package/src/runtime/build.ts +0 -43
  84. package/src/runtime/core/deploy-state.ts +0 -54
  85. package/src/runtime/core/manifest.ts +0 -283
  86. package/src/runtime/core/targets.ts +0 -133
  87. package/src/runtime/deploy-readiness.ts +0 -135
  88. package/src/runtime/deploy.ts +0 -1
  89. package/src/runtime/integrations/composio.ts +0 -425
  90. package/src/runtime/targets/cloudflare/build.ts +0 -3319
  91. package/src/runtime/targets/container/build.ts +0 -146
  92. package/src/runtime/targets/container/server.ts +0 -33
  93. package/src/runtime/targets/vps/deploy.ts +0 -223
  94. package/src/templates/skills/agentkit-deploy/SKILL.md +0 -52
  95. package/src/templates/skills/agentkit-integrations/SKILL.md +0 -98
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type AgentRuntime = "local" | "edge";
1
+ export type AgentRuntime = "local";
2
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";
@@ -275,38 +275,12 @@ export type AgentChannel =
275
275
  | GenericWebhookChannelConfig
276
276
  | GenericWebhookOutputChannelConfig;
277
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;
303
-
304
278
  export type AgentDatabaseConfig =
305
279
  | {
306
280
  driver: "none";
307
281
  }
308
282
  | {
309
- driver: "turso";
283
+ driver: "sqlite";
310
284
  schema?: string;
311
285
  migrations?: string;
312
286
  };
@@ -316,8 +290,7 @@ export type AgentFilesConfig =
316
290
  driver: "none";
317
291
  }
318
292
  | {
319
- driver: "r2";
320
- bucket?: string;
293
+ driver: "local";
321
294
  prefix?: string;
322
295
  maxUploadBytes?: number;
323
296
  };
@@ -417,10 +390,10 @@ export type ToolRenderContext<Input = unknown> = {
417
390
  };
418
391
 
419
392
  export type ToolRuntimeContext = {
420
- environment: "local" | "hosted" | "eval" | "test";
393
+ environment: "local" | "eval" | "test";
421
394
  invocation: "chat" | "tool" | "dev" | "channel" | "eval" | "sync";
422
- target: "bun" | "cloudflare";
423
- database: "sqlite" | "turso" | "none";
395
+ target: "bun";
396
+ database: "sqlite" | "none";
424
397
  };
425
398
 
426
399
  export type ToolClockContext = {
@@ -472,7 +445,6 @@ export type AgentConfig = {
472
445
  instructions: string;
473
446
  secrets: string[];
474
447
  tools?: AgentTool[];
475
- integrations?: AgentIntegration[];
476
448
  channels?: AgentChannel[];
477
449
  transcription?: AgentTranscriptionConfig;
478
450
  knowledge?: AgentKnowledgeConfig;
@@ -495,25 +467,6 @@ export function defineTool<Input = unknown, Output = unknown>(tool: AgentTool<In
495
467
  return tool;
496
468
  }
497
469
 
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
-
517
470
  export function websiteChannel(input: WebsiteChannelInput): WebsiteChannelConfig {
518
471
  return {
519
472
  type: "website",
@@ -663,109 +616,6 @@ function normalizeSecretName(secret: string, context: string): string {
663
616
  return secret;
664
617
  }
665
618
 
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();
767
- }
768
-
769
619
  function normalizeChannelBuffer(input: ChannelBufferInput, context: string): ChannelBufferConfig {
770
620
  if (input.mode === "off") {
771
621
  return { mode: "off" };
@@ -928,8 +778,6 @@ export { getConversationTraceFromCwd } from "./runtime/traces";
928
778
  export { runToolFromCwd } from "./runtime/tool-runner";
929
779
  export { startAgentDevServer } from "./runtime/dev-server";
930
780
  export { inspectAgentCapsule } from "./runtime/inspect";
931
- export { buildAgentCapsule } from "./runtime/build";
932
- export { deployBuildToAgentKitCloud } from "./runtime/deploy";
933
781
  export { AgentKitError } from "./runtime/errors";
934
782
  export type {
935
783
  ChannelAdapter,
@@ -117,7 +117,9 @@ export function providerToolResultText(result: {
117
117
  visibility?: "user" | "internal";
118
118
  rendered?: { text?: string };
119
119
  output: unknown;
120
+ modelText?: string;
120
121
  }): string {
122
+ if (result.modelText !== undefined) return result.modelText;
121
123
  if (result.visibility === "internal") {
122
124
  return `Internal tool ${result.name} completed.`;
123
125
  }
@@ -124,9 +124,9 @@ export const discordChannelAdapter: ChannelAdapter = {
124
124
  }
125
125
 
126
126
  return {
127
- status: "waiting_for_provider_event",
127
+ status: "needs_setup",
128
128
  checkedAt: new Date().toISOString(),
129
- message: "Invite the Discord bot to a server and enable Message Content Intent.",
129
+ message: "AgentKit does not connect to the Discord Gateway. Use interactions or run your own Gateway bridge to forward authenticated bot events; inviting the bot alone is insufficient. Bridge connectivity cannot be verified here.",
130
130
  };
131
131
  }
132
132
 
@@ -6,9 +6,8 @@ import type { ConversationRecord, ConversationSummary, PersistedChatRun } from "
6
6
  import type { LoadedAgentCapsule } from "./config";
7
7
  import { loadAgentCapsule } from "./config";
8
8
  import { openPreparedCapsuleStore } from "./database";
9
- import { loadCapsuleEnv } from "./env";
9
+ import { collectSecretValues, loadCapsuleEnv } from "./env";
10
10
  import { AgentKitError, isAgentKitError } from "./errors";
11
- import { createManagedComposioTools } from "./integrations/composio";
12
11
  import { syncConfiguredKnowledgeSources } from "./knowledge/ingest";
13
12
  import { appendKnowledgePromptPolicy } from "./knowledge/prompt-policy";
14
13
  import { createKnowledgeSearchTool } from "./knowledge/tool";
@@ -46,6 +45,7 @@ export async function runAgentMessage(
46
45
 
47
46
  const adapter = getProviderAdapter(capsule.config.provider);
48
47
  const env = await loadCapsuleEnv(capsule.root);
48
+ const secretValues = collectSecretValues(capsule.config, env);
49
49
  await syncConfiguredKnowledgeSources(capsule);
50
50
  const conversationId = normalizeConversationId(options.conversationId);
51
51
  const { store } = await openPreparedCapsuleStore(capsule);
@@ -81,6 +81,7 @@ export async function runAgentMessage(
81
81
  runId: run.id,
82
82
  conversationId: conversation.id,
83
83
  env,
84
+ secretValues,
84
85
  signal: options.signal,
85
86
  clock,
86
87
  runtime: {
@@ -140,6 +141,7 @@ export async function runAgentMessage(
140
141
  status: "failed",
141
142
  errorCode: isAgentKitError(error) ? error.code : "runtime_error",
142
143
  errorMessage: error instanceof Error ? error.message : String(error),
144
+ secretValues,
143
145
  });
144
146
  }
145
147
 
@@ -150,7 +152,7 @@ export async function runAgentMessage(
150
152
  }
151
153
 
152
154
  function withKnowledgeTools(capsule: LoadedAgentCapsule): NonNullable<LoadedAgentCapsule["config"]["tools"]> {
153
- const tools = [...createManagedComposioTools(capsule.config), ...(capsule.config.tools ?? [])];
155
+ const tools = capsule.config.tools ?? [];
154
156
  const knowledgeTool = createKnowledgeSearchTool(capsule);
155
157
 
156
158
  if (knowledgeTool) {
@@ -17,17 +17,15 @@ import type {
17
17
  TelegramAllowedUpdate,
18
18
  AgentKnowledgeEmbeddingProvider,
19
19
  ChannelBufferMode,
20
- AgentIntegration,
21
20
  ChannelAudioMode,
22
21
  TranscriptionProviderName,
23
22
  ChannelReplyRouteConfig,
24
23
  } from "../index";
25
- import { MANAGED_COMPOSIO_TOOL_NAME } from "./integrations/composio";
26
24
  import { AgentKitError } from "./errors";
27
25
  import { isValidTimeZone } from "./prompt-context";
28
26
 
29
27
  const CONFIG_FILE = "agentkit.config.ts";
30
- const AGENT_RUNTIMES = new Set<AgentRuntime>(["local", "edge"]);
28
+ const AGENT_RUNTIMES = new Set<AgentRuntime>(["local"]);
31
29
  const PROVIDERS = new Set<AgentProviderName>(["test", "openai", "openai-codex", "anthropic", "openrouter", "opencode", "opencode-go", "custom"]);
32
30
  const ACCESS_MODES = new Set<AccessMode>(["private", "token", "public"]);
33
31
  const TOOL_VISIBILITIES = new Set<ToolVisibility>(["user", "internal"]);
@@ -41,9 +39,6 @@ const KNOWLEDGE_EMBEDDING_PROVIDERS = new Set<AgentKnowledgeEmbeddingProvider>([
41
39
  const TRANSCRIPTION_PROVIDERS = new Set<TranscriptionProviderName>(["test", "openai", "groq"]);
42
40
  const CHANNEL_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
43
41
  const CHANNEL_REPLY_PATH_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
44
- const INTEGRATION_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
45
- const COMPOSIO_TOOLKIT_PATTERN = /^[a-z][a-z0-9_-]*$/;
46
- const COMPOSIO_TOOL_SLUG_PATTERN = /^[A-Z][A-Z0-9_]*$/;
47
42
  const SECRET_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
48
43
  const HTTP_HEADER_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9-]*$/;
49
44
  const moduleDir = dirname(fileURLToPath(import.meta.url));
@@ -125,7 +120,7 @@ function resolveLocalStoragePath(root: string, config: AgentConfig): string | un
125
120
 
126
121
  // Every import of the config goes through a uniquely named temp module, and
127
122
  // Node never evicts imported modules. Re-importing on each request (the dev and
128
- // container servers load the capsule per request) grows memory without bound,
123
+ // local servers load the capsule per request) grows memory without bound,
129
124
  // so reuse the import while the config source is unchanged. Edits still reload.
130
125
  const configModuleCache = new Map<string, { source: string; value: Promise<unknown> }>();
131
126
 
@@ -228,7 +223,7 @@ function validateAgentConfig(value: unknown): asserts value is AgentConfig {
228
223
  expectString(value.name, "name");
229
224
 
230
225
  if (!AGENT_RUNTIMES.has(value.runtime as AgentRuntime)) {
231
- throw invalidConfig('runtime must be "local" or "edge".');
226
+ throw invalidConfig('runtime must be "local". Hosted runtimes are no longer supported.');
232
227
  }
233
228
 
234
229
  if (!isRecord(value.provider)) {
@@ -267,9 +262,11 @@ function validateAgentConfig(value: unknown): asserts value is AgentConfig {
267
262
  }
268
263
  }
269
264
 
270
- validateIntegrations(value.integrations, value.runtime as AgentRuntime, value.tools);
265
+ if (value.integrations !== undefined) {
266
+ throw invalidConfig("Managed integrations are no longer supported. Connect external services through defineTool.");
267
+ }
271
268
  validateTranscriptionConfig(value.transcription);
272
- validateChannels(value.channels, value.runtime as AgentRuntime, Boolean(value.transcription));
269
+ validateChannels(value.channels, Boolean(value.transcription));
273
270
  validateKnowledgeConfig(value.knowledge);
274
271
 
275
272
  if (!isRecord(value.access) || !ACCESS_MODES.has(value.access.mode as AccessMode)) {
@@ -296,133 +293,6 @@ function validateAgentConfig(value: unknown): asserts value is AgentConfig {
296
293
  validateFilesConfig(value.storage.files);
297
294
  }
298
295
 
299
- function validateIntegrations(
300
- value: unknown,
301
- runtime: AgentRuntime,
302
- tools: AgentConfig["tools"] = [],
303
- ): void {
304
- if (value === undefined) {
305
- return;
306
- }
307
-
308
- if (!Array.isArray(value)) {
309
- throw invalidConfig("integrations must be an array when provided.");
310
- }
311
-
312
- if (value.length > 0 && runtime !== "edge") {
313
- throw invalidConfig('managed integrations require runtime: "edge". Use BYO defineTool wrappers for local-only integrations.');
314
- }
315
-
316
- let composioCount = 0;
317
-
318
- for (const [index, integration] of value.entries()) {
319
- if (!isRecord(integration)) {
320
- throw invalidConfig(`integrations[${index}] must be an object.`);
321
- }
322
-
323
- if (integration.provider !== "composio" || integration.type !== "composio" || integration.mode !== "managed") {
324
- throw invalidConfig(`integrations[${index}] must be composioManaged({...}) or { type: "composio", provider: "composio", mode: "managed", ... }.`);
325
- }
326
-
327
- composioCount += 1;
328
- validateComposioManagedIntegration(integration as unknown as AgentIntegration, index);
329
- }
330
-
331
- if (composioCount > 1) {
332
- throw invalidConfig("Only one managed Composio integration is supported per agent.");
333
- }
334
-
335
- const hasExplicitComposioTools = value.some(
336
- (integration) => isRecord(integration) && integration.provider === "composio" && isRecord(integration.tools),
337
- );
338
-
339
- if (hasExplicitComposioTools && tools.some((tool) => isRecord(tool) && tool.name === MANAGED_COMPOSIO_TOOL_NAME)) {
340
- throw invalidConfig(`tools must not declare reserved managed Composio tool name "${MANAGED_COMPOSIO_TOOL_NAME}".`);
341
- }
342
- }
343
-
344
- function validateComposioManagedIntegration(value: AgentIntegration, index: number): void {
345
- expectString(value.name, `integrations[${index}].name`);
346
-
347
- if (!INTEGRATION_NAME_PATTERN.test(value.name)) {
348
- throw invalidConfig(`integrations[${index}].name must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`);
349
- }
350
-
351
- if (!Array.isArray(value.toolkits) || value.toolkits.length === 0) {
352
- throw invalidConfig(`integrations[${index}].toolkits must include at least one Composio toolkit slug.`);
353
- }
354
-
355
- const toolkits = new Set<string>();
356
-
357
- for (const [toolkitIndex, toolkit] of value.toolkits.entries()) {
358
- expectString(toolkit, `integrations[${index}].toolkits[${toolkitIndex}]`);
359
-
360
- if (!COMPOSIO_TOOLKIT_PATTERN.test(toolkit)) {
361
- throw invalidConfig(`integrations[${index}].toolkits[${toolkitIndex}] must be a lowercase Composio toolkit slug.`);
362
- }
363
-
364
- if (toolkits.has(toolkit)) {
365
- throw invalidConfig(`integrations[${index}].toolkits must not contain duplicates.`);
366
- }
367
-
368
- toolkits.add(toolkit);
369
- }
370
-
371
- if (value.tools !== undefined) {
372
- if (!isRecord(value.tools)) {
373
- throw invalidConfig(`integrations[${index}].tools must be an object when provided.`);
374
- }
375
-
376
- for (const [toolkit, tools] of Object.entries(value.tools)) {
377
- if (!toolkits.has(toolkit)) {
378
- throw invalidConfig(`integrations[${index}].tools.${toolkit} must reference a toolkit listed in integrations[${index}].toolkits.`);
379
- }
380
-
381
- if (!Array.isArray(tools) || tools.length === 0) {
382
- throw invalidConfig(`integrations[${index}].tools.${toolkit} must include at least one Composio action slug.`);
383
- }
384
-
385
- const seenTools = new Set<string>();
386
-
387
- for (const [toolIndex, tool] of tools.entries()) {
388
- expectString(tool, `integrations[${index}].tools.${toolkit}[${toolIndex}]`);
389
-
390
- if (!COMPOSIO_TOOL_SLUG_PATTERN.test(tool)) {
391
- throw invalidConfig(`integrations[${index}].tools.${toolkit}[${toolIndex}] must be an uppercase Composio action slug.`);
392
- }
393
-
394
- if (seenTools.has(tool)) {
395
- throw invalidConfig(`integrations[${index}].tools.${toolkit} must not contain duplicates.`);
396
- }
397
-
398
- seenTools.add(tool);
399
- }
400
- }
401
- }
402
-
403
- if (value.tags !== undefined) {
404
- validateIntegrationTags(value.tags, `integrations[${index}].tags`);
405
- }
406
-
407
- if (value.confirmExternalWrites !== undefined && typeof value.confirmExternalWrites !== "boolean") {
408
- throw invalidConfig(`integrations[${index}].confirmExternalWrites must be a boolean when provided.`);
409
- }
410
- }
411
-
412
- function validateIntegrationTags(value: unknown, label: string): void {
413
- if (!isRecord(value)) {
414
- throw invalidConfig(`${label} must be an object when provided.`);
415
- }
416
-
417
- if (value.enable !== undefined) {
418
- expectStringArray(value.enable, `${label}.enable`);
419
- }
420
-
421
- if (value.disable !== undefined) {
422
- expectStringArray(value.disable, `${label}.disable`);
423
- }
424
- }
425
-
426
296
  function validateTranscriptionConfig(value: unknown): void {
427
297
  if (value === undefined) {
428
298
  return;
@@ -591,7 +461,7 @@ function validateKnowledgeRetrieval(value: unknown): void {
591
461
  }
592
462
  }
593
463
 
594
- function validateChannels(value: unknown, runtime: AgentRuntime, hasTranscriptionConfig: boolean): void {
464
+ function validateChannels(value: unknown, hasTranscriptionConfig: boolean): void {
595
465
  if (value === undefined) {
596
466
  return;
597
467
  }
@@ -600,10 +470,6 @@ function validateChannels(value: unknown, runtime: AgentRuntime, hasTranscriptio
600
470
  throw invalidConfig("channels must be an array when provided.");
601
471
  }
602
472
 
603
- if (value.length > 0 && runtime !== "edge") {
604
- throw invalidConfig('channels require runtime: "edge".');
605
- }
606
-
607
473
  const names = new Set<string>();
608
474
 
609
475
  for (const [index, channel] of value.entries()) {
@@ -1045,8 +911,8 @@ function validateDatabaseConfig(value: unknown): void {
1045
911
  throw invalidConfig("storage.database must be an object when provided.");
1046
912
  }
1047
913
 
1048
- if (value.driver !== "none" && value.driver !== "turso") {
1049
- throw invalidConfig('storage.database.driver must be "none" or "turso".');
914
+ if (value.driver !== "none" && value.driver !== "sqlite") {
915
+ throw invalidConfig('storage.database.driver must be "none" or "sqlite".');
1050
916
  }
1051
917
 
1052
918
  if (value.schema !== undefined && typeof value.schema !== "string") {
@@ -1067,12 +933,12 @@ function validateFilesConfig(value: unknown): void {
1067
933
  throw invalidConfig("storage.files must be an object when provided.");
1068
934
  }
1069
935
 
1070
- if (value.driver !== "none" && value.driver !== "r2") {
1071
- throw invalidConfig('storage.files.driver must be "none" or "r2".');
936
+ if (value.driver !== "none" && value.driver !== "local") {
937
+ throw invalidConfig('storage.files.driver must be "none" or "local".');
1072
938
  }
1073
939
 
1074
- if (value.bucket !== undefined && typeof value.bucket !== "string") {
1075
- throw invalidConfig("storage.files.bucket must be a string when provided.");
940
+ if (value.bucket !== undefined) {
941
+ throw invalidConfig("storage.files.bucket is no longer supported. Files are stored locally.");
1076
942
  }
1077
943
 
1078
944
  if (value.prefix !== undefined && typeof value.prefix !== "string") {
@@ -47,7 +47,7 @@ export async function applyCapsuleDatabaseMigrations(
47
47
  ): Promise<LocalDatabasePrepareResult["migrations"]> {
48
48
  const database = capsule.config.storage.database;
49
49
 
50
- if (!database || database.driver !== "turso") {
50
+ if (!database || database.driver !== "sqlite") {
51
51
  return {
52
52
  configured: false,
53
53
  path: null,
@@ -125,7 +125,7 @@ export async function applyCapsuleDatabaseSchema(
125
125
  ): Promise<LocalDatabasePrepareResult["schema"]> {
126
126
  const database = capsule.config.storage.database;
127
127
 
128
- if (!database || database.driver !== "turso" || !database.schema) {
128
+ if (!database || database.driver !== "sqlite" || !database.schema) {
129
129
  return {
130
130
  configured: false,
131
131
  applied: false,
@@ -2,7 +2,7 @@ import { createHash } from "node:crypto";
2
2
  import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
3
3
  import { createServer as createHttpServer, type IncomingMessage, type Server, type ServerResponse } from "node:http";
4
4
  import { createServer as createNetServer } from "node:net";
5
- import { dirname, join, relative, resolve } from "node:path";
5
+ import { dirname, relative, resolve } from "node:path";
6
6
  import { Readable } from "node:stream";
7
7
 
8
8
  import { openCapsuleStore, type ConversationRecord } from "../storage/sqlite";
@@ -423,6 +423,7 @@ async function authorizeDevRoute(
423
423
 
424
424
  const env = await loadCapsuleEnv(capsule.root);
425
425
 
426
+ // Preserve the legacy deploy_not_ready code for clients handling missing local credentials.
426
427
  if (kind === "admin") {
427
428
  return authorizeBearerSecret(request, body, env.AGENTKIT_PRIVATE_TOKEN, {
428
429
  missingCode: "deploy_not_ready",
@@ -438,15 +439,15 @@ async function authorizeDevRoute(
438
439
  if (capsule.config.access.mode === "private") {
439
440
  return authorizeBearerSecret(request, body, env.AGENTKIT_PRIVATE_TOKEN, {
440
441
  missingCode: "deploy_not_ready",
441
- missingMessage: "Private deploy requires AGENTKIT_PRIVATE_TOKEN to be set.",
442
- unauthorizedMessage: "Missing or invalid deploy access token.",
442
+ missingMessage: "Private access requires AGENTKIT_PRIVATE_TOKEN to be set.",
443
+ unauthorizedMessage: "Missing or invalid access token.",
443
444
  });
444
445
  }
445
446
 
446
447
  return authorizeBearerSecret(request, body, env.AGENTKIT_ACCESS_TOKEN, {
447
448
  missingCode: "deploy_not_ready",
448
- missingMessage: "Token deploy requires AGENTKIT_ACCESS_TOKEN to be set.",
449
- unauthorizedMessage: "Missing or invalid deploy access token.",
449
+ missingMessage: "Token access requires AGENTKIT_ACCESS_TOKEN to be set.",
450
+ unauthorizedMessage: "Missing or invalid access token.",
450
451
  });
451
452
  }
452
453
 
@@ -492,7 +493,6 @@ function readRequestAccessToken(request: Request, body: unknown): string {
492
493
 
493
494
  const header =
494
495
  request.headers.get("x-agentkit-access-token") ??
495
- request.headers.get("x-agentkit-deploy-access-token") ??
496
496
  "";
497
497
  const token = header.startsWith("Bearer ") ? header.slice("Bearer ".length) : header;
498
498
  if (token.trim()) {
@@ -900,7 +900,7 @@ async function flushDevChannelBuffer(
900
900
  },
901
901
  });
902
902
  } catch {
903
- // Local channel buffering is best-effort; hosted delivery logs own production failures.
903
+ // Local channel buffering is best-effort; the buffer is not a durable delivery queue.
904
904
  }
905
905
  }
906
906
 
@@ -911,7 +911,7 @@ function unrefTimer(timer: ReturnType<typeof setTimeout>): void {
911
911
  }
912
912
 
913
913
  async function handleLocalFile(capsule: LoadedAgentCapsule, request: Request, rawKey: string): Promise<Response> {
914
- if (capsule.config.storage.files?.driver !== "r2") {
914
+ if (capsule.config.storage.files?.driver !== "local") {
915
915
  throw new AgentKitError("files_not_configured", "File storage is not configured for this Agent Capsule.");
916
916
  }
917
917
 
@@ -3,6 +3,17 @@ import { join } from "node:path";
3
3
 
4
4
  import { AgentKitError } from "./errors";
5
5
 
6
+ export function collectSecretValues(
7
+ scope: { secrets?: string[]; tools?: Array<{ secrets?: string[] }> } | undefined,
8
+ env: Record<string, string | undefined>,
9
+ ): string[] {
10
+ const names = [...(scope?.secrets ?? []), ...(scope?.tools ?? []).flatMap((tool) => tool.secrets ?? [])];
11
+ return names.flatMap((name) => {
12
+ const value = env[name];
13
+ return value ? [value] : [];
14
+ });
15
+ }
16
+
6
17
  export async function loadCapsuleEnv(
7
18
  root: string,
8
19
  baseEnv: Record<string, string | undefined> = process.env,