OpenAI SDK (Agents)
Overview
Integrate Civic with the OpenAI Agents SDK using hostedMcpTool() — the simplest way to use Civic with OpenAI. No manual tool looping or schema conversion required.
For the older manual function calling approach, see OpenAI SDK (Node.js).
Prerequisites
- Civic account at app.civic.com with at least one MCP server connected
- OpenAI API key from platform.openai.com
Installation
npm install @openai/agents
The openai package is bundled as a dependency — no need to install it separately.
Authentication
For autonomous agents and server-side scripts — use a Civic token directly.
Generate a Civic Token
- Log in to app.civic.com
- Click your account name in the bottom left
- Go to Install → MCP URL
- Click Generate Token and copy it immediately — it won't be shown again
Never commit your token to source control. Store it in environment variables or a secrets manager. Tokens expire after 30 days.
Set Environment Variables
CIVIC_TOKEN=your-civic-token-here
CIVIC_URL=https://app.civic.com/hub/mcp
For production agents, lock to a specific toolkit by appending a profile parameter:
CIVIC_URL=https://app.civic.com/hub/mcp?profile=your-toolkit-alias
Use the Token
Pass the token as a Bearer token in the Authorization header:
headers = {"Authorization": f"Bearer {os.environ['CIVIC_TOKEN']}"}
headers: { Authorization: `Bearer ${process.env.CIVIC_TOKEN}` }
Token generation, URL parameters, OAuth vs token comparison
# .env
OPENAI_API_KEY=your_openai_api_key
CIVIC_TOKEN=your-civic-token-here
CIVIC_URL=https://app.civic.com/hub/mcp
For web apps where each user has their own Civic session.
Install the additional auth package:
npm install @civic/auth
Why Civic Auth? Civic needs to identify which user is accessing tools and authorize their permissions. Civic Auth provides the secure access token. (Support for additional identity providers coming soon.)
import { createCivicAuthPlugin } from "@civic/auth/nextjs"
import type { NextConfig } from "next";
const nextConfig: NextConfig = {};
const withCivicAuth = createCivicAuthPlugin({ clientId: "YOUR_CLIENT_ID" });
export default withCivicAuth(nextConfig)
File: src/app/api/auth/[...civicauth]/route.ts
import { handler } from "@civic/auth/nextjs"
export const GET = handler()
export const POST = handler()
File: src/middleware.ts
import { authMiddleware } from "@civic/auth/nextjs/middleware"
export default authMiddleware();
export const config = { matcher: ['/((?!_next|favicon.ico|.*\\.png).*)',] };
import { getTokens } from "@civic/auth/nextjs";
const { accessToken } = await getTokens();
// Use in headers:
headers: { Authorization: `Bearer ${accessToken}` }
Complete Next.js setup with frontend components, configuration options, and deployment details
Use Claude, ChatGPT, or other AI assistants to automatically set up Civic Auth
Get your Client ID at auth.civic.com
# .env.local
OPENAI_API_KEY=your_openai_api_key
CIVIC_AUTH_CLIENT_ID=your_client_id # from auth.civic.com
Basic Setup
import { Agent, hostedMcpTool, run } from '@openai/agents';
const agent = new Agent({
name: 'Civic Assistant',
model: 'gpt-4o-mini',
instructions: 'You are a helpful assistant with access to external tools through Civic.',
tools: [
hostedMcpTool({
serverLabel: 'civic',
serverUrl: process.env.CIVIC_URL!,
authorization: process.env.CIVIC_TOKEN!, // plain token string
}),
],
});
async function main() {
const result = await run(agent, 'List my GitHub repositories');
console.log(result.finalOutput); // the agent's final text response
}
main().catch(console.error);
// app/api/agent/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { Agent, hostedMcpTool, run } from '@openai/agents';
import { getTokens } from '@civic/auth/nextjs';
export async function POST(req: NextRequest) {
const { message } = await req.json();
const { accessToken } = await getTokens();
// getTokens() exchanges the user's Civic Auth session for a hub access token
if (!accessToken) {
return NextResponse.json({ error: 'Not authenticated' }, { status: 401 });
}
const agent = new Agent({
name: 'Civic Assistant',
model: 'gpt-4o-mini',
instructions: 'You are a helpful assistant with access to external tools through Civic.',
tools: [
hostedMcpTool({
serverLabel: 'civic',
serverUrl: 'https://app.civic.com/hub/mcp',
authorization: accessToken, // plain token string
}),
],
});
const result = await run(agent, message);
return NextResponse.json({ response: result.finalOutput });
}
The Agent automatically discovers available Civic tools, selects the right one, calls it, and returns the result.
Streaming
const result = await run(agent, 'Your question here?', { stream: true });
for await (const event of result) {
if (event.type === 'response.output_text.delta') {
process.stdout.write(event.delta);
}
}
console.log(`Final result: ${result.finalOutput}`);
Tool Approval
Control which tools require human approval before execution:
hostedMcpTool({
serverLabel: 'civic',
serverUrl: process.env.CIVIC_URL!,
authorization: process.env.CIVIC_TOKEN!,
requireApproval: {
never: { toolNames: ['github__list_repos', 'slack__search_messages'] },
always: { toolNames: ['github__delete_repo'] },
}
})