DEV Community

Cover image for Multi-Agent Systems Explained (Why One Agent Doing Everything Is a Bad Idea)
Syed Muhammad Ali Raza
Syed Muhammad Ali Raza

Posted on

Multi-Agent Systems Explained (Why One Agent Doing Everything Is a Bad Idea)

Multi-Agent Systems Explained (Why One Agent Doing Everything Is a Bad Idea)

Written by Syed Muhammad Ali Raza

Last article was about defending a single agent from getting tricked. This one's about a completely different problem that shows up once your agent's job list gets long enough, it just isn't very good at everything anymore.

I ran into this myself building something that was supposed to research a topic, write a summary, and then fact check its own summary. One giant prompt trying to do all three jobs at once kept blending them together, the research got sloppy because it was also thinking about writing style, the fact checking was weak because by that point the same context was cluttered with everything else it had already generated. Splitting it into three separate agents, each with one job, fixed it almost immediately. That's basically the entire idea behind multi-agent systems, and this article walks through why it works and how to actually build one.

A real life example before any of the technical stuff

Think about a small restaurant kitchen. In a tiny place, one cook might genuinely do everything, take the order, chop vegetables, grill the meat, plate the dish, wash up after. It works, barely, as long as orders come in slowly enough.

Now picture a busy restaurant trying to run the exact same way, one person doing every single step for every single order. Orders would pile up, quality would slip, that one cook would be trying to remember six things at once and dropping details on all of them.

That's why real kitchens have stations. One person on prep, chopping and getting ingredients ready. One person on the grill. One on plating. One expediting, checking that everything going out actually matches the order and looks right before it leaves the kitchen. Each person is genuinely good at their one job because that's the only thing they're focused on, and there's usually a head chef or expediter whose entire job is coordinating between stations, not cooking anything themselves.

A single AI agent trying to research, write, and fact check all in one go is the lone cook trying to do everything. A multi-agent system is the kitchen with stations, an agent focused purely on research, a separate one focused purely on writing, a separate one focused purely on checking facts, and something playing the head chef role, coordinating the handoffs between them.

Why splitting the work actually helps, not just organizationally but technically

There's a real technical reason this isn't just "neater code," it changes what the model is actually capable of doing well.

Every agent has a context window, its working memory for that conversation. If one agent is juggling research notes, half finished draft text, and a list of facts to verify all at once, that's a lot of competing information sitting in the same context, and models genuinely do get less precise when the relevant details are buried among a lot of unrelated stuff. Give an agent one narrow job with only the context it actually needs for that job, and it performs that one job noticeably better.

There's also a prompting benefit. A single mega prompt trying to describe "be a great researcher, and also a great writer, and also a meticulous fact checker" ends up vague and to some degree self contradicting, since good research writing and tight fact checking prose actually want slightly different habits. Three focused prompts, each describing one clear role, are each individually much easier to get right, and easier to improve later without breaking the other two jobs.

And there's a genuinely practical software engineering reason too, easier debugging. If the final output is wrong, a single giant agent gives you one blob of reasoning to dig through to figure out where it went wrong. Separate agents give you separate, inspectable steps, you can look at the research agent's output on its own, the draft on its own, the fact check result on its own, and immediately see which stage actually broke.

The most common pattern, the orchestrator

There are a few ways to structure multiple agents talking to each other, but the one I'd actually recommend starting with, because it's the easiest to reason about and debug, is called the orchestrator pattern. One agent, the orchestrator, doesn't do the actual work itself. Its entire job is deciding which specialist agent should handle the next step, sending them the task, and passing their result along to the next step or back to the user.

This maps directly onto our kitchen example, the orchestrator is the head chef, it never chops a single vegetable itself, it just knows the state of the whole order and directs traffic.

Let's actually build one

I'll build the exact three agent setup from my own story above, a researcher, a writer, and a fact checker, coordinated by an orchestrator. Each one is genuinely just a focused prompt plus, in a fancier version, its own set of tools, but I'll keep tools out of this example so the multi-agent structure itself stays the clear focus.

Step 1, define each specialist as its own focused function

