Files
Alberto Schiabel 62e51e838f chore(deps): refresh safe dependencies and Effect v4 (#4538)
## Summary

Refreshes the safe TypeScript, Python, and GitHub Actions dependency
surface in one maintainer-owned change. Effect 4 rc.115, Vitest 5, the
vendored Effect source, CLI migrations, and agent guidance move
together, while known incompatible boundaries stay pinned. The Effect v4
config schemas preserve unknown fields across `config.json` and
`user_data.json` read-update-write cycles.

Fixes #4535

## Changes

- Keeps Cloudflare Workers fixtures on Vitest 4 until
`@cloudflare/vitest-pool-workers` supports Vitest 5.
- Keeps Mastra on the Workers-compatible versions and AG2 below 1.0
because AG2 1.x no longer ships the imported `autogen` module.
- Removes the unused package-level `pnpm` dependency instead of changing
the repository's pinned pnpm 11 toolchain.
- Migrates the Effect CLI APIs, Eve callback contract, provider peer
ranges, and repository skills required by the selected upgrades.
- Preserves unknown CLI settings when `config.json` and `user_data.json`
are read, updated, and written back.
- Uses immutable SHA pins for the refreshed Claude Code actions and adds
release metadata for the affected published TypeScript packages.

## Type of change

- [x] Bug fix
- [ ] New feature
- [x] Refactor/Chore
- [x] Documentation
- [ ] Breaking change

## How Has This Been Tested?

- `pnpm install --frozen-lockfile` with pnpm 11.8.0
- `pnpm typecheck`
- `pnpm build:packages`
- `pnpm --filter @composio/cli test` — 1,400 passed, 1 skipped,
including targeted persistence regressions for `config.json` and
`user_data.json`
- Package tests — 28 workspace tasks passed
- Example typechecks/tests and all Cloudflare dry-runs
- Provider compatibility, experimental/Eve, Mastra, CLI keyring, and
JSON-schema Effect checks
- Agent-skill validation, routing validation, Effect skill example
compilation, and peer-dependency checks
- All three Python `uv lock --check` runs
- `nox -s tst_autogen`, `nox -s snt`, and `nox -s chk type_inference`
- Production dependency audit completed with the repository's three
existing ignored advisories

Docker CLI E2E was not run locally because the Docker daemon is
unavailable. The exact root lint command also enters the vendored Effect
submodule, whose checkout does not install its `@effect/oxc/oxlint`
plugin; scoped lint over the changed non-vendor files passed.

## Screenshots (if applicable)

Not applicable.

## Checklist

- [x] I have read the Code of Conduct and this PR adheres to it
- [ ] I ran linters/tests locally and they passed
- [x] I updated documentation as needed
- [x] I added tests or explain why not applicable
- [x] I added a changeset if this change affects published packages

The dependency migrations are covered by the focused and workspace
suites. Two targeted regression tests verify that CLI updates preserve
unknown fields in `config.json` and `user_data.json`.

## Additional context

The Connect client sync retains its existing `Bash(curl *)` permission
while moving the removed `allowed_tools` input to `claude_args`. A
separate hardening change should move logo downloads outside the
model-controlled shell boundary.

---

[![Compound
Engineering](https://img.shields.io/badge/Built_with-Compound_Engineering-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)
2026-09-21 15:23:42 +04:00
..
2025-06-25 09:45:29 +05:30

composio-openai

Adapts Composio tools to OpenAI function calling, for both the Responses API and the Chat Completions API.

Installation

pip install composio composio-openai openai

Set COMPOSIO_API_KEY (create one at https://dashboard.composio.dev/settings) and OPENAI_API_KEY in your environment.

Quickstart

This package exports two providers: OpenAIResponsesProvider for the Responses API and OpenAIProvider for Chat Completions. Both are non-agentic: the model returns tool calls, you execute them with handle_tool_calls, and you feed the results back.

import json
from openai import OpenAI
from composio import Composio
from composio_openai import OpenAIResponsesProvider

composio = Composio(provider=OpenAIResponsesProvider())
client = OpenAI()

# Create a session for your user
session = composio.create(user_id="user_123")
tools = session.tools()

response = client.responses.create(
    model="gpt-5.2",
    tools=tools,
    input=[
        {
            "role": "user",
            "content": "Send an email to john@example.com with the subject 'Hello' and body 'Hello from Composio!'"
        }
    ]
)

# Agentic loop: keep executing tool calls until the model responds with text
while True:
    tool_calls = [o for o in response.output if o.type == "function_call"]
    if not tool_calls:
        break
    results = composio.provider.handle_tool_calls(response=response, session=session)
    response = client.responses.create(
        model="gpt-5.2",
        tools=tools,
        previous_response_id=response.id,
        input=[
            {"type": "function_call_output", "call_id": tool_calls[i].call_id, "output": json.dumps(result)}
            for i, result in enumerate(results)
        ]
    )

# Print final response
for item in response.output:
    if item.type == "message":
        print(item.content[0].text)

Chat Completions

OpenAIProvider targets client.chat.completions.create and is the Composio SDK default, so Composio() with no provider uses it. The loop is the same shape: call handle_tool_calls(response=response, session=session), append the results as tool messages, and call the API again. Pass user_id instead for tools fetched with tools.get(). See the docs page for the full example.