@andreprado/agentkit 0.1.0-alpha.16 → 0.1.0-alpha.18

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 (39) hide show
  1. package/README.md +8 -0
  2. package/docs/guides/add-channel.md +4 -2
  3. package/docs/guides/add-managed-composio.md +161 -0
  4. package/docs/guides/channel-security.md +36 -39
  5. package/docs/guides/connect-telegram.md +3 -1
  6. package/docs/guides/debug-channel.md +141 -0
  7. package/docs/guides/prepare-deploy.md +7 -10
  8. package/docs/llms-full.txt +19 -5
  9. package/docs/llms.txt +11 -2
  10. package/package.json +1 -3
  11. package/src/cli/cloud-client.ts +12 -0
  12. package/src/cli/commands/channels.ts +119 -7
  13. package/src/cli/commands/transcribe.ts +171 -0
  14. package/src/cli/deploy-chat-ui.ts +146 -3
  15. package/src/cli/deploy-readiness.ts +112 -3
  16. package/src/cli/help.ts +19 -4
  17. package/src/cli/index.ts +198 -3
  18. package/src/create-project.ts +4 -32
  19. package/src/index.ts +149 -0
  20. package/src/runtime/chat.ts +2 -1
  21. package/src/runtime/config.ts +133 -0
  22. package/src/runtime/core/manifest.ts +31 -2
  23. package/src/runtime/deploy-readiness.ts +31 -1
  24. package/src/runtime/inspect.ts +109 -4
  25. package/src/runtime/integrations/composio.ts +423 -0
  26. package/src/runtime/skills.ts +95 -0
  27. package/src/runtime/targets/cloudflare/build.ts +395 -10
  28. package/src/runtime/tool-runner.ts +2 -1
  29. package/src/templates/skills/agentkit-capsule/SKILL.md +1 -0
  30. package/src/templates/skills/agentkit-channels/SKILL.md +2 -0
  31. package/src/templates/skills/agentkit-channels/references/channel-debugging.md +3 -1
  32. package/src/templates/skills/agentkit-channels/references/telegram.md +3 -1
  33. package/src/templates/skills/agentkit-deploy/SKILL.md +1 -1
  34. package/src/templates/skills/agentkit-integrations/SKILL.md +75 -0
  35. package/src/templates/skills/agentkit-troubleshooting/SKILL.md +3 -2
  36. package/docs/guides/agentkit-skills-architecture.md +0 -472
  37. package/docs/guides/channels-implementation-map.md +0 -243
  38. package/docs/guides/channels-production-handoff.md +0 -118
  39. package/docs/portable-deploy-release-checklist.md +0 -41
