mcpField
D
design-task

design-task

github.com/crewaiincAgent 工作流488.2k 次安装3 周前更新
代码仓库

关于 design-task

design-task 是用于设计 CrewAI 任务的技能,涵盖清晰的指令、输出、依赖关系和质量检查。它还说明结构化输出、护栏、异步执行及人工审核等配置与执行细节。

主要功能

  1. 01定义任务说明和预期输出
  2. 02说明任务上下文与依赖关系
  3. 03涵盖结构化输出和文件输出
  4. 04配置异步执行与人工审核
  5. 05介绍函数和 LLM 护栏

适用场景

  1. 01为研究任务设定明确标准
  2. 02向后续任务传递选定结果
  3. 03在结果传递前进行校验
  4. 04暂停关键结果以供人工审核

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/crewaiinc/skills --skill design-task

安装后在 Claude Code 中输入/design-task确认已加载。

附带文件references/structured-output.md

详细介绍

CrewAI 任务设计指南

如何编写有效的任务,让 Agent 产出可靠、高质量的结果。

已于 2026-10-01 针对 crewai 1.15.22 和 1.15.23 验证。 已于 2026-10-01 使用真实大模型进行实测。 关于当前准确的 API 格式(导入、参数名称、结构化输出、guardrail 签名),请以 check-crewai-api 技能为准;如果本技能与其内容有出入,请遵循 check-crewai-api。


80/20 法则:将 80% 的精力投入任务设计,20% 的精力投入 Agent 设计。 任务是你最重要的杠杆。设计良好的任务搭配普通 Agent,也胜过设计糟糕的任务搭配优秀 Agent。


1. 有效任务的构成

每个任务都需要两项内容:描述(要做什么以及如何做)和 expected_output(结果应是什么样)。两者缺一不可——仅使用 Task(description=...) 会引发 ValidationError ... expected_output Field required。

描述——指令

好的描述应包含:

  1. 做什么——核心操作
  2. 如何做——具体步骤或方法
  3. 背景——任务为何重要、结果将用于何处
  4. 约束——范围限制、需要避免的事项
  5. 输入——可用的数据或上下文
research_task:
  description: >
    Conduct thorough research about {topic} for the year {current_year}.

    Your research should:
    1. Identify the top 5 key trends and breakthroughs
    2. For each trend, find at least 2 credible sources
    3. Note any controversies or competing viewpoints
    4. Assess potential industry impact (high/medium/low)

    Focus on developments from the last 6 months.
    Do NOT include speculation or unverified claims.
    The output will feed into a report for {target_audience}.
  expected_output: >
    A structured research brief with 5 sections, one per trend.
    Each section includes: trend name, 2-3 paragraph summary,
    source citations, impact assessment (high/medium/low),
    and a confidence level for your findings.
  agent: researcher
预期输出——成功标准

expected_output 用于告诉 Agent 什么样的结果才算“完成”。请具体说明:

  • 格式——项目符号、段落、JSON、表格
  • 结构——章节、标题、顺序
  • 长度——大致字数或条目数
  • 质量指标——是否需要引用、置信度等级、具体字段
不佳的预期输出良好的预期输出
A research report一份结构化简报,包含 5 个部分,每部分包括:趋势名称、2-3 段摘要、来源引用和影响评级
An analysis of the data一个 Markdown 表格,包含以下列:指标名称、当前值、30 天趋势和建议采取的行动。至少包含 10 项指标。
A blog post一篇 1000-1500 字的技术博客文章,包含:标题、引言、3-4 个带代码示例的主体章节,以及包含后续步骤的结论

2. 单一目标原则

一个任务 = 一个目标。 切勿将多个操作合并到一个任务中。

# DON'T - a "god task" with four objectives
research_and_write_task:
  description: >
    Research {topic}, analyze the findings, write a blog post,
    and proofread it for grammar errors.
  expected_output: >
    A polished blog post about {topic}.

# DO - focused tasks, one objective each
research_task:
  description: >
    Research {topic} and identify the top 5 key developments.
  expected_output: >
    A research brief with 5 sections covering key trends.
  agent: researcher

writing_task:
  description: >
    Using the research findings, write a technical blog post about {topic}.
  expected_output: >
    A 1000-1500 word blog post with introduction, main sections, and conclusion.
  agent: writer
