← Back to dashboard
open-aiaifresh

OpenAI + Claude Code Integration Guide

What is the OpenAI API?

The real model

Multi-modal stateless API with tools, structured outputs, and a realtime channel.

GPT-5 / GPT-4o / o-series live behind a single API. Use `response_format: { type: "json_schema", schema: ... }` for guaranteed-shape outputs — no Zod re-parsing. Tools are first-class: `tools: [{ type: "function", function: {...} }]` with parallel calls. The Realtime API streams bidirectional audio over WebRTC/WebSocket for voice agents. For multi-step jobs, the Assistants API gives you durable threads + file search. For codeAmani, OpenAI is the structured-output and function-calling specialist; Claude takes the harder reasoning.

Five OpenAI primitives

Same API surface across models. Pick the right tier and the right output mode.

Text
 ██████╗ ██████╗ ███████╗███╗   ██╗ █████╗ ██╗
██╔═══██╗██╔══██╗██╔════╝████╗  ██║██╔══██╗██║
██║   ██║██████╔╝█████╗  ██╔██╗ ██║███████║██║
██║   ██║██╔═══╝ ██╔══╝  ██║╚██╗██║██╔══██║██║
╚██████╔╝██║     ███████╗██║ ╚████║██║  ██║██║
 ╚═════╝ ╚═╝     ╚══════╝╚═╝  ╚═══╝╚═╝  ╚═╝╚═╝

OpenAI + Claude Code Integration Guide

Focus: Integrating OpenAI models and APIs alongside Claude Code workflows — dual-provider pipelines, MCP access to OpenAI assistants, and cross-model automation.

Overview

Claude Code and OpenAI are complementary. OpenAI's Assistants, Files, Fine-tuning, and Responses APIs can be consumed inside Claude Code via the openai SDK, or accessed through an MCP server that exposes OpenAI account resources as tools. This lets you build hybrid workflows — e.g., route code tasks to Claude, creative/vision tasks to GPT-4o, all from one Claude Code session.

Here is the simple mental model of where OpenAI sits as the secondary provider — reach for it when structured output or function calling matters, while Claude stays primary for reasoning.

Official Documentation


MCP Server Setup

openai-mcp — Access OpenAI Account via MCP

The openai-mcp server exposes your OpenAI account (models, assistants, files, threads, fine-tuning jobs) as MCP tools.

Bash
npm install -g openai-mcp

.mcp.json Configuration

JSON
{
  "mcpServers": {
    "openai": {
      "command": "npx",
      "args": ["-y", "openai-mcp"],
      "env": {
        "OPENAI_API_KEY": "${OPENAI_API_KEY}"
      }
    }
  }
}

Add via Claude Code CLI:

Bash
claude mcp add openai -- npx -y openai-mcp

Available MCP Tools

ToolDescription
list_modelsList all available OpenAI models
create_chat_completionCall any OpenAI chat model
list_assistantsList your Assistants
create_assistantCreate a new Assistant
upload_fileUpload a file to OpenAI Files API
list_filesList uploaded files
create_fine_tuning_jobStart a fine-tuning run
get_fine_tuning_jobCheck fine-tuning status

CLI Integration

OpenAI CLI (Python)

Bash
pip install openai
Bash
# List models
openai api models.list

# Create a chat completion
openai api chat.completions.create \
  -m gpt-4o \
  -g user "Explain this TypeScript error: ..."

# Check fine-tuning job
openai api fine_tuning.jobs.retrieve -i <job_id>

One-liner from Claude Code

Inside a Claude Code session you can run shell commands:

Bash
# Pipe Claude Code output to OpenAI for a second opinion
echo "Review this code for memory leaks" | openai api chat.completions.create -m gpt-4o -g user -

OpenAI SDK Integration

You are about to wire up the core request flow — here is how a chat completion travels from your app through the SDK to the model and back.

Node.js / TypeScript

Bash
npm install openai
TypeScript
import OpenAI from "openai";

const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

// GPT-4o chat completion
const completion = await client.chat.completions.create({
  model: "gpt-4o",
  messages: [
    { role: "system", content: "You are a TypeScript expert." },
    { role: "user", content: "Convert this class to use composition over inheritance." },
  ],
});

console.log(completion.choices[0].message.content);

Python

Bash
pip install openai
Python
from openai import OpenAI

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Generate unit tests for this function."}],
)
print(response.choices[0].message.content)

Structured output & function calling

This is the reason OpenAI earns its place as the secondary provider. When you need the model to return data your code can trust — not prose you have to regex — reach for Structured Outputs. The Node SDK ships a client.chat.completions.parse() helper plus two Zod adapters from openai/helpers/zod: zodResponseFormat() constrains the whole response to a schema, and zodFunction() does the same for a tool's arguments. With strict: true (which zodFunction() sets for you), the model is guaranteed to emit JSON that matches your schema, and the SDK hands you a fully typed parsed object — no JSON.parse, no validation boilerplate.

Here is the flow: you define a Zod schema, the SDK ships it as a strict JSON schema, the model is constrained to match, and you get a typed object back.

(a) Structured output via a Zod schema

