{"record":{"id":"62366a8b688c2f37","repo":"tinyhumansai/openhuman","slug":"toolkit-toolkit-is-not-connected-connected-to","errorCode":null,"errorMessage":"toolkit `{toolkit}` is not connected. Connected toolkits: [{}]","messagePattern":"toolkit `(.+?)` is not connected\\. Connected toolkits: \\[(.+?)\\]","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/openhuman/agent/debug/mod.rs","lineNumber":272,"sourceCode":"/// dynamic prompt builder.\nasync fn render_integrations_agent(config: &Config, toolkit: &str) -> Result<DumpedPrompt> {\n    let mut agent = Agent::from_config_for_agent(config, INTEGRATIONS_AGENT_ID)\n        .with_context(|| format!(\"building integrations_agent session for `{toolkit}`\"))?;\n    agent.fetch_connected_integrations().await;\n\n    let mut integration = agent\n        .connected_integrations()\n        .iter()\n        .find(|ci| ci.connected && ci.toolkit.eq_ignore_ascii_case(toolkit))\n        .cloned()\n        .ok_or_else(|| {\n            let connected: Vec<String> = agent\n                .connected_integrations()\n                .iter()\n                .filter(|ci| ci.connected)\n                .map(|ci| ci.toolkit.clone())\n                .collect();\n            anyhow!(\n                \"toolkit `{toolkit}` is not connected. Connected toolkits: [{}]\",\n                connected.join(\", \")\n            )\n        })?;\n\n    // Resolve the live client kind via the mode-aware factory so a\n    // direct-mode user can still render the prompt even without a\n    // backend session (#1710 Wave 2). Backend mode keeps the existing\n    // `fetch_toolkit_actions` round-trip; direct mode skips the\n    // refresh (no backend allowlist to consult) and keeps the cached\n    // catalogue, mirroring `ComposioListToolsTool`'s short-circuit.\n    use crate::openhuman::integrations::composio::client::{\n        create_composio_client, ComposioClientKind,\n    };\n    let client_kind = create_composio_client(config)\n        .map_err(|e| anyhow!(\"composio client unavailable — is the user signed in? ({e})\"))?;\n\n    // Refresh the action catalogue for this toolkit at prompt-generation","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/src/openhuman/agent/debug/mod.rs#L254-L290","documentation":"render_integrations_agent (src/openhuman/agent/debug/mod.rs:272) looks up the requested toolkit in the agent's connected_integrations with a case-insensitive match AND `ci.connected == true`. A miss builds the connected-toolkit list (connected entries only) and errors with it, so the message doubles as a discovery aid.","triggerScenarios":"Prompt-dumping `integrations_agent --toolkit X` where X is not connected at all, is known but whose connection is currently disabled/disconnected (ci.connected false), or where the backend session's connected_integrations snapshot is stale.","commonSituations":"Toolkit was revoked/disconnected after the app started; user guesses a toolkit name (\"google\" vs \"gmail\"); case variants are fine but prefixes/aliases are not; backend returned an empty snapshot so everything appears disconnected.","solutions":["Pick a toolkit from the error's Connected toolkits list.","Run `composio list_connection` to see live connection state and connect the toolkit you want.","Reconnect a toolkit showing as known-but-disconnected, then retry the dump.","If the list is empty but you expect connections, sign in / refresh so the connected_integrations snapshot repopulates."],"exampleFix":"# before\n... --agent integrations_agent --toolkit google   # error lists: [gmail, notion]\n# after\n... --agent integrations_agent --toolkit gmail","handlingStrategy":"validation","validationCode":"let connected: Vec<String> = agent\n    .connected_integrations()\n    .iter()\n    .filter(|ci| ci.connected)\n    .map(|ci| ci.toolkit.clone())\n    .collect();\nif !connected.iter().any(|t| t.eq_ignore_ascii_case(&toolkit)) {\n    anyhow::bail!(\"toolkit `{toolkit}` not connected; connected: {connected:?}\");\n}","typeGuard":"fn is_connected_toolkit(agent: &AgentHandle, toolkit: &str) -> bool {\n    agent\n        .connected_integrations()\n        .iter()\n        .any(|ci| ci.connected && ci.toolkit.eq_ignore_ascii_case(toolkit))\n}","tryCatchPattern":"match render_integrations_agent(&config, toolkit).await {\n    Err(e) if e.to_string().contains(\"is not connected\") => {\n        // Parse the Connected toolkits list from the message, prompt the user\n        // to pick one or connect it, then retry with a valid toolkit.\n    }\n    other => other,\n}","preventionTips":["Check `composio list_connection` before naming a toolkit.","Remember the match requires ci.connected == true — known-but-disconnected toolkits fail too.","Use exact toolkit slugs (gmail, notion), not vendor names (google)."],"tags":["rust","integrations","composio","agent-prompts","not-found","debug"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}