Your First Two-Agent System in Python with Claude

A
Author
26 Oct, 2026 4 min read 0 views

The easiest multi-agent system to build is a writer and an editor. The writer drafts, the editor either approves or lists specific fixes, and your code loops until the editor approves or a revision limit is reached. This post builds it step by step in Python.

Setup

Install the SDK with pip install anthropic and export ANTHROPIC_API_KEY. The code uses claude-sonnet-5-5, a good general model for both roles. You can swap in a different model per agent later.

Step 1: a helper for one agent call

Each agent is a system prompt plus a call. Write one helper and reuse it.

import anthropic

client = anthropic.Anthropic()

def call(system: str, user: str, model: str = "claude-sonnet-5-5") -> str:
    response = client.messages.create(
        model=model,
        max_tokens=3000,
        system=system,
        messages=[{"role": "user", "content": user}],
    )
    return "".join(b.text for b in response.content if b.type == "text").strip()

Step 2: define the two roles

The writer should only write. The editor should only judge, and must answer in a form your code can parse. A simple rule works: the editor replies with APPROVED on the first line, or REVISE followed by a bullet list.

WRITER = (
    "You are a concise technical writer. Write for developers. "
    "When given editor feedback, rewrite the whole text and fix every point."
)

EDITOR = (
    "You are a strict editor. Check accuracy, clarity and length (max 120 words). "
    "Reply in one of two forms.\n"
    "Form 1: the single word APPROVED.\n"
    "Form 2: the word REVISE on the first line, then a bullet list of specific fixes."
)

Step 3: the loop that connects them

def write_with_review(topic: str, max_rounds: int = 3) -> str:
    draft = call(WRITER, "Write a short explanation of: " + topic)
    for round_number in range(1, max_rounds + 1):
        verdict = call(EDITOR, "Review this text:\n\n" + draft)
        print(f"--- round {round_number}: editor said ---\n{verdict}\n")
        if verdict.upper().startswith("APPROVED"):
            return draft
        draft = call(
            WRITER,
            "Topic: " + topic + "\n\nYour previous draft:\n" + draft
            + "\n\nEditor feedback:\n" + verdict + "\n\nWrite the improved version.",
        )
    return draft  # best effort after the round limit

print(write_with_review("how HTTP caching works"))

When you run it, you will see the editor's verdict for each round and then the final text. Often the first draft is approved; with a strict editor prompt you will usually see one or two revisions.

What makes this a real multi-agent system

  • The two agents have different system prompts and never share a conversation. The editor does not see the writer's reasoning, only the text.
  • Information moves only through the strings you pass. That makes the data flow easy to inspect and log.
  • The loop has a hard stop (max_rounds). Without it, a picky editor could run forever.

Improvements to try

  • Use a cheaper model for the editor if its job is simple, and a stronger one for the writer.
  • Ask the editor for JSON, such as {"approved": false, "fixes": []}, and parse it. The next posts cover structured messages.
  • Save every round's draft and verdict to a list so you can see how the text changed.
  • Change the editor's rubric to check a specific thing, like code correctness, and see how the loop behaves.

Common mistakes

  • Letting the editor rewrite the text. It then becomes a second writer, and responsibilities blur.
  • Parsing with an exact string match when the model may add punctuation. Use startswith on an uppercased string, as above.
  • Forgetting that the writer needs the full previous draft in the revision prompt. Agents have no memory between calls unless you pass it.

Reading the transcript

A useful habit is to print each agent's input and output while you build. With the printouts above you can check three things. First, does the editor's complaint match a real problem in the draft? If not, the editor prompt is too vague or too eager. Second, does the revised draft actually fix the listed points, or does it ignore some? If it ignores them, make the writer prompt stricter: "address every bullet". Third, does the loop converge? A healthy run approves within one or two revisions. If the draft oscillates between two states, your editor criteria probably conflict with each other.

Cost of the loop

Each round is two model calls, and the revision prompt contains the full draft plus the feedback, so inputs grow. With a three-round cap, the worst case is about seven calls: one first draft, then three reviews and three rewrites. For short texts this is cheap, but if you apply the same loop to long documents, the cost climbs quickly. Decide the round cap based on how much each extra round improves quality, which you can only know by measuring on real examples.

You now have the core loop that later patterns refine: independent roles, explicit messages, and a stop rule.

Was this article helpful?

Comments

No comments yet. Have a question or a tip? Be the first to share it.

Leave a comment

Comments are reviewed before they appear.