CloudCodeTree LogoCloudCodeTree
AI NewsTutorialsAbout
CloudCodeTree Logo
CloudCodeTree
  • AI News
  • Tutorials
  • About
← Back to AI News
Stream Live Tool Progress From Your Claude Agent: One Flag, Real-Time Output

Stream Live Tool Progress From Your Claude Agent: One Flag, Real-Time Output

Chris Harper

2 min read

Aug 1, 2026 · 20:05 UTC

AI
Workflow
Claude Code
Agents
Best Practices

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_start with content_block.type == "tool_use" — a tool call is starting; the tool name is available immediately
  • content_block_delta with delta.type == "input_json_delta" — partial JSON arguments streaming in
  • content_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