CAT
/Skills
SkillsMCPMarketplacesDigestToolsAdvertise

This week in Claude

Every Monday: Claude Code, Agent SDK, MCP, and the Anthropic platform moves worth your time.

Skills by Category
Frontend DevelopmentBackend & APIsTesting & QASecurityDevOps & CI/CDGit & Pull RequestsDocumentationCode Review & QualityAI & Agent BuildingSkill Development
MCP Servers by Category
Sales & MarketingWeb & Browser AutomationDatabasesAI & LLM ToolsCloud & InfrastructureCommunication & MessagingDeveloper ToolsDesign & CreativeDocuments & KnowledgeSearch & Web Crawling
Marketplaces by Category
AI Agents & OrchestrationLLM IntegrationDevelopment ToolsFrontend & UIBackend & APIsDatabasesTesting & Code QualityDevOps & CloudSecurity & ComplianceGit & Version Control

Cross AI Tools

Discover Claude Code plugins, extensions, and tools. Automatically updated directory of Anthropic Claude AI marketplaces with development tools, productivity plugins, and integrations.

Resources

  • Browse Skills
  • Browse MCP Servers
  • Browse Marketplaces
  • Plugins Reference

Community

  • About
  • Tools
  • Feedback
  • Privacy Policy
  • Advertise

Built for the Claude Code community with Claude Code by @mertduzgun

Independent project, not affiliated with Anthropic

Composio

starchild-ai-agent/official-skills
3k installs13 stars
Summary

This is a gateway skill that connects Claude to 1000+ external apps (Gmail, Slack, GitHub, Google Calendar, Notion, etc.) through Composio's API. It runs on Fly's internal network, so there's no API key juggling on your end. The workflow is search for tools, grab the full schema, then execute. One nice touch: failed executions return the tool schema in the error response so you can self-correct without another round trip. The Browserbase integration is worth noting because it's hybrid: Composio handles session lifecycle (create/delete), but you use Playwright over CDP for actual browser control. Good for when you need Claude to interact with external services without building individual integrations yourself.

Install to Claude Code

npx -y skills add starchild-ai-agent/official-skills --skill composio --agent claude-code

Installs into .claude/skills of the current project.

CodeRabbit
CodeRabbit
AI writes the code. CodeRabbit catches the slop.
Try For Free →
Keep your Mac awake
Keep your Mac awake
Keep your Mac awake while Claude Code and 40+ AI agents run. Sleeps when they're idle.
One time payment $9 →
Context.devContext.dev
Context.dev
Integrate web data into your AI product. One API to scrape website & brand data.
Get API Key Now →
Make your agent a DeFi expert
Make your agent a DeFi expert
Agent, run crypto. Access onchain data & trade routes via 1inch.
Install now →
Make money from your Skills
Make money from your Skills
On Capafy, your Skill runs online 24/7 as an agent product, and you get paid every time someone uses it.
Start earning →
AppSignal
AppSignal
Monitor with ease. Code with confidence.
Start Free Trial →
CodeRabbit
CodeRabbit
AI writes the code. CodeRabbit catches the slop.
Try For Free →
Keep your Mac awake
Keep your Mac awake
Keep your Mac awake while Claude Code and 40+ AI agents run. Sleeps when they're idle.
One time payment $9 →
Context.devContext.dev
Context.dev
Integrate web data into your AI product. One API to scrape website & brand data.
Get API Key Now →
Make your agent a DeFi expert
Make your agent a DeFi expert
Agent, run crypto. Access onchain data & trade routes via 1inch.
Install now →
Make money from your Skills
Make money from your Skills
On Capafy, your Skill runs online 24/7 as an agent product, and you get paid every time someone uses it.
Start earning →
AppSignal
AppSignal
Monitor with ease. Code with confidence.
Start Free Trial →
Files
  • logo.png
SKILL.mdView on GitHub

Composio — External App Integration via Gateway

Composio lets users connect 1000+ external apps (Gmail, Slack, GitHub, Google Calendar, Notion, etc.) to their Starchild agent. All operations go through the Composio Gateway (composio-gateway.fly.dev), which handles auth and API key management.

Architecture

Agent (Fly 6PN network)
    ↓  HTTP (auto-authenticated by IPv6)
Composio Gateway (composio-gateway.fly.dev)
    ↓  Composio SDK
