Metadata-Version: 2.5
Name: composio-client
Version: 2.0.0-rc.19
Summary: The official Python library for the Composio API, generated from the v3.1 OpenAPI spec with hey-api
Project-URL: Homepage, https://github.com/ComposioHQ/composio-client
Project-URL: Repository, https://github.com/ComposioHQ/composio-client
Author: Composio
License-Expression: Apache-2.0
Keywords: api,client,composio,tool_router
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic<3,>=2.9
Requires-Dist: typing-extensions>=4.12
Provides-Extra: aiohttp
Requires-Dist: aiohttp; extra == 'aiohttp'
Requires-Dist: httpx-aiohttp>=0.1.9; extra == 'aiohttp'
Description-Content-Type: text/markdown

# composio-client for Python

`composio-client` replaces the Stainless-generated package without requiring you to rewrite existing
`1.43.x` calls.

```python
from composio_client import Composio, ProjectAuth

client = Composio(auth=ProjectAuth("ak_..."))

session = client.tool_router.session.create(user_id="user@example.com")
result = client.tool_router.session.execute(
    session.session_id,
    tool_slug="GITHUB_CREATE_ISSUE",
    arguments={"owner": "composiohq", "repo": "composio", "title": "Example"},
)
```

The owned client preserves the public Python contract from `composio-client==1.43.0` and adds the
rest of the v3.1 API. You get all 113 operations, including the 64 operations published by
Stainless and 49 additive operations generated from the checked-in OpenAPI document.

The September 2026 schema adds `client.session_configs.list()` and
`client.session_configs.retrieve(id)`, premium usage settings, workbench tool-execution
controls, and trigger egress overrides. Generated public request and response types
include new fields while retaining existing Stainless declarations.

## Install the client

```bash
pip install composio-client
```

With `uv`:

```bash
uv add composio-client
```

## Authenticate and scope the client

`auth` is required and says which Composio credential the client sends:

| `auth` | Sends |
| --- | --- |
| `NoAuth()` | No Composio credential. `x-api-key` and its siblings are then ordinary headers you may set |
| `ProjectAuth(key)` | `x-api-key` on every request |
| `UserAuth(key)` | `x-user-api-key` on every request |
| `OrganizationAuth(key)` | `x-org-api-key` on every request |
| `AutoAuth(project=, user=, organization=)` | One of the configured keys per operation, chosen from the operation's declared security schemes, falling back to the project key |

A fixed mode never consults the operation table. A request carries at most one credential, and
only to the configured API origin.

A credential is a key or a function returning one. The function is called once per logical call
and its key is reused across that call's retries and same-origin redirects. `AsyncComposio` also
accepts an `async` function:

```python
client = Composio(auth=UserAuth(lambda: vault.read("composio-user-key")))
```

`scope` routes every request to an organization, a project, or both, sent as `x-org-id` and
`x-project-id`:

```python
from composio_client import Composio, Scope, UserAuth

client = Composio(auth=UserAuth("uak_..."), scope=Scope(organization_id="org_...", project_id="pr_..."))
```

A header a configured owner writes cannot also come through generic headers: with `auth` other
than `NoAuth()`, `x-api-key`, `x-user-api-key` and `x-org-api-key` are refused in
`default_headers`, `COMPOSIO_CUSTOM_HEADERS`, a raw call's `headers=` and `request_options`
headers; with `scope` set, so are `x-org-id` and `x-project-id`. Use `with_options(auth=...)` or
`with_options(scope=...)` to derive a client that sends something else. `with_options` re-runs every
constructor check; `scope=None` there clears the scope.

The few operations that declare `x-user-api-key` or `x-org-id` as a parameter (for example
`client.org.consumer.project.resolve(x_user_api_key=..., x_org_id=...)`) keep their keywords. The
key you pass replaces the configured `auth` for that call, and an `x_org_id` that disagrees with the
configured `scope` fails before anything is sent.

`client.auth_mode` and `client.scope` say how a client is configured. No attribute reads a
credential back; keep your own copy of a key you need.

## Configure from the environment

The constructor reads nothing from the process. `from_env` reads the mapping you hand it:

```python
import os

client = Composio.from_env(os.environ, environment="staging")
```

| Variable | Becomes |
| --- | --- |
| `COMPOSIO_API_KEY`, `COMPOSIO_USER_API_KEY`, `COMPOSIO_ORG_API_KEY` | `auth`: one set is that fixed mode, several are `AutoAuth`, none is `NoAuth()` |
| `COMPOSIO_BASE_URL` | `base_url` |
| `COMPOSIO_CUSTOM_HEADERS` | `default_headers`, held to the reserved-header rule |
| `COMPOSIO_ORG_ID`, `COMPOSIO_PROJECT_ID` | Not read: `scope` is always an explicit argument |

A keyword argument replaces the whole field it names: `auth=NoAuth()` means no credential whatever
the mapping holds, and `default_headers=` replaces `COMPOSIO_CUSTOM_HEADERS` rather than merging
into it.

## Identify the calling product

A product built on the client passes a `ClientIdentity` instead of setting headers by hand:

```python
from composio_client import ClientIdentity, Composio, ProjectAuth

client = Composio(
    auth=ProjectAuth("ak_..."),
    identity=ClientIdentity(product="composio", version="0.9.0", source="PYTHON_SDK", framework="openai"),
)
```

