LangChain (YT style)LangChain 1.4 · Python 3.12+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
46 small wins to finish your pathNext lesson →

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 supervisor and its three agents · from the Building Agents And Multi Agents With LangGraph, Part 3 · 16:45 to 21:16

A supervisor and its workers

In the supervisor architecture, one supervisor node has control. As soon as a task comes in, it decides whether to pass it to the researcher, the analyst or the writer. Asked to write an article on agentic AI, it can send the task to the researcher, who then passes it to the writer. Asked to analyze a report and write it up, it sends it to the analyst first, and the analyst passes it to the writer. Every agent depends on the task the supervisor hands it.

The supervisor sends work to the researcher, the analyst or the writer, each reports back, and the supervisor ends the run when the task is done.
The supervisor architecture

In the multi-agent crash course the graph's state holds next_agent, research_data, analysis, final_report, task_complete and current_task. A supervisor chain, a prompt joined to a Groq model, reads that state. Its prompt says "You are a supervisor managing a team of agents": a researcher who gathers information and data, an analyst who analyzes data and provides insights, and a writer who creates reports and summaries. Given whether research, analysis and a report exist yet, it names the agent that should work next, or answers done when the task is complete. The supervisor writes that name into next_agent, and the task moves through the agents one by one. The shop version calls each specialist as a tool and gets the reply straight back, which needs no graph.

The shop already has two agents: the orders agent from the create_agent lesson and the policies agent from the retrieval lesson. Now one customer asks a question that touches both.

Wrapping an agent in a tool

python
@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 text

The two specialist agents

The orders specialist answers order questions with lookup_order, the tool built in Tools: a function the model can call. Put it in its own file, orders.py, so the tests in Testing an agent can import it without building a Groq agent.

python
from langchain.tools import tool

ORDERS = {"A17": "shipped on 3 March", "C40": "waiting for stock"}


@tool
def lookup_order(order_id: str) -> str:
    """Look up an order's shipping status by its id, such as A17."""
    status = ORDERS.get(order_id)
    return f"{order_id} {status}." if status else f"{order_id} is not an order we have."
Project files used on this pageThis lesson builds on a project from earlier lessons. The code below imports these files. Click a file to see its code, or follow the link to the lesson that wrote it. To run the code yourself, keep them in the same folder.
View the code here
policies.py
from langchain_core.documents import Document
from langchain_text_splitters import RecursiveCharacterTextSplitter

POLICIES = {
    "refunds.md": "Refunds go back to the card you paid with. They take up to 5 working days to arrive."
                  "\n\nYou can ask for a refund within 30 days of delivery. Opened items can be refunded if they are faulty.",
    "shipping.md": "Standard shipping takes 3 to 5 working days. Shipping is free on orders over 50 euros."
                   "\n\nExpress shipping arrives the next working day and costs 9 euros.",
    "accounts.md": "To reset your password, use the reset link on the sign-in page. Support staff never ask for your password.",
}

docs = [Document(page_content=text, metadata={"source": name}) for name, text in POLICIES.items()]
splitter = RecursiveCharacterTextSplitter(chunk_size=120, chunk_overlap=0, add_start_index=True)
chunks = splitter.split_documents(docs)
word_embeddings.py
import re
import zlib

from langchain_core.embeddings import Embeddings

COMMON = {"a", "an", "and", "are", "can", "do", "does", "for", "how", "i",
          "if", "is", "it", "my", "of", "on", "the", "to", "what", "with", "you", "your"}


class WordEmbeddings(Embeddings):
    def embed_query(self, text):
        vector = [0.0] * 256
        for word in re.findall(r"[a-z]+", text.lower()):
            if word not in COMMON:
                vector[zlib.crc32(word.rstrip("s").encode()) % 256] += 1.0
        return vector

    def embed_documents(self, texts):
        return [self.embed_query(text) for text in texts]
search.py
from langchain.tools import tool
from langchain_core.vectorstores import InMemoryVectorStore
from policies import chunks
from word_embeddings import WordEmbeddings

store = InMemoryVectorStore(WordEmbeddings())
store.add_documents(chunks)


@tool
def search_policies(query: str) -> str:
    """Search the shop's policies on refunds, shipping and accounts.
    Pass the customer's question, word for word, as the query."""
    found = [doc for doc, score in store.similarity_search_with_score(query, k=2) if score >= 0.3]
    if not found:
        return "No policy covers this."
    return "\n".join(f"[{doc.metadata['source']}] {doc.page_content}" for doc in found)

Each specialist is a whole agent with its own model, tools and system prompt. last_reply sends it one question and returns the text of its final message. The code in this section goes in one file, specialists.py; the router lesson imports from it too.

python
from langchain.agents import create_agent
from langchain.tools import tool
from langchain.chat_models import init_chat_model      # uses your GROQ_API_KEY
from orders import lookup_order
from search import search_policies