Composio Cloud → Target API (Gmail, Slack, etc.)
  • You never touch the COMPOSIO_API_KEY — the gateway holds it
  • You never call Composio SDK directly — use the gateway HTTP API
  • Authentication is automatic — your Fly 6PN IPv6 resolves to a user_id via the billing DB
  • No env vars needed — the gateway is always accessible from any agent container

Gateway Base URL

GATEWAY = "http://composio-gateway.flycast"

All requests use plain HTTP over Fly internal network (flycast). No JWT needed.

API Reference

1. Search Tools (compact)

Find the right tool slug for a task. Returns compact tool info — just slug, description, and parameter names. Enough to pick the right tool.

curl -s -X POST $GATEWAY/internal/search \
  -H "Content-Type: application/json" \
  -d '{"query": "send email via gmail"}'

Response (compact):

{
  "results": [{"primary_tool_slugs": ["GMAIL_SEND_EMAIL"], "use_case": "send email", ...}],
  "tool_schemas": {
    "GMAIL_SEND_EMAIL": {
      "tool_slug": "GMAIL_SEND_EMAIL",
      "toolkit": "gmail",
      "description": "Send an email...",
      "parameters": ["to", "subject", "body", "cc", "bcc"],
      "required": ["to", "subject", "body"]
    }
  },
  "toolkit_connection_statuses": [...]
}

2. Get Tool Schema (full)

Get the complete parameter definitions for a specific tool — types, descriptions, enums, defaults. Use this after search when you need exact parameter formats.

curl -s -X POST $GATEWAY/internal/tool_schema \
  -H "Content-Type: application/json" \
  -d '{"tool": "GOOGLECALENDAR_EVENTS_LIST"}'

Response:

{
  "data": {
    "tool_slug": "GOOGLECALENDAR_EVENTS_LIST",
    "description": "Returns events on the specified calendar.",
    "input_parameters": {
      "properties": {
        "timeMin": {"type": "string", "description": "RFC3339 timestamp..."},
        "timeMax": {"type": "string", "description": "RFC3339 timestamp..."},
        "calendarId": {"type": "string", "default": "primary"}
      },
      "required": ["calendarId"]
    }
  },
  "error": null
}

3. Execute a Tool

Execute a Composio tool. Key name is arguments, not params.

curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "GMAIL_SEND_EMAIL", "arguments": {"to": "x@example.com", "subject": "Hi", "body": "Hello!"}}'

On success:

{"data": {"messages": [...]}, "error": null}

On failure — includes tool_schema so you can self-correct:

{
  "data": null,
  "error": "Missing required parameter: calendarId",
  "tool_schema": {
    "tool_slug": "GOOGLECALENDAR_EVENTS_LIST",
    "description": "...",
    "input_parameters": {"properties": {...}, "required": [...]}
  }
}

4. List User's Connections (and confirm OAuth completion)

# Optional toolkit filter: oauth_completed_active only turns true
# when that toolkit status is ACTIVE.
curl -s "$GATEWAY/internal/connections?toolkit=gmail"

Response includes:

  • connections: current deduplicated connection list
  • oauth_completed_active: boolean, true only when OAuth completion is observed as ACTIVE

Cache invalidation is triggered only after ACTIVE is observed, and it targets the user's instance (fly-force-instance-id=<user container_id from user_mapping>), not composio-gateway's own instance.

5. Initiate New Connection

curl -s -X POST $GATEWAY/api/connect \
  -H "Content-Type: application/json" \
  -d '{"toolkit": "gmail"}'

Returns connect_url for the user to complete OAuth.

6. Disconnect

curl -s -X DELETE $GATEWAY/api/connections/{connection_id}

Instagram Posting (important slug mapping)

Composio search may return legacy Instagram slugs that are not executable in this environment. When posting to Instagram, use these working slugs:

  1. Create draft container:
  • INSTAGRAM_CREATE_MEDIA_CONTAINER
  • Required: ig_user_id
  • Typical args for photo: {"ig_user_id":"...","image_url":"https://...","content_type":"photo","caption":"..."}
  1. Publish draft:
  • INSTAGRAM_CREATE_POST
  • Required: ig_user_id, creation_id

