Defining Agent Roles, Goals, and Backstories
Every CrewAI agent is steered by three strings: role, goal, and backstory.
Search across all documentation pages
Every CrewAI agent is steered by three strings: role, goal, and backstory.
Together they act as a job description the model cannot ignore as easily as a vague system prompt.
Write role as a crisp title, goal as a measurable outcome, and backstory as constraints plus taste - then pair them with least-privilege tools and tight task expected_output so behavior stays testable.
expected_output so acceptance criteria match the job.{placeholders} for run-specific topics; keep evergreen constraints in goal/backstory.from crewai import Agent, Task, Crew, Process
researcher = Agent(
role="{topic} Research Analyst",
goal=(
"Deliver accurate, source-aware notes an engineer can trust. "
"Prefer precision over coverage when time is limited."
),
backstory=(
"You spent years fact-checking technical claims. "
"You never invent URLs or statistics. "
"When evidence is thin, you say so in one line and move on."
),
allow_delegation=False,
max_iter=10,
verbose=True,
)
writer = Agent(
role="Staff Technical Writer",
goal=(
"Turn research notes into a scannable brief for senior engineers. "
"Preserve caveats; do not add new facts."
),
backstory=(
"You write for people who skim. "
"Short paragraphs, concrete nouns, no marketing language. "
"If notes conflict, you surface the conflict instead of picking a side."
),
allow_delegation=False,
verbose=True,
)
research = Task(
description="Research {topic}. Capture 5 facts with confidence labels.",
expected_output="Markdown bullets: fact | why it matters | confidence (high/med/low).",
agent=researcher,
)
draft = Task(
description="Write a 3-paragraph brief on {topic} using only the research notes.",
expected_output="Markdown with three paragraphs and a 'Caveats' section.",
agent=writer,
context=[research],
)
crew = Crew(
agents=[researcher, writer],
tasks=[research, draft],
process=Process.sequential,
verbose=True,
)
print(crew.kickoff(inputs={"topic": "agent evaluation harnesses"}).raw)| Field | Optimize for | Anti-pattern |
|---|---|---|
role | Instant identity in logs and prompts | Long essays, joke names, multi-jobs |
goal | Decision policy under ambiguity | Generic "help the user" |
backstory | Style, domain priors, refusals | Novel-length lore with no constraints |
The model uses these fields as standing orders.
Tasks are the ticket for this run.
If goal and expected_output disagree, expect thrash.
Specialist split. One role owns discovery; another owns packaging. Different tools, different success metrics.
Quality bar in the goal. Phrases like "prefer precision over coverage" change tool use and length more than adjectives in the backstory.
Refusal clauses in the backstory. "Never invent URLs" and "do not add facts not in notes" reduce confident hallucination at handoff boundaries.
Parameterized role titles. role="{topic} Research Analyst" keeps identity relevant without rewriting the agent class.
Do not stuff one-off formatting rules only into the backstory if they apply to a single ticket.
Put run-specific instructions in description and expected_output.
Keep role text stable so you can reuse the agent across crews.
In hierarchical crews, workers still need sharp roles. The manager routes work; it does not magically fix overlapping goals. If two workers both "own the full report," the manager will bounce work or duplicate effort.
allow_delegation. Accidental true turns a specialist into a middle manager.| Approach | When it wins | When it loses |
|---|---|---|
| Role + goal + backstory (CrewAI default) | Multi-specialist crews | Tiny single-step bots |
| Single system prompt, no roles | Prototypes | Tool and handoff complexity |
| Hierarchical manager + thin workers | Dynamic assignment | Cost-sensitive batch jobs |
| Skills / knowledge packs | Domain docs over persona | Replacing a clear goal |
A short paragraph is enough. If a sentence does not change tools, tone, or refusals, cut it.
Mention tools only when the policy depends on them ("use search before asserting currency"). Prefer outcome language over stack trivia.
Yes via {placeholders} and kickoff(inputs=...). Keep stable constraints outside placeholders.
They are the default persona channel. Advanced system_template overrides exist for model-specific formatting - verify at build if you need them.
Run the same task with A/B role text, compare tool calls, length, and factual errors. Keep the winner in version control.
Goals describe quality; max_iter is a host safety rail. Use both.
Yes. Manager goals should emphasize assignment, review, and stopping criteria, not deep specialist craft.
Share the tool class, not the entire tool list blindly. Still keep role goals distinct so usage differs.
Knowledge grounds facts; backstory still sets caution and style. Do not assume knowledge removes the need for refusal language.
Config files help non-Python editors and reviews. The writing craft is identical in code or JSONC.
Related: The CrewAI Mental Model: Roles, Tasks, and Crews
Related: CrewAI Basics
Related: Sequential vs Hierarchical Crew Processes
Related: CrewAI Best Practices
Stack versions: Pins from the category manifest (verify at build): OpenRouter (~315+ models, July 2026 pricing/fees); LangGraph 1.0+; CrewAI 1.14+; Microsoft Agent Framework 1.0; Vercel AI SDK 6; Pydantic AI (latest); LlamaIndex (latest); OpenAI Agents SDK (latest + MCP); MCP (Linux Foundation governance); A2A (HTTP+SSE+JSON-RPC 2.0); Solana
@solana/web3.js+@solana/spl-token.
Reviewed by Chris St. John·Last updated Jul 16, 2026