From 81aae8221122c43570ef83cc119d8982cf5598c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Tue, 30 Jun 2026 21:59:39 -0400 Subject: [PATCH] Add resilient error handling for Composio tool execution Tool execution now returns actionable error messages when a connected account is missing, directing the admin to set up the connection. Tool loading is resilient to API failures, falling back to cached tools if available instead of crashing the agent run. --- .../services/composio/composio-tool-bridge.ts | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/AgentCompany-New/src/main/services/composio/composio-tool-bridge.ts b/AgentCompany-New/src/main/services/composio/composio-tool-bridge.ts index a3842522..5af6b879 100644 --- a/AgentCompany-New/src/main/services/composio/composio-tool-bridge.ts +++ b/AgentCompany-New/src/main/services/composio/composio-tool-bridge.ts @@ -48,11 +48,15 @@ export async function loadComposioTools(db: DatabaseSync, orgId: string): Promis if (cached && cached.toolkitsKey === toolkitsKey && Date.now() - cached.fetchedAt < CACHE_TTL_MS) { return cached.tools; } - const client = new ComposioClient(apiKey); - const schemas = await client.getTools(toolkits); - const tools = schemas.map(composioSchemaToToolDefinition); - toolCache.set(orgId, { tools, fetchedAt: Date.now(), toolkitsKey }); - return tools; + try { + const client = new ComposioClient(apiKey); + const schemas = await client.getTools(toolkits); + const tools = schemas.map(composioSchemaToToolDefinition); + toolCache.set(orgId, { tools, fetchedAt: Date.now(), toolkitsKey }); + return tools; + } catch { + return cached?.tools ?? []; + } } export async function executeComposioTool( @@ -61,17 +65,25 @@ export async function executeComposioTool( call: ToolCall, ): Promise { const apiKey = getComposioApiKey(db, orgId); - if (!apiKey) return "ERROR: Composio API key is not configured."; + if (!apiKey) return "ERROR: Composio API key is not configured. Ask the admin to set it in Settings > Tools."; const toolName = originalToolName(call.name); const entityId = getComposioEntityId(db, orgId); const client = new ComposioClient(apiKey); - const result = await client.executeTool({ - toolName, - arguments: call.arguments, - entityId, - }); - if (result.error) return `ERROR: ${result.error}`; - return JSON.stringify(result.data); + try { + const result = await client.executeTool({ + toolName, + arguments: call.arguments, + entityId, + }); + if (result.error) return `ERROR: ${result.error}`; + return JSON.stringify(result.data); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + if (message.includes("ConnectedAccount") || message.includes("connected account") || message.includes("entity_id")) { + return `ERROR: No connected account for this tool. The admin needs to connect the service at https://app.composio.dev before agents can use it.`; + } + return `ERROR: ${message}`; + } } function getComposioApiKey(db: DatabaseSync, orgId: string): string | null {