Sign in Get started

OpenAI

Drive Pictograph from the OpenAI SDK or the openai-agents framework.

View as Markdown

Toolkit setup and guardrails live on Agents — overview. 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.

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:

pip install 'pictograph[agents]'
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:

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() directlyYou want multi-turn conversations with built-in dispatch
You need a custom dispatch loopYou need agent handoffs
You don’t want the openai-agents dependencyYou want tracing + replay + structured outputs

See also

  • Agents — toolkit setup, guardrails, and the registry
  • Cookbook — recipe-style examples
  • Dynamic discovery — for Vercel AI SDK, LangChain, and other stacks
Copied to clipboard