Skip to content

Composio Aggregator Setup

Composio is an OAuth aggregator. It holds the vendor’s tokens; NimbleBrain proxies tool calls through Composio’s MCP endpoint and persists only an opaque connectedAccountId per workspace per connector.

You only need this if your catalog has any auth: composio entries. The bundled catalog ships Gmail and Outlook as Composio-backed because Google and Microsoft require app verification (gmail.*, Mail.*) that most operators don’t hold on day one. Once your own OAuth app is verified, you can migrate the entry from auth: composio to auth: static or auth: dcr without losing the workspace’s existing state.

  • Sign up at platform.composio.dev.
  • One Composio account per environment is fine; staging and production can share the account during development, but production should get its own once you’re under volume.
  • Issue an API key under Project Settings → API keys. Save it — you’ll wire it into the pod as COMPOSIO_API_KEY.

2. Register a per-toolkit OAuth client (BYO credentials)

Section titled “2. Register a per-toolkit OAuth client (BYO credentials)”

For each toolkit you expose, register an OAuth client at the vendor’s developer console using your own credentials. Composio also offers a “managed” mode where they supply the OAuth app, but it ships with shared quota and Composio branding on the consent screen — bring your own client.

Gmail (Google Cloud Console):

  • console.cloud.google.com/apis/credentials
  • App: reuse an existing Google OAuth client or create a new one. Name it after your platform.
  • Authorized redirect URI: https://backend.composio.dev/api/v3.1/toolkits/auth/callback
  • Scopes (request via Google’s OAuth verification flow): gmail.readonly, gmail.send, gmail.modify, gmail.compose, plus openid email profile
  • Capture Client ID + Client Secret

Outlook (Azure Portal):

  • portal.azure.com → Azure Active Directory → App registrations → New registration
  • Supported account types: “Accounts in any organizational directory and personal Microsoft accounts”
  • Redirect URI (Web): https://backend.composio.dev/api/v3.1/toolkits/auth/callback
  • API permissions (delegated): Mail.Read, Mail.Send, Mail.ReadWrite, MailboxSettings.Read, Calendars.ReadWrite, offline_access
  • Certificates & secrets → New client secret
  • Capture Application (client) ID + the secret value

Repeat per toolkit you plan to enable.

3. Create one auth config per toolkit in Composio

Section titled “3. Create one auth config per toolkit in Composio”

In the Composio dashboard:

  1. Authentication management → Create Auth Config
  2. Select the toolkit (Gmail / Outlook / …)
  3. Toggle “Use your own developer credentials”
  4. Paste the Client ID + Client Secret from step 2
  5. Save — copy the resulting ac_… id

You’ll wire that id into the pod as COMPOSIO_<TOOLKIT>_AUTH_CONFIG_ID. The variable name comes from the catalog entry: each auth: composio entry declares its own composio.authConfigEnv, so Gmail reads COMPOSIO_GMAIL_AUTH_CONFIG_ID, Outlook reads COMPOSIO_OUTLOOK_AUTH_CONFIG_ID, etc.

Section titled “4. White-label the Composio consent screen (optional)”

In Project Settings → Auth Screen in the Composio dashboard, upload your platform’s logo and set the app title. For OAuth2 toolkits (Gmail, Outlook, most everything in the directory) the consent screen redirects through Composio briefly and the user-visible vendor consent uses your OAuth client’s branding — the Composio screen only flashes for non-OAuth2 flows.

Three variables per environment, plus one auth-config id per Composio-backed catalog entry. Source them from whatever secret store you’re already using (Kubernetes Secret, ExternalSecret pointing at a vault, AWS Secrets Manager, etc.).

Terminal window
COMPOSIO_API_KEY=... # from step 1
COMPOSIO_GMAIL_AUTH_CONFIG_ID=ac_... # from step 3
COMPOSIO_OUTLOOK_AUTH_CONFIG_ID=ac_... # from step 3
# Add one COMPOSIO_<TOOLKIT>_AUTH_CONFIG_ID per Composio-backed catalog entry.
# Multi-tenant deployments only — required so two tenants with
# the same wsId don't share a Composio user namespace.
NB_TENANT_ID=tenant-a

The full reference is in Environment Variables → Composio aggregator.

On pod startup, look for this log line:

