New: watch your coding agents work, step by step, on a live board. Try the demo, no account

Progress updates from an OpenAI Agents SDK agent

By Jake Marsh, who builds Taskhold. Updated 2026-11-11. Facts about other tools checked 2026-11-11. 4 min read.

Short answer: Runner.run_streamed returns a result whose stream_events() yields run item events (tool_called, tool_output, message_output_created) and raw text deltas, which covers a progress display in your own process. For a run nobody is watching, connect Taskhold's MCP server with MCPServerStreamableHttp and an API key, and the agent reports its steps and asks its questions on a live board.

In the OpenAI Agents SDK for Python, Runner.run_streamed() gives you every step of a run as it happens: each tool call, each tool result, each message and, if you want them, the text tokens. This guide covers which events to read, then how to see a run from outside the process it runs in.

For the same thing with Anthropic's SDK, see Claude Agent SDK progress updates. The Taskhold section at the end feeds the live board.

The live board, drawn with the same progress bar component the app uses. A working task with five steps, and a blocked task waiting on a reply.

Stream the run's events

Runner.run_streamed() returns a RunResultStreaming. Iterate result.stream_events() until it ends: post-processing can finish after the last visible token, and result.is_complete is only final once the loop exits. Three event types arrive:

  • raw_response_event: a Responses API event in event.data, such as a ResponseTextDeltaEvent for each piece of text.
  • run_item_stream_event: a whole item, with event.name saying which: tool_called, tool_output, message_output_created, handoff_requested, reasoning_item_created, mcp_approval_requested, mcp_list_tools and others.
  • agent_updated_stream_event: the current agent changed, for example after a handoff.
from agents import Agent, ItemHelpers, Runner
from openai.types.responses import ResponseTextDeltaEvent

result = Runner.run_streamed(agent, "Upgrade the payments service to the new API")
async for event in result.stream_events():
    if event.type == "raw_response_event" and isinstance(event.data, ResponseTextDeltaEvent):
        print(event.data.delta, end="", flush=True)
    elif event.type == "run_item_stream_event":
        if event.item.type == "tool_call_item":
            print("\n> tool called")
        elif event.item.type == "tool_call_output_item":
            print("> tool finished")
        elif event.item.type == "message_output_item":
            print(ItemHelpers.text_message_output(event.item))
    elif event.type == "agent_updated_stream_event":
        print(f"> now running: {event.new_agent.name}")
Handoffs emit handoff_requested, not tool_called. result.cancel() stops the run now; cancel(mode="after_turn") lets the current turn finish.

Seeing a run from outside the process

Stream events only reach the process that started the run. When the agent runs in a container, a queue worker or a cron job, nobody is reading that stream, and there's no one to answer when it needs a decision. The agent has to report somewhere you can see, and wait somewhere you can reply.

Connect Taskhold's MCP server

The SDK connects to remote MCP servers with MCPServerStreamableHttp. An agent running unattended can't do a browser sign-in, so it uses an API key: start the 7-day trial, open Settings > API keys and make one for this agent. Send it in the Authorization header, not the URL, and give the agent the workflow in its instructions:

import os
from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp

WORKFLOW = """You share a task list with the person through the taskhold tools. They watch a live board.
- Start: taskhold_begin with title, project "payments", a short list of steps and agent "Upgrade agent (Agents SDK)".
- Each step done: taskhold_complete on the step with start_next: true.
- Long step: taskhold_progress on the step with current, total and a short message. Every few minutes at most.
- Need a decision: taskhold_block with one question, then taskhold_updates with task_id, since and wait: 50 until the reply arrives.
- Done: taskhold_complete on the task with what changed and how you checked it."""

async with MCPServerStreamableHttp(
    name="taskhold",
    params={
        "url": "https://taskhold.com/api/mcp",
        "headers": {"Authorization": f"Bearer {os.environ['TASKHOLD_API_KEY']}"},
        "timeout": 60,
    },
    cache_tools_list=True,
) as taskhold:
    agent = Agent(name="Upgrade agent", instructions=WORKFLOW, mcp_servers=[taskhold])
    result = await Runner.run(agent, "Upgrade the payments service to the new API")
timeout here is in seconds, and covers taskhold_updates waiting up to 50 s for your reply. cache_tools_list is safe: Taskhold's tool list changes only with a release.
  • Each run shows on the board as a task with a bar split by step, the agent's label, how long it has run and what it's doing now.
  • When the agent blocks with a question, the card moves to the top. You answer from any browser or your phone, and the agent reads it with taskhold_updates and carries on.
  • To limit which tools the agent sees, pass tool_filter=create_static_tool_filter(allowed_tool_names=[...]) with the taskhold tools you want.
  • require_approval on the server asks before each call. For an unattended run, leave it off for the taskhold tools, or the board only moves when someone approves.
Share this page:XLinkedInBlueskyHacker News

Answer your coding agents from anywhere.

$12/month or $120/year after the trial. Card up front. Cancel before day 7 and you pay nothing. Every agent you run is included.

Or connect your agent first, no sign-up: add https://taskhold.com/api/mcp as an MCP server. The first time it uses Taskhold, it gives you the trial link.

Questions

How do I show progress from an OpenAI Agents SDK run?
Use Runner.run_streamed() and iterate result.stream_events(). run_item_stream_event events mark each tool call, tool output and message; raw_response_event carries the text deltas.
How do I connect a remote MCP server to the OpenAI Agents SDK?
Open MCPServerStreamableHttp with params url and headers (put the token in an Authorization header) in an async with block, and pass it to Agent(mcp_servers=[server]).
Can an Agents SDK agent ask me a question mid-run?
Not through the SDK alone, since nobody reads the stream of an unattended run. With Taskhold, the agent blocks its task with a question, you answer on the live board, and taskhold_updates returns your reply.

Sources

Related

Updated 2026-11-11. Something wrong or out of date? Email hello@greatwork.company.