Two-step flow:

  • Execute INSTAGRAM_CREATE_MEDIA_CONTAINER → read data.data.id as creation_id
  • Execute INSTAGRAM_CREATE_POST with that creation_id

Tip: If /internal/search suggests INSTAGRAM_POST_IG_USER_MEDIA or INSTAGRAM_POST_IG_USER_MEDIA_PUBLISH but execute returns "Tool ... not found", switch to the two slugs above.

Browserbase — Hybrid Workflow (Session Management + Playwright CDP)

Composio's Browserbase tools ONLY manage session lifecycle (open/close/list). They do NOT control web pages.

To actually operate a browser (navigate, click, fill forms, scrape data), use Playwright connect_over_cdp to connect to the session's WebSocket URL.

Step 1: Create a Browserbase Session via Composio

curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "BROWSERBASE_TOOL_SESSIONS_CREATE", "arguments": {"projectId": "YOUR_PROJECT_ID"}}'

Response includes id (session_id), status, and timestamps.

Step 2: Build the CDP WebSocket URL

import os
session_id = "<session_id from step 1>"
api_key = os.environ.get("BROWSERBASE_API_KEY")  # stored in workspace/.env
cdp_url = f"wss://connect.browserbase.com?apiKey={api_key}&sessionId={session_id}"

Step 3: Control the Browser with Playwright

from playwright.async_api import async_playwright

async with async_playwright() as p:
    browser = await p.chromium.connect_over_cdp(cdp_url)
    page = await browser.new_page()
    await page.goto("https://example.com")

    # Click, fill, screenshot — full Playwright API
    await page.click("button.submit")
    await page.fill("input[name='email']", "user@test.com")
    await page.screenshot(path="result.png")

    content = await page.content()

Step 4: Delete the Session (IMPORTANT — stops billing)

curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "BROWSERBASE_TOOL_SESSIONS_DELETE", "arguments": {"id": "YOUR_SESSION_ID"}}'

Key Concepts

AspectDetail
Composio roleSession lifecycle only — create, list, delete sessions
Playwright rolePage control — navigate, click, fill, scrape, screenshot
Memory cost~30-50MB locally (Playwright client only); Chromium runs on Browserbase servers
Anti-detectionBrowserbase handles it server-side — fingerprint masking, captcha solving, Cloudflare bypass. Playwright client does nothing special.
BillingPer-minute (rounded up). Always delete sessions when done.

Full Example Script (Create → Control → Delete)

#!/usr/bin/env python3
"""Browserbase: create session → control with Playwright → clean up."""
import asyncio, os, requests
from playwright.async_api import async_playwright

GATEWAY = "http://composio-gateway.flycast"
PROJECT_ID = os.environ.get("BROWSERBASE_PROJECT_ID")

async def main():
    # 1. Create session via Composio
    resp = requests.post(f"{GATEWAY}/internal/execute", json={
        "tool": "BROWSERBASE_TOOL_SESSIONS_CREATE",
        "arguments": {"projectId": PROJECT_ID}
    }).json()
    session_id = resp["data"]["id"]
    print(f"Session created: {session_id}")

    try:
        # 2. Connect via CDP
        api_key = os.environ["BROWSERBASE_API_KEY"]
        cdp_url = f"wss://connect.browserbase.com?apiKey={api_key}&sessionId={session_id}"

        async with async_playwright() as p:
            browser = await p.chromium.connect_over_cdp(cdp_url)
            page = await browser.new_page()
            await page.goto("https://example.com")
            title = await page.title()
            print(f"Page title: {title}")
            await browser.close()

    finally:
        # 3. Always delete session to stop billing
        requests.post(f"{GATEWAY}/internal/execute", json={
            "tool": "BROWSERBASE_TOOL_SESSIONS_DELETE",
            "arguments": {"id": session_id}
        })
        print("Session deleted")

asyncio.run(main())

Available Browserbase Tools via Composio

Tool SlugPurposeKey Arguments
BROWSERBASE_TOOL_SESSIONS_CREATECreate a browser sessionprojectId
BROWSERBASE_TOOL_SESSIONS_DELETEDelete a sessionid
BROWSERBASE_TOOL_SESSIONS_GETGet session infoid
BROWSERBASE_TOOL_SESSIONS_LISTList all sessions(none)
BROWSERBASE_TOOL_SESSIONS_GET_DEBUG_INFOGet debug infoid
BROWSERBASE_TOOL_SESSIONS_STOPStop a sessionid
BROWSERBASE_TOOL_CONTEXTS_CREATECreate persistent contextprojectId
BROWSERBASE_TOOL_CONTEXTS_DELETEDelete contextid
BROWSERBASE_TOOL_CONTEXTS_GETGet context infoid
BROWSERBASE_TOOL_CONTEXTS_LISTList contexts(none)
BROWSERBASE_TOOL_CONTEXTS_UPDATEUpdate context labelsid, labels
BROWSERBASE_TOOL_UPLOADS_CREATEUpload file to sessionprojectId, file data
BROWSERBASE_TOOL_UPLOADS_GETGet upload infoid
BROWSERBASE_TOOL_UPLOADS_LISTList uploads(none)
BROWSERBASE_TOOL_UPLOADS_DELETEDelete uploadid
BROWSERBASE_TOOL_DOWNLOADS_LISTList downloadssessionId
BROWSERBASE_TOOL_DOWNLOADS_GETGet downloaddownloadId
BROWSERBASE_TOOL_DOWNLOADS_GET_STREAMStream downloaddownloadId
BROWSERBASE_TOOL_KB_GET_KNOWLEDGEGet KB articleid

Browserbase / Browser Tool troubleshooting

If Browserbase is connected but execution fails, check naming mismatches across connection toolkit vs tool slug:

  • Connection may appear as toolkit browserbase_tool
  • Search may return tool slugs like BROWSER_TOOL_CREATE_TASK
  • Execute may still reject that slug (Tool ... not found) and only resolve legacy slugs under toolkit browserbase

Quick diagnosis:

# 1) Health + active connections
curl -s $GATEWAY/health
curl -s $GATEWAY/internal/connections

# 2) Search browser tool slugs
curl -s -X POST $GATEWAY/internal/search \
  -H "Content-Type: application/json" \
  -d '{"query":"browserbase create task"}'

# 3) Try execute and inspect exact error
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool":"BROWSER_TOOL_CREATE_TASK","arguments":{"task":"open https://example.com"}}'

If error says No active connection found for toolkit 'browserbase', gateway should normalize Browserbase aliases server-side (browser/browserbase/browserbase_tool) and normalize execute slug variants (BROWSERBASE_TOOL_* ↔ BROWSER_TOOL_*) so both old/new clients work with a browserbase_tool active connection.

Optimal Workflow (minimize tool calls)

Known tool → Direct execute (1 call)

If you already know the tool slug and parameters from previous use or the Common Tools table below, skip search entirely:

curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "GOOGLECALENDAR_EVENTS_LIST", "arguments": {"calendarId": "primary", "timeMin": "2026-04-02T00:00:00+08:00", "timeMax": "2026-04-09T00:00:00+08:00", "singleEvents": true, "timeZone": "Asia/Hong_Kong"}}'

Unknown tool → Search + Schema + Execute (2-3 calls)

  1. Search (compact) → pick the right tool slug
  2. Get schema (if param details unclear) → know exact argument format
  3. Execute → with correct arguments

If execute fails, the error response includes the full schema — so you can retry immediately without an extra schema call.

Wrap in a script for repeat use

For recurring queries, write a one-shot Python script:

#!/usr/bin/env python3
import sys, json, requests
from datetime import datetime, timedelta, timezone

GATEWAY = "http://composio-gateway.flycast"
days = int(sys.argv[1]) if len(sys.argv) > 1 else 7
tz_name = sys.argv[2] if len(sys.argv) > 2 else "UTC"

# ... build timeMin/timeMax ...
resp = requests.post(f"{GATEWAY}/internal/execute", json={
    "tool": "GOOGLECALENDAR_EVENTS_LIST",
    "arguments": {"calendarId": "primary", "timeMin": t_min, "timeMax": t_max,
                   "singleEvents": True, "timeZone": tz_name}
}).json()

# ... format and print ...

Then future calls are just: bash("python3 scripts/calendar_events.py 7 Asia/Hong_Kong") — 1 tool call.

Common Tools Quick Reference (skip search for these)

📧 Gmail

Tool SlugPurposeKey Arguments
GMAIL_SEND_EMAILSend emailto, subject, body, cc, bcc
GMAIL_FETCH_EMAILSFetch emailsmax_results (int), label_ids (list), q (Gmail search syntax)
GMAIL_CREATE_EMAIL_DRAFTCreate draftto, subject, body

Gmail Usage Examples:

# Send email
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "GMAIL_SEND_EMAIL", "arguments": {"to": "user@example.com", "subject": "Hello", "body": "Hi there!"}}'

# Fetch last 5 emails
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "GMAIL_FETCH_EMAILS", "arguments": {"max_results": 5}}'

# Search specific emails (using Gmail search syntax)
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "GMAIL_FETCH_EMAILS", "arguments": {"max_results": 10, "q": "from:github.com after:2026/03/01"}}'

Gmail Response Parsing: Email data is in data.data.messages[], each email has id, snippet, payload.headers[] (From/Subject/Date are in headers, lookup by name).

🐦 Twitter

Tool SlugPurposeKey Arguments
TWITTER_CREATION_OF_A_POSTCreate posttext (required), media_media_ids, reply_in_reply_to_tweet_id
TWITTER_POST_DELETE_BY_POST_IDDelete postid
TWITTER_POST_LOOKUP_BY_POST_IDGet single tweetid, tweet_fields
TWITTER_RECENT_SEARCHSearch last 7 daysquery, max_results (min 10)
TWITTER_USER_LOOKUP_MEGet own profile(no params)
TWITTER_USER_LOOKUP_BY_USERNAMEGet user profileusername

Twitter Usage Examples:

# Post tweet
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "TWITTER_CREATION_OF_A_POST", "arguments": {"text": "Hello from Composio!"}}'

# Delete tweet
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "TWITTER_POST_DELETE_BY_POST_ID", "arguments": {"id": "2039756730192601584"}}'

Twitter Response Structure: Post/create returns data.data.data (3-level nesting), contains id, text, edit_history_tweet_ids.

Twitter — Post with Image (FileUploadable flow)

Key constraint: the gateway's /internal/execute is a thin wrapper over Composio v2 actions/{slug}/execute — it does NOT support version pinning or FileUploadable synthesis. Twitter media upload tools (TWITTER_UPLOAD_MEDIA, TWITTER_UPLOAD_LARGE_MEDIA) require both, so they MUST be called via the composio_client Python SDK directly, not via gateway.

The gateway is intentionally generic — keep all per-tool flows (like this one) here in the skill.

3-step flow (proven working):

import hashlib, httpx, json
from pathlib import Path
from composio_client import Composio

# COMPOSIO_API_KEY: read from /data/workspace/composio-gateway/.env
# (gateway owns the key; for skill scripts, source it the same way)
client = Composio(api_key=COMPOSIO_API_KEY)

USER_ID = f"starchild-{user_id}"   # NOTE: hyphen, not underscore
img = Path("output/images/foo.jpg")

# 1. Get presigned S3 upload URL
md5 = hashlib.md5(img.read_bytes()).hexdigest()
presigned = client.files.create_presigned_url(
    filename=img.name, md5=md5, mimetype="image/jpeg",
    tool_slug="TWITTER_UPLOAD_MEDIA", toolkit_slug="twitter",
)
# presigned.type == "new" → file is new, must PUT
# presigned.type == "existing" → cached, skip PUT
if presigned.type == "new":
    httpx.put(presigned.new_presigned_url, content=img.read_bytes(),
              headers={"Content-Type": "image/jpeg"}, timeout=60).raise_for_status()

# 2. Execute upload tool — MUST pass version="20260501_00" (or current latest)
#    media is a FileUploadable dict, NOT base64
upload_resp = client.tools.execute(
    tool_slug="TWITTER_UPLOAD_MEDIA",
    user_id=USER_ID,
    version="20260501_00",
    arguments={
        "media": {"name": img.name, "mimetype": "image/jpeg", "s3key": presigned.key},
        "media_type": "image/jpeg",
        "media_category": "tweet_image",   # or "dm_image", "subtitles"
    },
)
result = upload_resp.model_dump()
assert result["successful"], result["error"]
# Response nesting: data.data.id (NOT data.id, NOT data.media_id_string)
media_id = result["data"]["data"]["id"]

