What Are AI Agents, and What Is a Multi-Agent System?
A plain-English tour of agents, why people wire several together, and how to build one in Python
Everyone is shipping "agents" right now, and almost nobody agrees on what the word means. Some people mean a chatbot with a search button. Others mean a fleet of programs negotiating with each other while you sleep. This post clears that up. By the end you will know what an agent actually is, when a single one is enough, what a multi-agent system buys you, and how to build a small one in Python that actually runs.
What an agent actually is#
Start with the non-technical version. A normal program follows a fixed script: do step one, then step two, then stop. An agent is different. You give it a goal, and it figures out the steps itself. It can look things up, use tools, check the result, and try again if it went wrong. Think of the difference between a vending machine and an assistant. The vending machine does exactly one thing when you press B4. The assistant you can just tell "find me a flight under £200 next Friday" and it goes off and works out how.
Now the technical version. An agent is a loop around a language model. On each turn, the model looks at the conversation so far and decides one of two things: call a tool, or give a final answer. If it calls a tool, your code runs that tool, feeds the result back into the model, and the loop continues. That is really the whole trick. The model is the brain that decides, the tools are the hands that act, and the loop is what lets it keep going until the job is done.
Here is the loop in pseudocode so it stops feeling magical:
while True:
decision = model.decide(messages) # think
if decision.is_final_answer:
return decision.answer # done
result = run_tool(decision.tool_call) # act
messages.append(result) # observe, then loopThree ingredients make an agent an agent: a model that can reason about what to do next, a set of tools it is allowed to use, and the freedom to choose its own path through them. Take away the tools and you have a chatbot. Take away the freedom and you have a fixed pipeline. Keep all three and you have an agent.
When a single agent is enough#
A lot of teams jump straight to fancy architectures when one agent would have done fine. One agent works well when the job has a clear goal, a manageable number of tools, and a fairly predictable shape. Answering questions over your docs, booking something, pulling data from an API and summarising it, triaging a support ticket: these are single-agent jobs. One brain, a handful of tools, done.
The honest rule of thumb: start with one agent. Only reach for more when one stops coping, and you can feel exactly where it breaks.
What a multi-agent system is#
A multi-agent system is what it sounds like. Instead of one agent doing everything, you have several, each focused on a slice of the problem, working together to finish a larger task. One might research, another might write, another might check the work. They pass information between them and combine their outputs into a final result.
The mental model that helps: a single agent is a freelancer, a multi-agent system is a small team with a lead. The freelancer is great until the work needs three different specialisms at once. Then you want a team, and you want someone coordinating it.
Why people split into multiple agents#
There are three real reasons to break one agent into several, and a lot of fake ones. The real ones, straight from how practitioners actually use these systems:
The first is context management. A model has a limited window of attention. If you cram one agent with fifty tools and five domains of knowledge, it gets confused and picks the wrong tool. Splitting the work means each agent only sees what it needs, so each one makes sharper decisions.
The second is parallel work. If a task has independent parts, separate agents can run them at the same time instead of one after another. Asking three specialists to each research a topic at once is faster than asking one generalist to do all three in sequence.
The third is independent development. Different people, or different teams, can own different agents and improve them without stepping on each other. Clear boundaries between agents mean clear boundaries between the humans maintaining them.
Notice what is not on that list: "it sounds more advanced." Multi-agent is a response to real pressure, not a status symbol. If a single agent is handling your tools and context fine, more agents will mostly add cost and latency.
The common patterns#
Once you have several agents, you need a way to coordinate them. A few patterns show up again and again.
The most popular is the supervisor (also called the orchestrator, or the subagents pattern). One main agent sits in charge. It looks at the request and decides which specialist to hand a piece of work to, gathers the results, and decides what to do next. All the routing flows through the supervisor, which keeps control in one place. LangChain calls this agent the supervisor, and Anthropic's writing calls the same idea an orchestrator with workers, so if you see either word, they mean this. This is the one we will build below.
There is also handoffs, where agents pass control directly to each other like a relay race, and a router, where a quick classification step sends each request to the right specialist. They trade control for efficiency in different ways. For a first multi-agent system, the supervisor pattern is the easiest to reason about, so we will start there.
Building one with LangChain in Python#
Let us build a tiny research assistant. A supervisor coordinates two specialists: one that researches a topic and one that writes a short summary. We will use LangChain's create_agent, which gives you a ready-made agent loop, and the supervisor pattern where each specialist is wrapped as a tool the supervisor can call.
First, install what we need:
pip install langchain langchain-openaiSet your model key in the environment (OPENAI_API_KEY here, but any supported provider works). Now build the two specialists. Each is just an agent with a focused prompt and its own tools.
from langchain.agents import create_agent
from langchain.tools import tool
# A simple tool the research agent can use.
# In real life this would hit a search API; we fake it to keep the example runnable.
@tool
def web_search(query: str) -> str:
"""Search the web for a query and return findings."""
return f"Top results for '{query}': LangChain is a framework for building agents..."
# Specialist 1: the researcher
research_agent = create_agent(
model="openai:gpt-4o",
tools=[web_search],
system_prompt="You research topics. Use web_search, then report the key facts plainly.",
)
# Specialist 2: the writer
writer_agent = create_agent(
model="openai:gpt-4o",
tools=[],
system_prompt="You turn rough notes into a clear, friendly two-paragraph summary.",
)Now the important part: wrap each specialist as a tool. A subagent becomes a function the supervisor can call, takes a query in, and returns the specialist's final message.
@tool("research", description="Research a topic and return the key findings.")
def call_research(query: str) -> str:
result = research_agent.invoke({"messages": [{"role": "user", "content": query}]})
return result["messages"][-1].content
@tool("write_summary", description="Turn research notes into a clean written summary.")
def call_write_summary(notes: str) -> str:
result = writer_agent.invoke({"messages": [{"role": "user", "content": notes}]})
return result["messages"][-1].contentFinally, the supervisor. It has no tools of its own except its two specialists, and a prompt telling it how to coordinate them.
supervisor = create_agent(
model="openai:gpt-4o",
tools=[call_research, call_write_summary],
system_prompt=(
"You coordinate a research assistant. "
"First call research to gather facts, then call write_summary "
"to produce the final answer. Return the summary to the user."
),
)
result = supervisor.invoke({
"messages": [{"role": "user", "content": "Explain what an AI agent is for a beginner."}]
})
print(result["messages"][-1].content)When you run this, the supervisor reads the request, calls research to gather facts, passes those notes to write_summary, and hands you back the polished answer. You have a working multi-agent system in about forty lines. Each specialist only sees its own job, the supervisor keeps control, and you can add a third specialist later without touching the first two.
The names and descriptions you give your subagent tools are not decoration. They are how the supervisor decides what to call. Vague descriptions lead to bad routing. Write them like you are explaining each specialist to a new hire.
When not to reach for this#
Multi-agent systems cost more and run slower than a single agent, because every handoff is another model call. If your task fits in one agent's head, keep it there. Reach for multiple agents when one agent is juggling too many tools, when parts of the work are genuinely independent and can run in parallel, or when separate teams need to own separate pieces. Those are the moments the extra complexity pays for itself. Everywhere else, it is just overhead wearing a fancy coat.
Wrapping up#
An agent is a model in a loop with tools and the freedom to choose its next move. A multi-agent system is several of those working as a team, usually with a supervisor keeping order. Start with one agent, and split into many only when you can name the specific reason: context, parallelism, or ownership. The LangChain example above is a real starting point you can extend.
Next in this series, I dig into Agentic RAG, where the retrieval step itself becomes something the agent reasons about rather than a fixed lookup. If you build the research assistant above and swap the fake web_search for a real retriever, you are already halfway there.
Folarin Akinloye is an AI Engineer based in London, UK. He builds production-ready agentic AI systems, multi-agent architectures, and sophisticated RAG implementations, and writes about the engineering decisions behind them.