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 openainpm install @composio/core @composio/openai openaiConfigure API Keys
Set COMPOSIO_API_KEY with your API key from Settings and OPENAI_API_KEY with your OpenAI API key.
COMPOSIO_API_KEY=xxxxxxxxx
OPENAI_API_KEY=xxxxxxxxxCreate 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:
OpenAIResponsesProviderfor the Responses API.handleToolCallsexecutes the tool calls and returnsfunction_call_outputitems keyed bycall_id. You pair it withprevious_response_idso you only resend new outputs each turn.OpenAIProviderfor the Chat Completions API. This is the SDK default, sonew Composio()with no provider uses it. You keep the full message list and append each assistant message plus itstoolresults yourself.OpenAIAgentsProviderfor the Agents SDK. Tools come with execution wired in, so the SDK runs the loop and you do not callhandleToolCallsat 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.