# ...and an editing_task with agent: editor

每个任务都有一个明确目标。顺序流程会自动传递上下文。


3. 任务配置参考

必需参数
Task(description="...", expected_output="...", agent=researcher)  # agent: required for sequential, optional for hierarchical

不含 Agent 的顺序型 Crew 会在 Crew(...) 处失败:Sequential process error: Agent is missing in the task ...。

使用 context 设置任务依赖关系
analysis_task = Task(description="Analyze the research findings...", expected_output="...",
                     agent=analyst, context=[research_task])  # receives only research_task's output

顺序型和层级型 Crew 遵循相同规则:

  • 不设置 context——任务会接收之前运行的所有任务的原始输出。
  • context=[a, b]——任务只会接收这些任务的输出。
  • context=[]——任务不会接收任何先前输出。

context 条目必须是 Crew 中较早的任务;如果指向较晚的任务,会在 Crew(...) 处失败(“context dependency on a future task”)。

结构化输出

如果下游代码需要解析结果,请使用 output_pydantic 或 output_json:

from pydantic import BaseModel

class ResearchReport(BaseModel):
    trends: list[str]
    confidence: float
    sources: list[str]

research_task = Task(description="...", agent=researcher,
                     expected_output="A structured report with trends, confidence score, and sources.",
                     output_pydantic=ResearchReport)   # agent's output is parsed into this model

重要: expected_output 始终是一个字符串描述,绝不能是类名。Pydantic 模型应放在 output_pydantic 中,而 expected_output 文本则告诉 Agent 应包含哪些字段。output_pydantic 和 output_json 只能设置其中一个(同时设置会引发 Only one output type can be set)。

访问结构化输出:

result = crew.kickoff(inputs={...})
last_task_output = result.pydantic          # Pydantic model from the LAST task (None if it has no output_pydantic)
all_outputs = result.tasks_output           # List of all TaskOutput objects
first_task = all_outputs[0].pydantic        # Pydantic from a specific task
assert first_task is not None, "structured output was dropped"

在 Python 中设置 output_pydantic,不要在 tasks.yaml 中设置(见第 5 节)。不要使用 Task(response_format=...)(会被静默忽略)或 Task(response_model=...)(.pydantic 仍为 None)。更多信息:structured-output.md。

文件输出

Task(..., output_file="output/report.md") 会保存输出;create_directory(默认为 True)会创建缺失的目录。写入内容取决于输出类型:普通任务写入原始文本;但如果设置了 output_pydantic 或 output_json,则会写入模型的 JSON(即使文件名以 .md 结尾)。如果你想从结构化任务生成人类可读的文件,请添加一个不使用模型的独立格式化任务,并为其指定 output_file。

异步执行
pros = Task(..., agent=analyst, async_execution=True)
cons = Task(..., agent=critic, async_execution=True)    # a DIFFERENT agent
verdict = Task(..., agent=analyst, context=[pros, cons])
crew = Crew(agents=[analyst, critic], tasks=[pros, cons, verdict])

异步任务启动后不会等待;连续的异步任务会并发运行。下一个同步任务会等待所有待处理的异步任务完成后才启动,并且(未设置 context 时)会看到它们的所有输出;设置 context=[...] 可选择要使用哪些输出。

以下规则均会强制执行:

  • 每个并发运行的异步任务都必须使用自己的 Agent。 两个异步任务使用同一个 Agent 时,会在启动时失败,并报错 RuntimeError: Executor is already running. Cannot invoke the same executor instance concurrently.
  • 一个 crew 最多只能以一个异步任务结束(The crew must end with at most one asynchronous task)——请以一个汇总结果的同步任务收尾。
  • 异步任务不能在自己的 context 中列出同一并发运行中的异步任务;ConditionalTask 也不能设为异步。
人工审核

Task(..., human_input=True) 会在最终确定前暂停,以供人工审核。Agent 生成答案后,终端会显示 “Human Feedback Required” 面板,并从 stdin 读取一行输入。输入反馈后,Agent 会修改答案并再次询问;输入空行(按 Enter)即可接受答案。适用于需要人工批准的关键输出。

