npx skills add ...
npx skills add crewaiinc/skills --skill design-agent
CrewAI agent design and configuration. Use when creating, configuring, or debugging crewAI agents — choosing role/goal/backstory, selecting LLMs, assigning tools, tuning max_iter/max_rpm/max_execution_time, enabling planning/code execution/delegation, setting up knowledge sources, using guardrails, or configuring agents in YAML vs code.
npx skills add crewaiinc/skills --skill design-agent
How to design effective agents with the right role, goal, backstory, tools, and configuration.
Spend 80% of your effort on task design, 20% on agent design. A well-designed task elevates even a simple agent. But even the best agent cannot rescue a vague, poorly scoped task. Get the task right first (see the design-task skill), then refine the agent.
Default to ONE agent. Add more only when the task genuinely splits into work that requires:
DO NOT add an agent just because the workflow has multiple steps. A single agent can:
Cost calculus: every extra agent = at least one more LLM kickoff plus a context handoff. Splitting linear, single-persona work into multiple agents multiplies token cost and adds fragility for marginal quality wins.
❌ Three agents for what is one researcher's job:
✅ One researcher does the gathering loop; one writer synthesizes — two agents because the personas and LLMs genuinely differ:
The researcher's task description tells it to search, then scrape, then return structured findings. One LLM loop, multiple tool calls.
❌ Two agents to read a string, summarize it, and post a Slack DM:
✅ One agent with the connector and a task that tells it to summarize on top, then DM:
If two "agents" share the same persona, the same tool surface, and the same LLM, they are one agent with a longer task description.
Use Agent.kickoff() directly inside a Flow method — no Crew, no Task ceremony. The Flow owns sequencing and state; each step is a single agent kickoff. See Section 4 — Agent.kickoff() — Direct Agent Execution below for the full pattern, and the upstream docs at https://docs.crewai.com/en/concepts/agents#direct-agent-interaction-with-kickoff.
Quick shape:
Reach for Crew.kickoff() only when a step genuinely benefits from multi-agent collaboration (delegation, hierarchical management, parallel specialists feeding one synthesis). For "one agent does one job", Agent.kickoff() inside a Flow listener is the right primitive.
Only after you've decided multi-agent is justified, read on for how to design each one.
Every agent needs three things: who it is, what it wants, and why it's qualified.
The role defines the agent's area of expertise. Be specific, not generic.
| Bad | Good |
|---|---|
Researcher | Senior Data Researcher specializing in {topic} |
Writer | Technical Blog Writer for developer audiences |
Analyst | Financial Risk Analyst with regulatory compliance expertise |
The role directly shapes how the LLM reasons. A "Senior Data Researcher" will produce different output than a "Research Assistant" even with the same task.
The goal is the agent's individual objective. It should be outcome-focused with quality standards.
| Bad | Good |
|---|---|
Do research | Uncover cutting-edge developments in {topic} and identify the top 5 trends with supporting evidence |
Write content | Produce publication-ready technical articles that explain complex topics clearly for non-technical readers |
Analyze data | Deliver actionable risk assessments with confidence levels and recommended mitigations |
The backstory establishes expertise, experience, values, and working style. It's the agent's "personality prompt."
What to include in a backstory:
What NOT to include:
Tuning max_iter:
Key rules:
design-task skill)Use function_calling_llm to save costs: the main llm handles reasoning while a cheaper model handles tool-calling mechanics.
Set allow_delegation=True only when:
Warning: Delegation without clear task boundaries leads to infinite loops or wasted iterations.
When a PlanningConfig is set on an agent, Agent.kickoff() (and Agent.execute_task()) routes through the new crewai.experimental.AgentExecutor. Instead of a single ReAct-style loop, the agent:
PlanSteps, each with a description and optional tool_to_use. Stored as state.todos.StepExecutor in an isolated multi-turn LLM loop (capped by max_step_iterations).PlannerObserver after every step — did the step succeed? Is the remaining plan still valid?reasoning_effort setting (see below).The presence of a PlanningConfig enables the mode. To disable: don't pass one, or set planning=False.
reasoning_effort — pick one| Level | After each step the planner... | Pick when |
|---|---|---|
"low" | observes (validates success), marks the todo complete, continues. No replan, no refine. | You want plan visibility (todos, observations) but trust the agent to follow it linearly. Fastest. |
"medium" (default) | observes; replans on failure only. Successful steps just continue. | The agent's tools can fail (network, exec, scrape) and you want graceful recovery without paying refinement cost on every success. The right default for sandbox-coding, research, and other tool-heavy loops. |
"high" | observes, then routes through decide_next_action which can trigger early goal achievement, full replan, or lightweight refinement after every step. | The task changes shape based on intermediate findings, or you need maximum adaptiveness. Most LLM calls per run. |
Source: crewai/experimental/agent_executor.py:450 (observe_step_result router) and crewai/agent/planning_config.py.
PlanningConfig knobsUse llm="anthropic/claude-haiku-4-5" (cheap) for the planner while keeping agent.llm="anthropic/claude-opus-4-7" (strong) for execution — common cost optimization.
Every step gets a PlannerObserver LLM call (~1 extra call per step). On "medium" a failed step adds a replan call. On "high" every step adds a decide_next_action call too. For an N-step plan, expect roughly:
low: N execution + N observation = 2N callsmedium: 2N + (failures × 1 replan)high: ~3N + replans/refinesMaterial at scale — measure before defaulting high for everything.
plan_promptIf you supply plan_prompt, include the placeholders the planner template expects: {description}, {expected_output}, {tools}, {max_steps}. The planner LLM gets these interpolated. Keep custom prompts focused on project-specific rules; let description/tools (auto-injected) carry the dynamic content.
"safe" requires Docker installed and running — executes in a container"unsafe" runs code directly on the host — only use in controlled environmentsWhen True, the agent automatically summarizes prior context if it approaches the LLM's token limit. When False, execution stops with an error on overflow.
Enable for time-sensitive tasks (research, news analysis, scheduling).
Agent guardrails validate every output the agent produces. The agent retries on failure up to guardrail_max_retries.
Knowledge sources give agents access to domain-specific data via RAG. Use when agents need to reference large documents, policies, or datasets.
Define agents in agents.yaml for clean separation of config and code:
Then wire in crew.py:
Critical: The method name (def researcher) must match the YAML key (researcher:). Mismatch causes KeyError.
Use Agent.kickoff() when you need one agent with tools and reasoning, without crew overhead. This is the most common pattern in Flows.
Note:
Agent.kickoff()returnsLiteAgentOutput— access structured output viaresult.pydantic. This differs fromLLM.call()which returns the Pydantic object directly.
The most powerful pattern is orchestrating multiple Agent.kickoff() calls inside a Flow. The Flow handles state and sequencing; each agent handles its specific step:
When to use Agent.kickoff() vs Crew.kickoff():
Agent.kickoff() when each step is a distinct agent and the Flow controls sequencingCrew.kickoff() when multiple agents need to collaborate on related tasks within a single stepIn experimental conversational Flows, the Flow owns the chat lifecycle and route selection. Agents should be called inside route handlers for bounded tool-backed work: research, docs lookup, account actions, triage, drafting, or escalation prep.
Design implications:
Flow responsible for session id, message history, routing, trace finalization, and approvals.append_agent_result(..., visibility="private") for scratch work that should not enter canonical chat history.append_assistant_message(reply) for the user-visible answer so the next turn has the assistant context.See the getting-started reference for the Flow lifecycle: skills/getting-started/references/conversational-flows.md.
Note: Apply this section after you've decided you genuinely need multiple agents (see Section 0). If you only need one agent, "specialist vs generalist" is not the question — the question is just how to design that one agent.
When you do need multiple agents, prefer specialists. An agent that does one thing well outperforms one that does many things acceptably.
Instead of one "Content Writer" agent, create:
technical_writer — deep technical accuracy, code examplescopywriter — persuasive, audience-focused marketing copyeditor — grammar, consistency, style guide enforcementEach specialist has a narrow role, specific goal, and backstory that reinforces their expertise.
Agents work one after another. Each agent receives prior agents' outputs as context.
Best for: linear pipelines where each step builds on the last.
A manager agent delegates and validates. Task assignment is dynamic.
Best for: complex workflows where task assignment depends on intermediate results.
When allow_delegation=True, an agent can ask another crew agent for help:
The agent will automatically discover other crew members and delegate subtasks as needed.
| Mistake | Impact | Fix |
|---|---|---|
| Generic role like "Assistant" | Agent produces unfocused, shallow output | Use specific expertise: "Senior Financial Analyst" |
| No tools for data-gathering tasks | Agent hallucinates data instead of searching | Always add tools when the task requires external info |
| Too many tools (10+) | Agent gets confused choosing between tools | Limit to 3-5 relevant tools per agent |
| Backstory full of task instructions | Agent mixes personality with task execution | Keep backstory about WHO the agent is; task details go in the task |
allow_delegation=True by default | Agents waste iterations delegating trivially | Only enable when delegation genuinely helps |
| max_iter too high for simple tasks | Agent loops unnecessarily on vague tasks | Lower max_iter; fix the task description instead |
| No guardrail on critical output | Bad output passes through unchecked | Add guardrails for outputs that feed into production systems |
| Using expensive LLM for tool calls | Unnecessary cost for mechanical operations | Set function_calling_llm to a cheaper model |
Before deploying an agent, verify:
For deeper dives into specific topics, see:
@tool decorator and BaseTool subclassFor related skills: