agentleFS
baofeng-techbaofeng-tech/agent-skills-so/saas-gateway/SKILL.md

saas-gateway

Skill0 starsChanged 7 months agoMITView on GitHub

Unified SaaS integration gateway via api.aisa.one (AISA gateway, v3.1): manage OAuth auth for third-party SaaS apps (Gmail/Slack/GitHub/Notion etc.), tool execution, tool-router sessions, triggers, webhooks, MCP servers, and usage stats. Use when connecting third-party SaaS accounts, running cross-SaaS tools, managing MCP servers, setting up triggers, or checking usage. Keywords: SaaS gateway, connect app, OAuth link, run tool, auth config, tool router, MCP server, trigger, webhook, connected account, usage stats

  • Reads credentials

The file

Show its rules and text

We split this skill into the rules it gives an agent

23 rules. About 0 are common, 10 are distinctive, and 13 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈10

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 13

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Create OAuth links, list connected accounts, or refresh credentials

    line 39
  2. Distinctive:

    Create and manage MCP servers for session-scoped tool access

    line 42
  3. Very specific:

    Windows note: Use curl.exe instead of curl in PowerShell (the built-in curl is an alias for Invoke-WebRequest and has different syntax).

    line 71
  4. Distinctive:

    If the user also asks for auth configs (e.g.

    line 117
  5. Very specific:

    If empty: ask the user whether to create an auth config, then POST /apis/v1/composio/auth_configs with {"toolkit": {"slug": "{slug}"}, …

    line 131
  6. Very specific:

    Confirm with user: before POST /apis/v1/composio/connected_accounts/link — body: auth_config_id, user_id (email or arbitrary string, e.g.

    line 132
  7. Distinctive:

    Poll interval: wait 3–5 seconds between checks, up to ~2 minutes

    line 135
  8. Very specific:

    If still PENDING after 2 minutes, tell the user the link may have expired and offer to create a new link

    line 137
  9. Distinctive:

    Not connected → run Workflow 2 first

    line 150
  10. Very specific:

    Confirm with user: before POST /apis/v1/composio/tools/execute/{tool_slug} — body requires:

    line 157
  11. Very specific:

    Check the response: successful field indicates if the tool call worked.

    line 161
  12. Distinctive:

    Use tool router when you need a persistent session for multiple tool calls, or when building an MCP integration.

    line 165
  13. Very specific:

    Search for tools: POST .../tool_router/session/{session_id}/search — body: {"query": "create issue"}

    line 169
  14. Very specific:

    Confirm with user: before POST .../tool_router/session/{session_id}/execute — body: {"tool_slug": "GITHUB_CREATE_AN_ISSUE", "arguments": …

    line 171
  15. Very specific:

    Confirm with user: before any create/update/delete on triggers or webhook subscriptions

    line 185
  16. Distinctive:

    Create and manage MCP (Model Context Protocol) servers for agent tool access.

    line 194
  17. Very specific:

    Create an MCP server for a single app: Confirm with user, then POST /apis/v1/composio/mcp/servers — body: {"app": {"slug": "github"}, …

    line 197
  18. Very specific:

    Create a custom MCP server with multiple apps: Confirm with user, then POST /apis/v1/composio/mcp/servers/custom — body: {"apps": [{"slug": …

    line 198
  19. Very specific:

    Create project: Confirm with user, then POST /apis/v1/composio/org/owner/project/new

    line 213
  20. Very specific:

    Search logs: POST /apis/v1/composio/logs/tool_execution — body: {"limit": 10}.

    line 225
  21. Distinctive:

    Important: Use the exact casing shown in the endpoint path.

    line 258
  22. Distinctive:

    Read-only GET calls (session, list configs, list tools) do not require confirmation unless the user asked you to avoid network calls

    line 265
  23. Distinctive:

    Rate limiting: if you receive 429 responses, wait briefly and retry.

    line 266

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

SaaS Gateway (saas-gateway) 🔌

Unified SaaS integration gateway (v3.1) for autonomous agents. Powered by AISA.

One API key. Connect third-party SaaS apps and run tools through the AISA gateway (api.aisa.one).

Compatibility

Works with any agentskills.io-compatible harness, including:

  • Claude Code and Claude (Anthropic)
  • OpenAI Codex
  • Cursor
  • Gemini CLI (Google)
  • OpenCode, Goose, OpenClaw, Hermes
  • and any other harness that implements the Agent Skills specification

Requires curl and AISA_API_KEY (get one at aisa.one).

When to use

  • Integrate Gmail, Slack, GitHub, or other third-party SaaS toolkits via api.aisa.one
  • Create OAuth links, list connected accounts, or refresh credentials
  • Discover and execute SaaS tools or tool-router sessions
  • Manage triggers and webhooks (with user confirmation for writes)
  • Create and manage MCP servers for session-scoped tool access
  • Upload/download files, check usage statistics, or manage projects

When NOT to use

  • The user needs direct access to the upstream provider's API without going through the AISA gateway
  • The task only needs generic web search (use a search skill instead)
  • No AISA_API_KEY is available

Quick Start

Linux / macOS:

export AISA_API_KEY="your-key"

Windows (PowerShell):

$env:AISA_API_KEY = "your-key"

All requests use:

  • Base URL: https://api.aisa.one
  • Path prefix: /apis/v1/composio/... (literal AISA gateway path — do not modify)
  • Auth header: Authorization: Bearer $AISA_API_KEY

Windows note: Use curl.exe instead of curl in PowerShell (the built-in curl is an alias for Invoke-WebRequest and has different syntax). Or use CMD rather than PowerShell.

Replace {param} in paths with real IDs from previous responses. Never use mock IDs like test_nanoid_001 in production.

What Can You Do?

"Check my AISA project session and list auth configs for GitHub"
"Create an OAuth link so user alice can connect Slack"
"Run the GitHub create-issue tool for a connected account"
"List active triggers and webhook subscriptions"
"Set up an MCP server so my agent can use GitHub tools in a session"
"Upload a file and check my project usage this month"

Intent → Workflow Quick Reference (Agent Entry Point)

Map the user's request to a workflow before reading further:

User intent keywordsWorkflow
connect / authorize / OAuth / link a third-party app→ Workflow 2
run tool / execute / create issue / send email→ Workflow 3 (resolve connected_account_id first)
MCP server / tool session / session-scoped access→ Workflow 3 tool-router or Workflow 5
trigger / webhook / event subscription→ Workflow 4
usage stats / call count / billing→ Workflow 6 Usage
file upload / file list→ Workflow 6 Files
project management / API key reset→ Workflow 6 Projects
verify session / list auth configs→ Workflow 1
notion / Notion workspace / page / database / wiki / task DB→ use notion-workspace skill

When intent is unclear, run Workflow 1 to confirm session context, then ask the user what they need.


Core Workflows

1. Verify session and project context

curl "https://api.aisa.one/apis/v1/composio/auth/session/info" \
  -H "Authorization: Bearer $AISA_API_KEY"

Key fields: project, org_member, api_key (nested IDs may appear under api_key).

If the user also asks for auth configs (e.g. GitHub), in the same flow:

curl "https://api.aisa.one/apis/v1/composio/auth_configs?toolkit_slug=github&limit=10" \
  -H "Authorization: Bearer $AISA_API_KEY"

Use: items[].id as auth_config_id for OAuth linking.

Details: references/auth_and_session.md

2. Connect a user to a third-party app (OAuth)

  1. GET /apis/v1/composio/auth_configs?toolkit_slug={slug} — find items[].id as auth_config_id
    • If empty: ask the user whether to create an auth config, then POST /apis/v1/composio/auth_configs with {"toolkit": {"slug": "{slug}"}, "auth_config": {"type": "use_composio_managed_auth"}} — use auth_config.id from response as auth_config_id
  2. Confirm with user before POST /apis/v1/composio/connected_accounts/link — body: auth_config_id, user_id (email or arbitrary string, e.g. alice@example.com); callback_url is optional
  3. Send the user to redirect_url from the response — the human must open this URL in a browser to complete OAuth
  4. Poll GET /apis/v1/composio/connected_accounts?user_ids={user_id}&toolkit_slugs={slug} until status is no longer PENDING
    • Poll interval: wait 3–5 seconds between checks, up to ~2 minutes
    • Possible statuses: ACTIVE (connected), PENDING (user has not completed OAuth yet), DISCONNECTED / REVOKED (link failed or expired)
    • If still PENDING after 2 minutes, tell the user the link may have expired and offer to create a new link
  5. On success, save items[].id (nanoid) as connected_account_id for tool execution

If an ACTIVE connection already exists: If GET connected_accounts already returns an ACTIVE connection for the given user_id + toolkit_slug, reuse that connected_account_id directly — no re-OAuth needed. Only create a new link when the user explicitly requests re-authorization (the old link is not automatically removed; ask the user whether to keep it).

Details: references/connect_account.md

3. Discover and execute tools

Direct execution (one-off tool call):

  1. Resolve connected_account_id:
    • User already connected → GET /apis/v1/composio/connected_accounts?toolkit_slugs={slug} (add user_ids= if multiple accounts exist) and use items[].id
    • Not connected → run Workflow 2 first
  2. Find the tool slug:
    • GET /apis/v1/composio/tools?toolkit_slug={slug} — map user intent (e.g. "create issue") to actual items[].slug (e.g. GITHUB_CREATE_AN_ISSUE)
    • Never guess tool_slug — always list tools first if unsure
  3. Get the tool's argument schema:
    • GET /apis/v1/composio/tools/{tool_slug} — inspect input_parameters.required (mandatory fields) and input_parameters.properties (all fields with types and descriptions)
    • Alternatively, use natural-language input generation: POST /apis/v1/composio/tools/execute/{tool_slug}/input with {"text": "Create an issue titled Hello in my-org/my-repo"} — may return error code: 1010 on restricted tiers, in which case use the schema from GET /tools/{tool_slug} instead
  4. Confirm with user before POST /apis/v1/composio/tools/execute/{tool_slug} — body requires:
    • connected_account_id: from step 1
    • entity_id: the user identifier string (same value used as user_id when linking the account, e.g. alice@example.com)
    • arguments: matching the tool's input_parameters schema
  5. Check the response: successful field indicates if the tool call worked. If successful is false, inspect error or data for details and retry with corrected arguments

Tool router (session-scoped, MCP-style access):

Use tool router when you need a persistent session for multiple tool calls, or when building an MCP integration.

  1. POST /apis/v1/composio/tool_router/session — body: {"user_id": "user-id", "toolkits": ["github"]}
  2. Save session_id from the response
  3. Search for tools: POST .../tool_router/session/{session_id}/search — body: {"query": "create issue"}
  4. List available tools: GET .../tool_router/session/{session_id}/tools
  5. Confirm with user before POST .../tool_router/session/{session_id}/execute — body: {"tool_slug": "GITHUB_CREATE_AN_ISSUE", "arguments": {...}}
  6. Other session operations:
    • GET .../session/{session_id} — check session status
    • GET .../session/{session_id}/toolkits — list session's toolkits
    • POST .../session/{session_id}/link — add a toolkit connection to the session
    • POST .../session/{session_id}/proxy_execute — raw HTTP proxy within session
    • GET .../session/{session_id}/config_history — view past config changes

Details: references/execute_tools.md

4. Triggers and webhooks (read-first)

  1. GET /apis/v1/composio/trigger_instances/active — list active triggers (read-only, no confirmation needed)
  2. GET /apis/v1/composio/triggers_types — browse available trigger types
  3. Confirm with user before any create/update/delete on triggers or webhook subscriptions
  4. GET /apis/v1/composio/webhook_endpoints — list registered webhook URLs
  5. GET /apis/v1/composio/webhook_subscriptions — list active subscriptions
  6. GET /apis/v1/composio/webhook_subscriptions/event_types — see available event types before creating a subscription

Details: references/triggers_webhooks.md

5. MCP servers

Create and manage MCP (Model Context Protocol) servers for agent tool access.

  1. List existing MCP servers: GET /apis/v1/composio/mcp/servers (optional: category, search filters)
  2. Create an MCP server for a single app: Confirm with user, then POST /apis/v1/composio/mcp/servers — body: {"app": {"slug": "github"}, "name": "My GitHub MCP"}
  3. Create a custom MCP server with multiple apps: Confirm with user, then POST /apis/v1/composio/mcp/servers/custom — body: {"apps": [{"slug": "github"}, {"slug": "slack"}], "name": "My Multi-App MCP"}
  4. Generate an MCP URL: POST /apis/v1/composio/mcp/servers/generate — produces a connection URL for the agent
  5. Manage instances: GET /apis/v1/composio/mcp/servers/{serverId}/instances, POST ... to create, DELETE .../instances/{instanceId} to remove
  6. Get/update/delete a server: GET/PATCH/DELETE /apis/v1/composio/mcp/{id}

Details: references/endpoint_catalog.md (group: mcp)

6. Files, projects, and usage

Files:

  • List uploaded files: GET /apis/v1/composio/files/list?limit=10
  • Upload: POST /apis/v1/composio/files/upload/request — get a presigned S3 URL, then PUT the file content to that URL

Projects:

  • List projects: GET /apis/v1/composio/org/owner/project/list
  • Create project: Confirm with user, then POST /apis/v1/composio/org/owner/project/new
  • Get/update/delete: GET/DELETE /apis/v1/composio/org/owner/project/{nano_id}
  • Regenerate API key: Confirm with user, then POST /apis/v1/composio/org/owner/project/{nano_id}/regenerate_api_key

Usage statistics:

  • Org-level summary: POST /apis/v1/composio/org/usage/summary — body: {}
  • Org-level breakdown by entity: POST /apis/v1/composio/org/usage/{entity_type} — common {entity_type} values: tool_calls, sessions; body accepts group_by, limit, order_by, order_direction
  • Project-level: POST /apis/v1/composio/project/usage/summary — body: {}; POST /apis/v1/composio/project/usage/{entity_type} — same fields as above

Response: Usage summary root field is entities (contains tool_calls and sessions sub-objects); breakdown root field is groups (aggregated by the group_by dimension)

Tool execution logs:

  • Search logs: POST /apis/v1/composio/logs/tool_execution — body: {"limit": 10}; response root field is logs (not items), pagination key is next_cursor
  • Get single log: GET /apis/v1/composio/logs/tool_execution/{id}
  • Key log entry fields: metadata.tool.slug, metadata.user_id, metadata.connected_account_id, metrics.duration_ms, status (success/error)

Details: references/execute_tools.md (logs section), references/mcp_projects_usage.md (usage section)

Reference routing

User intentRead this file
Session, auth configsreferences/auth_and_session.md
Connect accounts, OAuth linkreferences/connect_account.md
Toolkits, tools, tool routerreferences/execute_tools.md
Triggers, webhooksreferences/triggers_webhooks.md
MCP servers, projects, usage, file uploadreferences/mcp_projects_usage.md
Exact path or HTTP methodreferences/endpoint_catalog.md

Lookup order: intent → reference (curl examples) → endpoint_catalog.md → upstream API docs for semantics only. Request URLs must use AISA inner_uri paths.

Path parameters

PlaceholderExample sourceNaming note
{nanoid}items[].id from list responses (auth configs, connected accounts, webhooks)Most endpoints
{nanoId}Same as {nanoid} — camelCase per API conventionconnected_accounts/{nanoId}/status only
{nano_id}Same as {nanoid} — snake_casewebhook_endpoints/{nano_id}, org/owner/project/{nano_id}
{slug}toolkits[].slug or user-stated toolkit name (e.g. github, slack)
{tool_slug}tools list: items[].slug (e.g. GITHUB_CREATE_AN_ISSUE)
{session_id}tool_router/session create response
{serverId}MCP server list/create responsecamelCase
{triggerId}trigger_instances/active list responsecamelCase
{id}Context-dependent: log ID, MCP server ID, etc.

Important: Use the exact casing shown in the endpoint path. The API is case-sensitive.

Safety

  • Confirm with the user before POST / PATCH / DELETE that change production data (including connected_accounts/link, tools/execute, tool_router/session/{id}/execute, MCP server create/delete, auth config create/update, trigger upsert/delete, webhook create/delete)
  • DELETE may soft-delete configs, connections, or webhooks
  • OAuth redirect_url must be opened by a human in a browser
  • Read-only GET calls (session, list configs, list tools) do not require confirmation unless the user asked you to avoid network calls
  • Rate limiting: if you receive 429 responses, wait briefly and retry. Avoid rapid-fire API calls in loops without delays

Troubleshooting

SymptomAction
401 + quota exhaustedRenew or replace AISA_API_KEY
Empty items on auth_configsAsk user to create auth config or verify toolkit slug
Empty items on connected_accountsRun OAuth link workflow; connection may still be PENDING
404 on PATCH with path IDUse a real ID from a prior GET/POST list response; check casing ({nanoid} vs {nanoId})
500 on path with fake IDDo not use test placeholders
SSL timeout on large listsRetry with smaller limit or narrower filters
Multiple GitHub connections returnedRe-query with user_ids= filter or ask user which account
User says "create issue" but slug unknownList tools first; never guess tool_slug
Tool execution returns successful: falseInspect error field; common causes: wrong connected_account_id, missing required arguments, insufficient permissions — get tool schema via GET /tools/{tool_slug} and retry
Error 1811: entity_id requiredAdd user_id to tools/execute body — use the same value as user_id when the account was linked. entity_id is the deprecated alias for user_id
Error 10400: Invalid discriminator on auth_configauth_config.type is required; use use_composio_managed_auth or use_custom_auth
Error 1151: MCP server name already existsMCP server names must be unique per project; choose a different name
x-org-api-key required error on project listProject list requires an org-level API key, not a project-level AISA_API_KEY; use session/info to confirm which key you have
OAuth link expires before user completesCreate a new link with POST connected_accounts/link
Token refresh returns redirect_url with status INITIATEDOAuth cannot auto-refresh; user must re-authorize at the returned URL
logs/tool_execution response has no itemsResponse root field is logs (not items); pagination key is next_cursor (not cursor)
429 Too Many RequestsSlow down; add delays between API calls; reduce limit parameter

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.