# 3. Create tweet with media_media_ids — this one is fine via gateway too
tweet_resp = client.tools.execute(
    tool_slug="TWITTER_CREATION_OF_A_POST",
    user_id=USER_ID,
    arguments={"text": "your tweet text", "media_media_ids": [str(media_id)]},
)
tweet_id = tweet_resp.model_dump()["data"]["data"]["id"]
url = f"https://x.com/i/web/status/{tweet_id}"

Why this works (debugging notes — don't lose this knowledge):

  • GET /api/v3/tools/TWITTER_UPLOAD_MEDIA returns 404 without a version because it lives in toolkit version 20260501_00+, not the default 00000000_00.
  • client.tools.execute(version=...) routes through /api/v3/tools/execute/{slug} which IS version-aware.
  • Gateway uses v2 /api/v2/actions/{slug}/execute for execute — v2 has no version routing, so it can never reach versioned tools. Don't try to "fix" the gateway for this — adding version + FileUploadable would bloat it. Keep it thin.
  • The media param expects {name, mimetype, s3key} (FileUploadable schema), NOT base64. Passing base64 returns: "Input should be a valid dictionary or instance of FileUploadable on parameter media".
  • File size limit for TWITTER_UPLOAD_MEDIA is ~5 MB. For larger files / videos / GIFs, use TWITTER_UPLOAD_LARGE_MEDIA (chunked, same flow but additional segment params).

⚠️ Twitter Limitations & Fallback:

  • TWITTER_RECENT_SEARCH only covers last 7 days, older tweets won't appear
  • TWITTER_FULL_ARCHIVE_SEARCH requires Twitter API Pro access, regular OAuth App can't use it
  • When fetching user tweet history, prefer platform native tool twitter_user_tweets, not limited to 7 days

📅 Google Calendar

Tool SlugPurposeKey Arguments
GOOGLECALENDAR_EVENTS_LISTList eventscalendarId (default: "primary"), timeMin, timeMax (RFC3339+tz), singleEvents (true), timeZone
GOOGLECALENDAR_CREATE_EVENTCreate eventcalendarId, summary, start, end, description, attendees
GOOGLECALENDAR_DELETE_EVENTDelete eventcalendarId, eventId

🐙 GitHub

Tool SlugPurposeKey Arguments
GITHUB_CREATE_AN_ISSUECreate issueowner, repo, title, body, labels, assignees
GITHUB_LIST_REPOSITORY_ISSUESList issuesowner, repo, sort, state (open/closed/all), page, per_page
GITHUB_GET_AN_ISSUEGet issue detailowner, repo, issue_number
GITHUB_CREATE_A_PULL_REQUESTCreate PRowner, repo, title, head, base, body, draft
GITHUB_LIST_PULL_REQUESTSList PRsowner, repo, state, sort, head, base
GITHUB_MERGE_A_PULL_REQUESTMerge PRowner, repo, pull_number, commit_title, sha
GITHUB_GET_A_REPOSITORYGet repo infoowner, repo
GITHUB_SEARCH_CODESearch codeq (GitHub search syntax), sort, order, per_page
GITHUB_GET_REPOSITORY_CONTENTGet file contentowner, repo, path, ref
# Create issue
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "GITHUB_CREATE_AN_ISSUE", "arguments": {"owner": "myorg", "repo": "myrepo", "title": "Bug: login fails", "body": "Steps to reproduce..."}}'

# List open issues
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "GITHUB_LIST_REPOSITORY_ISSUES", "arguments": {"owner": "myorg", "repo": "myrepo", "state": "open", "per_page": 10}}'

📝 Notion

Tool SlugPurposeKey Arguments
NOTION_CREATE_NOTION_PAGECreate pageparent_id, title, markdown, icon, cover
NOTION_SEARCH_NOTION_PAGESearch pages/DBsquery, filter_value (page/database), page_size
NOTION_QUERY_DATABASE_WITH_FILTERQuery DB rowsdatabase_id, filter, sorts, page_size
NOTION_INSERT_ROW_DATABASEAdd DB rowdatabase_id, properties
NOTION_UPDATE_ROW_DATABASEUpdate DB rowrow_id, properties, icon, cover
NOTION_FETCH_DATABASEGet DB schemadatabase_id
NOTION_FETCH_BLOCK_CONTENTSGet page contentblock_id (= page_id)
NOTION_ADD_MULTIPLE_PAGE_CONTENTAdd blocksparent_block_id, content_blocks, after
NOTION_UPDATE_PAGEUpdate page propspage_id, properties, icon, cover, archived
NOTION_DELETE_BLOCKDelete/archive blockblock_id
# Search pages
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "NOTION_SEARCH_NOTION_PAGE", "arguments": {"query": "Meeting Notes", "page_size": 5}}'