`product` and `version` are sent as `x-client-provenance` and `x-client-version` (`version` also
as `x-sdk-version`); `source`, `framework` and `runtime` as `x-source`, `x-framework` and
`x-runtime`. The library headers (`x-client-library`, `x-client-library-version`,
`x-client-language`) are the package's own and are refused in `default_headers`,
`COMPOSIO_CUSTOM_HEADERS` and `request_options` headers; once `identity` is set, so is every
identity header. A refused name raises `ComposioError`. `ClientIdentity` is frozen and validates
that every value is non-empty printable ASCII.

## Use the async client

```python
import asyncio

from composio_client import AsyncComposio, ProjectAuth


async def main() -> None:
    async with AsyncComposio(auth=ProjectAuth("ak_...")) as client:
        session = await client.tool_router.session.create(user_id="user@example.com")
        print(session.session_id)


asyncio.run(main())
```

## Read raw response metadata

Every released resource keeps the Stainless raw and streaming accessors:

```python
from composio_client import Composio, ProjectAuth

client = Composio(auth=ProjectAuth("ak_..."))

response = client.tool_router.session.with_raw_response.retrieve("sess_123")
print(response.status_code)
session = response.parse()

with client.tool_router.session.with_streaming_response.retrieve("sess_123") as response:
    print(response.headers)
```

The async resource exposes the corresponding async response objects and context managers.

## Handle API errors

The exception hierarchy matches the Stainless package. Existing `except` blocks keep working:

```python
from composio_client import Composio, NotFoundError, ProjectAuth

client = Composio(auth=ProjectAuth("ak_..."))

try:
    client.tool_router.session.retrieve("missing")
except NotFoundError as error:
    print(error.status_code)
```

## Migrate pre-release owned-client calls

Earlier owned-client builds accepted aggregate `body`, `query`, and `headers` values. Those calls
remain valid during the transition:

```python
client.tool_router.session.create({"user_id": "user@example.com"})
client.tool_router.session.config_history("sess_123", query={"limit": 25})
```

Prefer the flat Stainless form in new code:

```python
client.tool_router.session.create(user_id="user@example.com")
client.tool_router.session.config_history("sess_123", limit=25)
```

See [the Python migration guide](./MIGRATION.md) for compatibility details and the stricter credential
transport rules.

### Removed in 2.0.0-rc.19

The TypeScript twins are in the root README. On this side the Stainless compatibility check carves
out `default_query` and `set_default_query` by name (`scripts/check_stainless_compatibility.py`).

| Removed | Migration |
| --- | --- |
| `Composio(default_query=...)`, `copy`/`with_options(default_query=..., set_default_query=...)` | None: generated methods own their query, and the raw methods (`get`, `post`, ...) take `query=` |
| `client.default_query` | None |
| `client.api_key`, `user_api_key`, `org_api_key` (read-only since rc.18) | Keep your own copy of the key; `client.auth_mode` says which mode is configured |
| Assigning `client.base_url`, `max_retries` or `timeout` | `client.with_options(...)`, which re-runs every validation. The three stay readable |

`environment=` stays, as sugar over `base_url`.

### Removed in 2.0.0-rc.18

Each row is a deliberate removal of this release. The TypeScript twins are declared in
`packages/codegen/assignability-ledger.json`; on this side the Stainless compatibility check carves
out the `api_key` keyword by name (`scripts/check_stainless_compatibility.py`).

| Removed | Migration |
| --- | --- |
| `Composio(api_key=k)` | `Composio(auth=ProjectAuth(k))` |
| `Composio(user_api_key=k)`, `Composio(org_api_key=k)` | `auth=UserAuth(k)`, `auth=OrganizationAuth(k)` |
| Several of `api_key`, `user_api_key`, `org_api_key` together | `auth=AutoAuth(project=..., user=..., organization=...)`, today's per-operation selection |
| No credential at all (`api_key=None`) | `auth=NoAuth()` |
| `x-user-api-key`, `x-org-api-key` (and an `x-api-key` override) in `default_headers` while a key is configured | `auth`; generic credential headers are allowed only under `NoAuth()` |
| `x-org-id`, `x-project-id` in `default_headers` | `scope=Scope(organization_id=..., project_id=...)` (allowed as plain headers only while `scope` is unset) |
| The constructor reading `COMPOSIO_API_KEY`, `COMPOSIO_USER_API_KEY`, `COMPOSIO_ORG_API_KEY`, `COMPOSIO_BASE_URL` and `COMPOSIO_CUSTOM_HEADERS` from `os.environ` | `Composio.from_env(os.environ)` |
| `from_env(..., api_key=None)` | `from_env(..., auth=NoAuth())`; and `default_headers=` there now replaces `COMPOSIO_CUSTOM_HEADERS` instead of merging |
| `copy(api_key=k)` / `with_options(api_key=k)` | `with_options(auth=ProjectAuth(k))` |
| Assigning `client.api_key` (or `user_api_key`, `org_api_key`) | `client.with_options(auth=...)`; the three read back until 2.0.0-rc.19 |

## Develop the Python package

Generate from the repository root:

```bash
pnpm generate:python
pnpm codegen:check
```

Run Python checks from `python/`:

```bash
uv run ruff check
uv run ruff format --check
uv run mypy src scripts
uv run pytest
uv run python scripts/check_stainless_compatibility.py
uv build
uv run python scripts/check_stainless_compatibility.py --wheel dist/*.whl
```

The normal compatibility check is offline. It reads the committed `1.43.0` fixture and does not
install or call the Stainless client.
