OpenAI Agents SDK
Trace the OpenAI Agents SDK in Python and TypeScript.
Register the Neatlogs trace processor once, and all agent runs, LLM generations, and tool calls from the OpenAI Agents SDK are captured.
Prerequisites
pip install -U "neatlogs[openai-agents]" openai-agentsUsage
import os
import neatlogs
neatlogs.init(api_key=os.environ["NEATLOGS_API_KEY"], workflow_name="openai-agents-demo")
from agents import Agent, Runner, add_trace_processor
add_trace_processor(neatlogs.openai_agents_processor())
agent = Agent(name="assistant", instructions="Be concise.")
result = Runner.run_sync(agent, "In one sentence, what is the OpenAI Agents SDK?")
print(result.final_output)
neatlogs.flush()
neatlogs.shutdown()The processor produces a WORKFLOW trace root for each agent run, with nested AGENT, LLM generation, and TOOL spans for each tool call — no manual @span / span() wrapping needed.
Sessions & end-user
Say a user chats with your OpenAI Agents app across several turns and you want every Runner.run_sync call stitched into one session, attributed to that person. The processor opens a WORKFLOW root for each agent run, so wrap the run in identify() and that root — plus every span beneath it — picks up the session and end-user:
# Same session_id every turn → one session; end_user_id attributes it to your user.
with neatlogs.identify(session_id=f"conv_{conversation_id}", end_user_id=user_id):
result = Runner.run_sync(agent, message)Keep reusing that same session_id across every run and the turns collapse into a single conversation.
Not every run is a conversation. A standalone workflow — a one-off job, not a back-and-forth — is a single trace with no turns to group. Attribute it to the customer it ran for, sourcing the id and any metadata from your own user or request object. When the workflow makes several agent runs, wrap them in trace() so they roll up into one trace (each Runner.run_sync otherwise opens its own root); a single run can use identify() instead:
A standalone workflow must not carry a session_id. Omit it entirely — Neatlogs sets session_id = trace_id, so the run is its own single-turn session, fully attributed to the end-user. Reusing one session_id across unrelated runs wrongly folds them into a single multi-turn conversation.
def run_report(topic, user):
# Multi-step workflow — trace() fuses both runs into ONE trace; no session_id.
with neatlogs.trace(
"report",
end_user_id=str(user.id),
end_user_metadata={"plan": user.plan},
):
draft = Runner.run_sync(writer_agent, topic)
return Runner.run_sync(editor_agent, draft.final_output)The Sessions and End-User Identity guides walk through the whole model.
