Back to Changelog

Apr 28, 2026

Latest updates and announcements

Markdown

SDKs: `link()` matches `initiate()` for the multi-connection guard

composio.connectedAccounts.link() (TypeScript) and composio.connected_accounts.link() (Python) now match the multi-connection guard that initiate() already had. With Composio-managed redirectable-OAuth callers being migrated off POST /api/v3/connected_accounts onto POST /api/v3/connected_accounts/link, the guard moves with them — so the migration doesn't quietly drop the duplicate-connection check.

Behavior change

Before: link() would happily create a second ACTIVE connection for the same (user_id, auth_config_id) pair without checking for an existing ACTIVE connection first.

After: link() first calls connectedAccounts.list({ userIds, authConfigIds, statuses: ['ACTIVE'] }). If any active connection exists, link() throws ComposioMultipleConnectedAccountsError unless the caller passes allowMultiple: true (TypeScript) / allow_multiple=True (Python).

SDK versions (patch releases)

PackagePreviousThis release
TypeScript @composio/corev0.8.0v0.8.1
Python composiov0.12.0v0.12.1

Migration

Most callers don't need to do anything — link() raised an unrelated error or succeeded by accident in the duplicate-connection case before, and now raises a typed error you can handle. Two scenarios that need attention:

1. You intentionally create multiple connections per (user, auth_config) — for example, two Gmail accounts for the same user. Opt in:

connection_request = composio.connected_accounts.link(
    user_id="user_123",
    auth_config_id="ac_xxx",
    alias="work-gmail",
    allow_multiple=True,
)
const connectionRequest = await composio.connectedAccounts.link(
  'user_123',
  'ac_xxx',
  { alias: 'work-gmail', allowMultiple: true },
);

Pair with a session-level multiAccount / multi_account config so the agent can disambiguate at execution time. See Managing multiple connected accounts for the session shape.

2. You're migrating from initiate() to link() as part of the Composio-managed OAuth migration. Pass allow_multiple / allowMultiple through unchanged — same flag name, same default (False), same exception (ComposioMultipleConnectedAccountsError).

Why

The migration changelog moves callers off connected_accounts/create onto /link. initiate() had allow_multiple and the duplicate-connection check; link() didn't. Without this fix, every customer who migrates would silently lose the guard and start creating duplicate ACTIVE connections on auth configs that were never meant to hold more than one. This release closes that gap.

SDKs add sandbox compute tier for Tool Router workbench

The Composio SDKs now let you pick the compute tier of the workbench sandbox when creating a Tool Router session. Heavier code execution and larger in-memory data benefit from a bigger sandbox.

TiervCPURAM
standard11 GB
medium22 GB
large44 GB
xlarge88 GB

The field is optional and defaults to standard server-side when omitted, so existing code keeps working unchanged.

Pricing: Sandboxes are not billed today. Composio plans to begin billing for sandbox usage soon (metered by tier and runtime). Pick a tier that matches your workload — but expect future pricing to track actual usage.

SDK versions (patch releases)

PackagePreviousThis release
TypeScript @composio/corev0.8.0v0.8.1
Python composiov0.12.0v0.12.1

Usage

TypeScript (camelCase on the SDK surface):

import { Composio } from '@composio/core';
const composio = new Composio({ apiKey: process.env.COMPOSIO_API_KEY! });

const session = await composio.create('user_123', {
  workbench: {
    enable: true,
    sandboxSize: 'large',
  },
});

The SandboxSize literal type and SandboxSizeSchema zod enum are exported from @composio/core.

Python (snake_case throughout):

session = composio.create(
    user_id="user_123",
    workbench={
        "sandbox_size": "large",
    },
)

The SandboxSize literal alias is available at composio.core.models.tool_router.SandboxSize.

Updating an existing session

Calling session.update() (or the equivalent PATCH /api/v3/tool_router/sessions/{id}) with a different sandbox_size recreates the sandbox on next access. The sandbox's in-memory filesystem state is lost, but the persistent /mnt/files/ mount survives the restart.

See Configuring Sessions → Sandbox compute tier for the full reference.