npx skills add ...
npx skills add crewaiinc/skills --skill design-task
CrewAI task design and configuration. Use when creating, configuring, or debugging crewAI tasks — writing descriptions and expected_output, setting up task dependencies with context, configuring output formats (output_pydantic, output_json, output_file), using guardrails for validation, enabling human_input, async execution, markdown formatting, or debugging task execution issues.
npx skills add crewaiinc/skills --skill design-task
How to write effective tasks that produce reliable, high-quality output from your agents.
Spend 80% of your effort on task design, 20% on agent design. The task is the most important lever you have. A well-designed task with a mediocre agent will outperform a poorly designed task with an excellent agent.
Every task needs two things: a description (what to do and how) and an expected_output (what the result looks like).
A good description includes:
The expected_output tells the agent what "done" looks like. Be specific about:
| Bad Expected Output | Good Expected Output |
|---|---|
A research report | A structured brief with 5 sections, each containing: trend name, 2-3 paragraph summary, source citations, and impact rating |
An analysis of the data | A markdown table with columns: metric name, current value, 30-day trend, and recommended action. Include at least 10 metrics. |
A blog post | A 1000-1500 word technical blog post with: title, introduction, 3-4 main sections with code examples, and a conclusion with next steps |
One task = one objective. Never combine multiple operations into a single task.
Each task has one clear objective. The sequential flow passes context automatically.
contextIn sequential process: Each task auto-receives all prior task outputs. Use context only when you need non-linear dependencies.
In hierarchical process: context is how you create explicit data flow between tasks.
Use output_pydantic or output_json when downstream code needs to parse the result:
Important: expected_output is always a string description — never a class name. The Pydantic model goes in output_pydantic, and the expected_output text tells the agent what fields to include.
Access structured output:
File output and structured output can be combined — the file gets the raw text, and output_pydantic gets the parsed model.
Use for tasks that can run in parallel. The crew continues to the next task while this one executes. Use context on downstream tasks to wait for async results.
When enabled, the agent presents its result and waits for human feedback before marking the task complete. Use for critical outputs that need human approval.
Do not use human_input=True or Flow @human_feedback to model normal follow-up chat. In conversational Flows, the next user line should be another flow.handle_turn(message, session_id=...) call. Human review is for approving or correcting a specific task/step output before it moves downstream.
Automatically instructs the agent to format output with proper markdown headers, lists, emphasis, and code blocks.
Guardrails validate task output before it passes to the next step. If validation fails, the agent retries.
Return format: (bool, Any) — first element is pass/fail, second is the result (on success) or error message (on failure).
String guardrails use the agent's LLM to evaluate the output. Good for subjective quality checks.
Guardrails execute sequentially. Each receives the output of the previous guardrail. Mix function-based (deterministic) and LLM-based (subjective) checks.
Critical: The method name (def research_task) must match the YAML key (research_task:).
In Process.sequential, tasks run in order. Each task automatically receives all prior task outputs as context.
You don't need context= in sequential — it's implicit. Use it only to create non-linear dependencies:
Tasks can have their own tools that override the agent's default tools for that specific task:
When to use task-level tools:
Use {variable} placeholders in YAML for reusable tasks:
Variables are replaced when you call crew.kickoff(inputs={...}):
Common mistakes:
inputs → literal {variable} appears in the prompt{{ }} Jinja2 syntax → crewAI uses single braces { }inputs → silently ignored (no error)| Mistake | Impact | Fix |
|---|---|---|
| Vague description ("Research the topic") | Agent produces shallow, unfocused output | Add specific steps, constraints, and context |
| Vague expected_output ("A report") | Agent guesses at format and structure | Specify format, sections, length, quality markers |
| Multiple objectives in one task | Agent does all of them poorly | Split into focused single-purpose tasks |
| Modeling each chat turn as a Crew task | Tasks are batch/workflow units, not the conversational session loop | Use a conversational Flow and call handle_turn() per user message |
| No context between dependent tasks | Agent lacks information from prior steps | Use context=[prior_task] for explicit dependencies |
expected_output references a Pydantic class | Agent sees a class name string, not field names | Keep expected_output as a human-readable string; use output_pydantic for the model |
| Missing tools for data tasks | Agent fabricates data instead of fetching it | Add tools to the task or agent |
| No guardrails on critical output | Bad output flows downstream unchecked | Add function or LLM guardrails |
| Overly strict expected_output | Agent loops trying to match impossible criteria | Be specific but achievable; lower guardrail_max_retries to fail faster |
| Description duplicates backstory | Wasted tokens and confused agent | Description = what to do; backstory = who you are |
Before running a task, verify:
context where neededinputs dict keysFor deeper dives into specific topics, see:
output_pydantic, output_json, and response_format patterns across LLM, Agent, Task, and Crew levelsFor related skills: