# Composio

> Composio - Tool Execution Platform for AI Agents

- Skill: `johnalbertini14-glitch/composio` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add johnalbertini14-glitch/composio`
- Raw SKILL.md: https://api.skillmd.com/api/skills/johnalbertini14-glitch/composio/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: johnalbertini14-glitch (https://skillmd.com/u/johnalbertini14-glitch)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/johnalbertini14-glitch/composio

---

# Composio - Tool Execution Platform for AI Agents

Composio connects your AI agent to 500+ apps — Gmail, Slack, GitHub, Notion, Google Workspace, Microsoft (Outlook, Teams), X/Twitter, Figma, Web Search, Browser automation, Meta apps, TikTok, and more — for seamless cross-app automation.

Use this guide to discover tools, manage connections, and execute actions across any supported app.

**API Base:** `https://backend.composio.dev/api/v3`
**Auth:** All requests require `x-api-key: YOUR_API_KEY`

---

## Setup (One-Time)

### 1. Get Your API Key

Go to [platform.composio.dev](https://platform.composio.dev) and sign in with Google or another account. Navigate to your project settings and copy your API key.

```bash
export COMPOSIO_API_KEY="your_api_key_here"
export COMPOSIO_BASE="https://backend.composio.dev/api/v3"
```

That's it. You can now call any Composio tool.

---

## Core Operations

Every tool is called through one endpoint — the tool slug goes in the URL:

```
POST /api/v3/tools/execute/{TOOL_SLUG}
```

```bash
curl -X POST "$COMPOSIO_BASE/tools/execute/TOOL_SLUG_HERE" \
  -H "x-api-key: $COMPOSIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "arguments": { ... }
  }'
```

Optional fields on every request:

| Field | Description |
|-------|-------------|
| `arguments` | Tool-specific input parameters (see each tool below) |
| `user_id` | Your end-user's identifier (for multi-user connected accounts) |
| `connected_account_id` | Override which connected account to use |

---

### COMPOSIO_SEARCH_TOOLS — Discover Tools

**Always call this first.** Searches 500+ apps to find the right tools for your task. Returns tool schemas, execution plans, connection status, and pitfalls.

```bash
curl -X POST "$COMPOSIO_BASE/tools/execute/COMPOSIO_SEARCH_TOOLS" \
  -H "x-api-key: $COMPOSIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "arguments": {
      "queries": [
        {
          "use_case": "send an email to someone",
          "known_fields": "recipient_name: John"
        },
        {
          "use_case": "create a meeting invite",
          "known_fields": "meeting_date: tomorrow"
        }
      ],
      "session": {
        "generate_id": true
      }
    }
  }'
```

| Parameter | Required | Description |
|-----------|----------|-------------|
| `queries` | Yes | Array of search queries (1-7 items) |
| `queries[].use_case` | Yes | Normalized English description of the task. Include app name if known. No personal identifiers here. |
| `queries[].known_fields` | No | Comma-separated key:value pairs of known inputs (e.g., `"channel_name: general, timezone: UTC"`) |
| `session.generate_id` | Yes (first call) | Set `true` for new workflows to get a session ID |
| `session.id` | Yes (subsequent) | Reuse the session ID returned from first call |
| `model` | No | Your LLM model name (e.g., `"claude-4.5-sonnet"`) for optimized planning |

**Response:**

```json
{
  "data": {
    "results": [
      {
        "index": 1,
        "use_case": "send an email to someone",
        "primary_tool_slugs": ["GMAIL_SEND_EMAIL"],
        "related_tool_slugs": ["GMAIL_CREATE_EMAIL_DRAFT"],
        "toolkits": ["gmail"],
        "recommended_plan_steps": ["Step 1: ...", "Step 2: ..."],
        "known_pitfalls": ["Always set user_id to 'me'"],
        "reference_workbench_snippets": [...]
      }
    ],
    "tool_schemas": {
      "GMAIL_SEND_EMAIL": {
        "toolkit": "gmail",
        "tool_slug": "GMAIL_SEND_EMAIL",
        "description": "Send an email",
        "input_schema": { ... }
      }
    },
    "toolkit_connection_statuses": [
      {
        "toolkit": "gmail",
        "has_active_connection": false,
        "status_message": "No active connection. Initiate via COMPOSIO_MANAGE_CONNECTIONS."
      }
    ],
    "time_info": {
      "current_time_utc": "2025-01-15T10:30:00Z",
      "current_time_utc_epoch_seconds": 1736935800
    },
    "session": {
      "id": "abcd",
      "instructions": "Pass this session ID in all subsequent calls"
    }
  },
  "successful": true
}
```

**Splitting guidelines:**
- 1 query = 1 tool action. Include hidden prerequisites (e.g., "get issue" before "update issue").
- Include app names in every sub-query if the user specified one.
- Translate non-English prompts to English while preserving identifiers.

**After searching:**
- Review the `recommended_plan_steps` and `known_pitfalls` before executing.
- If a tool has `schemaRef` instead of `input_schema`, call `COMPOSIO_GET_TOOL_SCHEMAS` first.
- If `has_active_connection` is `false` for a toolkit, call `COMPOSIO_MANAGE_CONNECTIONS` before executing its tools.

---

### COMPOSIO_MANAGE_CONNECTIONS — Connect to Apps

Creates or checks OAuth/API connections for toolkits. Returns auth links for user authentication.

```bash
curl -X POST "$COMPOSIO_BASE/tools/execute/COMPOSIO_MANAGE_CONNECTIONS" \
  -H "x-api-key: $COMPOSIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "arguments": {
      "toolkits": ["gmail", "slack"],
      "session_id": "abcd"
    }
  }'
```

| Parameter | Required | Description |
|-----------|----------|-------------|
| `toolkits` | Yes | Toolkit names from SEARCH_TOOLS response (e.g., `["gmail", "github"]`). Never invent names. |
| `reinitiate_all` | No | Force reconnection even if already active (default: `false`) |
| `session_id` | No | Session ID from SEARCH_TOOLS |

**Response:**

```json
{
  "data": {
    "message": "1 active, 1 initiated",
    "results": {
      "gmail": {
        "toolkit": "gmail",
        "status": "initiated",
        "redirect_url": "https://accounts.google.com/o/oauth2/...",
        "instruction": "Click the link to authenticate"
      },
      "slack": {
        "toolkit": "slack",
        "status": "active",
        "has_active_connection": true,
        "connected_account_id": "ca_xxx",
        "current_user_info": { "email": "user@example.com" }
      }
    },
    "summary": {
      "total_toolkits": 2,
      "active_connections": 1,
      "initiated_connections": 1,
      "failed_connections": 0
    }
  },
  "successful": true
}
```

**Connection workflow:**
1. Call SEARCH_TOOLS — check `toolkit_connection_statuses`
2. If `has_active_connection` is false, call MANAGE_CONNECTIONS
3. If status is `"initiated"`, present the `redirect_url` to the user for authentication
4. Once the user completes auth, the connection becomes active
5. Only execute tools after the connection is confirmed active

---

### COMPOSIO_GET_TOOL_SCHEMAS — Get Full Input Schemas

Retrieves complete input schemas for tools. Call this when SEARCH_TOOLS returns `schemaRef` instead of a full `input_schema`.

```bash
curl -X POST "$COMPOSIO_BASE/tools/execute/COMPOSIO_GET_TOOL_SCHEMAS" \
  -H "x-api-key: $COMPOSIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "arguments": {
      "tool_slugs": ["GMAIL_SEND_EMAIL", "SLACK_SEND_MESSAGE"],
      "session_id": "abcd"
    }
  }'
```

| Parameter | Required | Description |
|-----------|----------|-------------|
| `tool_slugs` | Yes | Array of tool slugs from SEARCH_TOOLS |
| `session_id` | No | Session ID |

**Response:**

```json
{
  "data": {
    "success": true,
    "tool_schemas": {
      "GMAIL_SEND_EMAIL": {
        "toolkit": "gmail",
        "tool_slug": "GMAIL_SEND_EMAIL",
        "description": "Send an email via Gmail",
        "input_schema": {
          "properties": {
            "to": { "type": "string", "description": "Recipient email" },
            "subject": { "type": "string" },
            "body": { "type": "string" }
          },
          "required": ["to", "subject", "body"]
        }
      }
    },
    "not_found": []
  },
  "successful": true
}
```

---

### COMPOSIO_MULTI_EXECUTE_TOOL — Execute Tools

Executes one or more tools in parallel. This is how you run the tools discovered through SEARCH_TOOLS.

```bash
curl -X POST "$COMPOSIO_BASE/tools/execute/COMPOSIO_MULTI_EXECUTE_TOOL" \
  -H "x-api-key: $COMPOSIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "arguments": {
      "tools": [
        {
          "tool_slug": "GMAIL_SEND_EMAIL",
          "arguments": {
            "to": "john@example.com",
            "subject": "Hello",
            "body": "Welcome to the team!"
          }
        },
        {
          "tool_slug": "SLACK_SEND_MESSAGE",
          "arguments": {
            "channel": "#general",
            "text": "New member joined!"
          }
        }
      ],
      "sync_response_to_workbench": false,
      "session_id": "abcd"
    }
  }'
```

| Parameter | Required | Description |
|-----------|----------|-------------|
| `tools` | Yes | Array of tool executions (1-50 items) |
| `tools[].tool_slug` | Yes | Valid slug from SEARCH_TOOLS |
| `tools[].arguments` | Yes | Arguments matching the tool's input schema exactly |
| `sync_response_to_workbench` | Yes | Set `true` if response may be large or needed for later scripting |
| `session_id` | No | Session ID |

**Response:**

```json
{
  "data": {
    "results": [
      {
        "tool_slug": "GMAIL_SEND_EMAIL",
        "index": 0,
        "response": {
          "data": { "id": "msg_123", "threadId": "thread_456" },
          "successful": true
        },
        "error": null
      },
      {
        "tool_slug": "SLACK_SEND_MESSAGE",
        "index": 1,
        "response": {
          "data": { "ok": true, "ts": "1234567890.123456" },
          "successful": true
        },
        "error": null
      }
    ],
    "total_count": 2,
    "success_count": 2,
    "error_count": 0,
    "remote_file_info": null
  },
  "successful": true
}
```

**Rules:**
- Only batch tools that are logically independent (no ordering dependencies).
- Never invent tool slugs or argument fields — always use what SEARCH_TOOLS returned.
- Ensure active connections exist before executing.
- If response is large, it may be saved to a remote file — use `remote_file_info.file_path` with the Remote Workbench or Bash tools to process it.

---

### COMPOSIO_REMOTE_WORKBENCH — Run Python Code

Executes Python code in a persistent remote Jupyter sandbox. Use for processing large tool outputs, bulk operations, and scripting multi-tool chains.

```bash
curl -X POST "$COMPOSIO_BASE/tools/execute/COMPOSIO_REMOTE_WORKBENCH" \
  -H "x-api-key: $COMPOSIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "arguments": {
      "code_to_execute": "result, error = run_composio_tool(\"GMAIL_FETCH_EMAILS\", {\"max_results\": 5, \"user_id\": \"me\"})\nif error:\n    print(\"Error:\", error)\nelse:\n    emails = result.get(\"data\", {})\n    print(\"Fetched:\", len(emails.get(\"messages\", [])))",
      "thought": "Fetching recent emails for bulk processing",
      "session_id": "abcd"
    }
  }'
```

| Parameter | Required | Description |
|-----------|----------|-------------|
| `code_to_execute` | Yes | Python code to run in the sandbox |
| `thought` | No | One-sentence objective description |
| `timeout` | No | Execution timeout in seconds (1-780, default: 600) |
| `session_id` | No | Session ID |

**Response:**

```json
{
  "data": {
    "results": "Fetched: 5",
    "stdout": "Fetched: 5\n",
    "stderr": "",
    "error": "",
    "sandbox_id_suffix": "a1b2"
  },
  "successful": true
}
```

If output exceeds 40,000 characters, it is saved to a file and `results_file_path` / `stdout_file_path` is returned instead.

**Pre-loaded helper functions** (do NOT import or redeclare these):

| Function | Signature | Description |
|----------|-----------|-------------|
| `run_composio_tool` | `(tool_slug: str, arguments: dict) -> tuple[dict, str]` | Execute a Composio app tool. Returns `(response, error)`. |
| `invoke_llm` | `(query: str) -> tuple[str, str]` | Call an LLM for analysis, summarization, extraction. Max 200k chars input. Returns `(response, error)`. |
| `proxy_execute` | `(method, endpoint, toolkit, query_params?, body?, headers?) -> tuple[any, str]` | Direct API call to a connected toolkit when no Composio tool exists. Returns `(response, error)`. |
| `web_search` | `(query: str) -> tuple[str, str]` | Search the web via Exa AI. Returns `(results, error)`. |
| `upload_local_file` | `(*file_paths) -> tuple[dict, str]` | Upload sandbox files to cloud storage. Returns `({"s3_url": ...}, error)`. |
| `smart_file_extract` | `(sandbox_file_path: str) -> tuple[str, str]` | Extract text from PDF, images, etc. Returns `(text, error)`. |

**All helpers return `(result, error)` — always check error before using result.**

**Coding rules:**
1. Split work into small steps; save intermediate results to `/tmp/` files.
2. State persists across executions (variables, imports, files).
3. Hard timeout of 4 minutes — use `ThreadPoolExecutor` for bulk operations.
4. Always check error from helper functions before using results.
5. Use `invoke_llm` for summarization and analysis — it gives better results than ad-hoc filtering.
6. Do NOT call `COMPOSIO_*` meta tools via `run_composio_tool` — only use it for app tools (e.g., `GMAIL_SEND_EMAIL`).

**Example — bulk email processing:**

```python
import concurrent.futures

def process_email(email_id):
    result, error = run_composio_tool("GMAIL_GET_EMAIL", {
        "message_id": email_id, "user_id": "me"
    })
    if error:
        return {"id": email_id, "error": error}
    subject = result.get("data", {}).get("subject", "")
    return {"id": email_id, "subject": subject}

# Fetch email list
emails, err = run_composio_tool("GMAIL_FETCH_EMAILS", {
    "max_results": 50, "user_id": "me"
})
if not err:
    ids = [m["id"] for m in emails.get("data", {}).get("messages", [])]
    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as ex:
        results = list(ex.map(process_email, ids))
    print(f"Processed {len(results)} emails")
```

---

### COMPOSIO_REMOTE_BASH_TOOL — Run Bash Commands

Executes bash commands in the same persistent sandbox as the workbench.

```bash
curl -X POST "$COMPOSIO_BASE/tools/execute/COMPOSIO_REMOTE_BASH_TOOL" \
  -H "x-api-key: $COMPOSIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "arguments": {
      "command": "cat /home/user/.code_out/response.json | jq \".results[] | .tool_slug\"",
      "session_id": "abcd"
    }
  }'
```

| Parameter | Required | Description |
|-----------|----------|-------------|
| `command` | Yes | Bash command to execute |
| `session_id` | No | Session ID |

**Response:**

```json
{
  "data": {
    "stdout": "\"GMAIL_SEND_EMAIL\"\n\"SLACK_SEND_MESSAGE\"\n",
    "stdoutLines": 2,
    "stderr": "",
    "stderrLines": 0,
    "sandbox_id_suffix": "a1b2"
  },
  "successful": true
}
```

**Use cases:**
- Process large tool responses saved to remote files (via `jq`, `awk`, `sed`, `grep`)
- File system operations in the sandbox
- Commands run from `/home/user` by default
- 5-minute timeout, max 40,000 chars output per stream

---

## Typical Workflow

```
1. COMPOSIO_SEARCH_TOOLS
   | Find tools for your task
   | Check connection statuses
   | Review execution plan and pitfalls

2. COMPOSIO_GET_TOOL_SCHEMAS (if needed)
   | Get full input schemas for tools with schemaRef

3. COMPOSIO_MANAGE_CONNECTIONS (if needed)
   | Initiate connections for toolkits without active connections
   | Present auth URL to user -> user completes OAuth

4. COMPOSIO_MULTI_EXECUTE_TOOL
   | Execute tools with schema-compliant arguments
   | Process inline results or note remote file paths

5. COMPOSIO_REMOTE_WORKBENCH / COMPOSIO_REMOTE_BASH_TOOL (if needed)
   | Process large outputs saved to remote files
   | Run bulk operations or multi-tool scripts
   | Upload artifacts via upload_local_file
```

**Example — complete "send email" workflow:**

```bash
# Step 1: Search for email tools
curl -X POST "$COMPOSIO_BASE/tools/execute/COMPOSIO_SEARCH_TOOLS" \
  -H "x-api-key: $COMPOSIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "arguments": {
      "queries": [{"use_case": "send an email via gmail", "known_fields": "recipient: john@example.com"}],
      "session": {"generate_id": true}
    }
  }'
# -> Returns GMAIL_SEND_EMAIL tool with schema
# -> Check toolkit_connection_statuses for gmail
# -> Save session.id from response (e.g., "abcd")

# Step 2: Connect gmail (if not active)
curl -X POST "$COMPOSIO_BASE/tools/execute/COMPOSIO_MANAGE_CONNECTIONS" \
  -H "x-api-key: $COMPOSIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "arguments": {
      "toolkits": ["gmail"],
      "session_id": "abcd"
    }
  }'
# -> If status is "initiated", present redirect_url to user for OAuth

# Step 3: Execute the tool
curl -X POST "$COMPOSIO_BASE/tools/execute/COMPOSIO_MULTI_EXECUTE_TOOL" \
  -H "x-api-key: $COMPOSIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "arguments": {
      "tools": [{
        "tool_slug": "GMAIL_SEND_EMAIL",
        "arguments": {
          "to": "john@example.com",
          "subject": "Welcome!",
          "body": "Welcome to the team, John!",
          "user_id": "me"
        }
      }],
      "sync_response_to_workbench": false,
      "session_id": "abcd"
    }
  }'
```

---

## Best Practices

### Session Management
- Pass `session: {generate_id: true}` on your first SEARCH_TOOLS call to get a session ID.
- Pass that `session_id` into all subsequent tool calls within the same workflow.
- Generate a new session when the user pivots to a different task.

### Tool Discovery
- Always call SEARCH_TOOLS first — never guess tool slugs or argument fields.
- Re-run SEARCH_TOOLS when you need additional tools due to errors or changed requirements.
- Review `recommended_plan_steps` and `known_pitfalls` before executing.

### Connections
- Never execute a toolkit tool without an active connection.
- Use exact toolkit names from SEARCH_TOOLS — never invent names.
- If a connection fails, present the auth URL to the user.

### Execution
- Use schema-compliant arguments only — check input_schema before every call.
- Batch independent tools into a single MULTI_EXECUTE call.
- For large responses, set `sync_response_to_workbench: true` and process in the workbench.

### Workbench
- Only use the workbench for remote file processing or bulk scripting — not for data already visible inline.
- Keep code concise; split long operations into multiple workbench calls.
- Use `ThreadPoolExecutor` for parallelism within the 4-minute timeout.

---

## Quick Reference

| Action | Tool Slug | Key Arguments |
|--------|-----------|---------------|
| Discover tools | `COMPOSIO_SEARCH_TOOLS` | `queries`, `session` |
| Get input schemas | `COMPOSIO_GET_TOOL_SCHEMAS` | `tool_slugs` |
| Connect to apps | `COMPOSIO_MANAGE_CONNECTIONS` | `toolkits`, `reinitiate_all` |
| Execute tools | `COMPOSIO_MULTI_EXECUTE_TOOL` | `tools`, `sync_response_to_workbench` |
| Run Python code | `COMPOSIO_REMOTE_WORKBENCH` | `code_to_execute`, `thought` |
| Run bash commands | `COMPOSIO_REMOTE_BASH_TOOL` | `command` |

**Endpoint for all tools:**

```
POST /api/v3/tools/execute/{TOOL_SLUG}
```

**Common errors:**

| Error | Meaning |
|-------|---------|
| 401 | Invalid or missing API key |
| 403 | Forbidden — insufficient permissions |
| 404 | Tool or resource not found |
| 422 | Invalid arguments (check input schema) |
| 429 | Rate limited — back off and retry |
| 500 | Internal server error |

**Rate limits:** Respect 429 responses with exponential backoff.

---

## Agent Notes

_Gotchas and non-obvious behavior discovered during testing._

- **Some tools return `schemaRef` instead of `input_schema`**. When you see `"hasFullSchema": false`, you MUST call `COMPOSIO_GET_TOOL_SCHEMAS` before executing that tool.
- **Response nesting**: Tool execution results live at `response.data.results[].response.data` — two levels of `data`. Parse carefully.
- **Workbench state persists** across calls. Variables, imports, and files in `/tmp/` survive between executions within the same sandbox session.
- **String formatting in workbench code**: Avoid f-strings with nested quotes when sending code via JSON. Use string concatenation instead to prevent quoting issues.
- **`invoke_llm`** works well for classification and analysis of tool output. Request explicit JSON format for structured results.