此功能需要交互式 stdin。在 CI、服务器或任何 stdin 已关闭的运行环境中,input() 会引发 EOFError,并且会在 Agent 重试后才发生,因此你还要为额外的大模型调用付费。若要通过脚本驱动,请通过管道传入答案:printf 'Make it shorter.\n\n' | python run.py(一轮反馈,然后接受答案)。对于无法依赖终端的审批步骤,请参阅 build-flow 技能中的 Flow @human_feedback。

不要使用 human_input=True 或 Flow @human_feedback 来模拟常规的后续聊天。 在对话式 Flow 中,下一条用户消息应通过另一次 flow.handle_turn(message, session_id=...) 调用来处理。人工审核用于在特定任务/步骤输出传递到下游之前,对其进行批准或修正。

Markdown 格式

Task(..., markdown=True) 会向任务提示词追加一条指令,要求最终答案必须使用 Markdown(标题、粗体/斜体、项目符号列表、代码跨度和围栏代码块)。

回调
def log_completion(output: TaskOutput) -> None:   # from crewai import TaskOutput
    print(f"Task completed: {output.description[:50]}...")

Task(..., callback=log_completion)  # called with the TaskOutput after the task and its guardrails finish

4. 任务护栏——质量控制

护栏会在任务输出传递到下一步之前对其进行验证。如果验证失败,错误会反馈给 Agent,任务会重试,最多重试 guardrail_max_retries 次(默认为 3)。之后任务会引发 Task failed guardrail validation after N retries. Last error: ...。

基于函数的护栏
from typing import Any

from crewai import Task, TaskOutput


def validate_word_count(output: TaskOutput) -> tuple[bool, Any]:
    """Ensure output is between 500-2000 words."""
    word_count = len(output.raw.split())
    if word_count < 500:
        return (False, f"Output too short ({word_count} words). Expand to at least 500 words.")
    if word_count > 2000:
        return (False, f"Output too long ({word_count} words). Condense to under 2000 words.")
    return (True, output.raw)

Task(..., guardrail=validate_word_count, guardrail_max_retries=3)  # max retries (default: 3)

返回格式: (bool, Any)——第一个元素表示通过/失败,第二个元素是在成功时返回的结果(一个会成为任务原始输出的字符串——通常是 output.raw;绝不能为 None),或在失败时返回的错误消息。应返回字符串,而不是 TaskOutput 本身:当任务设置了 output_pydantic 且其 Agent 使用了工具时,护栏内部的 output.pydantic 仍为 None;(True, output) 会使其保持为 None,因此 result.pydantic 最终也会是 None;而 (True, output.raw) 则允许 crewai 对其进行转换(已在 1.15.22 和 1.15.23 上验证)。将返回类型标注为 tuple[bool, Any],或不进行标注:在 Task(...) 中使用 -> bool 会引发 If return type is annotated, it must be Tuple[bool, Any]。请使用 guardrail_max_retries,不要使用已弃用的 max_retries。

基于 LLM 的护栏
Task(..., agent=writer, guardrail="Verify the output contains at least 3 source citations and no speculative claims.")

字符串护栏会通过一次额外的大模型调用进行检查,该调用使用任务 Agent 的大模型。适合主观质量检查。任务必须设置 agent,否则 Task(...) 会引发 Agent is required to use non-programmatic guardrails。

串联多个护栏
def validate_no_pii(output: TaskOutput) -> tuple[bool, Any]:
    if "@" in output.raw:
        return (False, "Remove email addresses.")
    return (True, output.raw)

Task(..., guardrails=[
    validate_word_count,           # Function: check length
    validate_no_pii,               # Function: check for PII
    "Ensure the tone is professional and appropriate for a business audience.",  # LLM check
])

护栏按顺序执行。每个护栏都会接收上一个护栏的输出(字符串结果会替换下一个护栏的 output.raw)。可以混合使用基于函数的(确定性)检查和基于 LLM 的(主观)检查。如果同时设置了 guardrails=[...] 和 guardrail=,则只会使用列表。


5. YAML 配置(推荐)

tasks.yaml
research_task:            # full description/expected_output as in section 1
  description: >
    Conduct thorough research about {topic} for {current_year}.
  expected_output: >
    A structured research brief with 5 sections.
  agent: researcher

analysis_task:
  description: >
    Analyze the research findings and recommend actions for {target_audience}.
  expected_output: >
    A prioritized list of 5 recommendations with rationale and expected impact.
  agent: analyst
  context:
    - research_task

report_task:
  description: >
    Compile a final report combining research and analysis for {target_audience}.
  expected_output: >
    A polished markdown report with executive summary, findings and recommendations.
  agent: writer
  output_file: output/report.md
在 crew.py 中连接配置
from pydantic import BaseModel

from crewai import Agent, Crew, Task
from crewai.project import CrewBase, agent, crew, task

class Recommendations(BaseModel):
    items: list[str]

@CrewBase
class ResearchCrew:
    agents_config = "config/agents.yaml"
    tasks_config = "config/tasks.yaml"

    # @agent methods researcher, analyst, writer omitted

    @task
    def research_task(self) -> Task:
        return Task(config=self.tasks_config["research_task"])

    @task
    def analysis_task(self) -> Task:
        # context and agent come from YAML; the model class must be set here in Python
        return Task(config=self.tasks_config["analysis_task"], output_pydantic=Recommendations)

    @task
    def report_task(self) -> Task:
        return Task(config=self.tasks_config["report_task"])   # output_file comes from YAML

    @crew
    def crew(self) -> Crew:
        return Crew(agents=self.agents, tasks=self.tasks)

方法名称必须与 YAML 键完全相同。 YAML 中的 context: 条目会通过调用对应名称的 @task 方法解析,agent: 则通过调用对应名称的 @agent 方法解析,因此名称不匹配会导致 crew 构建失败。description、expected_output、agent、context、output_file、human_input、async_execution 和 markdown 可在 YAML 中使用;output_pydantic、output_json、函数护栏和 tools 应放在 Python 方法中。


6. 任务依赖和上下文流

任务按列表顺序运行。不带 context 的任务会接收所有更早任务的原始输出。

research_task → analysis_task → report_task
     ↓               ↓              ↓
  (none)         output 1      output 1 + 2

无需为此设置 context=——这是隐式的。使用它可以缩小或调整依赖关系:

# Diamond dependency pattern
task_a = Task(...)                            # Entry point
task_b = Task(..., context=[task_a])          # Depends on A
task_c = Task(..., context=[task_a])          # Also depends on A
task_d = Task(..., context=[task_b, task_c])  # Depends on both B and C
条件任务
from pydantic import BaseModel

from crewai import Task, TaskOutput
from crewai.tasks.conditional_task import ConditionalTask   # not crewai.task

class Items(BaseModel):
    items: list[str]

gather = Task(description="List data sources for {topic}...", expected_output="A list of sources.",
              agent=researcher, output_pydantic=Items)   # the condition below reads .pydantic

def needs_more_data(output: TaskOutput) -> bool:
    return len(output.pydantic.items) < 10

extra_research = ConditionalTask(description="Fetch additional data sources...", expected_output="...",
                                 agent=researcher,
                                 condition=needs_more_data)  # runs only if the previous output has < 10 items

条件会接收紧邻它之前的任务的 TaskOutput。被跳过的条件任务仍会出现在 result.tasks_output 中,且 raw == ""。ConditionalTask 不能是第一个任务,不能异步运行,且 crew 不能只包含条件任务。


7. 任务工具

任务可以拥有自己的工具,这些工具会替代 Agent 在该特定任务中的默认工具:

from crewai_tools import SerperDevTool, ScrapeWebsiteTool

Task(description="Search for and scrape the top 5 articles about {topic}...", expected_output="...",
     agent=researcher, tools=[SerperDevTool(), ScrapeWebsiteTool()])  # task-specific tools

如果在任务上设置了 tools,Agent 在该任务中将仅使用这些工具——工具列表不会合并。若要使用 Agent 的工具,请不要设置该项。

当任务需要 Agent 通常没有的工具、需要限制 Agent 在某个任务中的工具,或同一个 Agent 在不同任务中需要不同工具集时,请使用任务级工具。


8. 变量插值

在 YAML 中使用 {variable} 占位符来创建可复用任务:

research_task:
  description: >
    Research {topic} trends for {current_year}, targeting {target_audience}.
  expected_output: >
    A report on {topic} suitable for {target_audience}.

