Files
composiohq__composio/ts
Alberto Schiabel 025a657597 feat(ts): drop CommonJS support (#3494)
This PR moves the TypeScript SDK support floor to the latest Node.js 22
release and uses that as the point where we stop carrying custom
CommonJS compatibility machinery. The e2e runtime coverage now exercises
the latest Node 22, Node 24, and Node 25 lines, so the SDK is tested
against the minimum supported version and the newer runtimes users are
likely to adopt next.

Because the SDK packages are still on `0.x`, the accompanying changeset
uses `minor` bumps while calling out that this is a breaking change
inside the existing 0.x line.

It also moves pnpm under mise on this Node 22 layer. That belongs here,
not in #3493, because the pinned `pnpm@10.28.2` requires Node.js
`>=22.13`. Removing Corepack is intentional: Node.js documents that
Corepack is no longer distributed starting with Node.js v25, so relying
on `corepack enable` would keep a toolchain dependency that is already
on the way out of the Node distribution.

## What changed

- Pins the local/toolchain Node.js floor to `22.22.3` in `mise.toml`,
`mise.lock`, `toolchain-versions.json`, and root `devEngines`.
- Pins pnpm in `mise.toml` as `"npm:pnpm" = "10.28.2"` and makes mise
the single source of truth for the pnpm version. Removes the root
`packageManager` / `devEngines.packageManager` Corepack pin entirely
(rather than keeping a second copy of the version that could drift) and
removes stale `packageManager` metadata from real TS packages/examples
and generators.
- Sets `dangerouslyDisablePackageManagerCheck: true` in `turbo.jsonc` so
Turbo discovers pnpm from `pnpm-lock.yaml` instead of requiring a
`packageManager` field. Without this, Turbo fails workspace resolution
(`Could not resolve workspaces -> Missing 'packageManager' field`),
which is the only reason the field would otherwise need to stay.
- Replaces `corepack enable` in the shared setup action with
mise-managed pnpm. The E2E Docker images install bun + pnpm directly
from `mise.toml`/`mise.lock` (with
`dangerouslyDisablePackageManagerCheck`-style separation: Node/Deno stay
on the base image as the test matrix axis and are disabled via
`MISE_DISABLE_TOOLS` so mise does not shadow them; the tool binaries are
symlinked into `/usr/local/bin`). No `BUN_VERSION`/`PNPM_VERSION` build
args are threaded from the host anymore, and bun+pnpm now carry
`mise.lock` checksum verification.
- Extends the install-time toolchain check to validate pnpm against mise
alongside Bun.
- Sets the Node E2E matrix and install fallback checks to `22.22.3`,
`24.16.0`, and `25.9.0`.
- Makes TS package builds ESM-only: `tsdown` now emits `.mjs` / `.d.mts`
only and uses the ATTW `esm-only` profile.
- Removes explicit `require` / `.cjs` / `.d.cts` package export paths
and internal import mappings from the public TS SDK packages.
- Marks public TS SDK packages as `type: module` where they were missing
it.
- Replaces the remaining runtime `require('pusher-js')` with dynamic ESM
import.
- Deletes the legacy CJS example.
- Reintroduces `node/cjs-basic` as a modern Node `require(esm)` interop
E2E: it verifies `require('@composio/core')` works through Node's native
ESM loader on Node 22, 24, and 25 while resolving to `dist/index.mjs`,
not a `.cjs` artifact.
- Removes `.cjs` / `.cts` handling from example validation and CLI
project-language detection.
- Updates provider scaffolding so newly generated providers are
ESM-only.
- Adds a minor changeset warning that CommonJS callers can only rely on
Node's native `require(esm)` interop and that custom CommonJS
compatibility machinery is gone.

## Bundled behavior changes

Two changes here are technically independent of the CommonJS removal but
ride along because they touch the same files and ship in the same
release cut. Calling them out explicitly so they are not missed in
review:

- **`PusherUtils` realtime channel auth (`@composio/core`).** Replacing
the runtime `require('pusher-js')` with a dynamic ESM `import()` was
done alongside conforming `channelAuthorization` to pusher-js's typed
`customHandler(params, callback)` contract. The previous `(authOptions)
=> Promise` shape did not match pusher-js's actual calling convention —
it read `endpoint`/`headers`/`params` off an argument that pusher-js
never passes — so this also fixes that latent mismatch. New unit tests
(`ts/packages/core/test/utils/pusher.test.ts`) cover the auth request
shape (endpoint, `x-api-key` header, JSON `socket_id`/`channel_name`
body) and the success / invalid-JSON / network-failure callback paths.
- **CLI meta-tool slug list (`@composio/cli`).** Drops
`COMPOSIO_UPSERT_RECIPE` and `COMPOSIO_GET_RECIPE` from
`META_TOOL_SLUG_LIST` in `tools-executor.ts`; `@composio/client`
alpha.74 removed those slugs from the `SessionExecuteMetaParams['slug']`
union. The list is declared `satisfies
ReadonlyArray<SessionExecuteMetaParams['slug']>`, so this is enforced at
compile time (`pnpm typecheck`) — keeping the stale slugs would be a
type error — and needs no separate runtime test.

## Verification

- Verified latest Node 22/24/25 releases from the official Node dist
index: `22.22.3`, `24.16.0`, `25.9.0`
(https://nodejs.org/dist/index.json).
- Verified Node docs state Corepack is no longer distributed starting
with Node.js v25:
https://nodejs.org/download/release/v22.22.3/docs/api/corepack.html
- `mise exec -- pnpm --version` -> `10.28.2`
- `mise exec -- pnpm install --frozen-lockfile`
- `mise exec -- bun run ts/scripts/pre-install/check-toolchain.ts`
- `mise exec -- pnpm --filter @e2e-tests/utils typecheck`
- `mise exec -- pnpm --filter @e2e-tests/node-cjs-basic typecheck`
- `mise exec -- pnpm --filter @e2e-tests/node-cjs-basic test:e2e:node`
- `mise exec -- pnpm --filter @e2e-tests/node-esm-basic typecheck`
- `mise exec -- pnpm --filter @composio/cli typecheck`
- `mise exec -- pnpm --filter @composio/cli test -- --runInBand`
- `mise exec -- pnpm --filter @composio/core typecheck`
- `mise exec -- pnpm --filter @composio/core exec vitest run
test/utils/pusher.test.ts`
- `mise exec -- pnpm run build:packages`
- `mise exec -- turbo run build --dry-run` resolves all workspace
packages with no root `packageManager` field (pnpm discovered from
`pnpm-lock.yaml`).
- `mise exec -- pnpm --filter @composio/cli exec vitest run
test/src/services/project-environment-detector.test.ts`
- `mise exec -- pnpm exec prettier --check ...`
- `docker build -f ts/e2e-tests/_utils/Dockerfile.node --build-arg
NODE_VERSION=24.16.0 -t composio-e2e-node:misecheck .` (also
`Dockerfile.deno` with `DENO_VERSION=2.6.7 NODE_MAJOR=22`) — both build
green; runtime resolves Node/Deno from the base image and pnpm 10.28.2 /
bun 1.3.10 from mise.
- `docker manifest inspect node:24.16.0-slim`
- `docker manifest inspect node:25.9.0-slim`
- `bash -n ts/scripts/create-provider.sh && git diff --check`
- `ruby -e "require 'yaml';
YAML.load_file('.github/workflows/ts.test-e2e.yml')"`
- Tracked example validation in a clean temporary tree: `Validated 21
example packages.`
2026-06-19 22:22:17 +04:00
..

Composio SDK v3

The Composio SDK is a powerful toolkit that enables you to integrate third-party tools and services into your applications. It helps you connect to various services (toolkits), execute tools, and manage user connections seamlessly.

Features

  • Execute tools from various services (GitHub, Gmail, Slack, etc.)
  • Manage user connections to external services
  • Create session-scoped custom tools with your own logic
  • Integrate with AI providers like OpenAI
  • Powerful middleware and modifier support
  • Extensive error handling

Documentation

The SDK is thoroughly documented in the docs directory:

API Reference

Provider Documentation

Advanced Topics

Internal Documentation

For SDK maintainers and contributors:

Installation

# Using npm
npm install @composio/core

# Using yarn
yarn add @composio/core

# Using pnpm
pnpm add @composio/core

Quick Start

import { Composio } from '@composio/core';

// Initialize the SDK
const composio = new Composio({
  apiKey: 'your-api-key',
});

// Get tools from a specific toolkit
const tools = await composio.tools.get('default', {
  toolkits: ['github'],
});

// Get a specific tool
const specificTool = await composio.tools.get('default', 'GITHUB_GET_REPOS');

// Execute a tool
const result = await composio.tools.execute('GITHUB_GET_REPO', {
  userId: 'default',
  arguments: {
    owner: 'composio',
    repo: 'sdk',
  },
});

console.log(result.data);

OpenAI Integration

import { Composio } from '@composio/core';
import OpenAI from 'openai';

// Initialize Composio and OpenAI
const composio = new Composio({
  apiKey: 'your-composio-api-key',
});

const openai = new OpenAI({
  apiKey: 'your-openai-api-key',
});

// Get GitHub tools
const tools = await composio.tools.get('default', {
  toolkits: ['github'],
});


// Create a chat completion with the tools
const completion = await openai.chat.completions.create({
  model: 'gpt-4',
  messages: [
    { role: 'system', content: 'You are a helpful assistant with access to GitHub tools.' },
    { role: 'user', content: 'Find information about the Composio SDK repository' },
  ],
  tools, // Pass the tools to OpenAI
});

// If the model wants to use a tool
if (completion.choices[0].message.tool_calls) {
  const toolCall = completion.choices[0].message.tool_calls[0];
  const args = JSON.parse(toolCall.function.arguments);

  // Execute the tool
  const result = await composio.tools.execute(toolCall.function.name, {
    userId: 'default',
    arguments: args,
  });

  console.log(result.data);
}

Creating Custom Tools

import { Composio, experimental_createTool } from '@composio/core';
import { z } from 'zod';

const composio = new Composio({ apiKey: process.env.COMPOSIO_API_KEY });

const weatherForecast = experimental_createTool('WEATHER_FORECAST', {
  name: 'Weather Forecast',
  description: 'Get the weather forecast for a location',
  inputParams: z.object({
    location: z.string().describe('The location to get the forecast for'),
    days: z.number().optional().default(3).describe('Number of days for the forecast'),
  }),
  execute: async (input) => {
    const { location, days = 3 } = input;
    const forecast = await getWeatherForecast(location, days);
    return { forecast };
  },
});

const session = await composio.create('default', {
  experimental: { customTools: [weatherForecast] },
});

const result = await session.execute('WEATHER_FORECAST', {
  location: 'San Francisco, CA',
});

Project Structure

composio/
├── packages/                  # Main packages directory
│   ├── core/                  # Core SDK package
│   └── providers/             # Provider implementations
├── examples/                  # Example implementations
│   ├── connected-accounts/    # Connected accounts examples
│   ├── langchain/            # LangChain integration examples
│   ├── openai/               # OpenAI integration examples
│   ├── modifiers/            # Modifiers examples
│   ├── toolkits/             # Toolkits examples
│   └── vercel/               # Vercel AI examples
├── docs/                      # Documentation
├── scripts/                   # Development and build scripts
└── .github/                   # GitHub configuration

Development Setup

  1. Prerequisites

    • Node.js (Latest LTS version recommended)
    • pnpm (v10.8.0 or later)
    • bun for productivity (optional)
  2. Clone and Install

    git clone https://github.com/ComposioHQ/sdk-v3-ts.git
    cd composio
    pnpm install
    
  3. Build

    pnpm build
    
  4. Development Commands

    # Lint code
    pnpm lint
    
    # Fix linting issues
    pnpm lint:fix
    
    # Format code
    pnpm format
    
    # Create a new provider
    pnpm create:provider <provider-name> [--agentic]
    
    # Create a new example
    pnpm create:example <example-name>
    
    # Check peer dependencies
    pnpm check:peer-deps
    
    # Update peer dependencies
    pnpm update:peer-deps
    

Creating a New Example

  1. Use the create:example script:

    pnpm create:example my-example
    
  2. The script will create a new example in examples/my-example with:

    • package.json with minimal dependencies (@composio/core and dotenv)
    • tsconfig.json for TypeScript configuration
    • .env.example and .env files for environment variables
    • src/index.ts with basic Composio SDK setup
    • README.md with setup and usage instructions
    • Dependencies automatically installed
  3. Next steps after creation:

    • Edit .env and add your COMPOSIO_API_KEY
    • Customize src/index.ts with your example logic
    • Add any additional dependencies as needed
    • Run with pnpm start or pnpm dev (with file watching)

Creating a New Provider

  1. Use the create:provider script:

    pnpm create:provider my-provider [--agentic]
    
  2. The script will create a new provider in packages/providers/my-provider with:

    • Basic provider implementation
    • TypeScript configuration
    • Package configuration
    • README template
  3. Implement the required methods in src/index.ts:

    • For non-agentic providers: wrapTool and wrapTools
    • For agentic providers: wrapTool, wrapTools, and execution handlers

Release Process

For detailed information about both automated and manual release processes, please refer to our Release Process Documentation.

Environment Variables

  • COMPOSIO_API_KEY: Your Composio API key
  • COMPOSIO_BASE_URL: Custom API base URL (optional)
  • COMPOSIO_LOG_LEVEL: Logging level (silent, error, warn, info, debug)
  • COMPOSIO_DISABLE_TELEMETRY: Disable telemetry when set to "true"
  • COMPOSIO_TOOLKIT_VERSION_<TOOLKIT_NAME>: Specific version for a toolkit (e.g., COMPOSIO_TOOLKIT_VERSION_GITHUB=20250902_00)
  • DEVELOPMENT: Development mode flag
  • CI: CI environment flag

Contributing

We welcome contributions! Please see our Contributing Guide for more details.

License

ISC License

Support

For support, please visit our Documentation or join our Discord Community.