# Query database with filter
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "NOTION_QUERY_DATABASE_WITH_FILTER", "arguments": {"database_id": "abc123", "filter": {"property": "Status", "select": {"equals": "In Progress"}}, "page_size": 10}}'

📁 Google Drive

Tool SlugPurposeKey Arguments
GOOGLEDRIVE_CREATE_FILE_FROM_TEXTCreate filefile_name, text_content, mime_type, parent_id
GOOGLEDRIVE_FIND_FILESearch filesq (Drive search syntax), fields, spaces
GOOGLEDRIVE_DOWNLOAD_FILEDownload filefileId, mime_type
GOOGLEDRIVE_COPY_FILECopy filefileId
GOOGLEDRIVE_ADD_FILE_SHARING_PREFERENCEShare filefileId, role, type, emailAddress
# Search files by name
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "GOOGLEDRIVE_FIND_FILE", "arguments": {"q": "name contains '\''report'\'' and mimeType != '\''application/vnd.google-apps.folder'\''"}}'

# Create text file
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "GOOGLEDRIVE_CREATE_FILE_FROM_TEXT", "arguments": {"file_name": "notes.txt", "text_content": "Hello World"}}'

Google Drive Search Syntax (q param): name contains 'keyword', mimeType = 'application/vnd.google-apps.folder' (folders), '<folderId>' in parents (files in folder), modifiedTime > '2026-01-01'.

📄 Google Docs

Tool SlugPurposeKey Arguments
GOOGLEDOCS_CREATE_DOCUMENT_MARKDOWNCreate doc from markdowntitle, markdown_text
GOOGLEDOCS_GET_DOCUMENT_PLAINTEXTGet doc as textdocument_id, include_tables, include_headers
GOOGLEDOCS_GET_DOCUMENT_BY_IDGet raw doc objectid
# Create doc with markdown content
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "GOOGLEDOCS_CREATE_DOCUMENT_MARKDOWN", "arguments": {"title": "Meeting Notes", "markdown_text": "# Q2 Planning\n\n- Item 1\n- Item 2"}}'

# Read doc as plain text
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "GOOGLEDOCS_GET_DOCUMENT_PLAINTEXT", "arguments": {"document_id": "1abc...xyz"}}'

📊 Google Sheets

Tool SlugPurposeKey Arguments
GOOGLESHEETS_CREATE_GOOGLE_SHEET1Create spreadsheettitle
GOOGLESHEETS_GET_SHEET_NAMESList sheets in spreadsheetspreadsheet_id, exclude_hidden
GOOGLESHEETS_BATCH_GETRead cell valuesspreadsheet_id, ranges (list, A1 notation), majorDimension, valueRenderOption
GOOGLESHEETS_UPDATE_VALUES_BATCHWrite cell valuesspreadsheet_id, data (list of {range, values}), valueInputOption
GOOGLESHEETS_SPREADSHEETS_VALUES_APPENDAppend rowsspreadsheetId, range, values, valueInputOption, insertDataOption
GOOGLESHEETS_SPREADSHEETS_VALUES_BATCH_CLEARClear rangesspreadsheet_id, ranges
GOOGLESHEETS_GET_SPREADSHEET_INFOGet full spreadsheet metadataspreadsheet_id
GOOGLESHEETS_UPDATE_SHEET_PROPERTIESUpdate sheet propsspreadsheet_id, sheet_id, title, index
# Read cells
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "GOOGLESHEETS_BATCH_GET", "arguments": {"spreadsheet_id": "1abc...xyz", "ranges": ["Sheet1!A1:D10"]}}'

# Write cells
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "GOOGLESHEETS_UPDATE_VALUES_BATCH", "arguments": {"spreadsheet_id": "1abc...xyz", "valueInputOption": "USER_ENTERED", "data": [{"range": "Sheet1!A1:B2", "values": [["Name", "Score"], ["Alice", 95]]}]}}'

