
Stream Live Tool Progress From Your Claude Agent: One Flag, Real-Time Output
Chris Harper
2 min read
Aug 1, 2026 · 20:05 UTC
Set include_partial_messages=True in the Claude Agent SDK and your agent emits live tool events — enough to show [Using Read…] done in any terminal or web UI instead of a blank screen.
By default the Claude Agent SDK yields complete AssistantMessage objects after each response finishes. That's fine for batch pipelines; for anything user-facing it means 30 seconds of silence while the agent works.
One option changes this. Set include_partial_messages=True (Python) or includePartialMessages: true (TypeScript) and you get StreamEvent objects wrapping raw Claude API events as they arrive. Three event types do the work:
content_block_startwithcontent_block.type == "tool_use"— a tool call is starting; the tool name is available immediatelycontent_block_deltawithdelta.type == "input_json_delta"— partial JSON arguments streaming incontent_block_stop— the tool call is complete
Here's the full pattern for a live UI:
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
from claude_agent_sdk.types import StreamEvent
import asyncio, sys
async def streaming_ui():
options = ClaudeAgentOptions(
include_partial_messages=True,
allowed_tools=["Read", "Bash", "Grep"],
)
in_tool = False
async for message in query(
prompt="Find all TODO comments in the codebase", options=options
):
if isinstance(message, StreamEvent):
event = message.event
etype = event.get("type")
if etype == "content_block_start":
block = event.get("content_block", {})
if block.get("type") == "tool_use":
print(f"\n[Using {block['name']}...]", end="", flush=True)
in_tool = True
elif etype == "content_block_delta":
delta = event.get("delta", {})
if delta.get("type") == "text_delta" and not in_tool:
sys.stdout.write(delta.get("text", ""))
sys.stdout.flush()
elif etype == "content_block_stop" and in_tool:
print(" done", flush=True)
in_tool = False
elif isinstance(message, ResultMessage):
print("\n--- Complete ---")
asyncio.run(streaming_ui())
One caveat: StreamEvents come from the main session only — subagent deltas are not forwarded to the parent. For multi-agent pipelines you still see subagent completions via complete AssistantMessages, but not token-by-token. If you need token-level streaming from a specific subagent, run it as a separate top-level query() call.
The TypeScript equivalent uses includePartialMessages: true and checks message.type === "stream_event" with the same nested event structure. The docs page has both versions side by side.
Sources: Stream responses in real-time — Claude Code Agent SDK · Streaming Tool Calls: Parse Anthropic SSE Without Loading the Whole Message — DEV Community