Subagents as tools
A subagent is a whole agent wrapped as a tool, so a main agent can call it, choose what to ask it, and combine what several return.
Last updated: 27 Sep, 2026 · LangChain 1.4
The shop already has two agents: the orders agent from lesson 7 and the policies agent from lesson 28. A customer asks one question that touches both. In the subagents pattern a main agent, often called a supervisor, calls each specialist as a tool; they answer it, not the customer.
Wrapping an agent in a tool
@tool
def ask_specialist(question: str) -> str: # looks like any tool
"""One line the main agent reads to know when to call this."""
reply = specialist_agent.invoke({"messages": [{"role": "user", "content": question}]})
return reply["messages"][-1].text # hand back only the final textThe two specialist agents
Each specialist is a whole agent with its own model and tools. last_reply sends it one question and returns the text of its final message.
from langchain.agents import create_agent
from langchain.tools import tool
from help_model import HelpModel
from search import search_policies
from shop_model import ShopModel
from tools import lookup_order
orders_agent = create_agent(ShopModel(), tools=[lookup_order]) # knows orders
policies_agent = create_agent(HelpModel(), tools=[search_policies]) # knows policies
def last_reply(agent, question):
return agent.invoke({"messages": [{"role": "user", "content": question}]})["messages"][-1].textWrapping each specialist as a tool
Wrap each specialist in @tool. To the main agent it looks like any other tool: a name, a description and one string argument. The main agent sees a short answer, not the specialist's whole conversation.
@tool
def ask_orders(question: str) -> str:
"""Ask the orders specialist where an order is."""
return last_reply(orders_agent, question) # only the final text comes back
@tool
def ask_policies(question: str) -> str:
"""Ask the policies specialist about refunds, shipping or accounts."""
return last_reply(policies_agent, question)The supervisor model
Now the main agent. When the customer's message arrives, the supervisor reads it and decides which specialists to ask.
import re
from langchain.messages import AIMessage
from shop_model import ShopModel
class Supervisor(ShopModel):
def decide(self, messages):
if messages[-1].type == "tool": # the specialists have replied
return AIMessage("\n".join(m.text for m in messages if m.type == "tool"))
text = messages[-1].textChoosing which specialists to ask
It asks the orders specialist about each order id it finds, writing a short question of its own, and asks the policies specialist when the text mentions a policy topic. When both apply, it asks both in one message.
calls = [{"name": "ask_orders", "args": {"question": f"Where is {o}?"}, "id": f"call_{o}"}
for o in re.findall(r"\b[A-Z]\d+\b", text)] # one ask per order id
if any(word in text.lower() for word in ("refund", "shipping", "password")):
calls.append({"name": "ask_policies", "args": {"question": text}, "id": "call_policies"})
if not calls:
return AIMessage("Which order or policy is this about?")
return AIMessage("", tool_calls=calls) # ask them all at onceGiving the supervisor its tools
Give the supervisor the two specialist tools, and it can delegate.
from langchain.agents import create_agent
from specialists import ask_orders, ask_policies
from supervisor import Supervisor
agent = create_agent(Supervisor(), tools=[ask_orders, ask_policies])Running one question through the supervisor
One question that touches both specialists, run through the supervisor. The loop prints each message's type and either its text or the tools it called.
question = "Where is A17, and how long does a refund take?"
result = agent.invoke({"messages": [{"role": "user", "content": question}]})
for message in result["messages"][1:]:
print(f"{message.type:<4}", message.text or [c["name"] for c in message.tool_calls])How the supervisor split the question
- Both specialists ran from one message: the supervisor called
ask_ordersandask_policiestogether, so the first line shows both names. - The orders specialist got "Where is A17?", not the whole sentence, because the supervisor writes each subagent's question.
- The final answer joins the two replies: when the tool results came back,
decidereturned them combined. - A subagent keeps no memory between calls by default, so each question starts it fresh.
One agent vs a supervisor
| One agent, all tools | Supervisor with subagents | |
|---|---|---|
| Who picks the tool | One model, every turn | The supervisor, then each specialist |
| What a specialist sees | The whole conversation | Only the question it was asked |
| Combining answers | One model does everything | The supervisor joins the replies |
When to use a subagent
- One question that spans two areas, such as an order and a refund policy.
- Keeping each specialist's prompt and tools small, so each one stays reliable.
Related
- Previous: MCPAdapter: tools from another program
- Next: Routing with a router node
- Reference: Multi-agent
- Ask a question with two order ids and count the calls to
ask_orders. - Ask "How do I reset my password?" and check which specialist answers.
- Make
ask_ordersreturn the specialist's whole message list and print what the supervisor gets.
This is what real progress feels like.