# Append rows
curl -s -X POST $GATEWAY/internal/execute \
  -H "Content-Type: application/json" \
  -d '{"tool": "GOOGLESHEETS_SPREADSHEETS_VALUES_APPEND", "arguments": {"spreadsheetId": "1abc...xyz", "range": "Sheet1!A:B", "valueInputOption": "USER_ENTERED", "values": [["Bob", 88], ["Charlie", 92]]}}'

⚠️ Google Sheets Notes:

  • valueInputOption: "USER_ENTERED" (parses formulas/numbers) or "RAW" (literal text)
  • ranges uses A1 notation: "Sheet1!A1:D10", "Sheet1!A:A" (entire column)
  • BATCH_GET returns data.data.valueRanges[].values (2D array)
  • spreadsheetId vs spreadsheet_id: some tools use camelCase, some snake_case — check schema if unsure

Important Notes

  • Tool slugs are UPPERCASE: GMAIL_SEND_EMAIL
  • Toolkit slugs are lowercase: gmail, github
  • Arguments key: always use "arguments", never "params" — params silently gets ignored
  • Time parameters: use RFC3339 with timezone offset (2026-04-08T00:00:00+08:00), not UTC unless intended
  • OAuth tokens are managed by Composio — auto-refreshed on expiry
  • Response nesting: Composio execute response is usually data.data, but Twitter is data.data.data (3 levels). Parse by recursively accessing data.
  • Native tool fallback: When Composio tools have limitations (e.g., Twitter search only 7 days), prefer platform built-in native tools (e.g., twitter_user_tweets)

Common Issues

Browserbase connection name mismatch

If /internal/connections shows toolkit browserbase_tool as ACTIVE, but executing BROWSER_TOOL_* returns "No active connection found for toolkit 'browser'", this is a gateway-side toolkit alias mismatch (browserbase_tool vs browser).

What to do:

  1. For session management tools (SESSIONS_*, CONTEXTS_*, UPLOADS_*, etc.), the gateway should normalize Browserbase aliases server-side. If it doesn't, try both BROWSER_TOOL_* and BROWSERBASE_TOOL_* slugs.
  2. For actual browser control (navigate, click, fill, scrape), do NOT use Composio execute — use Playwright connect_over_cdp as described in the Browserbase section above. Composio tools only manage sessions, not page interactions.

Gmail Nested JSON Parsing

Gmail returns complex JSON structure with multiple levels of HTML content. Do not try to parse nested strings with json.loads. Access directly as dict in Python — gateway already returns parsed JSON.


Featured
CodeRabbit
CodeRabbit
AI writes the code. CodeRabbit catches the slop.
Try For Free →
Keep your Mac awake
Keep your Mac awake
Keep your Mac awake while Claude Code and 40+ AI agents run. Sleeps when they're idle.
One time payment $9 →
Context.devContext.dev
Context.dev
Integrate web data into your AI product. One API to scrape website & brand data.
Get API Key Now →
Make your agent a DeFi expert
Make your agent a DeFi expert
Agent, run crypto. Access onchain data & trade routes via 1inch.
Install now →
Make money from your Skills
Make money from your Skills
On Capafy, your Skill runs online 24/7 as an agent product, and you get paid every time someone uses it.
Start earning →
AppSignal
AppSignal
Monitor with ease. Code with confidence.
Start Free Trial →
Categories
AI & Agent Building
First SeenMay 16, 2026
View on GitHub

Recommended

More AI & Agent Building →
agent-memory-mcp

sickn33/antigravity-awesome-skills

agent memory mcp
954
39.4k
agent-memory-mcp

davila7/claude-code-templates

agent memory mcp
521
27.7k
llm-application-dev-langchain-agent

sickn33/antigravity-awesome-skills

llm application dev langchain agent
306
39.4k
llm-application-dev

moizibnyousaf/ai-agent-skills

Building applications with Large Language Models - prompt engineering, RAG patterns, and LLM integration. Use for AI-powered features, chatbots, or LLM-based automation.
1.1k
ai-prompt-engineering-safety-review

github/awesome-copilot

Comprehensive safety analysis and improvement framework for AI prompts with detailed assessment methodologies.
9.4k
34.3k
emblem-ai-prompt-examples

emblemcompany/agent-skills

emblem ai prompt examples
8.7k
10