docs/content/cookbooks/fast-api.mdx
This cookbook builds a FastAPI server where users can chat with an AI agent that has access to over 1000 tools like Gmail, GitHub, Slack, Notion, and more. Along the way we'll add endpoints to manage which apps a user has connected.
Create a new project and install dependencies:
mkdir composio-fastapi && cd composio-fastapi
uv init && uv add composio composio-openai-agents openai-agents fastapi uvicorn pydantic
Add your API keys to a .env file:
COMPOSIO_API_KEY=your_composio_api_key
OPENAI_API_KEY=your_openai_api_key
Composio takes an OpenAIAgentsProvider so that when we ask for tools later, they come back in the format the OpenAI Agents SDK expects.
<include>../../examples/fast-api/main.py#setup</include>
The core of the server is a /chat endpoint. A user sends a message, and the agent responds, using whatever tools it needs.
composio.create() creates a session scoped to a user. Calling session.tools() returns a set of meta tools that let the agent discover tools across all apps, handle OAuth when needed, and execute actions. We pass these to an Agent and let Runner.run_sync handle the agentic loop.
<include>../../examples/fast-api/main.py#chat</include>
<Callout> If the user hasn't connected the app they're trying to use, the agent will automatically return an authentication link in its response. The user can complete OAuth and then retry. </Callout>That's a working agent. But in most apps you'll also want to manage connections outside of chat, for example to show users what's connected or let them connect new apps from a settings page.
session.toolkits() returns every toolkit in the session along with its connection status. We can expose this as a simple GET endpoint so your frontend can render a connections UI.
<include>../../examples/fast-api/main.py#list-connections</include>
If you just need to check a single toolkit, say before kicking off a workflow that requires Gmail, you can scope the session to that toolkit:
<include>../../examples/fast-api/main.py#check-connection</include>
When a user wants to connect a new app, session.authorize() starts the OAuth flow and returns a redirect URL. Your frontend sends the user there, and once they complete auth, they're connected.
<include>../../examples/fast-api/main.py#connect</include>
Here's everything together:
<include>../../examples/fast-api/main.py</include>
uv run --env-file .env uvicorn main:app --reload
The server runs at http://localhost:8000. Visit /docs for the interactive Swagger UI.
curl -X POST http://localhost:8000/chat \
-H "Content-Type: application/json" \
-d '{"user_id": "user_123", "message": "Star the composiohq/composio repo on GitHub"}'
curl http://localhost:8000/connections/user_123
curl http://localhost:8000/connections/user_123/gmail
curl -X POST http://localhost:8000/connect/gmail \
-H "Content-Type: application/json" \
-d '{"user_id": "user_123"}'
Open the redirect_url from the response in your browser to complete OAuth.