Skip to main content
skill CX Codex

design-agent — Claude Code skill: what it does, how to install

Teaches your AI assistant how to configure CrewAI agents: define roles, set goals and backstories, assign tools, and adjust execution limits without token waste.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add crewAIInc/skills --skill design-agent -a claude-code
Open on GitHub

What design-agent does

The skill guides agent architecture for CrewAI 1.15.23. Its core heuristic advises starting with a single agent. Splitting work across multiple agents makes sense only when steps require distinct tools, different LLM tiers, or separate output schemas. Routine multi-step loops run faster inside a single Agent.kickoff() without building an entire Crew.

It defines the Role-Goal-Backstory framework and separates persona prompts from task logic. Task implementation details do not belong in the backstory. The configuration sets reasoning bounds: max_iter defaults to 25 reasoning steps, while max_execution_time applies exclusively to crew tasks.

Keep in mind that the Agent class silently ignores unknown keyword arguments. A typo in parameter names will not raise a runtime error, so checking Agent.model_fields is required whenever a setting appears inactive.

What it helps with

  • define specific role, goal, and backstory parameters for a CrewAI agent
  • decide whether a workflow needs one agent or a multi-agent crew
  • configure reasoning limits including max_iter and max_execution_time
  • eliminate redundant agent handoffs to reduce token costs

Example prompts for the agent

  • Design a CrewAI researcher agent with a specific role, goal, and backstory for scraping news.
  • Review these three CrewAI agents and check if they should be consolidated into one.
  • Configure max_iter and tool assignments for an Agent.kickoff() step in a Flow.

How to install design-agent

1Skills CLI (Vercel)

npx skills add crewAIInc/skills --skill design-agent -a claude-code

2Manually: put the files in place

~/.claude/skills/design-agent/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/design-agent/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about design-agent

How do I install design-agent in Claude Code?

Run npx skills add crewAIInc/skills --skill design-agent -a claude-code in your terminal.

What does the design-agent skill do?

It provides guidelines for configuring CrewAI agents, focusing on role definition, proper tool assignment, and avoiding unnecessary multi-agent complexity.

Why does CrewAI ignore misspelled agent parameters?

The Agent class silently drops unrecognized keyword arguments without raising exceptions. Verify parameter names against Agent.model_fields if a configuration has no effect.

Source text

SKILL.md · MIT
---
name: 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/delegation, setting up knowledge sources, using guardrails, or configuring agents in YAML vs code."
---

# CrewAI Agent Design Guide

How to design effective agents with the right role, goal, backstory, tools, and configuration.

Verified against crewai 1.15.23 on 2026-10-01.
Live-tested with real LLMs on 2026-10-01.

Exact API forms (imports, defaults, provider extras, structured output) are in the **check-crewai-api** skill, and tools and MCP are in **connect-tools-and-mcp**. Where this skill and those disagree, follow them.

---

## The 80/20 Rule

**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.

---

## 0. How Many Agents Do You Actually Need?

**Default to ONE agent.** Add more only when the task genuinely splits into work that requires:

- **Different tools or permissions** — e.g. one agent has Slack write access, another reads docs only.
- **Different personas the LLM must clearly switch between** — a writer's voice is not a researcher's voice.
- **Different LLMs** — a cheap model for mechanical steps, a stronger one for synthesis.
- **Different guardrails or output schemas** — separate agents make the contract per stage explicit.