变量会在启动时替换:crew.kickoff(inputs={"topic": "AI Agents", "current_year": "2026", "target_audience": "developers"})。

常见错误:

  • inputs 中缺少变量 → kickoff 会引发 ValueError: Missing required template variable ... 'audience' not found in inputs dictionary
  • 使用 {{ }} Jinja2 语法 → crewAI 使用单层花括号 { };{{topic}} 会渲染为 {AI Agents}
  • inputs 中有未使用的变量 → 会被静默忽略(不会报错)

9. 常见任务设计错误

错误影响修复方法
描述含糊(“研究这个主题”)Agent 生成的内容浅显且缺乏重点添加具体步骤、限制条件和上下文
预期输出含糊(“一份报告”)Agent 自行猜测格式和结构指定格式、章节、篇幅和质量标准
在一个任务中包含多个目标Agent 无法把其中任何一个做好将任务拆分为目标明确、用途单一的任务
将每轮聊天都建模为一个 Crew 任务任务是批处理/工作流单元,而不是对话会话循环使用对话式 Flow,并针对每条用户消息调用 handle_turn()
下游任务看到过多或错误的先前输出默认会传递所有先前输出使用 context=[prior_task](或 context=[])进行选择
expected_output 引用了 Pydantic 类Agent 看到的是类名字符串,而非字段名称将 expected_output 保留为人类可读的字符串;使用 output_pydantic 指定模型
在 tasks.yaml 中设置 output_pydantic出现 KeyError,或模型被丢弃且 .pydantic 为 None在 @task 方法中设置 output_pydantic=Model
同一 Agent 上有两个异步任务RuntimeError: Executor is already running每个并发运行的异步任务使用一个 Agent
在 CI 或服务端设置 human_input=True重试浪费后出现 EOFError将答案传入 stdin,或使用 Flow @human_feedback
数据任务缺少工具Agent 会编造数据,而不是获取数据为任务或 Agent 添加工具
关键输出没有护栏错误输出未经检查便传递到下游添加函数或 LLM 护栏
结构化任务的护栏返回 (True, output)虽然运行通过,但 result.pydantic 为 None返回 (True, output.raw);断言 .pydantic 不为 None
预期输出或护栏过于严格Agent 不断重试,直到出现 Task failed guardrail validation设定具体但可实现的要求;调低 guardrail_max_retries,以便更快失败
描述重复背景故事浪费 token,并使 Agent 困惑描述 = 要做什么;背景故事 = 你是谁

10. 任务设计检查清单

运行任务前,请确认:

  • 描述包含要做什么、如何做、上下文和限制条件
  • 预期输出指定格式、结构和质量标准
  • 目标单一——每个任务有一个明确目标
  • 已分配 Agent(顺序执行的 crews 和字符串护栏均为必需)
  • 当默认设置(所有先前输出)不合适时,通过 context 设置依赖项
  • 为需要外部数据的任务提供工具
  • 在 Python 中设置结构化输出,并断言 .pydantic 非 None
  • 为关键输出设置护栏,并返回 (bool, value)
  • 异步任务各自使用独立的 Agent,之后跟随一个同步任务
  • YAML 中的变量与 inputs 字典的键相匹配
  • 预期输出可实现——在增加复杂度前,先用简单运行进行测试

参考资料

如需深入了解特定主题,请参阅:

  • 结构化输出 - output_pydantic、output_json、response_model 和 response_format 在 LLM、Agent、Task 和 Crew 各级别的用法

相关技能:

  • check-crewai-api - crewai 1.15.x 中当前的导入路径、参数名称、结构化输出和护栏形式
  • getting-started — 项目脚手架、选择合适的抽象、Flow 架构
  • design-agent — Agent 的角色-目标-背景故事框架、参数调优、工具分配、记忆与知识配置
  • build-flow - Flow 状态、路由器和 @human_feedback
  • test-crewai-project - 使用存根 LLM 离线测试护栏和任务连接
  • connect-tools-and-mcp - 附加到任务的工具,以及现有的 crewai_tools 名称
  • ask-docs - 查询 CrewAI 实时文档,获取这些技能未涵盖的问题

评论

支持 Markdown