Roles and Personas: Give Each Agent One Clear Job

A
Author
30 Oct, 2026 4 min read 0 views

Each agent in a team should have one job that you can describe in a single sentence, with a defined input and a defined output. When roles overlap, agents duplicate work, contradict each other or skip steps because each assumes another agent handles them. Good role design is the cheapest way to improve a multi-agent system.

Roles are contracts, not costumes

A common beginner habit is to write "You are a world-class senior researcher with 20 years of experience". Personas like this add little. What matters is the contract: what the agent receives, what it must produce, what it must not do, and when it should stop. Replace flattery with specifics.

A role template

Use the same structure for every agent. It forces you to think about the interface, and it makes prompts easy to review.

ROLE: Source Checker
GOAL: Decide whether each claim in the draft is supported by the provided sources.
INPUT: A draft (text) and a list of sources (text with ids).
OUTPUT: JSON list. One item per claim: {"claim": str, "supported": bool, "source_id": str|null}
RULES:
- Use only the provided sources. Do not use outside knowledge.
- If no source supports a claim, mark supported=false.
- Do not edit the draft.
DONE WHEN: Every claim has an entry.

Notice the explicit "Do not edit the draft" rule. It prevents the checker from drifting into the writer's job.

Common role sets

RoleJobTypical tools
PlannerBreak a goal into stepsNone
ResearcherGather facts on one subtopicSearch, fetch
WriterProduce text from notesNone
CriticFind problems, never fix themNone
ExecutorCarry out one actionThe action's tool
RouterChoose which agent handles a requestNone

Defining roles in code

Keep roles as data so you can version, test and reuse them. A small dataclass is enough.

from dataclasses import dataclass, field

@dataclass(frozen=True)
class Role:
    name: str
    goal: str
    output_format: str
    rules: list = field(default_factory=list)

    def system_prompt(self) -> str:
        rules = "\n".join("- " + r for r in self.rules)
        return (
            "You are the " + self.name + ".\n"
            "Goal: " + self.goal + "\n"
            "Output format: " + self.output_format + "\n"
            "Rules:\n" + rules
        )

CRITIC = Role(
    name="critic",
    goal="Find concrete problems in the text you are given.",
    output_format="A bullet list, or the single word NONE if there are no problems.",
    rules=["Never rewrite the text.", "Quote the problem sentence.", "Max 5 bullets."],
)
print(CRITIC.system_prompt())

Printing the prompt shows a short, structured system message. Because the role is an object, you can test that every role has a goal and rules, and diff changes in code review.

Signs your roles are wrong

  • Two agents produce nearly the same output when given the same input.
  • You cannot say what one agent returns without saying "and also".
  • An agent frequently ignores its role and does a neighbour's work.
  • The orchestrator has to repair or reformat most outputs.

Practical tips

  • Say what the agent must not do. Negative rules prevent role creep.
  • Specify the output format exactly, so the next agent can consume it.
  • Merge roles that always run together and never disagree. Two agents that share a context and a goal are one agent.
  • Split roles when a prompt grows past one screen or mixes conflicting instructions, like "be creative" and "be strictly accurate".

Example: refactoring a vague role

Suppose you start with one agent called "Content Expert" whose prompt says: research the topic, write the article, check the facts and make it engaging. That is four jobs in one prompt. When the output is poor, you cannot tell which job failed. Split it into a researcher that returns bullet notes with source ids, a writer that turns notes into prose without adding new facts, and a fact checker that compares claims in the draft with the notes. Each now has a testable output. If articles contain wrong facts, you inspect the researcher's notes first; if the notes are right and the draft is wrong, the writer is at fault.

Roles and models

Clear roles also let you choose models sensibly. A router that picks between three specialists needs little reasoning and can run on a small, fast model. A planner that must foresee dependencies may deserve a stronger one. When roles are blurry you end up using the strongest model everywhere because you cannot tell which agent needs it.

Versioning roles

Treat role definitions like code. Keep them in files, review changes, and record which version produced which run. When a team's behaviour changes after a prompt edit, you want to be able to see exactly what changed. A later post covers versioning prompts and agent configs in detail.

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.