OpenAI Agents SDK¶
Ingest traces from the OpenAI Agents SDK (the openai-agents package: Agent, Runner, handoffs, guardrails) into Pisama's detectors.
This is a different API surface from the Assistants and Responses APIs, which Pisama ingests through adapters/openai.py. All three share Platform.OPENAI and are distinguished by platform_version:
| Surface | platform_version |
|---|---|
| Assistants API | assistants-v2 |
| Responses API | responses-v1 |
| Agents SDK | agents-sdk-v1 |
Why now¶
OpenAI Agent Builder shuts down on 30 November 2026 (announced 3 June 2026). Teams migrating off it are choosing between the Agents SDK and ChatGPT Workspace Agents, and the ones picking the Agents SDK are re-picking their observability layer at the same time.
How it works¶
The Agents SDK has its own tracing system. Every run produces a trace and a tree of spans, and you can register a TracingProcessor to receive them. Pisama's adapter consumes exactly what that processor receives, so there is nothing to instrument by hand and no monkey-patching of Runner.
The adapter does not import openai-agents. It takes the exported dicts, so it works against whatever SDK version you are on and adds no dependency.
Wiring it up¶
Register a processor that forwards exported spans to Pisama:
from agents.tracing import set_trace_processors
from agents.tracing.processor_interface import TracingProcessor
from pisama_core.adapters import parse_openai_agents_trace
class PisamaProcessor(TracingProcessor):
def __init__(self):
self._spans = []
self._trace = None
def on_trace_start(self, trace):
pass
def on_span_start(self, span):
pass
def on_span_end(self, span):
self._spans.append(span.export())
def on_trace_end(self, trace):
self._trace = trace.export()
pisama_trace = parse_openai_agents_trace(self._trace, self._spans)
# hand pisama_trace to your detection entry point, or POST the
# spans to /api/v1/traces/ingest
self._spans = []
def force_flush(self):
pass
def shutdown(self):
pass
set_trace_processors([PisamaProcessor()])
set_trace_processors replaces the default processor list, so traces stop going to the OpenAI tracing backend. Use add_trace_processor instead if you want both.
What gets mapped¶
| Agents SDK span type | Pisama SpanKind | Carried across |
|---|---|---|
agent | AGENT | name, declared handoffs, declared tools, output_type |
handoff | HANDOFF | from_agent, to_agent |
function | TOOL | name, input arguments, output, MCP data |
generation | LLM | model, model config, input, output, token usage |
response | LLM | response id, token usage |
guardrail | SYSTEM | name, triggered |
mcp_tools | TOOL | server, result |
task, turn, custom | TASK / AGENT_TURN / SYSTEM | name, data |
Anything else keeps its raw payload rather than being dropped, so a newer SDK version degrades quietly instead of losing data.
Two things worth knowing¶
Declared handoffs stay separate from handoffs that fired. An agent span records the handoffs the agent was allowed to make; handoff spans record the ones it took. Keeping them apart is what lets a detector ask whether a declared route was never used, which is a different question from which routes were.
Token keys are normalised. The Agents SDK reports input_tokens and output_tokens; the Assistants and Responses APIs use prompt_tokens and completion_tokens. Both are written to gen_ai.usage.input_tokens and gen_ai.usage.output_tokens, so token-budget detectors need no per-API branch. gen_ai.usage.total_tokens is derived when the SDK does not supply it.
Span status is inferred. Agents SDK spans carry no status field, only an optional error. An error means ERROR. No error plus a set ended_at means OK. Neither means IN_PROGRESS, not success.
Detectors that apply¶
The multi-agent coordination detectors are the relevant set for handoff architectures: coordination failure, loop detection, persona drift, information withholding.
Per-detector measured F1 lives on the detection overview, generated from the capability registry. This page deliberately does not restate those numbers: a figure printed on a framework page implies it was measured on that framework's traces, and it was not.