OpenAI

The OpenAI provider formats Composio tools for OpenAI's function-calling and executes the tool calls the model returns. It works three ways:

  • The Responses API, the recommended way to build agentic flows, where you run the tool-call loop yourself.
  • The Chat Completions API, the classic message-based interface, where you also run the loop.
  • The Agents SDK, where the SDK runs the loop and executes Composio tools for you.

The OpenAI provider is the default provider for the Composio SDK, so you get it without configuring anything. Pick the tab that matches your integration.

The OpenAIResponsesProvider transforms Composio tools into OpenAI's function-calling format for the Responses API, then executes the tool calls the model returns and shapes the results into function_call_output items you feed back in.

Install

pip install composio composio_openai openai
npm install @composio/core @composio/openai openai

Configure API Keys

Set COMPOSIO_API_KEY with your API key from Settings and OPENAI_API_KEY with your OpenAI API key.

.env
COMPOSIO_API_KEY=xxxxxxxxx
OPENAI_API_KEY=xxxxxxxxx

Create session and run

The Responses API is the recommended way to build agentic flows with OpenAI. You pass previous_response_id on each turn so the model keeps the prior context, and you send back only the new function_call_output items.

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, user_id="user_123")
    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)
import OpenAI from 'openai';
import { Composio } from '@composio/core';
import { OpenAIResponsesProvider } from '@composio/openai';

const composio = new Composio({
    provider: new OpenAIResponsesProvider(),
});
const client = new OpenAI();

// Create a session for your user
const session = await composio.create("user_123");
const tools = await session.tools();

let response = await 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) {
    const toolCalls = response.output.filter((o) => o.type === "function_call");
    if (toolCalls.length === 0) break;

    const results = await composio.provider.handleToolCalls("user_123", response.output);
    response = await client.responses.create({
        model: "gpt-5.2",
        tools: tools,
        previous_response_id: response.id,
        input: results.map((result, i) => ({
            type: "function_call_output" as const,
            call_id: toolCalls[i].call_id,
            output: JSON.stringify(result),
        })),
    });
}

// Print final response
for (const item of response.output) {
    if (item.type === "message") {
        const block = item.content[0];
        if (block.type === "output_text") {
            console.log(block.text);
        }
    }
}

Provider specifics

The OpenAI integration ships three providers, one per API surface:

  • OpenAIResponsesProvider for the Responses API. handleToolCalls executes the tool calls and returns function_call_output items keyed by call_id. You pair it with previous_response_id so you only resend new outputs each turn.
  • OpenAIProvider for the Chat Completions API. This is the SDK default, so new Composio() with no provider uses it. You keep the full message list and append each assistant message plus its tool results yourself.
  • OpenAIAgentsProvider for the Agents SDK. Tools come with execution wired in, so the SDK runs the loop and you do not call handleToolCalls at all.

Use the Responses or Agents provider for new agentic flows; reach for Chat Completions when you are extending an existing Chat Completions codebase.

Next

What is a session?

How sessions scope users, tools, and auth, and how to reuse them across requests.