---
title: OpenAI
description: Drive Pictograph from the OpenAI SDK or the openai-agents framework.
section: Agents
order: 2
---
Toolkit setup and guardrails live on [Agents — overview](/docs/agents.md). This page shows the two OpenAI-specific integration paths.

## Path 1: OpenAI SDK (raw function tools)

No extra dependencies — works with the standard `openai` package.

```python
import json
from openai import OpenAI
from pictograph.agents import create_toolkit, for_openai_responses

toolkit = create_toolkit()
tools = for_openai_responses(toolkit)
client = OpenAI()

input_messages = [
    {"role": "user", "content": "Show my Pictograph credit balance and recent training runs"},
]

while True:
    response = client.responses.create(
        model="gpt-5",
        input=input_messages,
        tools=tools,
    )

    function_calls = [o for o in response.output if o.type == "function_call"]
    if not function_calls:
        print(response.output_text)
        break

    for call in function_calls:
        result = toolkit.dispatch(call.name, json.loads(call.arguments))
        input_messages.append(call)
        input_messages.append({
            "type": "function_call_output",
            "call_id": call.call_id,
            "output": json.dumps(result, default=str),
        })
```

`toolkit.dispatch(name, args)` is the same dispatcher used by the Anthropic path — single source of truth.

## Path 2: openai-agents SDK

The framework manages the tool-call loop, streaming, handoffs, and tracing. Requires the extra:

```bash
pip install 'pictograph[agents]'
```

```python
from agents import Agent, Runner
from pictograph.agents import create_toolkit, for_openai_agents

toolkit = create_toolkit()
agent_tools = for_openai_agents(toolkit)

agent = Agent(
    name="Pictograph driver",
    instructions=(
        "Drive Pictograph for the user. Confirm destructive operations. "
        "Prefer the workflow tools (full_pipeline, train_pipeline) over "
        "chaining individual resource tools."
    ),
    tools=agent_tools,
)

result = Runner.run_sync(
    agent,
    "Annotate ./road_signs as cars and people, then train a YOLOX model",
)
print(result.final_output)
```

Streaming:

```python
result = await Runner.run(agent, user_input)
async for event in result.stream_events():
    if event.type == "raw_response_event":
        print(event.data, end="", flush=True)
```

## Picking between paths

| Path 1 (raw dicts) | Path 2 (openai-agents) |
| --- | --- |
| You already call `responses.create()` directly | You want multi-turn conversations with built-in dispatch |
| You need a custom dispatch loop | You need agent handoffs |
| You don't want the `openai-agents` dependency | You want tracing + replay + structured outputs |

## See also

- [Agents](/docs/agents.md) — toolkit setup, guardrails, and the registry
- [Cookbook](/docs/agents/cookbook.md) — recipe-style examples
- [Dynamic discovery](/docs/agents/dynamic-discovery.md) — for Vercel AI SDK, LangChain, and other stacks