Authentication

Composio organizes everything around your users. A user is whoever your agent acts on behalf of: a person in your app, identified by a userID you choose. Authentication is always per user. Each user connects their own accounts, their Gmail, their GitHub, their Slack, and Composio stores and refreshes those credentials against that userID.

This is the core idea: your agent runs the same tools for many people, and every tool call runs as a specific user against that user's connected accounts. User A's agent never touches user B's data. You pass the userID when you create a session, and Composio handles the auth from there.

Because connections are stored under the userID, use a stable identifier, like your database ID, never one that can change.

Your users connect their accounts through a secure Connect Link, and Composio manages their tokens for you.

~/projects/composio
active connections
ops@acme.comwork

How Composio handles authentication

Every session includes the COMPOSIO_MANAGE_CONNECTIONS meta tool. When a tool needs an account, it reads the toolkit's auth config (how that toolkit authenticates: method, scopes, credentials), creates a connection, and returns a secure Connect Link. This works for all Composio managed connections, so you don't have to set up any OAuth credentials yourself.

The user signs in on the hosted link and Composio stores the resulting connected account. Credentials never pass through your app or the model, so it's safe to surface the link right in the chat.

You only need a custom auth config to bring your own OAuth app, request specific scopes, or use a toolkit without managed auth.

In-chat authentication

The agent posts the Connect Link straight into the conversation. The user clicks it, signs in, and the agent retries the tool and continues. No auth UI for you to build.

agent
Summarize my emails from today
COMPOSIO_MANAGE_CONNECTIONS
Gmail not connected — sent Connect Link
Connect your Gmail account to continue:
COMPOSIO_WAIT_FOR_CONNECTIONS
✓ Gmail connected
GMAIL_FETCH_EMAILS
12 emails
Here's a summary of your emails from today...

You can also call COMPOSIO_MANAGE_CONNECTIONS yourself, intercept the Connect Link, and surface it wherever you need: DM it to the user, render it in your own UI, or email it. See redirect auth links for a worked example.

Custom callback URL

To send users back to your app after they connect, pass a callback_url:

session = composio.create(
    user_id="user_123",
    manage_connections={"callback_url": "https://yourapp.com/chat"},
)
const session = await composio.create("user_123", {
  manageConnections: { callbackUrl: "https://yourapp.com/chat" },
});

Manually triggering authentication

Don't want to wait for the agent? Call session.authorize() to generate a Connect Link on demand, for onboarding, a settings page, or a pre-flight check before a task.

Manual auth management

session.authorize(), callback URLs, connection status, and disabling in-chat prompts

Behind the scenes

Composio manages authentication with auth configs. An auth config is a blueprint for how a toolkit authenticates across all your users. It defines three things:

  • Authentication method: OAuth2, Bearer token, API key, or Basic Auth
  • Scopes: what actions your tools can perform
  • Credentials: your own app credentials, or Composio's managed auth

Composio creates one auth config per toolkit and applies it to every user who connects that toolkit. Most toolkits use Composio managed auth, so you don't create or configure anything. You only need a custom auth config to use your own OAuth app or customize scopes.

ac_gmail_oauth2

One OAuth2 blueprint: auth method, scopes, and credentials. Reused for every user who connects Gmail.

Uuser_1
  • Work Gmailca_1a2b3c
  • Personal Gmailca_4d5e6f
Uuser_2
  • Gmailca_7g8h9i

one auth config a connected account per user, fully isolated

When a user authenticates, Composio creates a connected account: their credentials (OAuth tokens or API keys) linked to your userID. Each user can have multiple, even for the same toolkit (e.g. work and personal Gmail).

Connection lifecycle

For OAuth, Composio refreshes access tokens automatically before they expire, so connections stay ACTIVE with no work from you. If a refresh token is revoked or expires, the connection moves to EXPIRED and the user has to reconnect.

Composio
every 30 min
Gmailwork@acme.com
ACTIVEoauth · ••••9f3a
Notionacme-workspace
ACTIVEoauth · ••••2c7d
GitHubacme-bot
ACTIVEoauth · ••••b18e

Composio rotates every connection’s token on a schedule connections stay ACTIVE with no work from you

Catch this before a tool call fails by subscribing to the composio.connected_account.expired event on a webhook subscription. When it fires, send the user a fresh Connect Link to re-authenticate:

session = composio.create(user_id="user_123")
connection_request = session.authorize("gmail")

# Send this URL to the user (email, in-app notification, etc.)
print(connection_request.redirect_url)
const session = await composio.create("user_123");
const connectionRequest = await session.authorize("gmail");

// Send this URL to the user (email, in-app notification, etc.)
console.log(connectionRequest.redirectUrl);

Next

Manual auth management

Generate Connect Links yourself, check connection status, and disable in-chat prompts