[composio] integration: configured (base=https://backend.composio.dev)

If you see integration: not configured instead, COMPOSIO_API_KEY isn’t reaching the pod.

If the platform refuses to start with NB_TENANT_ID is required when running in bouncer (multi-tenant) mode or COMPOSIO_API_BASE_URL must be http(s), the deployment config is malformed — fix per the error message.

If running behind strict egress filters, allow:

  • backend.composio.dev (HTTPS, all paths) — SDK calls and the MCP endpoint
  • connect.composio.dev (HTTPS, all paths) — hosted Connect Link redirect
  • Google / Microsoft OAuth endpoints (most fleets already allow these for native integrations)

The full procedure to add (say) Slack to a Composio-backed deployment:

  1. Vendor side: register a Slack OAuth app (BYO) — api.slack.com/apps. Set redirect URI to https://backend.composio.dev/api/v3.1/toolkits/auth/callback. Capture Client ID + Client Secret.
  2. Composio side: dashboard → Create Auth Config → Slack → BYO credentials → paste. Capture ac_….
  3. Secret store: add COMPOSIO_SLACK_AUTH_CONFIG_ID=ac_… to your environment.
  4. Catalog YAML: add a auth: composio entry with composio.toolkit: slack and composio.authConfigEnv: COMPOSIO_SLACK_AUTH_CONFIG_ID. Curate composio.tools aggressively — Slack publishes 100+ tools, and the agent’s first-turn tool search will spend tens of thousands of tokens listing them all if you let it. See Connectors Catalog → auth: composio.
  5. Roll the deployment: bump the platform image (or restart pods). The new env var and catalog entry are picked up on next start.

Some toolkits in Composio’s directory authenticate by API key, not OAuth (PostHog, among others). There’s no vendor OAuth app and no consent redirect: when a user connects, they paste the toolkit’s API key (plus any region/host) into a short form, the platform hands it to Composio, and only the opaque connectedAccountId is persisted. The platform never stores the key. It’s the same trust posture as the OAuth path — Composio custodies the credential.

Setup differs from the OAuth procedure above in three ways:

1. Create the auth config with the API_KEY scheme

Section titled “1. Create the auth config with the API_KEY scheme”

In the Composio dashboard → Authentication management → Create Auth Config, pick the toolkit and choose the API Key auth scheme. There is no “use your own developer credentials” step — API-key toolkits have no OAuth client. Save and copy the ac_… id, then wire it into the pod as COMPOSIO_<TOOLKIT>_AUTH_CONFIG_ID exactly as for OAuth toolkits. (It is not a secret on its own — inert without COMPOSIO_API_KEY.)

2. Declare authScheme + fields in the catalog

Section titled “2. Declare authScheme + fields in the catalog”

The catalog entry sets authScheme: API_KEY and lists the fields the connect form collects from the user. See Connectors Catalog → auth: composio with API keys for the YAML shape.

3. Verify field keys and tool slugs against Composio

Section titled “3. Verify field keys and tool slugs against Composio”

Composio exposes three slightly different slug namespaces — the REST tool catalog, the connection-initiation fields, and the tool-router session filter — so two values must be confirmed against Composio’s own naming rather than guessed:

  • fields[].key must be the connection-initiation field name. Confirm with getConnectedAccountInitiationFields("<toolkit>", "API_KEY") (or the toolkit’s auth page on composio.dev). It is often not the obvious name — e.g. PostHog’s key field is generic_api_key (not api_key) plus a subdomain.
  • tools[] must be the tool-router config.tools names, which differ from the REST catalog (GET /api/v3/tools). The authoritative check is to install the connector with your candidate list: session-create returns 400 Invalid tool slugs in config.tools: … naming every wrong one. Iterate until it installs clean. (A no-filter install’s exposed tool list is a third namespace — also not authoritative for the filter.)

Everything else — COMPOSIO_API_KEY, env wiring, the [composio] integration: configured startup check, the egress allowlist — is identical to the OAuth setup above.

When a user clicks Disconnect on a Composio-backed connector:

  1. The platform calls Composio’s SDK to delete the connected account (best-effort — failures don’t block local cleanup).
  2. The platform deletes <workDir>/workspaces/<wsId>/credentials/composio/<connectorId>/connection.json.
  3. The bundle’s MCP source is stopped and removed from the registry.
  4. Bundle state transitions to not_authenticated. The UI shows Connect again.

Reconnect after disconnect runs a fresh OAuth flow at the vendor — there’s no adopt-existing shortcut because the upstream account was deleted in step 1. For API-key toolkits there’s no OAuth flow: reconnect re-opens the key form. Re-connecting an already-connected API-key toolkit (key rotation) replaces and revokes the prior Composio account and is gated to workspace admins, since it swaps the credential every member’s agent runs under.

When your own OAuth app passes vendor verification for a given toolkit:

  1. Update the catalog entry’s _meta.connector.auth from composio to static (or dcr if the vendor supports DCR).
  2. Provision the platform-side OAuth client for that toolkit (see Connectors Catalog → static auth).
  3. Existing Composio-connected workspaces will see “needs auth” — connection.json is still on disk but the catalog’s auth discriminator has changed, so the boot probe says re-authenticate.
  4. Once all workspaces have re-authenticated, you can remove the Composio dashboard entries for that toolkit and drop the COMPOSIO_<TOOLKIT>_AUTH_CONFIG_ID env var.

The catalog name (com.google/gmail) stays stable across the migration. Composio state (credentials/composio/<connectorId>/connection.json) and native OAuth state (credentials/oauth/<connectorId>/tokens.json) live at distinct paths, so neither overwrites the other during the cutover.

  • One platform-wide Composio API key. Per-tenant Composio sub-accounts aren’t supported yet — every tenant on a pod shares the same Composio account. Plan multi-tenant Composio sharing accordingly (NB_TENANT_ID namespaces within a single Composio account but tools, quotas, and tokens are still pooled).
  • Tool allowlist is source-controlled. Curating composio.tools requires a platform image release. Per-workspace overrides are not yet exposed.
  • Composio sees tool inputs and outputs. Email bodies, message contents, every argument and result transits Composio’s infrastructure. Acceptable for general productivity workflows; a no-go for tenants under data-residency or PII-handling NDAs. Move those tenants to a native OAuth client before exposing them to a Composio-backed connector.
  • @composio/core is pre-1.0 (pinned to 0.9.x). Monitor release notes before upgrading; major bumps may make breaking changes.
SymptomLikely causeFix
Connect button shows “Failed to start OAuth flow”Web bundle stale or catalog projection didn’t loadHard refresh the browser; check the [composio] integration: configured log line at pod startup
Install succeeds but “Sign-in required” persists after OAuthconnection.json didn’t land at the callbackCheck <workDir>/workspaces/<wsId>/credentials/composio/<connectorId>/connection.json; if missing, the callback handler logged the failure
Install returns “Installed … click Connect to retry”Eager source-start failed (transient upstream / network). The install itself succeeded — workspace.json has the entry, the bundle just couldn’t kick its tool list.Click Connect on the connector. If retries keep failing, check pod logs for [bundles] <serverName> start failed:
Connect returns 502 composio_adopt_source_start_failedThe adopt-existing path matched a Composio account but couldn’t bring the local MCP source online. No partial state was persisted.Click Disconnect then Connect to run a fresh OAuth flow. Investigate pod logs if it persists.
Install fails with 400 Invalid auth config IDs from ComposioCOMPOSIO_<TOOLKIT>_AUTH_CONFIG_ID points at an ac_… that doesn’t exist in the Composio dashboardConfirm the id in platform.composio.dev → Auth Configs; update your secret; refresh the in-pod value; roll the deployment
Install fails with 400 Invalid tool slugs in config.tools: … (API-key toolkit)The tools allowlist uses REST-catalog names, not the tool-router config.tools namespaceReplace the named slugs with their tool-router equivalents and reinstall to re-validate — see API-key toolkits
Connect form rejects a field or the connection 401s on first tool call (API-key toolkit)A fields[].key doesn’t match Composio’s connection-initiation field name (e.g. api_key vs generic_api_key), or the wrong key type was enteredVerify keys via getConnectedAccountInitiationFields; confirm the user pasted the correct key type (e.g. PostHog needs a phx_ personal key, not a phc_ project key)
Agent returns “model returned an error” on first tool callTool allowlist missing or too broad — nb__search returns hundreds of tool descriptions and blows past the input-token capAdd or tighten composio.tools in the catalog entry; reinstall
Composio API errors after deployAPI key not propagated through the secret pipelinekubectl exec (or equivalent) into the pod and check printenv COMPOSIO_API_KEY
Multiple connected accounts piling up in the Composio dashboardLegacy state from before the adopt-existing path landed. New connects auto-dedup against the active account.Manual cleanup in the Composio dashboard for old duplicates