orders_agent = create_agent(init_chat_model("groq:openai/gpt-oss-120b", temperature=0),
    tools=[lookup_order], system_prompt="Answer the order question in one short sentence, using only what the lookup_order tool returned.")
policies_agent = create_agent(init_chat_model("groq:openai/gpt-oss-120b", temperature=0),
    tools=[search_policies], system_prompt="Answer in one short sentence of plain text, using only what the search_policies tool returned. Name the source file in square brackets, like [refunds.md]. If the tool finds nothing, say the policies do not cover it.")


def last_reply(agent, question):
    return agent.invoke({"messages": [{"role": "user", "content": question}]})["messages"][-1].text

Wrapping each specialist as a tool

Wrap each specialist in @tool and add both to the end of specialists.py. 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.

python
@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 and accounts."""
    return last_reply(policies_agent, question)

The supervisor agent

Now the main agent. Give it the two specialist tools and a system prompt that says when to use each. When the customer's message arrives, the supervisor reads it, calls the specialists it needs, and combines their replies into one answer.

python
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from specialists import ask_orders, ask_policies

supervisor = create_agent(
    init_chat_model("groq:openai/gpt-oss-120b", temperature=0),
    tools=[ask_orders, ask_policies],
    system_prompt="You are a support supervisor. Use ask_orders for order status and "
                  "ask_policies for policy questions. Call whichever the question needs; "
                  "answer in one or two short sentences, using only what the specialists returned.")

Running one question through the supervisor

One question that touches both specialists, run through the supervisor. The loop prints each message's type, then either its text or, for a tool call, the tool's name and the arguments the supervisor sent.

ExampleAPI key
question = "Where is A17, and how long does a refund take?"
result = supervisor.invoke({"messages": [{"role": "user", "content": question}]})

for message in result["messages"][1:]:   # skip the question
    print(f"{message.type:<4}", message.text or [(c["name"], c["args"]) for c in message.tool_calls])

How the supervisor split the question

  • Both specialists were called: the supervisor called ask_orders for the order and ask_policies for the refund, so each name shows on its own line.
  • Each specialist got only its own question: the arguments on each ai line are what the supervisor wrote for that subagent, not the customer's whole sentence.
  • The final answer joins the two replies: once both specialists had answered, the supervisor combined their replies into one message.
  • A subagent keeps no memory between calls by default, so each question starts it fresh.
What a subagent is · from the Complete Deep Agents Course With LangChain · 137:47 to 142:07

Subagents in Deep Agents

The deepagents library, built on LangChain, packages this pattern. A deep agent can create subagents to delegate work, given in its subagents parameter. Subagents give context quarantine: they keep the main agent's context clean and carry their own specialized instructions. Each is a specialized agent with its own context, tools, memory and instructions, does one focused job and returns a structured result. The main agent understands the overall goal, plans, delegates to the subagents, collects their results and returns the final answer. With synchronous subagents, the main agent waits, blocked, until the subagent finishes. Asked to build a research report on agentic AI, the main agent might hand parts to a research agent, a writing agent, a data agent and a critic agent.

Creating a research subagent · from the Complete Deep Agents Course With LangChain · 144:00 to 149:37

In code, a subagent is a dictionary. The video first writes an internet_search tool around the Tavily client, then describes research_subagent with a name, a description the main agent reads to decide when to delegate ("Used to research more in depth questions"), a system prompt ("You are a great researcher"), its tools and an optional model that falls back to the main agent's model. create_deep_agent takes the list in its subagents parameter. The video's version, shown here and not run in this course, needs the deepagents package and Tavily and OpenAI keys:

python
from deepagents import create_deep_agent

research_subagent = {
    "name": "research-agent",
    "description": "Used to research more in depth questions",
    "system_prompt": "You are a great researcher",
    "tools": [internet_search],         # a Tavily web search function
    "model": "groq:qwen/qwen3-32b",     # optional, defaults to the main agent's model
}

agent = create_deep_agent(
    model="openai:gpt-5.4",
    subagents=[research_subagent],
)

Asked to "research about LLM gateways and provide me a detailed summary", the main agent wrote a to-do list, delegated the research to the subagent, which searched the internet, and returned the summary. The subagent's searches and long results stay inside it, and only its answer goes back to the main agent, which keeps the main conversation short. That is the same reason this lesson wraps each specialist in a tool.

One agent vs a supervisor

One agent, all toolsSupervisor with subagents
Who picks the toolOne model, every turnThe supervisor, then each specialist
What a specialist seesThe whole conversationOnly the question it was asked
Combining answersOne model does everythingThe 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.
Watch out. A subagent keeps no memory between calls, so the supervisor must put everything the specialist needs into the question. Send half the question and the specialist answers half of it.
Try it yourself
  • 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_orders return the specialist's whole message list and print what the supervisor gets.

This is what real progress feels like.