Use this when you want the model's answer shaped to a schema — extraction, classification, form-filling. The parsed field is typed as z.infer<typeof Schema>.

TypeScript
import OpenAI from "openai";
import { zodResponseFormat } from "openai/helpers/zod";
import { z } from "zod";

const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

// e.g. extract structured order data from a free-text M-Pesa SMS
const OrderExtraction = z.object({
  amount_kes: z.number().int(),       // Daraja amounts are integer KES
  phone: z.string(),                   // normalise to 254XXXXXXXXX downstream
  reference: z.string(),
  confidence: z.enum(["high", "medium", "low"]),
});

const completion = await client.chat.completions.parse({
  model: "gpt-4o-2024-08-06",
  messages: [
    { role: "system", content: "Extract the payment fields from the message." },
    { role: "user", content: "Got KES 1500 from 0712345678 ref INV-204" },
  ],
  response_format: zodResponseFormat(OrderExtraction, "order_extraction"),
});

const order = completion.choices[0].message.parsed;
if (order) {
  console.log(order.amount_kes, order.phone, order.confidence); // fully typed
}

(b) Tool / function call

Use this when you want the model to decide which function to call and with what arguments. zodFunction() builds the tool definition (with strict: true), and the parsed arguments arrive on tool_calls[].function.parsed_arguments.

TypeScript
import OpenAI from "openai";
import { zodFunction } from "openai/helpers/zod";
import { z } from "zod";

const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

const StkPushArgs = z.object({
  amount_kes: z.number().int(),
  phone: z.string(),
  account_ref: z.string(),
});

const completion = await client.chat.completions.parse({
  model: "gpt-4o-2024-08-06",
  messages: [
    { role: "user", content: "Charge 0712345678 KES 500 for order INV-9" },
  ],
  tools: [zodFunction({ name: "initiate_stk_push", parameters: StkPushArgs })],
});

const toolCall = completion.choices[0].message.tool_calls?.[0];
if (toolCall) {
  const args = toolCall.function.parsed_arguments as z.infer<typeof StkPushArgs>;
  // now call your real lib/mpesa-stk.ts with typed, schema-validated args
  console.log(args.amount_kes, args.phone, args.account_ref);
}

Gotcha: Structured Outputs requires a recent snapshot — use gpt-4o-2024-08-06 or newer (not the older gpt-4o-2024-05-13), or the request will error. Also, every field in a strict schema is required by default; to make a field optional, model it as z.union([T, z.null()]) (a nullable field) rather than .optional(), since strict mode does not allow omitted keys.


Environment Variables

Bash
# Required
OPENAI_API_KEY=sk-proj-...

# Optional
OPENAI_ORG_ID=org-...
OPENAI_PROJECT_ID=proj_...
OPENAI_BASE_URL=https://api.openai.com/v1    # default; change for Azure OpenAI

Store in .env and load with dotenv or python-dotenv.


Automation Workflows

Dual-Provider Review Hook

Use a Claude Code Stop hook to send the session summary to OpenAI for a cross-model review:

.claude/settings.json:

JSON
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "node scripts/openai-second-opinion.js"
          }
        ]
      }
    ]
  }
}

scripts/openai-second-opinion.js:

JavaScript
import OpenAI from "openai";
import { readFileSync } from "fs";

const client = new OpenAI();
const sessionLog = readFileSync(".claude/session.log", "utf-8");

const result = await client.chat.completions.create({
  model: "gpt-4o",
  messages: [
    { role: "system", content: "Review this Claude Code session for potential issues." },
    { role: "user", content: sessionLog },
  ],
});

console.log("GPT-4o review:", result.choices[0].message.content);

Slash Command: Route to GPT-4o

.claude/commands/gpt.md:

Markdown
Use the Bash tool to call OpenAI's GPT-4o API with this prompt: $ARGUMENTS

Command:
```bash
curl https://api.openai.com/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-4o","messages":[{"role":"user","content":"'"$ARGUMENTS"'"}]}'
Text

Usage: `/project:gpt "What are the tradeoffs of this architecture?"`

### CI/CD: OpenAI Code Quality Gate

```yaml
# .github/workflows/ai-review.yml
name: AI Code Review
on: [pull_request]

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Get diff
        run: git diff origin/main...HEAD > diff.txt
      - name: OpenAI review
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          pip install openai
          python scripts/review.py diff.txt

Common Use Cases

Use CaseApproach
Vision-based UI reviewSend screenshots to GPT-4o via Files API
Embeddings for code searchtext-embedding-3-small on your codebase
Fine-tuning for styleTrain GPT-4o-mini on your code patterns
Assistants for long tasksUse Assistants API with file_search tool
Cross-model validationClaude drafts, GPT-4o validates

Troubleshooting

IssueFix
openai-mcp not foundRun npm install -g openai-mcp first
401 UnauthorizedCheck OPENAI_API_KEY value and project permissions
Model not availableCheck model access in platform.openai.com/settings
Rate limitsUse exponential backoff; check tier limits
Azure OpenAI endpointSet OPENAI_BASE_URL=https://<resource>.openai.azure.com