package/src/index.ts CHANGED
@@ -145,6 +145,32 @@ export type WhatsappChannelConfig = {
145
145
 
146
146
  export type AgentChannel = WebsiteChannelConfig | TelegramChannelConfig | WhatsappChannelConfig;
147
147
 
148
+ export type IntegrationTagsConfig = {
149
+ enable?: string[];
150
+ disable?: string[];
151
+ };
152
+
153
+ export type ComposioManagedIntegrationInput = {
154
+ name?: string;
155
+ toolkits: string[];
156
+ tools?: Record<string, string[]>;
157
+ tags?: IntegrationTagsConfig;
158
+ confirmExternalWrites?: boolean;
159
+ };
160
+
161
+ export type ComposioManagedIntegration = {
162
+ type: "composio";
163
+ provider: "composio";
164
+ mode: "managed";
165
+ name: string;
166
+ toolkits: string[];
167
+ tools?: Record<string, string[]>;
168
+ tags?: IntegrationTagsConfig;
169
+ confirmExternalWrites?: boolean;
170
+ };
171
+
172
+ export type AgentIntegration = ComposioManagedIntegration;
173
+
148
174
  export type AgentDatabaseConfig =
149
175
  | {
150
176
  driver: "none";
@@ -316,6 +342,7 @@ export type AgentConfig = {
316
342
  instructions: string;
317
343
  secrets: string[];
318
344
  tools?: AgentTool[];
345
+ integrations?: AgentIntegration[];
319
346
  channels?: AgentChannel[];
320
347
  transcription?: AgentTranscriptionConfig;
321
348
  knowledge?: AgentKnowledgeConfig;
@@ -338,6 +365,25 @@ export function defineTool<Input = unknown, Output = unknown>(tool: AgentTool<In
338
365
  return tool;
339
366
  }
340
367
 
368
+ export function composioManaged(input: ComposioManagedIntegrationInput): ComposioManagedIntegration {
369
+ const name = normalizeIntegrationName(input.name ?? "composio", "composio integration name");
370
+ const toolkits = normalizeToolkitList(input.toolkits, "composioManaged.toolkits");
371
+ const tools = input.tools ? normalizeComposioToolMap(input.tools, toolkits) : undefined;
372
+ const tags = input.tags ? normalizeIntegrationTags(input.tags) : undefined;
373
+ const confirmExternalWrites = input.confirmExternalWrites;
374
+
375
+ return {
376
+ type: "composio",
377
+ provider: "composio",
378
+ mode: "managed",
379
+ name,
380
+ toolkits,
381
+ ...(tools ? { tools } : {}),
382
+ ...(tags ? { tags } : {}),
383
+ ...(confirmExternalWrites === undefined ? {} : { confirmExternalWrites }),
384
+ };
385
+ }
386
+
341
387
  export function websiteChannel(input: WebsiteChannelInput): WebsiteChannelConfig {
342
388
  return {
343
389
  type: "website",
@@ -404,6 +450,109 @@ function normalizeChannelSecrets(secrets: string[], context: string): string[] {
404
450
  return Array.from(uniqueSecrets).sort();
405
451
  }
406
452
 
453
+ function normalizeIntegrationName(value: string, context: string): string {
454
+ const name = value.trim();
455
+
456
+ if (!/^[a-z][a-z0-9-]*$/.test(name)) {
457
+ throw new Error(`${context} must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`);
458
+ }
459
+
460
+ return name;
461
+ }
462
+
463
+ function normalizeToolkitList(values: string[], context: string): string[] {
464
+ if (!Array.isArray(values) || values.length === 0) {
465
+ throw new Error(`${context} must include at least one toolkit slug.`);
466
+ }
467
+
468
+ const toolkits = new Set<string>();
469
+
470
+ for (const value of values) {
471
+ if (typeof value !== "string") {
472
+ throw new Error(`${context} entries must be toolkit slug strings.`);
473
+ }
474
+
475
+ const toolkit = value.trim().toLowerCase();
476
+
477
+ if (!/^[a-z][a-z0-9_-]*$/.test(toolkit)) {
478
+ throw new Error(`${context} entries must start with a letter and contain only letters, numbers, underscores, and hyphens.`);
479
+ }
480
+
481
+ toolkits.add(toolkit);
482
+ }
483
+
484
+ return Array.from(toolkits).sort();
485
+ }
486
+
487
+ function normalizeComposioToolMap(values: Record<string, string[]>, toolkits: string[]): Record<string, string[]> | undefined {
488
+ const toolkitSet = new Set(toolkits);
489
+ const normalized: Record<string, string[]> = {};
490
+
491
+ for (const [rawToolkit, rawTools] of Object.entries(values)) {
492
+ const toolkit = rawToolkit.trim().toLowerCase();
493
+
494
+ if (!toolkitSet.has(toolkit)) {
495
+ throw new Error(`composioManaged.tools.${rawToolkit} must reference a toolkit listed in composioManaged.toolkits.`);
496
+ }
497
+
498
+ if (!Array.isArray(rawTools) || rawTools.length === 0) {
499
+ throw new Error(`composioManaged.tools.${rawToolkit} must include at least one Composio action slug.`);
500
+ }
501
+
502
+ const tools = new Set<string>();
503
+
504
+ for (const rawTool of rawTools) {
505
+ if (typeof rawTool !== "string") {
506
+ throw new Error(`composioManaged.tools.${rawToolkit} entries must be Composio action slug strings.`);
507
+ }
508
+
509
+ const tool = rawTool.trim().toUpperCase();
510
+
511
+ if (!/^[A-Z][A-Z0-9_]*$/.test(tool)) {
512
+ throw new Error(`composioManaged.tools.${rawToolkit} entries must be uppercase Composio action slugs.`);
513
+ }
514
+
515
+ tools.add(tool);
516
+ }
517
+
518
+ normalized[toolkit] = Array.from(tools).sort();
519
+ }
520
+
521
+ return Object.keys(normalized).length > 0 ? normalized : undefined;
522
+ }
523
+
524
+ function normalizeIntegrationTags(tags: IntegrationTagsConfig): IntegrationTagsConfig {
525
+ const normalized: IntegrationTagsConfig = {};
526
+
527
+ if (tags.enable !== undefined) {
528
+ normalized.enable = normalizeTagList(tags.enable, "composioManaged.tags.enable");
529
+ }
530
+
531
+ if (tags.disable !== undefined) {
532
+ normalized.disable = normalizeTagList(tags.disable, "composioManaged.tags.disable");
533
+ }
534
+
535
+ return normalized;
536
+ }
537
+
538
+ function normalizeTagList(values: string[], context: string): string[] {
539
+ if (!Array.isArray(values)) {
540
+ throw new Error(`${context} must be an array of tag strings.`);
541
+ }
542
+
543
+ return Array.from(
544
+ new Set(
545
+ values.map((value) => {
546
+ if (typeof value !== "string" || value.trim().length === 0) {
547
+ throw new Error(`${context} entries must be non-empty strings.`);
548
+ }
549
+
550
+ return value.trim();
551
+ }),
552
+ ),
553
+ ).sort();
554
+ }
555
+
407
556
  function normalizeChannelBuffer(input: ChannelBufferInput, context: string): ChannelBufferConfig {
408
557
  if (input.mode === "off") {
409
558
  return { mode: "off" };
@@ -7,6 +7,7 @@ import { loadAgentCapsule } from "./config";
7
7
  import { openPreparedCapsuleStore } from "./database";
8
8
  import { loadCapsuleEnv } from "./env";
9
9
  import { AgentKitError, isAgentKitError } from "./errors";
10
+ import { createManagedComposioTools } from "./integrations/composio";
10
11
  import { syncConfiguredKnowledgeSources } from "./knowledge/ingest";
11
12
  import { appendKnowledgePromptPolicy } from "./knowledge/prompt-policy";
12
13
  import { createKnowledgeSearchTool } from "./knowledge/tool";
@@ -145,7 +146,7 @@ export async function runAgentMessage(
145
146
  }
146
147
 
147
148
  function withKnowledgeTools(capsule: LoadedAgentCapsule): NonNullable<LoadedAgentCapsule["config"]["tools"]> {
148
- const tools = [...(capsule.config.tools ?? [])];
149
+ const tools = [...createManagedComposioTools(capsule.config), ...(capsule.config.tools ?? [])];
149
150
  const knowledgeTool = createKnowledgeSearchTool(capsule);
150
151
 
151
152
  if (knowledgeTool) {
@@ -16,9 +16,11 @@ import type {
16
16
  TelegramAllowedUpdate,
17
17
  AgentKnowledgeEmbeddingProvider,
18
18
  ChannelBufferMode,
19
+ AgentIntegration,
19
20
  ChannelAudioMode,
20
21
  TranscriptionProviderName,
21
22
  } from "../index";
23
+ import { MANAGED_COMPOSIO_TOOL_NAME } from "./integrations/composio";
22
24
  import { AgentKitError } from "./errors";
23
25
  import { isValidTimeZone } from "./prompt-context";
24
26
 
@@ -35,6 +37,9 @@ const TELEGRAM_ALLOWED_UPDATES = new Set<TelegramAllowedUpdate>(["message"]);
35
37
  const KNOWLEDGE_EMBEDDING_PROVIDERS = new Set<AgentKnowledgeEmbeddingProvider>(["none", "test", "openai"]);
36
38
  const TRANSCRIPTION_PROVIDERS = new Set<TranscriptionProviderName>(["test", "openai", "groq"]);
37
39
  const CHANNEL_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
40
+ const INTEGRATION_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
41
+ const COMPOSIO_TOOLKIT_PATTERN = /^[a-z][a-z0-9_-]*$/;
42
+ const COMPOSIO_TOOL_SLUG_PATTERN = /^[A-Z][A-Z0-9_]*$/;
38
43
  const SECRET_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
39
44
  const moduleDir = dirname(fileURLToPath(import.meta.url));
40
45
  let configImportNonce = 0;
@@ -234,6 +239,7 @@ function validateAgentConfig(value: unknown): asserts value is AgentConfig {
234
239
  }
235
240
  }
236
241
 
242
+ validateIntegrations(value.integrations, value.runtime as AgentRuntime, value.tools);
237
243
  validateTranscriptionConfig(value.transcription);
238
244
  validateChannels(value.channels, value.runtime as AgentRuntime, Boolean(value.transcription));
239
245
  validateKnowledgeConfig(value.knowledge);
@@ -258,6 +264,133 @@ function validateAgentConfig(value: unknown): asserts value is AgentConfig {
258
264
  validateFilesConfig(value.storage.files);
259
265
  }
260
266
 
267
+ function validateIntegrations(
268
+ value: unknown,
269
+ runtime: AgentRuntime,
270
+ tools: AgentConfig["tools"] = [],
271
+ ): void {
272
+ if (value === undefined) {
273
+ return;
274
+ }
275
+
276
+ if (!Array.isArray(value)) {
277
+ throw invalidConfig("integrations must be an array when provided.");
278
+ }
279
+
280
+ if (value.length > 0 && runtime !== "edge") {
281
+ throw invalidConfig('managed integrations require runtime: "edge". Use BYO defineTool wrappers for local-only integrations.');
282
+ }
283
+
284
+ let composioCount = 0;
285
+
286
+ for (const [index, integration] of value.entries()) {
287
+ if (!isRecord(integration)) {
288
+ throw invalidConfig(`integrations[${index}] must be an object.`);
289
+ }
290
+
291
+ if (integration.provider !== "composio" || integration.type !== "composio" || integration.mode !== "managed") {
292
+ throw invalidConfig(`integrations[${index}] must be composioManaged({...}) or { type: "composio", provider: "composio", mode: "managed", ... }.`);
293
+ }
294
+
295
+ composioCount += 1;
296
+ validateComposioManagedIntegration(integration as unknown as AgentIntegration, index);
297
+ }
298
+
299
+ if (composioCount > 1) {
300
+ throw invalidConfig("Only one managed Composio integration is supported per agent.");
301
+ }
302
+
303
+ const hasExplicitComposioTools = value.some(
304
+ (integration) => isRecord(integration) && integration.provider === "composio" && isRecord(integration.tools),
305
+ );
306
+
307
+ if (hasExplicitComposioTools && tools.some((tool) => isRecord(tool) && tool.name === MANAGED_COMPOSIO_TOOL_NAME)) {
308
+ throw invalidConfig(`tools must not declare reserved managed Composio tool name "${MANAGED_COMPOSIO_TOOL_NAME}".`);
309
+ }
310
+ }
311
+
312
+ function validateComposioManagedIntegration(value: AgentIntegration, index: number): void {
313
+ expectString(value.name, `integrations[${index}].name`);
314
+
315
+ if (!INTEGRATION_NAME_PATTERN.test(value.name)) {
316
+ throw invalidConfig(`integrations[${index}].name must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`);
317
+ }
318
+
319
+ if (!Array.isArray(value.toolkits) || value.toolkits.length === 0) {
320
+ throw invalidConfig(`integrations[${index}].toolkits must include at least one Composio toolkit slug.`);
321
+ }
322
+
323
+ const toolkits = new Set<string>();
324
+
325
+ for (const [toolkitIndex, toolkit] of value.toolkits.entries()) {
326
+ expectString(toolkit, `integrations[${index}].toolkits[${toolkitIndex}]`);
327
+
328
+ if (!COMPOSIO_TOOLKIT_PATTERN.test(toolkit)) {
329
+ throw invalidConfig(`integrations[${index}].toolkits[${toolkitIndex}] must be a lowercase Composio toolkit slug.`);
330
+ }
331
+
332
+ if (toolkits.has(toolkit)) {
333
+ throw invalidConfig(`integrations[${index}].toolkits must not contain duplicates.`);
334
+ }
335
+
336
+ toolkits.add(toolkit);
337
+ }
338
+
339
+ if (value.tools !== undefined) {
340
+ if (!isRecord(value.tools)) {
341
+ throw invalidConfig(`integrations[${index}].tools must be an object when provided.`);
342
+ }
343
+
344
+ for (const [toolkit, tools] of Object.entries(value.tools)) {
345
+ if (!toolkits.has(toolkit)) {
346
+ throw invalidConfig(`integrations[${index}].tools.${toolkit} must reference a toolkit listed in integrations[${index}].toolkits.`);
347
+ }
348
+
349
+ if (!Array.isArray(tools) || tools.length === 0) {
350
+ throw invalidConfig(`integrations[${index}].tools.${toolkit} must include at least one Composio action slug.`);
351
+ }
352
+
353
+ const seenTools = new Set<string>();
354
+
355
+ for (const [toolIndex, tool] of tools.entries()) {
356
+ expectString(tool, `integrations[${index}].tools.${toolkit}[${toolIndex}]`);
357
+
358
+ if (!COMPOSIO_TOOL_SLUG_PATTERN.test(tool)) {
359
+ throw invalidConfig(`integrations[${index}].tools.${toolkit}[${toolIndex}] must be an uppercase Composio action slug.`);
360
+ }
361
+
362
+ if (seenTools.has(tool)) {
363
+ throw invalidConfig(`integrations[${index}].tools.${toolkit} must not contain duplicates.`);
364
+ }
365
+
366
+ seenTools.add(tool);
367
+ }
368
+ }
369
+ }
370
+
371
+ if (value.tags !== undefined) {
372
+ validateIntegrationTags(value.tags, `integrations[${index}].tags`);
373
+ }
374
+
375
+ if (value.confirmExternalWrites !== undefined && typeof value.confirmExternalWrites !== "boolean") {
376
+ throw invalidConfig(`integrations[${index}].confirmExternalWrites must be a boolean when provided.`);
377
+ }
378
+ }
379
+
380
+ function validateIntegrationTags(value: unknown, label: string): void {
381
+ if (!isRecord(value)) {
382
+ throw invalidConfig(`${label} must be an object when provided.`);
383
+ }
384
+
385
+ if (value.enable !== undefined) {
386
+ expectStringArray(value.enable, `${label}.enable`);
387
+ }
388
+
389
+ if (value.disable !== undefined) {
390
+ expectStringArray(value.disable, `${label}.disable`);
391
+ }
392
+ }
393
+
261
394
  function validateTranscriptionConfig(value: unknown): void {
262
395
  if (value === undefined) {
263
396
  return;
@@ -2,6 +2,11 @@ import { relative, resolve } from "node:path";
2
2
 
3
3
  import type { AgentConfig, AgentTool } from "../../index";
4
4
  import type { LoadedAgentCapsule } from "../config";
5
+ import {
6
+ createManagedComposioTools,
7
+ managedComposioRequiredSecrets,
8
+ resolveManagedComposioIntegrations,
9
+ } from "../integrations/composio";
5
10
  import { resolveKnowledgeConfig } from "../knowledge/config";
6
11
  import { KNOWLEDGE_SEARCH_TOOL_NAME } from "../knowledge/tool";
7
12
  import { resolveTranscriptionConfig } from "../transcription";
@@ -28,6 +33,15 @@ export type SharedAgentManifest = {
28
33
  permissions: string[];
29
34
  timeoutMs: number | null;
30
35
  }>;
36
+ integrations: Array<{
37
+ name: string;
38
+ provider: "composio";
39
+ mode: "managed";
40
+ toolkits: string[];
41
+ tools: string[];
42
+ userId: string;
43
+ confirmExternalWrites: boolean;
44
+ }>;
31
45
  channels: NonNullable<AgentConfig["channels"]>;
32
46
  transcription: {
33
47
  enabled: boolean;
@@ -94,6 +108,8 @@ export function buildSharedAgentManifest(
94
108
  const database = buildDatabaseManifest(capsule, options.databaseSchema ?? null);
95
109
  const files = buildFilesManifest(capsule);
96
110
  const knowledge = resolveKnowledgeConfig(capsule.config);
111
+ const integrationTools = createManagedComposioTools(capsule.config);
112
+ const tools = [...integrationTools, ...(capsule.config.tools ?? [])];
97
113
  const transcription = resolveTranscriptionConfig(capsule.config.transcription);
98
114
 
99
115
  requiredSecrets.add("AGENTKIT_PRIVATE_TOKEN");
@@ -119,7 +135,11 @@ export function buildSharedAgentManifest(
119
135
  requiredSecrets.add(transcription.secret);
120
136
  }
121
137
 
122
- for (const tool of capsule.config.tools ?? []) {
138
+ for (const secret of managedComposioRequiredSecrets(capsule.config)) {
139
+ requiredSecrets.add(secret);
140
+ }
141
+
142
+ for (const tool of tools) {
123
143
  for (const secret of tool.secrets ?? []) {
124
144
  requiredSecrets.add(secret);
125
145
  }
@@ -139,7 +159,7 @@ export function buildSharedAgentManifest(
139
159
  timeZone: capsule.config.timeZone ?? null,
140
160
  prompt: toCapsulePath(capsule, capsule.instructionsPath),
141
161
  secrets: Array.from(requiredSecrets).sort(),
142
- tools: (capsule.config.tools ?? []).map((tool) => ({
162
+ tools: tools.map((tool) => ({
143
163
  name: tool.name,
144
164
  description: tool.description,
145
165
  inputSchema: tool.inputSchema,
@@ -148,6 +168,15 @@ export function buildSharedAgentManifest(
148
168
  permissions: [...(tool.permissions ?? [])].sort(),
149
169
  timeoutMs: tool.timeoutMs ?? null,
150
170
  })),
171
+ integrations: resolveManagedComposioIntegrations(capsule.config).map((integration) => ({
172
+ name: integration.name,
173
+ provider: integration.provider,
174
+ mode: integration.mode,
175
+ toolkits: integration.toolkits,
176
+ tools: integration.allowedTools,
177
+ userId: integration.userId,
178
+ confirmExternalWrites: integration.confirmExternalWrites !== false,
179
+ })),
151
180
  channels: capsule.config.channels ?? [],
152
181
  transcription: {
153
182
  enabled: transcription.enabled,
@@ -3,6 +3,10 @@ import { createHash } from "node:crypto";
3
3
  import { loadAgentCapsule } from "./config";
4
4
  import { buildSharedAgentManifest } from "./core/manifest";
5
5
  import { listCapsuleEnv } from "./env";
6
+ import {
7
+ MANAGED_COMPOSIO_API_KEY_SECRET,
8
+ resolveManagedComposioIntegrations,
9
+ } from "./integrations/composio";
6
10
 
7
11
  export type DeployReadinessSecretSource = {
8
12
  dotenv: boolean;
@@ -30,6 +34,14 @@ export type DeployReadinessContext = {
30
34
  embeddingProvider: string;
31
35
  databaseDriver: "none" | "turso";
32
36
  };
37
+ integrations: {
38
+ managedComposio: {
39
+ enabled: boolean;
40
+ toolkits: string[];
41
+ toolCount: number;
42
+ userId: string | null;
43
+ };
44
+ };
33
45
  };
34
46
 
35
47
  export async function loadDeployReadinessContext(
@@ -38,6 +50,7 @@ export async function loadDeployReadinessContext(
38
50
  ): Promise<DeployReadinessContext> {
39
51
  const capsule = await loadAgentCapsule(cwd);
40
52
  const manifest = buildSharedAgentManifest(capsule);
53
+ const managedComposio = resolveManagedComposioIntegrations(capsule.config)[0];
41
54
  const dotenvNames = new Set(await listCapsuleEnv(capsule.root));
42
55
  const requiredSecrets = manifest.secrets;
43
56
  const localSecrets: Record<string, DeployReadinessSecretSource> = {};
@@ -57,6 +70,7 @@ export async function loadDeployReadinessContext(
57
70
  isAgentKitManagedDeploySecret(name, {
58
71
  accessMode: capsule.config.access.mode,
59
72
  databaseDriver: manifest.storage.database.driver,
73
+ managedComposioEnabled: Boolean(managedComposio),
60
74
  }),
61
75
  );
62
76
  const managed = new Set(agentKitManagedSecrets);
@@ -82,6 +96,14 @@ export async function loadDeployReadinessContext(
82
96
  embeddingProvider: manifest.knowledge.embedding.provider,
83
97
  databaseDriver: manifest.storage.database.driver,
84
98
  },
99
+ integrations: {
100
+ managedComposio: {
101
+ enabled: Boolean(managedComposio),
102
+ toolkits: managedComposio?.toolkits ?? [],
103
+ toolCount: managedComposio?.allowedTools.length ?? 0,
104
+ userId: managedComposio?.userId ?? null,
105
+ },
106
+ },
85
107
  };
86
108
  }
87
109
 
@@ -91,7 +113,11 @@ export function stableCloudProjectId(name: string, accountId?: string | null): s
91
113
 
92
114
  function isAgentKitManagedDeploySecret(
93
115
  name: string,
94
- context: { accessMode: DeployReadinessContext["accessMode"]; databaseDriver: "none" | "turso" },
116
+ context: {
117
+ accessMode: DeployReadinessContext["accessMode"];
118
+ databaseDriver: "none" | "turso";
119
+ managedComposioEnabled: boolean;
120
+ },
95
121
  ): boolean {
96
122
  if (context.databaseDriver === "turso" && (name === "TURSO_DATABASE_URL" || name === "TURSO_AUTH_TOKEN")) {
97
123
  return true;
@@ -101,5 +127,9 @@ function isAgentKitManagedDeploySecret(
101
127
  return true;
102
128
  }
103
129
 
130
+ if (context.managedComposioEnabled && name === MANAGED_COMPOSIO_API_KEY_SECRET) {
131
+ return true;
132
+ }
133
+
104
134
  return false;
105
135
  }