venkat82 7ff870b138 feat(core): surface accountType + per-user ACL on SHARED connected accounts (#3392)
## Summary

SDK wrappers for the Apollo-side Shared Accounts feature shipped across
four Hermes PRs:

- [hermes#9860](https://github.com/ComposioHQ/hermes/pull/9860) —
`account_type` enum (PRIVATE / SHARED) + pin-only invariant
- [hermes#9882](https://github.com/ComposioHQ/hermes/pull/9882) — echo
`account_type` in create-flow responses
- [hermes#9887](https://github.com/ComposioHQ/hermes/pull/9887) — echo
`account_type` in internal link-session GET (no public docs surface)
- [hermes#9902](https://github.com/ComposioHQ/hermes/pull/9902) —
per-user ACL for SHARED connections, nested under
`acl_config_for_shared`

Ready for review — Apollo, the OpenAPI spec, and
`@composio/client@0.1.0-alpha.71` (published from
[composio-base-ts#77](https://github.com/ComposioHQ/composio-base-ts/pull/77))
all carry the merged contract.

## Implemented

### Types (`types/connectedAccounts.types.ts`)
- `ConnectedAccountTypes` constants + `ConnectedAccountTypeSchema` Zod
enum + `ConnectedAccountType` TS type.
- `ConnectedAccountAclConfigSchema` (input — all 3 fields optional) and
`ConnectedAccountAclConfigResponseSchema` (output — fields populated
when block visible). Per-list cap **1000 entries**, per-`userId` length
cap **1..256 chars** — matches Apollo's `aclConfig.ts`.
- Extended `CreateConnectedAccountLinkOptionsSchema` with `accountType`
+ `aclConfigForShared` (nested object).
- Extended `ConnectedAccountRetrieveResponseSchema` with `accountType` +
optional `aclConfigForShared` (`undefined` when caller can't see ACL —
distinguishes hidden-ACL from default-state).
- New `UpdateConnectedAccountAclParamsSchema`, refined to require ≥1
field (rejects no-op `{}`). Inline comment notes the ZodEffects `.shape`
quirk for future maintainers.

### Model (`models/ConnectedAccounts.ts`)
- `link(userId, authConfigId, options)` — forwards `accountType` and
serializes `aclConfigForShared` to the nested `acl_config_for_shared`
wire block via a new internal `serializeAclConfigForWire` helper.
Default behaviour (no options) creates a PRIVATE connection exactly as
today.
- **New** `updateAcl(nanoid, params)` — wraps
`client.connectedAccounts.patch` (PATCH `/connected_accounts/{id}`),
serialising flat camelCase params into the nested wire block. PATCH
semantics: omit a field to leave unchanged; pass `[]` to clear an
allow/deny list. JSDoc flags the empty-array footgun
(`notAllowedUserIds: []` silently re-grants previously-blocked users).
Returns `ConnectedAccountPatchResponse` to match sibling-method
ergonomics.
- Clarifying JSDoc on existing `update()` pointing readers at
`updateAcl()` for ACL and noting the historical "alias and/or
credentials" doc is inaccurate (separate cleanup PR).

### Model (`models/ToolRouterSession.ts`)
- `authorize(toolkit, options)` — options gain `accountType` +
`aclConfigForShared`. The `/tool_router/session/{session_id}/link`
endpoint accepts the same fields, so a SHARED connection with an ACL can
be created in one call from inside a tool-router session.

### Transformer (`utils/transformers/connectedAccounts.ts`)
- Maps `account_type` → `accountType`.
- Maps `acl_config_for_shared` (nested) → `aclConfigForShared` (nested
camelCase). Forwards `undefined` when the block is absent so callers can
distinguish *"I can't see the ACL"* (cookie caller, non-creator) from
*"ACL is the default deny-by-default state"*.

### Errors (`errors/ConnectedAccountsErrors.ts`)
- `ComposioAclOnlyForSharedError` (400) — **wired** at three call sites:
`link()`, `updateAcl()`, `ToolRouterSession.authorize()`. Substring
match on `'acl_config_for_shared is only valid on SHARED'` (verified
against Apollo's `createConnectedAccount.ts` in hermes#9902).
- `ComposioSharedAccessDeniedError` (403) — exported, **not yet wrapped
by SDK code**. Will be wrapped when `Tools.execute()`/direct-execute
error mapping lands in a follow-up. For now, callers seeing this from a
raw `BadRequestError`/`ForbiddenError` can match on message substring.
- `ComposioSharedConnectionNotAccessibleError` (400) — same status. Will
be wrapped when `ToolRouterSession.create()`/`update()`
session-validator error mapping lands.

### Tests (`test/connectedAccounts/connectedAccounts.test.ts`)
- 12 new behaviour tests covering `link()` ACL forwarding (5),
`updateAcl()` body construction + empty-object refine + AclOnlyForShared
mapping (6), and `link()` error-mapping fallback (1). 911 tests pass (up
from 899).

### Changeset
- `.changeset/connected-accounts-acl.md` — `@composio/core: minor`
(additive surface, no breaking changes), describes the nested shape and
resolution rule.

## Not implemented (deliberate scope cuts)

| Skipped | Why | Where it lands |
|---|---|---|
| **Python SDK mirror** | `composio-client@1.38.0` (from
[composio-base-py#66](https://github.com/ComposioHQ/composio-base-py/pull/66))
now exposes the same fields. Better as its own PR scoped to
`python/composio/` so Python's release cadence stays independent. |
Separate PR, same release train (called out in changeset). |
| **Docs cookbook entry** ("share a connection with specific users") |
Needs `@composio/core` to be published before the TS code samples can
`twoslash`-typecheck against the new methods. | Separate PR under
`docs/content/cookbooks/`. |
| **`docs/public/openapi*.json` spec refresh** | Auto-PR
[#3399](https://github.com/ComposioHQ/composio/pull/3399) already opened
against `next` with the post-9902 spec. | Mergeable independently from
this PR. |
| **`update()` → real PATCH endpoint** | Pre-existing — JSDoc says
"alias and/or credentials" but implementation calls `updateStatus`. The
new JSDoc explicitly disclaims it; the behaviour-change rewrite is
unrelated to ACL. | Separate cleanup PR. |
| **`ComposioSharedAccessDeniedError` +
`ComposioSharedConnectionNotAccessibleError` wiring** | Need to map at
`Tools.execute()` and `ToolRouterSession.create()`/`update()`/`patch()`.
Out of scope for a connected-accounts PR — the failure modes are in
different SDK touchpoints. Exported now so the public-API contract is
stable, JSDocs explicit about when they'll start being thrown. |
Follow-up PR scoped to execute/session error mapping. |
| **Internal link-session GET (hermes#9887)** | Endpoint is
`/api/v3/internal/...` and filtered out of the public spec by
`docs/scripts/fetch-openapi.mjs`. Dashboard UI consumes it, not the SDK.
| N/A — internal only. |
| **Cast tightening / shared wire-ACL fragment** (review P3-13, P3-14) |
Casts and local body types are gone (commit `483af3607`). Shared
fragment was already extracted as `AclConfigWireShape` in commit
`752efd886` — now removed since it lives in the generated types. | Done.
|
| **Duplicate-account guard extraction** (review P3-16) | Reviewer
explicitly says "parity-by-copy is fine for this PR" — `link()` and
`initiate()` share a 14-line guard. Extracting
`assertNoActiveConnections()` is mechanical and unrelated. | Follow-up.
|

## Commits

1.
[`84a3a074`](https://github.com/ComposioHQ/composio/pull/3392/commits/84a3a074b)
— initial draft against the flat-field shape described in 9902's PR
body.
2.
[`752efd88`](https://github.com/ComposioHQ/composio/pull/3392/commits/752efd886)
— reshape to the nested `aclConfigForShared` shape that actually merged
in 9902. Verified against `staging-backend.composio.dev`'s spec.
3.
[`483af3607`](https://github.com/ComposioHQ/composio/pull/3392/commits/483af3607)
— bump `@composio/client` to `0.1.0-alpha.71`, drop the three casts +
local body types, apply the 9 in-scope multi-agent review fixes, wire
`ComposioAclOnlyForSharedError` at three call sites, add 12 behaviour
tests.

## Test plan

- [x] `pnpm --filter @composio/core typecheck` — clean
- [x] `pnpm --filter @composio/core test` — 911/911 pass (12 new, 899
pre-existing)
- [x] `pnpm --filter @composio/core build` — `publint` + `attw` clean
- [x] Wire contract spot-checked against prod spec for all five
endpoints (POST link, POST connected_accounts, PATCH, GET single, GET
list, tool_router/session link)
- [x] All forward-compat casts removed; SDK now uses `LinkCreateParams`,
`ConnectedAccountPatchParams`, `SessionLinkParams` from the generated
client directly
- [ ] **Manual smoke (reviewer or merger):** create SHARED →
`updateAcl({ allowAllUsers: true, notAllowedUserIds: ['user_bob'] })` →
verify `get()` returns `aclConfigForShared` for creator, returns
`undefined` for non-creator.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-05-12 01:33:22 +05:30
2025-09-28 04:02:01 +05:30
2026-02-26 21:20:38 +04:00
2025-06-17 18:06:05 -07:00
2026-02-01 12:21:20 +04:00
2025-06-16 19:52:20 +05:30
2025-11-13 21:18:45 +05:30

Composio Logo

Composio SDK

Skills that evolve for your Agents

🌐 Website • 📚 Documentation

GitHub Stars PyPI Downloads NPM Downloads Discord

This repository contains the official Software Development Kits (SDKs) for Composio, providing seamless integration capabilities for Python and Typescript Agentic Frameworks and Libraries.

Getting Started

TypeScript SDK 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',
});

Simple Agent with OpenAI Agents

npm install @composio/openai-agents @openai/agents
import { Composio } from '@composio/core';
import { OpenAIAgentsProvider } from '@composio/openai-agents';
import { Agent, run } from '@openai/agents';

const composio = new Composio({
  provider: new OpenAIAgentsProvider(),
});

const userId = 'user@acme.org';

const tools = await composio.tools.get(userId, {
  toolkits: ['HACKERNEWS'],
});

const agent = new Agent({
  name: 'Hackernews assistant',
  tools: tools,
});

const result = await run(agent, 'What is the latest hackernews post about?');

console.log(JSON.stringify(result.finalOutput, null, 2));
// will return the response from the agent with data from HACKERNEWS API.

Python SDK Installation

# Using pip
pip install composio

# Using poetry
poetry add composio

Quick start:

from composio import Composio

composio = Composio(
  # api_key="your-api-key",
)

Simple Agent with OpenAI Agents

pip install composio_openai_agents openai-agents
import asyncio
from agents import Agent, Runner
from composio import Composio
from composio_openai_agents import OpenAIAgentsProvider

# Initialize Composio client with OpenAI Agents Provider
composio = Composio(provider=OpenAIAgentsProvider())

user_id = "user@acme.org"
tools = composio.tools.get(user_id=user_id, toolkits=["HACKERNEWS"])

# Create an agent with the tools
agent = Agent(
    name="Hackernews Agent",
    instructions="You are a helpful assistant.",
    tools=tools,
)

# Run the agent
async def main():
    result = await Runner.run(
        starting_agent=agent,
        input="What's the latest Hackernews post about?",
    )
    print(result.final_output)

asyncio.run(main())
# will return the response from the agent with data from HACKERNEWS API.

For more detailed usage instructions and examples, please refer to each SDK's specific documentation.

Open API Specification

To update the OpenAPI specifications used for generating SDK documentation:

# Pull the latest API specifications from the backend
pnpm api:pull

This command pulls the OpenAPI specification from https://backend.composio.dev/api/v3/openapi.json and updates the local API documentation files.

This is pulled automatically with build step.

Available SDKs

TypeScript SDK (/ts)

The TypeScript SDK provides a modern, type-safe way to interact with Composio's services. It's designed for both Node.js and browser environments, offering full TypeScript support with comprehensive type definitions.

For detailed information about the TypeScript SDK, please refer to the TypeScript SDK Documentation.

Python SDK (/python)

The Python SDK offers a Pythonic interface to Composio's services, making it easy to integrate Composio into your Python applications. It supports Python 3.10+ and follows modern Python development practices.

For detailed information about the Python SDK, please refer to the Python SDK Documentation.

Provider Support

The following table shows which AI frameworks and platforms are supported in each SDK:

Provider TypeScript Python
OpenAI ✅ ✅
OpenAI Agents ✅ ✅
Anthropic ✅ ✅
LangChain ✅ ✅
LangGraph ✅* ✅
LlamaIndex ✅ ✅
Vercel AI SDK ✅ ❌
Google Gemini ✅ ✅
Google ADK ❌ ✅
Mastra ✅ ❌
Cloudflare Workers AI ✅ ❌
CrewAI ❌ ✅
AutoGen ❌ ✅

* LangGraph in TypeScript is supported via the @composio/langchain package.

Don't see your provider? Learn how to build a custom provider to integrate with any AI framework.

Packages

Core Packages

Package Version
TypeScript
@composio/core npm version
Python
composio PyPI version

Provider Packages

Package Version
TypeScript
@composio/openai npm version
@composio/openai-agents npm version
@composio/anthropic npm version
@composio/langchain npm version
@composio/llamaindex npm version
@composio/vercel npm version
@composio/google npm version
@composio/mastra npm version
@composio/cloudflare npm version
Python
composio-openai PyPI version
composio-openai-agents PyPI version
composio-anthropic PyPI version
composio-langchain PyPI version
composio-langgraph PyPI version
composio-llamaindex PyPI version
composio-crewai PyPI version
composio-autogen PyPI version
composio-gemini PyPI version
composio-google PyPI version
composio-google-adk PyPI version

Utility Packages

Package Version
@composio/json-schema-to-zod npm version
@composio/ts-builders npm version

if you are looking for the older sdk, you can find them here

Rube

Rube is a Model Context Protocol (MCP) server built with Composio. It connects your AI tools to 500+ apps like Gmail, Slack, GitHub, and Notion. Simply install it in your AI client, authenticate once with your apps, and start asking your AI to perform real actions like "Send an email" or "Create a task."

It integrates with major AI clients like Cursor, Claude Desktop, VS Code, Claude Code and any custom MCP‑compatible client. You can switch between these clients and your integrations follow you.

Contributing

We welcome contributions to both SDKs! Please read our contribution guidelines before submitting pull requests.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

If you encounter any issues or have questions about the SDKs:

S
Description
Route and complete Composio work across Composio For You and Composio Platform. Use when the user mentions Composio; wants an agent to use apps such as Gmail,…
Readme 1.3 GiB
Languages
TypeScript 72.2%
Python 23.3%
Shell 2.1%
JavaScript 2%
Swift 0.4%