**DO NOT add an agent just because the workflow has multiple steps.** A single agent can call multiple tools in sequence within one kickoff (search → scrape → summarize is one agent's loop), produce structured multi-section output in one response, and iterate via its own tool-use loop.

**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.

### Anti-patterns

❌ Three agents for what is one researcher's job:
```python
source_finder = Agent(role="Finds URLs via Firecrawl search", tools=[firecrawl_search])
scraper       = Agent(role="Scrapes URLs via Firecrawl scrape", tools=[firecrawl_scrape])
writer        = Agent(role="Writes the report")  # plus goal, backstory, llm
```

✅ One researcher does the gathering loop; one writer synthesizes — two agents because the personas and LLMs genuinely differ:
```python
researcher = Agent(role="Web Researcher", tools=[firecrawl_search, firecrawl_scrape], llm="anthropic/claude-haiku-4-5")
writer     = Agent(role="Technical Report Writer",                                    llm="anthropic/claude-sonnet-4-6")
```

❌ A `Summarizer` agent plus a `Slack Sender` agent (`apps=["slack"]`) to summarize a string and DM it.
✅ One `Slack Reporter` agent with `apps=["slack"]` and a task: "Write a 2-3 sentence executive summary at the top, then DM {recipient_email} the summary followed by the full body."

> **Heuristic:** if two "agents" share the same persona, the same tool surface, and the same LLM, they are one agent with a longer task description.

### Once you've decided "one agent is enough"

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 (Flow mechanics: **build-flow** skill; docs: <https://docs.crewai.com/en/concepts/agents#direct-agent-interaction-with-kickoff>).

```python
@listen(previous_step)
def my_step(self):
    agent = Agent(role="…", goal="…", backstory="…", tools=[...], llm="anthropic/claude-haiku-4-5")
    result = agent.kickoff(
        f"Use this prior step's output: {self.state.prior_field}",
        response_format=MyPydanticModel,  # optional
    )
    self.state.my_field = result.pydantic  # or result.raw
```

Reach for `Crew.kickoff()` *only* when a step genuinely benefits from multi-agent collaboration (delegation, hierarchical management, parallel specialists feeding one synthesis), or when the agent needs something that only works inside a crew task: **knowledge sources** and **`max_execution_time`** (Section 2).

---

## 1. The Role-Goal-Backstory Framework

Every agent needs three things: **who** it is, **what** it wants, and **why** it's qualified. `{placeholders}` in all three are filled from `crew.kickoff(inputs={...})`.

### Role — Who the Agent Is

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.

### Goal — What the Agent Wants

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` |

### Backstory — Why the Agent Is Qualified

The backstory establishes expertise, experience, values, and working style. It's the agent's "personality prompt."

```yaml
backstory: >
  You're a seasoned researcher with 15 years of experience in AI/ML.
  You're known for your ability to find obscure but relevant papers
  and synthesize complex findings into clear, actionable insights.
  You always cite your sources and flag uncertainty explicitly.
```

**Include:** years/depth of experience, specific domain knowledge, working style and values ("always cites sources", "prefers concise output"), and the quality standards the agent holds itself to.

**Leave out:** implementation details (tools, models, config), task-specific instructions (those go in the task description), and personality traits that don't affect output quality.

---

## 2. Agent Configuration Reference

`Agent` silently ignores keyword arguments it does not know, so a misspelled or removed parameter does nothing and raises nothing. Check `"name" in Agent.model_fields` when in doubt.

```python
Agent(
    role="...", goal="...", backstory="...",   # Required
    llm="anthropic/claude-haiku-4-5",          # See LLM Selection
    tools=[...],                               # Tool instances
    max_iter=25,             # Max reasoning iterations per task (default: 25)
    max_execution_time=300,  # Seconds, crew tasks only (default: None - no limit)
    max_rpm=10,              # Max LLM calls per minute for this agent (default: None)
    max_retry_limit=2,       # Retries when task execution errors (default: 2)
    allow_delegation=False,  # Default: False — agent works alone
    respect_context_window=True,  # Summarize and continue on overflow (default: True)
    inject_date=False,       # Put today's date in the prompt (default: False; format via date_format)
    verbose=False,           # Detailed execution logs (default: False)
)
```

### Execution limits (measured on 1.15.23)

| Limit | Behaviour |
|---|---|
| `max_iter` | Reaching it does **not** raise. The agent is told to give its final answer now, and the run "succeeds" with whatever it has. With `max_iter=1`, a four-step tool procedure recorded one step and returned an incomplete answer. |
| `max_rpm` | Calls over the limit block until the next minute window. With `max_rpm=2`, the third LLM call started at 62 s instead of about 2 s. |
| `max_execution_time` | Applies only when the agent runs a `Task` inside a `Crew`; `Agent.kickoff()` ignores it (a 5 s limit with a 15 s tool completed normally after 17 s). In a crew it does **not** stop work at the deadline: the running tool and LLM calls finish, then the task raises `TimeoutError: Task '...' execution timed out after 5 seconds` (raised at 18.8 s), and the finished work is discarded. |

So `max_execution_time` turns a slow run into an error but does not stop a hang. To bound wall-clock time, set timeouts where the time is spent: `LLM(model=..., timeout=60)` and timeouts inside your tools, or run the kickoff in a subprocess you can kill.

**Tuning `max_iter`:** the default 25 is generous - most tasks finish in 3-8 iterations. Lower it to 10-15 to fail faster when tasks are well-defined. If an agent keeps hitting it, the task is too vague (fix the task, not the limit). Hitting it does not raise, so check outputs, not exit codes.

**Other switches:** `respect_context_window=True` summarizes the conversation and continues when the provider reports that the context length was exceeded; with `False` the run stops with `SystemExit: Context length exceeded ...`. `inject_date=True` is worth it for time-sensitive tasks (research, news, scheduling): asked for today's date, an agent with it answered correctly, and one without it answered UNKNOWN.

### Tools

- 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.
- Prefer **fewer, focused tools** - too many tools confuses the agent.
- Agent-level tools are available for all tasks the agent performs. `Task(tools=[...])` **replaces** them for that task. In a live test, an agent with a weather tool given a task with only a population tool could call only the population tool.
- Prebuilt tools need their keys (`SerperDevTool()` needs `SERPER_API_KEY`). Custom tools, the `crewai_tools` names that really exist, caching and MCP servers: **connect-tools-and-mcp**.

### LLM Selection

```python
from crewai import LLM

Agent(..., llm="anthropic/claude-haiku-4-5")
Agent(..., llm=LLM(model="anthropic/claude-haiku-4-5", temperature=0.2, timeout=60))
```

- With no `llm=`, the agent uses env `MODEL`, then `MODEL_NAME`, then `OPENAI_MODEL_NAME`, else `gpt-4.1-mini`. That is an OpenAI model, so kickoff fails without `OPENAI_API_KEY`.
- Only OpenAI ships with core crewai. `anthropic/...` needs `uv add "crewai[anthropic]"`, `gemini/...` needs `crewai[google-genai]`, and non-native providers need `crewai[litellm]` (full table in **check-crewai-api**).
- Give mechanical agents a cheaper model. `function_calling_llm` (a separate model for tool calls) is deprecated on both `Agent` and `Crew` - set each agent's `llm` instead.

### Collaboration

Set `allow_delegation=True` only when the agent is part of a crew with other specialized agents, the task genuinely benefits from handing off subtasks, or you're using hierarchical process where the manager delegates. **Warning:** delegation without clear task boundaries leads to infinite loops or wasted iterations.

### Planning (Plan-and-Execute Mode)

With a `PlanningConfig`, the agent first generates a plan (a list of steps), executes each step in its own multi-turn loop (capped by `max_step_iterations`), checks each result, then continues, replans, or finishes early.

```python
from crewai import Agent
from crewai.agent.planning_config import PlanningConfig

agent = Agent(
    role="…", goal="…", backstory="…", tools=[...],
    planning_config=PlanningConfig(reasoning_effort="medium"),  # most common
)
```

To disable planning, omit `planning_config`. `planning=True` alone is shorthand for `PlanningConfig(reasoning_effort="low", max_attempts=1)`. `reasoning=True` is deprecated (DeprecationWarning) - use `planning_config`.

| `reasoning_effort` | After each step the planner... | Pick when |
|---|---|---|
| `"low"` | checks the step with a heuristic (**no extra LLM call**) and continues. No replan, no refine. | You want plan visibility (todos, observations) but trust the agent to follow it linearly. Fastest. |
| `"medium"` (default) | observes the step with an LLM call; **replans on failure only**. | The agent's tools can fail (network, exec, scrape) and you want graceful recovery. **The right default for sandbox-coding, research, and other tool-heavy loops.** |
| `"high"` | observes, then can finish early, replan fully, or refine the plan after every step. | The task changes shape based on intermediate findings, or you need maximum adaptiveness. Most LLM calls per run. |

```python
PlanningConfig(
    reasoning_effort="medium",
    observe_steps=None,      # None = LLM observation for medium/high, heuristic for low
    max_steps=20,            # cap on planned steps
    max_replans=3,           # full re-plans before finalizing
    max_attempts=None,       # refinement attempts during plan generation
    max_step_iterations=15,  # LLM turns per step
    step_timeout=None,       # wall-clock seconds per step
    system_prompt=None, plan_prompt=None, refine_prompt=None,  # custom prompts
    llm=None,                # separate (cheaper) LLM for planning; else agent.llm
)
```

**When to enable:** for autonomous loops where the agent picks its own steps and you want failure recovery (a coding agent that writes → runs → patches; a research agent that searches → scrapes → revises). **Skip** it for single-tool, single-purpose calls ("summarize this string", "post this Slack DM").

**Cost:** In one measured run, planning added 3-7 calls to a two-step task and wrapped the answer in prose. Measure on your own tasks before turning it on.

### Code Execution

`allow_code_execution` and `code_execution_mode` are deprecated no-ops (`allow_code_execution=True` emits a DeprecationWarning), and `CodeInterpreterTool` no longer exists in `crewai_tools`. Give the agent a sandbox tool such as `E2BPythonTool` or `DaytonaPythonTool` instead (see **connect-tools-and-mcp**).

### Agent Guardrails

```python
from typing import Any

def require_uppercase(result) -> tuple[bool, Any]:
    if result.raw != result.raw.upper():
        return (False, "Rewrite the whole answer in UPPERCASE letters only.")
    return (True, result.raw)

agent = Agent(..., guardrail=require_uppercase, guardrail_max_retries=3)  # default retries: 3
result = agent.kickoff("...")   # the agent guardrail runs here
```

A guardrail can also be a string, which is checked by an extra LLM call. Agent guardrails have two limits on 1.15.23, both verified with a real LLM:
- **They run only on `Agent.kickoff()`.** When the same agent executes a `Task` in a `Crew`, the agent guardrail is never called.
- **On crewai 1.15.23 the agent-level guardrail retry re-sent the original prompt without the feedback**, and all three attempts failed the uppercase check above. Prefer a task-level guardrail, which passes the feedback. When retries run out, `kickoff` raises `ValueError: Agent's guardrail failed validation after N retries. Last error: ...`.

When output must be fixed and not just rejected, put the guardrail on the **Task** (`Task(guardrail=..., guardrail_max_retries=...)`). The error message is fed back there, and the same uppercase check passed on the second attempt. See `design-task` and **check-crewai-api**.

### Knowledge Sources

```python
from crewai.knowledge.source.text_file_knowledge_source import TextFileKnowledgeSource

Agent(
    ...,
    knowledge_sources=[TextFileKnowledgeSource(file_paths=["company_handbook.txt"])],  # read from ./knowledge/
    embedder={"provider": "onnx"},   # local, no API key; omit it to use OpenAI embeddings
)
```

Knowledge sources give agents domain-specific data via RAG. Use them when agents need to reference large documents, policies, or datasets. Two things to know:
- **Agent knowledge is only queried when the agent runs a task inside a `Crew`.** `Agent.kickoff()` silently ignores `knowledge_sources`. In a live test, the same agent answered "UNKNOWN" from `kickoff()` and correctly from a one-task crew.
- Without `embedder=`, knowledge uses OpenAI embeddings. With no `OPENAI_API_KEY`, agent knowledge raises `ValueError: Invalid Knowledge Configuration` at crew kickoff. Crew-level knowledge only logs `Failed to upsert documents` and runs **without** it.

Embedders that work without OpenAI, `KnowledgeConfig`, memory and storage paths: [references/memory-and-knowledge.md](references/memory-and-knowledge.md).

---

## 3. YAML Configuration (Recommended)

Define agents in `agents.yaml` for clean separation of config and code. Create a YAML project with `crewai create crew <name> --classic`. Without `--classic`, `crewai create crew` starts an interactive wizard that writes a JSON project instead.

```yaml
researcher:
  role: >
    {topic} Senior Data Researcher
  goal: >
    Uncover cutting-edge developments in {topic}
    with supporting evidence and source citations
  backstory: >
    You're a seasoned researcher with 15 years of experience.
    Known for finding obscure but relevant sources and
    synthesizing complex findings into clear insights.
    You always cite your sources and flag uncertainty.
  # Optional overrides: llm: anthropic/claude-haiku-4-5, max_iter: 15, max_rpm: 10,
  # allow_delegation: false, verbose: true
```

Then wire in `crew.py`:

```python
@CrewBase
class MyCrew:
    agents_config = "config/agents.yaml"
    tasks_config = "config/tasks.yaml"

    @agent
    def researcher(self) -> Agent:
        return Agent(config=self.agents_config["researcher"], tools=[SerperDevTool()])
```

**Critical:** The method name (`def researcher`) must match the YAML key (`researcher:`). Mismatch causes `KeyError` (verified: `KeyError: 'researcher'`).

Verified live: `llm` and `max_iter` set in YAML are applied, `{topic}` in the role is filled at kickoff, and tools attach in Python. Keep tools, guardrail functions and Pydantic models in Python; YAML holds the text and scalar settings.

---

## 4. Agent.kickoff() — Direct Agent Execution

Use `Agent.kickoff()` when you need one agent with tools and reasoning, without crew overhead. This is the most common pattern in Flows. It does not use the agent's knowledge sources or `max_execution_time` (Section 2).

```python
from pydantic import BaseModel
from crewai import Agent

researcher = Agent(
    role="Senior Research Analyst",
    goal="Find comprehensive, factual information with source citations",
    backstory="Expert researcher known for thorough, evidence-based analysis.",
    tools=[...],
    llm="anthropic/claude-haiku-4-5",
)

result = researcher.kickoff("What are the latest developments in quantum computing?")
print(result.raw)             # str — the agent's full response
print(result.usage_metrics)   # dict: total_tokens, prompt_tokens, completion_tokens, ...

class ResearchFindings(BaseModel):
    key_trends: list[str]
    sources: list[str]
    confidence: float

result = researcher.kickoff("Research the latest AI agent frameworks", response_format=ResearchFindings)
print(result.pydantic.key_trends, result.pydantic.confidence)

result = await researcher.kickoff_async("...", response_format=ResearchFindings)  # async variant
```

> **Note:** `Agent.kickoff()` returns `LiteAgentOutput` - access structured output via `result.pydantic`. This differs from `llm.call(messages, response_model=Model)`, which returns the Pydantic object directly. `Agent.kickoff(..., response_model=...)` is a `TypeError`.

**File inputs** need an extra: `uv add "crewai[file-processing]"`, then `from crewai_files import FileInput` and `researcher.kickoff("Summarize this document", input_files={"document": FileInput(path="report.pdf")})`. Without the extra, the import fails with `ModuleNotFoundError: No module named 'crewai_files'`.

**Agent.kickoff() vs Crew.kickoff():** use `Agent.kickoff()` when each step is a distinct agent and a Flow controls sequencing (the Section 0 shape - verified live as a two-step Flow). Use `Crew.kickoff()` when multiple agents collaborate on related tasks within a single step, or the agent needs knowledge sources or `max_execution_time`.

### Agents in Conversational Flow Routes

In conversational Flows (`from crewai.flow import ConversationState`), the Flow owns the chat lifecycle and route selection. Call agents inside route handlers for bounded tool-backed work: research, docs lookup, account actions, triage, drafting, or escalation prep. The mechanics (`handle_turn`, `ConversationConfig`, a tested example) are in the **build-flow** skill's conversational-flows reference.

Design implications:
- Keep the conversational `Flow` responsible for session id, message history, routing, trace finalization, and approvals.
- Keep each agent narrow: one route, one tool surface, one job.
- Use `self.append_agent_result(name, result, visibility="private")` for scratch work that should not enter canonical chat history.
- Return the user-visible reply from the handler (or call `self.append_assistant_message(reply)`) so the next turn has the assistant context.
- Do not make a "chat agent" with every tool. Route first, then invoke a focused agent for the selected route.

---

## 5. Specialist vs Generalist Agents

> Apply this section *after* you've decided you genuinely need multiple agents (Section 0). With one agent, the only question is how to design that agent.

**When you do need multiple agents, prefer specialists.** An agent that does one thing well outperforms one that does many things acceptably. Use a specialist when the task needs deep domain knowledge, quality matters more than speed, or the task is complex enough to benefit from focused expertise. A generalist is acceptable for simple tasks with clear instructions, for prototyping you'll specialize later, and for tasks that truly span several domains equally.

Instead of one "Content Writer" agent, create `technical_writer` (technical accuracy, code examples), `copywriter` (persuasive, audience-focused copy) and `editor` (grammar, consistency, style guide). Each has a narrow role, specific goal, and a backstory that reinforces that expertise.

---

## 6. Agent Interaction Patterns

**Sequential (default):** `Researcher → Writer → Editor`. Agents work one after another, and each receives prior outputs as context. Best for linear pipelines where each step builds on the last.

**Hierarchical:** a manager agent delegates and validates; task assignment is dynamic. Best for complex workflows where assignment depends on intermediate results.

```python
Crew(
    agents=[researcher, writer, editor],
    tasks=[research_task, writing_task, editing_task],
    process=Process.hierarchical,
    manager_llm="anthropic/claude-haiku-4-5",   # or manager_agent=...; one is required
)
```

Without `manager_llm` or `manager_agent`, `Crew(...)` raises a `ValidationError`.

**Agent-to-agent delegation:** with `allow_delegation=True`, an agent gets two tools, `Delegate work to coworker` and `Ask question to coworker`, that name the other crew members. Verified live: asked to get a sentence from the Writer, a lead agent called `ask_question_to_coworker` and returned the Writer's answer.

---

## 7. Common Agent Design Mistakes

| 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 a Task guardrail for outputs that feed into production systems |
| Agent guardrail on an agent used in a Crew | Guardrail never runs | Put the guardrail on the Task |
| Trusting `max_execution_time` to stop a hang | It raises only after the slow call returns, and `Agent.kickoff()` ignores it | Add LLM and tool timeouts |
| Knowledge sources on an agent run via `Agent.kickoff()` | Knowledge silently unused | Run it as a crew task, or put the facts in the prompt |
| No `llm=` and no OpenAI key | Kickoff fails: the default is OpenAI `gpt-4.1-mini` | Set `llm=` (or env `MODEL`) and install the provider extra |
| Planning on a simple task | 2-3x the LLM calls, sometimes a worse answer | Enable planning only for open-ended tool loops |

---

## 8. Agent Design Checklist

Before deploying an agent, verify:

- [ ] **Role** is specific and domain-focused (not "Assistant" or "Helper")
- [ ] **Goal** includes desired outcome AND quality standards
- [ ] **Backstory** establishes expertise and working style
- [ ] **Tools** are assigned for any task requiring external data
- [ ] **No excess tools** — 3-5 per agent maximum
- [ ] **max_iter** is tuned for expected task complexity (10-15 for simple, 20-25 for complex)
- [ ] **Timeouts** are set where time is spent (LLM `timeout`, tool timeouts); `max_execution_time` is only a backstop for crew tasks
- [ ] **Guardrails** for critical outputs are on the Task
- [ ] **LLM** is set explicitly, fits the task's complexity, and has its provider extra installed
- [ ] **Knowledge** has an explicit `embedder`, and the agent runs inside a crew
- [ ] **Delegation** is disabled unless genuinely needed

---

## References

For deeper dives into specific topics, see:

- [Custom Tools](references/custom-tools.md) — building your own tools with `@tool` decorator and `BaseTool` subclass
- [Memory & Knowledge](references/memory-and-knowledge.md) - memory, knowledge sources, embedders that work without OpenAI, storage, scoping

For related skills:

- **check-crewai-api** - current imports, parameters, defaults and provider extras
- **connect-tools-and-mcp** - custom tools, real `crewai_tools` names, caching, MCP servers
- **build-flow** - Flow state, routing, persistence, conversational flows
- **getting-started** - project scaffolding, choosing the right abstraction
- **design-task** — task description/expected_output best practices, guardrails, structured output, dependencies
- **test-crewai-project** - testing agents and crews offline with a stub LLM
- **ask-docs** - query the live CrewAI docs for questions not covered by these skills

© crewAIInc · MIT · crewAIInc/skills

Similar skills

All skills for Agent setup: memory, context, orchestration →

From the same set5

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor