Subagent structured output with response_format
Structured output is a reply that fills a schema you define, such as a Pydantic class; a subagent with response_format hands its result back to the main agent as JSON in that shape instead of free text.
Last updated: 29 Sep, 2026 · Deep Agents 0.7
ToolStrategy(...) around the class, as the next section explains.The video's ResearchFindings schema
The video's second subagent example returns structured output. It defines a Pydantic class, ResearchFindings, with three fields: a summary, a confidence score from 0 to 1, and a list of sources. The subagent dictionary gets one more key, response_format, set to that class. Asked to research recent advances in quantum computing, the main agent calls task with subagent_type researcher, the tool message that comes back holds the summary, confidence and source URLs, and the main agent writes its answer from them.
The run below uses web_search, the Tavily tool from Tools: a travel search the agent can call, which needs TAVILY_API_KEY. The agent runs on Gemini, so it also needs GOOGLE_API_KEY, the free key from Installation and setup; with the Groq line it needs GROQ_API_KEY instead. Start findings.py with it.
import os
from tavily import TavilyClient
from typing import Literal
tavily_client = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
def web_search(query: str, max_results: int = 5,
topic: Literal["general", "sports", "news", "finance"] = "general"):
"""Run a web search"""
return tavily_client.search(query, max_results=min(max_results, 5), topic=topic)Add the video's code under web_search in findings.py, with four changes: the model is google_genai:gemini-2.5-flash, Gemini's free key, which leaves Groq's daily limit for the other lessons (the Groq line works the same); the schema goes in ToolStrategy, as the next section explains; the subagent's prompt names web_search, so it searches instead of answering from memory; and invoke replaces await agent.ainvoke, which runs only inside a notebook or an async function.
from deepagents import create_deep_agent
from langchain.agents.structured_output import ToolStrategy
from langchain.chat_models import init_chat_model
from pydantic import BaseModel, Field
class ResearchFindings(BaseModel):
"""Structured findings from a research task."""
summary: str = Field(description="Summary of findings")
confidence: float = Field(description="Confidence score from 0 to 1")
sources: list[str] = Field(description="List of source URLs")
research_subagent = {
"name": "researcher",
"description": "Researches topics and returns structured findings",
"system_prompt": "Research the given topic thoroughly with web_search. Return your findings.",
"tools": [web_search],
"response_format": ToolStrategy(ResearchFindings),
}
model = init_chat_model("google_genai:gemini-2.5-flash", temperature=0, max_retries=6)
agent = create_deep_agent(model=model, subagents=[research_subagent])
result = agent.invoke({"messages": [{"role": "user", "content": "Research recent advances in quantum computing"}]})
for message in result["messages"]:
if message.type == "tool":
print("researcher returned:", message.text)
print("final:", result["messages"][-1].text[:600])researcher returned: {"summary":"Recent advances in quantum computing show significant progress across algorithms, hardware, and error correction, moving closer to practical applications. In algorithms, Google has developed a more efficient implementation of Shor's algorithm, requiring fewer qubits to break elliptic curve encryption, and a new algorithm by Oded Regev may surpass Shor's efficiency. There's a growing focus on practical implementations and quantum-inspired algorithms for classical hardware. Hardware breakthroughs include Google's 105-qubit Willow chip demonstrating below-threshold error correction, where accuracy improves with more qubits, and IBM's 1,121-qubit Condor processor. Qolab has introduced superconducting devices optimized for scalability, and SaxonQ developed a mobile, room-temperature quantum computer. NVIDIA is integrating AI for quantum processor calibration and error correction, while Cisco is working on a Universal Quantum Switch to connect different quantum systems. In error correction, Google's Willow chip achieved a critical milestone with below-threshold error correction, indicating a path towards more reliable quantum computers. Companies like Google, IBM, and Microsoft are demonstrating real-time error correction and logical qubit operations. The Institute of Science Tokyo has discovered a new error-correction method nearing theoretical limits, and Cuera has made breakthroughs in quantum state distillation, crucial for fault-tolerant quantum computing.","confidence":0.95,"sources":["https://www.discovermagazine.com/quantum-computing-is-beginning-to-take-shape-here-are-three-recent-breakthroughs-48938","https://www.wevolver.com/article/breakthroughs-in-quantum-computing","https://www.bqpsim.com/blogs/quantum-computing-breakthroughs","https://www.youtube.com/watch?v=EQM25seTqO4","https://www.quantamagazine.org/new-advances-bring-the-era-of-quantum-computers-closer-than-ever-20260403","https://www.techpowerup.com/news-tags/quantum%20computing","https://www.hannovermesse.de/en/news/news-articles/ai-on-the-verge-of-breakthrough-thanks-to-quantum-technology","https://www.linkedin.com/posts/yossimatias_today-were-announcing-a-major-algorithmic-activity-7386780979618738176-Myh9","https://medium.com/@meisshaily/shocking-breakthroughs-in-quantum-error-correction-b10946b37c36","https://www.nature.com/articles/s42254-024-00706-3","https://research.google/blog/dynamic-surface-codes-open-new-avenues-for-quantum-error-correction","https://phys.org/news/2026-01-error-technology-quantum-real-world.html","https://www.riverlane.com/quantum-error-correction"]}
final: Recent advances in quantum computing show significant progress across algorithms, hardware, and error correction.
**Algorithms:**
* Google has developed a more efficient implementation of Shor's algorithm, requiring fewer qubits for elliptic curve encryption.
* A new algorithm by Oded Regev may surpass Shor's efficiency.
* There's an increasing focus on practical implementations and quantum-inspired algorithms for classical hardware.
**Hardware:**
* Google's 105-qubit Willow chip has demonstrated below-threshold error correction, where accuracy improves with more qubits.
* IBM has The tool message is the subagent's reply as JSON in the ResearchFindings shape: a summary, a confidence of 0.95 and a list of source URLs. The final answer is the main agent rewriting that summary under headings, starting with Algorithms and Hardware. Search results change from day to day, so your run will find other sources.
Passing the schema on Groq with ToolStrategy
The video passes the class directly, and on OpenAI the model's built-in JSON mode returns it. Groq cannot use JSON mode and tools in the same request, so a subagent with tools fails with "json mode cannot be combined with tool/function calling". Wrapping the class in ToolStrategy asks for the schema as one more tool call instead, which works on any model that can call tools.
from langchain.agents.structured_output import ToolStrategy
subagent = {..., "response_format": ToolStrategy(HotelPick)} # the reply fills HotelPickThe HotelPick schema
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.
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}."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)from langchain.agents.structured_output import ToolStrategy
from pydantic import BaseModel, Field
class HotelPick(BaseModel):
"""One hotel chosen from the catalog."""
name: str = Field(description="Hotel name")
price_per_night: int = Field(description="Price per night in rupees")
reason: str = Field(description="One short reason for the pick")A hotel-scout that returns HotelPick
hotel_scout = {
"name": "hotel-scout",
"description": "Finds a hotel in a city that fits a nightly budget.",
"system_prompt": "Look up hotels with search_travel and pick one. Use only catalog data.",
"tools": [search_travel],
"response_format": ToolStrategy(HotelPick), # the subagent returns this schema
}The main agent
agent = create_deep_agent(
model=model,
subagents=[hotel_scout],
system_prompt="Give every hotel question to hotel-scout with the task tool, then answer in one sentence.",
)Printing what hotel-scout handed back
result = agent.invoke({"messages": [{"role": "user", "content": "Find me a Paris hotel under 8,000 rupees a night."}]})
for message in result["messages"]:
if message.type == "tool":
print("hotel-scout returned:", message.text)
print("final:", result["messages"][-1].text)hotel-scout returned: {"name":"Seine Budget Inn, Latin Quarter","price_per_night":5200,"reason":"Affordable location in the Latin Quarter well under 8000 rupees"}
final: Seine Budget Inn in Paris’s Latin Quarter costs about 5,200 rupees per night, comfortably staying under your 8,000‑rupee budget.What the structured reply shows
- The tool message is JSON with exactly the three fields of
HotelPick. - price_per_night is a number,
5200, not the text "5,200 rupees", because the schema saysint. - The main agent read the JSON and wrote the one-sentence answer from it.
Free text vs structured output
| Free-text report | response_format | |
|---|---|---|
| What comes back | Any wording the subagent chooses | JSON that fits the schema |
| Reading it in code | Parse text yourself | Load the JSON, fields are named |
| Good for | Explanations, summaries | Prices, scores, lists another step uses |
The main agent can take a response_format too; its parsed result is in result["structured_response"].
Where structured subagent output helps
- A subagent whose numbers the main agent adds up, like a price per night.
- Research findings with a confidence score and sources, as in the video.
- Passing results to code after the agent finishes.
price_per_night: int with "Price per night in rupees" gets 5200; without the unit, a model may return a price in euros.Related
- Previous: Subagents: delegating with the task tool
- Next: CompiledSubAgent: your own agent as a subagent
- Reference: Subagents: structured output
- Add a
district: strfield toHotelPickand run it again. - Pass
HotelPickwithoutToolStrategyand read the error Groq returns. - Give the main agent
response_format=ToolStrategy(HotelPick)and printresult["structured_response"].
Slow is fine. Stopping is the only problem.