{"name":"design-agent","url":"https://skills.sh/crewaiinc/skills/design-agent","install":"npx skills add crewaiinc/skills --skill design-agent","sdk":"crewai","key":"crewai/design-agent","description":"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.","hasContent":true,"content":"---\nname: design-agent\ndescription: \"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.\"\n---\n\n# CrewAI Agent Design Guide\n\nHow to design effective agents with the right role, goal, backstory, tools, and configuration.\n\n---\n\n## The 80/20 Rule\n\n**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.\n\n---\n\n## 0. How Many Agents Do You Actually Need?\n\n**Default to ONE agent.** Add more only when the task genuinely splits into work that requires:\n\n- **Different tools or permissions** — e.g. one agent has Slack write access, another reads docs only.\n- **Different personas the LLM must clearly switch between** — a writer's voice is not a researcher's voice.\n- **Different LLMs** — a cheap model for mechanical steps, a stronger one for synthesis.\n- **Different guardrails or output schemas** — separate agents make the contract per stage explicit.\n\n**DO NOT add an agent just because the workflow has multiple steps.** A single agent can:\n- Call multiple tools in sequence within one kickoff (search → scrape → summarize is one agent's loop).\n- Produce structured multi-section output in one response.\n- Iterate via its own tool-use loop without you orchestrating it as separate agents.\n\n**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.\n\n### Anti-pattern: Sequential mechanical steps as separate agents\n\n❌ Three agents for what is one researcher's job:\n```python\nsource_finder = Agent(role=\"Finds URLs via Firecrawl search\", tools=[firecrawl_search])\nscraper       = Agent(role=\"Scrapes URLs via Firecrawl scrape\", tools=[firecrawl_scrape])\nwriter        = Agent(role=\"Writes the report\", ...)\n```\n\n✅ One researcher does the gathering loop; one writer synthesizes — two agents because the personas and LLMs genuinely differ:\n```python\nresearcher = Agent(role=\"Web Researcher\", tools=[firecrawl_search, firecrawl_scrape], llm=\"anthropic/claude-haiku-4-5\")\nwriter     = Agent(role=\"Technical Report Writer\",                                    llm=\"anthropic/claude-sonnet-4-6\")\n```\nThe researcher's task description tells it to search, then scrape, then return structured findings. One LLM loop, multiple tool calls.\n\n### Anti-pattern: \"Summarize then send\" as two agents\n\n❌ Two agents to read a string, summarize it, and post a Slack DM:\n```python\nsummarizer       = Agent(role=\"Summarizer\")\nslack_messenger  = Agent(role=\"Slack Sender\", apps=[\"slack\"])\n```\n\n✅ One agent with the connector and a task that tells it to summarize on top, then DM:\n```python\nslack_dm_agent = Agent(\n    role=\"Slack Reporter\",\n    goal=\"Post a Slack DM containing a one-paragraph summary plus the full markdown body.\",\n    apps=[\"slack\"],\n)\n# Task: \"Read the report below. Write a 2-3 sentence executive summary at the top.\n#        Post a DM to {recipient_email} with the summary followed by the full body.\"\n```\n\n### Heuristic\n\n> If two \"agents\" share the same persona, the same tool surface, and the same LLM, they are one agent with a longer task description.\n\n### Once you've decided \"one agent is enough\"\n\nUse `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>.\n\nQuick shape:\n\n```python\n@listen(previous_step)\ndef my_step(self):\n    agent = Agent(role=\"…\", goal=\"…\", backstory=\"…\", tools=[...])\n    result = agent.kickoff(\n        messages=f\"Use this prior step's output: {self.state.prior_field}\",\n        response_format=MyPydanticModel,  # optional\n    )\n    self.state.my_field = result.pydantic  # or result.raw\n```\n\nReach 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.\n\nOnly after you've decided multi-agent is justified, read on for how to design each one.\n\n---\n\n## 1. The Role-Goal-Backstory Framework\n\nEvery agent needs three things: **who** it is, **what** it wants, and **why** it's qualified.\n\n### Role — Who the Agent Is\n\nThe role defines the agent's area of expertise. **Be specific, not generic.**\n\n| Bad | Good |\n|---|---|\n| `Researcher` | `Senior Data Researcher specializing in {topic}` |\n| `Writer` | `Technical Blog Writer for developer audiences` |\n| `Analyst` | `Financial Risk Analyst with regulatory compliance expertise` |\n\nThe role directly shapes how the LLM reasons. A \"Senior Data Researcher\" will produce different output than a \"Research Assistant\" even with the same task.\n\n### Goal — What the Agent Wants\n\nThe goal is the agent's individual objective. It should be **outcome-focused with quality standards**.\n\n| Bad | Good |\n|---|---|\n| `Do research` | `Uncover cutting-edge developments in {topic} and identify the top 5 trends with supporting evidence` |\n| `Write content` | `Produce publication-ready technical articles that explain complex topics clearly for non-technical readers` |\n| `Analyze data` | `Deliver actionable risk assessments with confidence levels and recommended mitigations` |\n\n### Backstory — Why the Agent Is Qualified\n\nThe backstory establishes expertise, experience, values, and working style. It's the agent's \"personality prompt.\"\n\n```yaml\nbackstory: >\n  You're a seasoned researcher with 15 years of experience in AI/ML.\n  You're known for your ability to find obscure but relevant papers\n  and synthesize complex findings into clear, actionable insights.\n  You always cite your sources and flag uncertainty explicitly.\n```\n\n**What to include in a backstory:**\n- Years/depth of experience\n- Specific domain knowledge\n- Working style and values (e.g., \"always cites sources\", \"prefers concise output\")\n- Quality standards the agent holds itself to\n\n**What NOT to include:**\n- Implementation details (tools, models, config)\n- Task-specific instructions (those go in the task description)\n- Arbitrary personality traits that don't affect output quality\n\n---\n\n## 2. Agent Configuration Reference\n\n### Essential Parameters\n\n```python\nAgent(\n    role=\"...\",              # Required: agent's expertise area\n    goal=\"...\",              # Required: what the agent aims to achieve\n    backstory=\"...\",         # Required: context and personality\n    llm=\"openai/gpt-4o\",    # Optional: defaults to OPENAI_MODEL_NAME env var or \"gpt-4\"\n    tools=[...],             # Optional: list of tool instances\n)\n```\n\n### Execution Control\n\n```python\nAgent(\n    ...,\n    max_iter=25,             # Max reasoning iterations per task (default: 25)\n    max_execution_time=300,  # Timeout in seconds (default: None — no limit)\n    max_rpm=10,              # Rate limit: max API calls per minute (default: None)\n    max_retry_limit=2,       # Retries on error (default: 2)\n    verbose=True,            # Show detailed execution logs (default: False)\n)\n```\n\n**Tuning `max_iter`:**\n- Default 25 is generous — most tasks finish in 3-8 iterations\n- Lower to 10-15 to fail faster when tasks are well-defined\n- If agent consistently hits max_iter, the task is too vague (fix the task, not the limit)\n\n### Tool Configuration\n\n```python\nfrom crewai_tools import SerperDevTool, ScrapeWebsiteTool, FileReadTool\n\nAgent(\n    ...,\n    tools=[SerperDevTool(), ScrapeWebsiteTool()],  # Agent-level tools\n)\n```\n\n**Key rules:**\n- An agent with **no tools** will hallucinate data when asked to search, fetch, or read files — always provide tools for tasks that require external data\n- Prefer **fewer, focused tools** over many tools — too many tools confuses the agent\n- Tools can also be assigned at the **task level** for task-specific access (see `design-task` skill)\n- Agent-level tools are available for all tasks the agent performs; task-level tools override for that specific task\n\n### LLM Selection\n\n```python\nAgent(\n    ...,\n    llm=\"openai/gpt-4o\",              # Main reasoning model\n    function_calling_llm=\"openai/gpt-4o-mini\",  # Cheaper model for tool calls only\n)\n```\n\nUse `function_calling_llm` to save costs: the main `llm` handles reasoning while a cheaper model handles tool-calling mechanics.\n\n### Collaboration\n\n```python\nAgent(\n    ...,\n    allow_delegation=False,  # Default: False — agent works alone\n)\n```\n\nSet `allow_delegation=True` only when:\n- The agent is part of a crew with other specialized agents\n- The task genuinely benefits from the agent handing off subtasks\n- You're using hierarchical process where the manager delegates\n\n**Warning:** Delegation without clear task boundaries leads to infinite loops or wasted iterations.\n\n### Planning (Plan-and-Execute Mode)\n\nWhen 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:\n\n1. **Generates a plan** — a list of `PlanStep`s, each with a description and optional `tool_to_use`. Stored as `state.todos`.\n2. **Executes each step** via a `StepExecutor` in an isolated multi-turn LLM loop (capped by `max_step_iterations`).\n3. **Observes the result** via a `PlannerObserver` after every step — did the step succeed? Is the remaining plan still valid?\n4. **Routes the next action** based on the agent's `reasoning_effort` setting (see below).\n\nThe presence of a `PlanningConfig` enables the mode. To disable: don't pass one, or set `planning=False`.\n\n```python\nfrom crewai import Agent\nfrom crewai.agent.planning_config import PlanningConfig\n\nagent = Agent(\n    role=\"…\",\n    goal=\"…\",\n    backstory=\"…\",\n    tools=[...],\n    planning_config=PlanningConfig(reasoning_effort=\"medium\"),  # most common\n)\n```\n\n#### `reasoning_effort` — pick one\n\n| Level | After each step the planner... | Pick when |\n|---|---|---|\n| `\"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. |\n| `\"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.** |\n| `\"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. |\n\nSource: `crewai/experimental/agent_executor.py:450` (`observe_step_result` router) and `crewai/agent/planning_config.py`.\n\n#### Other `PlanningConfig` knobs\n\n```python\nPlanningConfig(\n    reasoning_effort=\"medium\",\n    max_steps=20,            # cap on planned steps (default 20)\n    max_replans=3,           # max full re-plans before finalizing (default 3)\n    max_attempts=None,       # planning refinement attempts during plan generation\n    max_step_iterations=15,  # max LLM turns per step's StepExecutor (default 15)\n    step_timeout=None,       # wall-clock seconds per step; None = no cap\n    system_prompt=None,      # custom planning system prompt (uses default if None)\n    plan_prompt=None,        # custom initial-plan prompt; placeholders: {description}, {expected_output}, {tools}, {max_steps}\n    refine_prompt=None,      # custom refinement prompt\n    llm=None,                # separate LLM for planning (else uses agent.llm)\n)\n```\n\nUse `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.\n\n#### When to enable\n\n- **Enable** for autonomous loops where the agent picks its own steps and you want failure recovery (e.g. coding agent that writes → runs → patches; research agent that searches → scrapes → revises).\n- **Skip** for single-tool, single-purpose calls (e.g. \"summarize this string\", \"post this Slack DM\") — observation overhead doesn't pay off.\n\n#### Cost shape\n\nEvery 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:\n\n- `low`: N execution + N observation = **2N calls**\n- `medium`: 2N + (failures × 1 replan)\n- `high`: ~3N + replans/refines\n\nMaterial at scale — measure before defaulting `high` for everything.\n\n#### Custom `plan_prompt`\n\nIf 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.\n\n### Code Execution\n\n```python\nAgent(\n    ...,\n    allow_code_execution=True,        # Enable code execution (default: False)\n    code_execution_mode=\"safe\",       # \"safe\" (Docker) or \"unsafe\" (direct) — default: \"safe\"\n)\n```\n\n- `\"safe\"` requires Docker installed and running — executes in a container\n- `\"unsafe\"` runs code directly on the host — only use in controlled environments\n\n### Context Window Management\n\n```python\nAgent(\n    ...,\n    respect_context_window=True,      # Auto-summarize to stay within limits (default: True)\n)\n```\n\nWhen `True`, the agent automatically summarizes prior context if it approaches the LLM's token limit. When `False`, execution stops with an error on overflow.\n\n### Date Injection\n\n```python\nAgent(\n    ...,\n    inject_date=True,                 # Add current date to task context (default: False)\n    date_format=\"%Y-%m-%d\",           # Date format (default: \"%Y-%m-%d\")\n)\n```\n\nEnable for time-sensitive tasks (research, news analysis, scheduling).\n\n### Agent Guardrails\n\n```python\ndef validate_no_pii(result) -> tuple[bool, Any]:\n    \"\"\"Reject output containing PII.\"\"\"\n    if contains_pii(result.raw):\n        return (False, \"Output contains PII. Remove all personal information and try again.\")\n    return (True, result)\n\nAgent(\n    ...,\n    guardrail=validate_no_pii,\n    guardrail_max_retries=3,          # default: 3\n)\n```\n\nAgent guardrails validate every output the agent produces. The agent retries on failure up to `guardrail_max_retries`.\n\n### Knowledge Sources\n\n```python\nfrom crewai.knowledge.source.text_file_knowledge_source import TextFileKnowledgeSource\n\nAgent(\n    ...,\n    knowledge_sources=[\n        TextFileKnowledgeSource(file_paths=[\"company_handbook.txt\"]),\n    ],\n    embedder={\n        \"provider\": \"openai\",\n        \"config\": {\"model\": \"text-embedding-3-small\"},\n    },\n)\n```\n\nKnowledge sources give agents access to domain-specific data via RAG. Use when agents need to reference large documents, policies, or datasets.\n\n---\n\n## 3. YAML Configuration (Recommended)\n\nDefine agents in `agents.yaml` for clean separation of config and code:\n\n```yaml\nresearcher:\n  role: >\n    {topic} Senior Data Researcher\n  goal: >\n    Uncover cutting-edge developments in {topic}\n    with supporting evidence and source citations\n  backstory: >\n    You're a seasoned researcher with 15 years of experience.\n    Known for finding obscure but relevant sources and\n    synthesizing complex findings into clear insights.\n    You always cite your sources and flag uncertainty.\n  # Optional overrides (uncomment as needed):\n  # llm: openai/gpt-4o\n  # max_iter: 15\n  # max_rpm: 10\n  # allow_delegation: false\n  # verbose: true\n```\n\nThen wire in `crew.py`:\n\n```python\n@CrewBase\nclass MyCrew:\n    agents_config = \"config/agents.yaml\"\n    tasks_config = \"config/tasks.yaml\"\n\n    @agent\n    def researcher(self) -> Agent:\n        return Agent(\n            config=self.agents_config[\"researcher\"],\n            tools=[SerperDevTool()],\n        )\n```\n\n**Critical:** The method name (`def researcher`) must match the YAML key (`researcher:`). Mismatch causes `KeyError`.\n\n---\n\n## 4. Agent.kickoff() — Direct Agent Execution\n\nUse `Agent.kickoff()` when you need one agent with tools and reasoning, without crew overhead. This is the most common pattern in Flows.\n\n### Basic Usage\n\n```python\nfrom crewai import Agent\nfrom crewai_tools import SerperDevTool\n\nresearcher = Agent(\n    role=\"Senior Research Analyst\",\n    goal=\"Find comprehensive, factual information with source citations\",\n    backstory=\"Expert researcher known for thorough, evidence-based analysis.\",\n    tools=[SerperDevTool()],\n    llm=\"openai/gpt-4o\",\n)\n\n# Pass a string prompt — the agent reasons, uses tools, and returns a result\nresult = researcher.kickoff(\"What are the latest developments in quantum computing?\")\nprint(result.raw)             # str — the agent's full response\nprint(result.usage_metrics)   # token usage stats\n```\n\n### With Structured Output\n\n```python\nfrom pydantic import BaseModel\n\nclass ResearchFindings(BaseModel):\n    key_trends: list[str]\n    sources: list[str]\n    confidence: float\n\nresult = researcher.kickoff(\n    \"Research the latest AI agent frameworks\",\n    response_format=ResearchFindings,\n)\n\n# Access via .pydantic (NOT directly — Agent.kickoff wraps the result)\nprint(result.pydantic.key_trends)    # list[str]\nprint(result.pydantic.confidence)    # float\nprint(result.raw)                    # raw string version\n```\n\n> **Note:** `Agent.kickoff()` returns `LiteAgentOutput` — access structured output via `result.pydantic`. This differs from `LLM.call()` which returns the Pydantic object directly.\n\n### With File Inputs\n\n```python\nresult = researcher.kickoff(\n    \"Analyze this document and summarize the key findings\",\n    input_files={\"document\": FileInput(path=\"report.pdf\")},\n)\n```\n\n### Async Variant\n\n```python\nresult = await researcher.kickoff_async(\n    \"Research quantum computing breakthroughs\",\n    response_format=ResearchFindings,\n)\n```\n\n### Agent.kickoff() in Flows (Recommended Pattern)\n\nThe most powerful pattern is orchestrating multiple `Agent.kickoff()` calls inside a Flow. The Flow handles state and sequencing; each agent handles its specific step:\n\n```python\nfrom crewai import Agent\nfrom crewai.flow.flow import Flow, listen, start\nfrom crewai_tools import SerperDevTool, ScrapeWebsiteTool\nfrom pydantic import BaseModel\n\nclass ResearchState(BaseModel):\n    topic: str = \"\"\n    research: str = \"\"\n    analysis: str = \"\"\n    report: str = \"\"\n\nclass ResearchFlow(Flow[ResearchState]):\n\n    @start()\n    def gather_data(self):\n        researcher = Agent(\n            role=\"Senior Researcher\",\n            goal=\"Find comprehensive data with sources\",\n            backstory=\"Expert at finding and validating information.\",\n            tools=[SerperDevTool(), ScrapeWebsiteTool()],\n        )\n        result = researcher.kickoff(f\"Research: {self.state.topic}\")\n        self.state.research = result.raw\n\n    @listen(gather_data)\n    def analyze(self):\n        analyst = Agent(\n            role=\"Data Analyst\",\n            goal=\"Extract actionable insights from raw research\",\n            backstory=\"Skilled at pattern recognition and synthesis.\",\n        )\n        result = analyst.kickoff(\n            f\"Analyze this research and extract key insights:\\n\\n{self.state.research}\"\n        )\n        self.state.analysis = result.raw\n\n    @listen(analyze)\n    def write_report(self):\n        writer = Agent(\n            role=\"Report Writer\",\n            goal=\"Create clear, well-structured reports\",\n            backstory=\"Technical writer who makes complex topics accessible.\",\n        )\n        result = writer.kickoff(\n            f\"Write a comprehensive report from this analysis:\\n\\n{self.state.analysis}\"\n        )\n        self.state.report = result.raw\n\nflow = ResearchFlow()\nflow.kickoff(inputs={\"topic\": \"AI agents\"})\nprint(flow.state.report)\n```\n\n**When to use Agent.kickoff() vs Crew.kickoff():**\n- Use `Agent.kickoff()` when each step is a distinct agent and the Flow controls sequencing\n- Use `Crew.kickoff()` when multiple agents need to collaborate on related tasks within a single step\n\n### Agent.kickoff() in Conversational Flow Routes\n\nIn 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.\n\n```python\nfrom crewai import Agent, Flow\nfrom crewai.flow import listen\nfrom crewai.experimental.conversational import ConversationState\n\n\nclass SupportFlow(Flow[ConversationState]):\n    conversational = True\n\n    def research_agent(self) -> Agent:\n        return Agent(\n            role=\"Support Research Specialist\",\n            goal=\"Find accurate information with sources for the user's current question.\",\n            backstory=\"You are precise, evidence-driven, and explicit about uncertainty.\",\n            tools=[...],\n        )\n\n    @listen(\"RESEARCH\")\n    def handle_research(self) -> str:\n        \"\"\"Fresh research, current lookups, and source-backed synthesis.\"\"\"\n        result = self.research_agent().kickoff(self.state.current_user_message)\n        self.append_agent_result(\"research_agent\", result, visibility=\"private\")\n        reply = result.raw\n        self.append_assistant_message(reply)\n        return reply\n```\n\nDesign implications:\n- Keep the conversational `Flow` responsible for session id, message history, routing, trace finalization, and approvals.\n- Keep each agent narrow: one route, one tool surface, one job.\n- Use `append_agent_result(..., visibility=\"private\")` for scratch work that should not enter canonical chat history.\n- Use `append_assistant_message(reply)` for the user-visible answer so the next turn has the assistant context.\n- Do not make a \"chat agent\" with every tool. Route first, then invoke a focused agent for the selected route.\n\nSee the getting-started reference for the Flow lifecycle: `skills/getting-started/references/conversational-flows.md`.\n\n---\n\n## 5. Specialist vs Generalist Agents\n\n> **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.\n\n**When you do need multiple agents, prefer specialists.** An agent that does one thing well outperforms one that does many things acceptably.\n\n### When to Use a Specialist\n\n- Task requires deep domain knowledge\n- Output quality matters more than speed\n- The task is complex enough to benefit from focused expertise\n\n### When a Generalist Is Acceptable\n\n- Simple tasks with clear instructions\n- Prototyping where you'll specialize later\n- Tasks that truly span multiple domains equally\n\n### Specialist Design Pattern\n\nInstead of one \"Content Writer\" agent, create:\n- `technical_writer` — deep technical accuracy, code examples\n- `copywriter` — persuasive, audience-focused marketing copy\n- `editor` — grammar, consistency, style guide enforcement\n\nEach specialist has a narrow role, specific goal, and backstory that reinforces their expertise.\n\n---\n\n## 6. Agent Interaction Patterns\n\n### Sequential (Default)\n\nAgents work one after another. Each agent receives prior agents' outputs as context.\n\n```\nResearcher → Writer → Editor\n```\n\nBest for: linear pipelines where each step builds on the last.\n\n### Hierarchical\n\nA manager agent delegates and validates. Task assignment is dynamic.\n\n```python\nCrew(\n    agents=[researcher, writer, editor],\n    tasks=[research_task, writing_task, editing_task],\n    process=Process.hierarchical,\n    manager_llm=\"openai/gpt-4o\",\n)\n```\n\nBest for: complex workflows where task assignment depends on intermediate results.\n\n### Agent-to-Agent Delegation\n\nWhen `allow_delegation=True`, an agent can ask another crew agent for help:\n\n```python\nlead_researcher = Agent(\n    role=\"Lead Researcher\",\n    goal=\"Coordinate research efforts\",\n    backstory=\"...\",\n    allow_delegation=True,  # Can delegate to other agents in the crew\n)\n```\n\nThe agent will automatically discover other crew members and delegate subtasks as needed.\n\n---\n\n## 7. Common Agent Design Mistakes\n\n| Mistake | Impact | Fix |\n|---|---|---|\n| Generic role like \"Assistant\" | Agent produces unfocused, shallow output | Use specific expertise: \"Senior Financial Analyst\" |\n| No tools for data-gathering tasks | Agent hallucinates data instead of searching | Always add tools when the task requires external info |\n| Too many tools (10+) | Agent gets confused choosing between tools | Limit to 3-5 relevant tools per agent |\n| Backstory full of task instructions | Agent mixes personality with task execution | Keep backstory about WHO the agent is; task details go in the task |\n| `allow_delegation=True` by default | Agents waste iterations delegating trivially | Only enable when delegation genuinely helps |\n| max_iter too high for simple tasks | Agent loops unnecessarily on vague tasks | Lower max_iter; fix the task description instead |\n| No guardrail on critical output | Bad output passes through unchecked | Add guardrails for outputs that feed into production systems |\n| Using expensive LLM for tool calls | Unnecessary cost for mechanical operations | Set `function_calling_llm` to a cheaper model |\n\n---\n\n## 8. Agent Design Checklist\n\nBefore deploying an agent, verify:\n\n- [ ] **Role** is specific and domain-focused (not \"Assistant\" or \"Helper\")\n- [ ] **Goal** includes desired outcome AND quality standards\n- [ ] **Backstory** establishes expertise and working style\n- [ ] **Tools** are assigned for any task requiring external data\n- [ ] **No excess tools** — 3-5 per agent maximum\n- [ ] **max_iter** is tuned for expected task complexity (10-15 for simple, 20-25 for complex)\n- [ ] **max_execution_time** is set for production agents to prevent hangs\n- [ ] **Guardrails** are configured for critical outputs\n- [ ] **LLM** is appropriate for task complexity (don't use GPT-4 for classification)\n- [ ] **Delegation** is disabled unless genuinely needed\n\n---\n\n## References\n\nFor deeper dives into specific topics, see:\n\n- [Custom Tools](references/custom-tools.md) — building your own tools with `@tool` decorator and `BaseTool` subclass\n- [Memory & Knowledge](references/memory-and-knowledge.md) — memory configuration, knowledge sources, embedder setup, scoping\n\nFor related skills:\n\n- **getting-started** — project scaffolding, choosing the right abstraction, Flow architecture\n- **design-task** — task description/expected_output best practices, guardrails, structured output, dependencies\n- **ask-docs** — query the live CrewAI documentation MCP server for questions not covered by these skills\n","contentSource":"https://raw.githubusercontent.com/crewaiinc/skills/main/skills/design-agent/SKILL.md","contentFetchedAt":"2026-07-27T09:00:57.983Z"}