import anthropic

client = anthropic.Anthropic(api_key="your-api-key-here")

def call_model(system_prompt, user_message):
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=800,
        system=system_prompt,
        messages=[{"role": "user", "content": user_message}]
    )
    return response.content[0].text


def researcher_agent(topic):
    system_prompt = """
You are a research specialist. Your only job is gathering and
organizing key facts about a topic into clear bullet points.
Do not write prose, do not worry about tone or style, just
accurate, well organized factual bullet points. Stay strictly
within this job, do not attempt to write a final article.
"""
    return call_model(system_prompt, f"Research this topic: {topic}")


def writer_agent(topic, research_notes):
    system_prompt = """
You are a writing specialist. You take research notes someone
else already gathered and turn them into a clear, engaging
short article, around 200 words. Do not invent new facts that
aren't in the notes you were given, only work with what's there.
"""
    prompt = f"Topic: {topic}\n\nResearch notes:\n{research_notes}\n\nWrite the article."
    return call_model(system_prompt, prompt)


def fact_checker_agent(article_text, research_notes):
    system_prompt = """
You are a fact checking specialist. Compare the article text
against the original research notes. List any claims in the
article that are NOT supported by the research notes. If
everything checks out, say so clearly. Do not rewrite the
article yourself, only report what you find.
"""
    prompt = f"Research notes:\n{research_notes}\n\nArticle to check:\n{article_text}"
    return call_model(system_prompt, prompt)
Enter fullscreen mode Exit fullscreen mode

Notice each one has a narrow, clearly bounded job description, and each one is explicitly told what NOT to do, not to write the final article, not to rewrite anything, not to invent facts. That negative framing matters as much as the positive instructions, it keeps each specialist from drifting into someone else's job.

Step 2, the orchestrator that coordinates them

def run_content_pipeline(topic):
    print(f"--- Orchestrator starting pipeline for: {topic} ---\n")

    print("Step 1, sending topic to researcher_agent")
    research_notes = researcher_agent(topic)
    print(f"Research notes received:\n{research_notes}\n")

    print("Step 2, sending research notes to writer_agent")
    article = writer_agent(topic, research_notes)
    print(f"Draft article received:\n{article}\n")

    print("Step 3, sending article and notes to fact_checker_agent")
    fact_check_result = fact_checker_agent(article, research_notes)
    print(f"Fact check result:\n{fact_check_result}\n")

    if "not supported" in fact_check_result.lower() or "unsupported" in fact_check_result.lower():
        print("Issues found, this is where you'd loop back to writer_agent with feedback")
        # a more advanced version would automatically send the fact
        # checker's notes back to the writer and ask for a revision,
        # right here, before ever showing the result to a real user
    else:
        print("Fact check passed, pipeline complete")

    return {
        "research_notes": research_notes,
        "article": article,
        "fact_check_result": fact_check_result
    }


result = run_content_pipeline("the basics of how solar panels work")
Enter fullscreen mode Exit fullscreen mode

Notice the orchestrator itself never actually researches, writes, or fact checks anything. It just moves information between three specialists in a defined order and makes a simple decision about what happens next based on what it gets back. That's the whole job of an orchestrator, coordination, not doing the work itself.

Step 3, a slightly smarter orchestrator that actually loops back on failure

The version above just prints a message when the fact checker finds a problem. A genuinely useful pipeline would actually act on that, sending the article back to the writer with specific feedback and trying again.

def run_content_pipeline_with_revision(topic, max_revisions=2):
    research_notes = researcher_agent(topic)
    article = writer_agent(topic, research_notes)

    for attempt in range(max_revisions):
        fact_check_result = fact_checker_agent(article, research_notes)

        if "unsupported" not in fact_check_result.lower() and "not supported" not in fact_check_result.lower():
            print(f"Passed fact check after {attempt} revision(s)")
            return article

        print(f"Revision {attempt + 1}, sending feedback back to writer_agent")
        revision_prompt = f"""
Topic: {topic}

Research notes:
{research_notes}

Your previous draft:
{article}

A fact checker found these issues:
{fact_check_result}

Please rewrite the article, fixing these specific issues, staying
strictly within what the research notes actually support.
"""
        article = call_model(
            "You are a writing specialist revising a draft based on fact checker feedback.",
            revision_prompt
        )

    print("Max revisions reached, returning best attempt with a warning")
    return article
Enter fullscreen mode Exit fullscreen mode

This is genuinely the shape of most real multi-agent pipelines you'll see in production, specialists doing narrow jobs, an orchestrator moving work between them, and a feedback loop where one specialist's output becomes the input for revising another's work, until things pass some check or you hit a reasonable retry limit.

Multiple agents that genuinely talk to each other, not just a pipeline

The researcher, writer, fact checker example is a straight line, research feeds writing, writing feeds checking. Some problems genuinely need agents going back and forth with each other more freely rather than a strict one way pipeline, think of a debate style setup where one agent proposes a solution and another actively critiques it, back and forth, before a final answer gets produced.

def debate_pattern(question, rounds=2):
    proposer_system = "You propose a clear, well reasoned answer to the question given."
    critic_system = "You critically examine the proposed answer, looking specifically for weak reasoning, missing considerations, or mistakes. Be genuinely critical, don't just agree."

    proposal = call_model(proposer_system, question)

    for round_num in range(rounds):
        critique = call_model(critic_system, f"Question: {question}\n\nProposed answer: {proposal}")
        print(f"Round {round_num + 1} critique:\n{critique}\n")

        proposal = call_model(
            proposer_system,
            f"Question: {question}\n\nYour previous answer: {proposal}\n\nCritique received: {critique}\n\nImprove your answer based on this critique."
        )

    return proposal
Enter fullscreen mode Exit fullscreen mode

This pattern genuinely produces more carefully reasoned answers on tricky questions than a single agent thinking once and stopping, because the critic's entire job is finding weaknesses, which a single agent grading its own work tends to be much softer about than a separate agent whose only job is to poke holes.

The problems that show up once you actually build these

I want to be honest about the downsides here too, because multi-agent systems introduce their own headaches that a single agent doesn't have.

Cost and latency add up fast, since you're making several model calls per task instead of one, and a pipeline with revision loops can call the model quite a few times for a single user request. Before adding another agent to a pipeline, it's worth actually asking whether the task genuinely needs a separate specialist, or whether a good single prompt with clear instructions would honestly do just fine, more agents isn't automatically better, it's a tool for genuinely large or genuinely distinct sub tasks.

Coordination failures are also a real thing, an orchestrator can misroute a task to the wrong specialist, or a specialist can misunderstand what it was handed if the handoff prompt isn't clear enough. This is exactly why I kept every specialist's job description narrow and explicit in the code above, vague handoffs between agents are where these systems tend to quietly fall apart.

And infinite loops are a genuine risk in anything with a feedback pattern, like the revision loop or debate pattern above, which is why both of my examples included a hard max attempt limit. Never let two agents just keep going back and forth with no cap, that's an easy way to burn through cost with nothing to show for it.

When to actually reach for this pattern

A good rule of thumb I've settled on, if you can describe a task as one clear job, use one well written agent, don't overcomplicate it. Reach for multiple agents when the task genuinely has distinct phases that benefit from different focuses, like research versus writing versus verification, or when you specifically want one agent checking another's work rather than an agent grading its own homework, or when different steps genuinely need different tools and you don't want one agent juggling every tool for every possible task all the time.

Bringing this back to the whole series

Across this series we've gone from a single model just answering from memory, to giving it your own data through RAG, to reshaping its behavior through fine-tuning, to letting it take real actions through tool use, to defending that agent from being manipulated, and now, to coordinating several of these agents together so each one can actually be good at its own narrow job instead of mediocre at everything. That's genuinely the direction a lot of real AI products are heading, not one enormous do everything model, but smaller, focused pieces working together, coordinated carefully, each one good at exactly one thing.


If you build your own multi-agent pipeline, I'd love to hear how you split up the jobs, that decision alone usually tells you a lot about whether the system will hold up.

Top comments (0)