Deep AgentsDeep Agents 0.7 · Python 3.11+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
28 small wins to finish your pathNext lesson →

Streaming a deep agent's steps

Streaming is running the agent with stream instead of invoke, so each step, a model reply or a tool result, reaches your code as soon as it happens instead of all at once at the end.

Last updated: 29 Sep, 2026 · Deep Agents 0.7

A deep agent can take minutes on a large task. The video waits for invoke to finish and mentions that streaming shows the work as it goes; this lesson does that. stream_mode="updates" yields one dictionary per step, keyed by the node that ran: model for a model reply, tools for tool results.

The stream call

python
for step in agent.stream({"messages": [...]}, stream_mode="updates"):
    for node, update in step.items():   # node is "model", "tools" or a middleware step
        ...

Building the agent

Start trip.py with search_travel, the catalog tool from Tools: a travel search the agent can call. Everything below goes in the same file, under it.

python
from langchain.tools import tool

CATALOG = {
    "paris": {
        "flight": ["Return flight Delhi to Paris: 42,000 rupees"],
        "hotel": ["Seine Budget Inn, Latin Quarter: 5,200 rupees a night",
                  "Hotel Lumiere, Montmartre: 7,500 rupees a night",
                  "Le Grand Opera Hotel: 16,000 rupees a night"],
        "sight": ["Eiffel Tower summit: 3,100 rupees", "Louvre Museum: 2,000 rupees",
                  "Seine river cruise: 1,500 rupees", "Versailles day trip: 2,600 rupees",
                  "Montmartre walking tour: free"],
        "food": ["Cafe breakfast and bistro dinner: 3,000 rupees a day"],
    },
}


@tool
def search_travel(city: str, kind: str) -> str:
    """Search the travel catalog. kind is "flight", "hotel", "sight" or "food". Prices are in rupees."""
    entries = CATALOG.get(city.lower(), {}).get(kind)
    return "\n".join(entries) if entries else f"The catalog has no {kind} entries for {city}."
python
from deepagents import create_deep_agent
from langchain.chat_models import init_chat_model

model = init_chat_model("groq:openai/gpt-oss-120b", temperature=0, max_retries=6)
python
agent = create_deep_agent(model=model, tools=[search_travel], system_prompt="You are a travel planner. Look up every price with search_travel and use only "
                  "what it returns. Answer in two short sentences.")

Streaming a question about cheap sights

Some steps come from middleware and carry no messages, so the loop reads messages with a default of an empty list.

ExampleAPI keytrip.py, continued
question = {"messages": [{"role": "user", "content": "Which two Paris sights cost the least?"}]}
for step in agent.stream(question, stream_mode="updates"):
    for node, update in step.items():
        for message in (update or {}).get("messages", []):
            print(f"{node:<6} {message.type:<5}", message.text or [c["name"] for c in message.tool_calls])

What the stream showed

  • model, ai: the first step was the model asking for search_travel. It printed before the tool ran.
  • tools, tool: the catalog's sight list, printed as soon as the tool returned.
  • model, ai with text: the final answer, the last step.

Stream modes compared

stream_modeWhat each item isUse it for
"updates"The changes one node madeShowing progress step by step
"messages"Tokens of model text as they are generatedTyping the answer out live
"values"The whole state after each stepDebugging what the agent holds

For new applications the docs recommend event streaming, added in 0.6: agent.stream_events(..., version="v3") gives separate streams for messages, tool calls and each subagent through stream.subagents. With stream and subagents, pass subgraphs=True as well; each item then comes with a namespace that says which agent produced it. Subagents: delegating with the task tool uses it.

Where streaming helps

  • A chat UI that shows "searching hotels..." while the agent works.
  • Watching a long run to see where it spends its time.
  • Logging every tool call without waiting for the end.
Watch out. With stream nothing runs until you loop over it. Creating the stream and never iterating it does no work at all.
Try it yourself
  • Change the mode to "values" and print len(step["messages"]) for each step.
  • Stream tokens with for token, meta in agent.stream(question, stream_mode="messages"): print(token.text, end="").
  • Ask a question that needs two lookups and count the tools steps.

Little by little, you're building something great.