Skip to Content

Why is my OpenAI Agents SDK agent slow to respond?

Rius shows where a slow OpenAI Agents SDK run spends its time by recording each model call and each tool call as its own timed span under the run’s root span. Open the slow trace, find the longest span in the waterfall, and read whether it is a model call, a tool or the gaps between them. Then add a duration alert so the next slow run reaches you without checking by hand. The Monitor AI agents in production guide covers the wider workflow.

How it works

The OpenAI Agents SDK integration records model calls through the openai instrumentation underneath the framework. Your own observe wrappers give the run its shape. A run that crosses a handoff looks like this:

handle-ticket AGENT 9.8s ├─ Response LLM 2.3s triage decides to hand off ├─ Response LLM 2.8s billing agent decides to call the tool ├─ execute_tool account_status TOOL 0ms └─ Response LLM 4.6s billing agent answers

The durations tell you where to look:

  • One long LLM span. The model call itself is the cost. Check the model and the token counts on that span. A large input is a common reason for a slow call.
  • Many LLM spans in a row. The agent loops through several reasoning steps, and each adds its own wait. The total is the sum.
  • A long TOOL span. The tool body is slow, not the model.
  • A root span longer than its children combined. The time is spent outside the recorded calls, in your own code or in a handoff, which has no span of its own.

Two details matter when you read the tree. Responses API calls are all named Response, so the span name does not say which agent spoke. Read the order and the content instead. Handoffs appear only as consecutive generations from different agents.

For streamed calls, each model-call span also carries time to first token, the wait before the first chunk arrives. A long wait there means the model was slow to start, not slow to finish.

Set it up

  1. Install the integration and wrap the entrypoint and the tool bodies with observe. Without the wrappers you see model calls but not the run or the tools, so you cannot tell a slow tool from a slow model. Put @function_tool outermost and observe on the function body, and name your agents with underscores, not hyphens.
pip install "glassflow-rius[openai]" openai-agents
import rius from agents import Agent, Runner, function_tool, set_tracing_disabled from rius import SpanKind rius.init(api_key="ri_...", service_name="my-agent") set_tracing_disabled(True) @function_tool @rius.observe(kind=SpanKind.TOOL) def account_status(email: str) -> str: """Fetch a customer's account standing by email.""" return lookup(email) support_agent = Agent( name="support_agent", instructions="Answer support questions; check accounts with the tool.", tools=[account_status], model="gpt-5-mini", ) @rius.observe(name="handle-ticket", kind=SpanKind.AGENT) def handle_ticket(ticket: str) -> str: result = Runner.run_sync(support_agent, ticket) return str(result.final_output)
  1. Run one slow request, then open Traces in the console. Sort or scan the latency column to find the slow run, as described in Exploring traces.
  2. Open the trace and read the waterfall for the longest span. Switch to the Map tab and choose the latency lens to see the hot spot at a glance. Clicking a node takes you to that span in the tree.
  3. To rank steps across many runs, use the Spans tab. Filter with the All kinds menu to Tool or LLM, then click the Duration header to sort.
  4. Add alerts. Create a custom alert on duration, and filter by Agent or Service so the rule measures whole runs. A rule measures only the spans that match its filter, so a filter on tool spans alone measures just those spans. A second rule on time to first token covers slow starts on streamed calls. Rius also ships a pre-defined Tool Loop alert. It counts only spans of kind TOOL, which is why the tool above uses SpanKind.TOOL.

What you get

  • A per-step timeline for every run, so you can tell a slow model call from a slow tool.
  • Tokens and cost on each model-call span. A call with a very large input stands out, and the Context growth strip on a trace with several model calls plots input tokens per call in order.
  • Since previous llm call on a model span shows what each step added to the prompt, which explains a prompt that keeps growing.
  • Compare runs puts a slow trace beside a normal run of the same agent, so you can see which steps changed and where latency moved.
  • Trends on Home, covered in Usage and cost: latency percentiles (p50, p95, p99) over finished traces, and time to first token for the workspace, per agent and per model. Time to first token covers streamed calls only, and the panel shows what share of calls it was measured on.
  • Notifications when duration or time to first token crosses your threshold, so you hear about the next slow run before a user reports it.

When something else fits

  • If the slowness is a handoff, which has no span, add an observe wrapper per agent entry or use the framework’s RunHooks to open spans at agent boundaries.
  • If your streamed calls show no token counts or cost, enable usage on the OpenAI client as described on the OpenAI Agents SDK page. For other frameworks and libraries, see Integrations.

Still stuck? Get help

Last updated on