《数字工匠的蓝图:揭秘Cooragent中AI智能体模板的设计与运作》

在人工智能的浪潮之巅,多智能体协作系统 (Multi-Agent Systems) 正以其解决复杂问题的卓越潜力,吸引着全球研究者的目光。它们如同一个高度协同的数字工匠团队,每个成员各司其职,共同完成宏伟的目标。然而,如何高效、灵活地定义和管理这些“数字工匠”的行为模式,一直是该领域的核心挑战。来自 LeapLabTHU 的 Cooragent 项目,为我们展示了一种精巧的解决方案——基于模板的智能体设计。今天,就让我们一同深入 Cooragent 的内核,揭开其 Agent 模板设计与运作的神秘面纱,探索这些“蓝图”如何赋予 AI 智能体生命与智慧。

📜 引言:AI智能体编排的艺术

想象一下,我们要构建一个能够自动化完成复杂软件项目或深度研究任务的 AI 系统。这需要不同类型的 AI 智能体——有的擅长编码,有的精于研究,有的则负责任务规划与协调。Cooragent 的设计者们巧妙地意识到,为每一种智能体从零开始定制行为逻辑既耗时又不灵活。他们引入了“模板”这一核心概念,如同为不同工种的工匠预先绘制好的行为蓝图。这些模板不仅定义了智能体的基本属性和能力,更重要的是,它们规范了智能体的思考方式和行动指南,使得整个多智能体系统能够像一部精密编排的交响乐般和谐运作。

🧩 基石:智能体模板的精巧构造 (.md 的魔力)

Cooragent 中智能体模板的物理载体,是一系列位于 src/prompts/ 目录下的 Markdown (.md) 文件 [coder.md:1-40, researcher.md:1-42]。这种选择本身就体现了设计的匠心:Markdown 格式易于人类阅读和编辑,同时也能被程序高效解析。每个 .md 文件都代表着一种特定类型智能体的“基因序列”。

打开其中一个模板,例如 coder.md (一个为软件工程智能体设计的模板),我们会发现其结构清晰,通常包含以下几个核心部分 [coder.md:1-40]:

  1. 时间戳 (CURRENT_TIME: `<<CURRENT_TIME>>`): 这是一个动态变量,会在运行时被替换为当前时间,为智能体提供时间上下文,这对于需要时效性信息的任务至关重要。
  2. 角色定义 (Role Definition): 开宗明义地声明智能体的身份和专业领域。例如,coder.md 中定义其为“一个专业的软件工程智能体,精通 Python 和 bash 脚本编写” [coder.md:4-5]。
  3. 任务描述 (Task Description): 这是一个非常有趣的设计。模板并不总是直接给出具体任务,有时它会指导智能体如何 自行寻找 任务描述。例如,在 coder.mdresearcher.md 中,智能体被告知需要在用户输入的 ["steps"] 列表中,根据自己的 agent_name (如 “coder” 或 “researcher”) 找到对应的 ["description"]["note"] [coder.md:8-15, researcher.md:8-12]。这种“元指令”赋予了智能体一定程度的自主性和对复杂指令结构的理解能力。
  4. 执行步骤 (Steps): 这是模板的核心,详细列出了智能体完成任务时应遵循的思考和行动流程。例如,coder.md 的步骤包括:寻找任务描述、需求分析、方案规划、方案实现(区分 Python 和 bash 的使用场景)、测试验证、方法文档化和结果呈现 [coder.md:17-32]。而 researcher.md 则强调理解问题、规划方案、执行方案(使用 tavily_tool 搜索和 crawl_tool 爬取内容)、综合信息等步骤 [researcher.md:15-29]。
  5. 注意事项 (Notes): 这部分提供了智能体在执行任务时必须遵守的规则、约束和最佳实践。比如,coder.md 强调代码效率、错误处理、代码注释、仅用 Python 进行数学计算和文件操作、以及如何安装缺失库(uv add <library name>)等 [coder.md:34-40]。researcher.md 则提醒要验证信息相关性和可信度,不要进行数学计算或文件操作等 [researcher.md:38-42]。

这些 .md 模板通过 <<VAR>> 的形式定义变量占位符,这些占位符将在运行时被具体情境下的值所替换,从而实现模板的动态适应性 [template.py:12-25]。

⚙️ 引擎:模板的动态生命力 (template.py 的魔法)

静态的 .md 文件是如何转化为驱动 AI 智能体行动的动态指令的呢?这背后的“魔法引擎”便是 src/prompts/template.py 文件。该文件中的函数负责读取、解析和应用这些模板。

关键函数之一是 get_prompt_template(prompt_name: str) [template.py:12-25]。它的工作流程大致如下:

  1. 根据 prompt_name (例如 “coder” 或 “researcher”) 找到对应的 .md 模板文件。
  2. 读取文件内容。
  3. 使用正则表达式 re.findall(r"<<([^>>]+)>>", template) 提取出所有 <<VAR>> 格式的变量名。
  4. 为了与 Python 的字符串格式化兼容,它会先将模板中的 {} 转义为 {{}},然后将 <<VAR>> 替换为 {VAR} 格式。
  5. 最终返回处理后的模板字符串和提取出的变量名列表。

另一个核心函数是 apply_prompt_template(prompt_name: str, state: AgentState, template:str=None) [template.py:28-47]。此函数负责将具体的智能体状态 AgentState (包含了当前对话历史、用户信息等) 应用到加载好的模板上:

  1. 它首先获取模板 (如果未直接提供 template 参数,则调用 get_prompt_template)。
  2. 然后,使用 PromptTemplate (可能来自 LangChain 或类似库) 将模板中的变量 (如 CURRENT_TIMEstate 中包含的其他信息) 替换为实际值,生成最终的系统提示 system_prompt
  3. 这个 system_prompt 会与当前的消息历史 messages (同样经过格式化,区分为 “user” 和 “assistant” 角色) 结合,构成发送给大型语言模型 (LLM) 的完整输入。

通过这种机制,每个智能体在执行任务前,都会获得一个根据其角色模板和当前情境量身定制的、充满动态信息的“行动纲领”。

# template.py 中的核心逻辑示意
def get_prompt_template(prompt_name: str) -> tuple[str, list[str]]:
    # ... 读取 prompts_dir / f"{prompt_name}.md" ...
    template_content = read_file_content()
    variables = re.findall(r"<<([^>>]+)>>", template_content)
    # 将 <<VAR>> 替换为 {VAR} 以便格式化
    formatted_template = re.sub(r"<<([^>>]+)>>", r"{\1}", template_content)
    return formatted_template, variables

def apply_prompt_template(prompt_name: str, state: AgentState, template_str:str=None) -> list:
    # ... 获取并格式化消息 ...
    _template, _ = get_prompt_template(prompt_name) if not template_str else (template_str, [])
    # 使用 state 中的值填充模板
    system_prompt_content = _template.format(CURRENT_TIME=datetime.now().strftime(...), **state)
    return [{"role": "system", "content": system_prompt_content}] + formatted_messages

👤 化身:Agent 类的定义与 AgentManager 的统筹

模板定义了“角色类型”,而具体的“角色实例”则由 src/interface/agent_types.py 文件中定义的 Agent 类来承载 [agent_types.py:30-46]。一个 Agent 对象封装了一个智能体实例的所有关键信息:

  • user_id: 用户标识。
  • agent_name: 智能体的唯一名称。
  • nick_name: 智能体的昵称。
  • description: 对智能体能力的描述。
  • llm_type: 该智能体背后驱动的语言模型类型 (例如,特定的 GPT 版本或其他模型)。
  • selected_tools: 一个列表,定义了该智能体可以使用的工具集 (如搜索工具、代码执行器等)。
  • prompt: 该智能体所使用的提示模板内容 (通常是 get_prompt_template 返回的模板字符串)。

这些 Agent 实例并非孤立存在,而是由 src/manager/agents.py 中的 AgentManager 类进行统一管理 [agents.py]。AgentManager 负责智能体的创建、保存、加载、编辑和删除等生命周期操作。

值得注意的是,AgentManager 在初始化时,会预定义一系列基础的、共享的智能体 (user_id="share"),例如:

  • researcher: 使用 tavily_tool (搜索) 和 crawl_tool (网页内容爬取) 的研究型智能体,其 prompt 来自 get_prompt_template("researcher") [agents.py:49-55]。
  • coder: 使用 python_repl_tool (Python代码执行) 和 bash_tool (Bash命令执行) 的编码型智能体,其 prompt 来自 get_prompt_template("coder") [agents.py:56-62]。
  • browser: 使用 browser_tool 进行网页交互的智能体 [agents.py:65-71]。
  • reporter: 专注于基于提供信息生成报告的智能体,不使用额外工具 [agents.py:73-79]。

_create_mcp_agent 方法展示了如何将工具定义和模板字符串组装成一个完整的 Agent 对象并保存 [agents.py:99-119]。这套机制确保了智能体定义的一致性和可管理性。

🌐 协作之舞:Agent Factory 与 Agent Workflow 的双重奏

Cooragent 的强大之处不仅在于单个智能体的模板化定义,更在于它支持两种灵活的智能体运作模式,使得这些“数字工匠”能够协同工作,共同应对复杂挑战。

Agent Factory 模式:即时创造的力量

在某些场景下,用户可能需要一个当前系统中不存在的、特定用途的智能体。此时,Agent Factory 模式便派上了用场。src/workflow/agent_factory.py 中的 agent_factory_node 扮演了“智能体创造工厂”的角色 [agent_factory.py:20-53]。

其工作流程大致为:

  1. 应用名为 “agent_factory” 的特定模板,该模板可能指导 LLM 如何根据用户对新智能体的描述来定义其属性。
  2. LLM (通过 get_llm_by_type(AGENT_LLM_MAP["agent_factory"]).with_structured_output(Router)) 的响应会被结构化解析,提取出新智能体的名称、LLM 类型、所需工具、提示内容和描述。
  3. 调用 agent_manager._create_agent_by_prebuilt (或类似方法) 来创建并注册这个全新的智能体。
  4. 新创建的智能体随后便可以加入到团队中,参与后续的任务。

这种模式赋予了 Cooragent 动态扩展其智能体团队的能力,极大地增强了系统的适应性和灵活性。

Agent Workflow 模式:多智能体协作的编排艺术

当任务需要多个不同类型的智能体接力协作时,Agent Workflow 模式便登上了舞台。这一模式的核心逻辑主要体现在 src/workflow/coor_task.pysrc/workflow/graph.py 中。

coor_task.py 定义了一系列关键的“节点函数 (Node Functions)”,它们共同构成了一个决策和执行流程图:

  1. coordinator_node (协调员节点) [coor_task.py:143-159]:
    • 作为与用户交互的第一个接触点。
    • 应用 “coordinator” 模板,LLM 会分析用户输入,决定是否需要将任务移交给规划师进行更详细的计划。如果响应中包含 “handover_to_planner”,流程将转向规划师节点。
  2. planner_node (规划师节点) [coor_task.py:105-140]:
    • 负责生成详细的任务执行计划。
    • 应用 “planner” 模板,LLM 会分析当前状态和用户需求,输出一个包含具体步骤和所需智能体类型的计划 (通常是 JSON 格式)。
    • 支持“深度思考模式” (使用不同的 LLM) 和“规划前搜索” (先用 tavily_tool 搜索相关信息辅助规划)。
  3. publisher_node (发布者/调度器节点) [coor_task.py:56-79]:
    • 在规划师制定计划后,或一个智能体完成其子任务后,此节点决定下一步应该由哪个智能体接手。
    • 应用 “publisher” 模板,LLM (同样使用 with_structured_output(Router)) 会分析当前状态和计划,决定下一个行动者 (next)。
    • 如果 next 是 “FINISH”,则工作流结束。如果 next 是 “agent_factory”,则会调用智能体工厂。否则,通常会导向 agent_proxy_node
  4. agent_proxy_node (智能体代理节点) [coor_task.py:82-102]:
    • 作为执行具体智能体任务的代理。
    • 根据 publisher_node 决定的 state["next"] (即要执行的智能体名称),从 agent_manager 获取对应的智能体定义。
    • 创建一个可执行的 React Agent (一种能够进行思考-行动-观察循环的智能体),配置好其 LLM、工具和从模板生成的提示。
    • 调用智能体的 invoke 方法执行任务,并将结果更新到状态中,然后流程通常返回到 publisher_node 以决定下一步。

整个工作流程的执行由 src/workflow/graph.py 中的 CompiledWorkflow 类控制 [graph.py:27-50]。它维护了一个节点 (nodes) 和边 (edges) 的图结构,从起始节点 (start_node) 开始,根据每个节点函数的返回值 (command.goto),在不同的节点之间传递和更新状态 (state),直至到达 __end__ 节点。

这种基于图的流程控制,结合模板化的智能体定义,使得 Cooragent 能够以高度结构化和可扩展的方式编排复杂的多智能体协作。

🚀 实战演练:从“股票分析专家”看模板的威力

README_zh.md 中提供了一个生动的例子:“创建一个股票分析专家 agent. 今天是 2025年 4 月 22 日,查看过去一个月的小米股票走势,分析当前小米的热点新闻,预测下个交易日的股价走势,并给出买入或卖出的建议。” [README_zh.md:157-159]。

让我们想象一下 Cooragent 如何通过其模板驱动的机制来响应这个请求:

  1. 协调员 (coordinator_node) 接收到用户请求。其模板驱动的 LLM 识别出这是一个复杂任务,决定移交给规划师。
  2. 规划师 (planner_node) 接手。其模板引导 LLM 将任务分解:
    • 可能需要一个 researcher 智能体来搜索小米过去一个月的股票数据和热点新闻。
    • 可能需要一个 coder (或特定分析型) 智能体来处理数据、进行趋势分析,并结合新闻进行预测。
    • 最后可能需要一个 reporter 智能体来整合所有信息,给出买卖建议并生成报告。
    • 如果系统中没有现成的“股票分析专家”模板,规划师甚至可能指示先调用 agent_factory 创建一个。
  3. 发布者 (publisher_node) 根据计划,首先调度 researcher
  4. 代理 (agent_proxy_node) 执行 researcherresearcher.md 模板被应用,CURRENT_TIME 被设为 “2025年 4 月 22 日”。它使用搜索工具查找股票数据和新闻。
  5. 结果返回给 发布者,它再根据计划调度 coder (或分析师)。
  6. 代理 执行 codercoder.md 模板被应用。它接收研究员的结果,利用 Python (可能配合数据分析库) 进行分析和预测。
  7. 如此往复,直到所有子任务完成,最终由 reporter 智能体(应用 reporter.md 模板)汇总并呈现结果。

在这个过程中,每个智能体的行为都严格遵循其模板的指引,而模板中的变量 (<<CURRENT_TIME>>, <<任务描述>> 等) 则确保了它们能够适应具体的任务情境。

🔬 超越指令:模板作为高级提示工程的实践

Cooragent 中的 Agent 模板,远不止是简单的指令列表。它们是高级提示工程 (Prompt Engineering) 的精妙体现。模板的结构,特别是“任务描述的自我寻找机制”和详尽的“注意事项”,实际上是在引导 LLM 进行更深层次的思考和更规范的行动。

例如,coder.md 中“你需要自己寻找你的任务描述”这一指令 [coder.md:8-15],迫使 LLM 理解并解析一个结构化的输入,而不是被动等待一个扁平化的任务字符串。这提升了 LLM 处理复杂上下文的能力。同样,“注意事项”部分 [coder.md:34-40, researcher.md:38-42] 如同为 LLM 内置了一套行为准则和质量控制标准,有助于减少错误,提高输出的可靠性和实用性。

这些精心设计的模板,实质上是在与 LLM 进行一种“元对话”,教会它们如何成为一个合格的“研究员”、“编码员”或“规划师”,而不仅仅是完成一次性的文本生成。

🔮 结语:模板驱动的未来——构建复杂AI生态的基石

LeapLabTHU/cooragent 项目通过其创新的 Agent 模板机制,为我们描绘了一幅构建复杂、可扩展、可维护的多智能体系统的清晰蓝图。这些 .md 文件不仅仅是静态的文本,它们是智能体行为的DNA,通过 template.py 的解析和 AgentWorkflow 的编排,被赋予了鲜活的生命力。

coder.md 的严谨逻辑到 researcher.md 的探索精神,每一种模板都精心雕琢了对应智能体的“性格”与“技能”。这种将智能体设计模块化、规范化的思想,极大地降低了构建和管理多智能体应用的复杂度。

未来,随着我们对 AI 认知能力的深入探索,这类模板驱动的架构无疑将扮演越来越重要的角色。它们是连接人类意图与机器执行之间的桥梁,是培育繁荣 AI 生态的肥沃土壤。Cooragent 的实践,无疑为我们点亮了前行的一盏明灯,昭示着一个由精心设计的“数字工匠蓝图”所驱动的、更加智能化的未来。


参考文献

  1. LeapLabTHU/cooragent. src/prompts/coder.md.
  2. LeapLabTHU/cooragent. src/prompts/researcher.md.
  3. LeapLabTHU/cooragent. src/prompts/template.py.
  4. LeapLabTHU/cooragent. src/interface/agent_types.py.
  5. LeapLabTHU/cooragent. src/manager/agents.py.
  6. LeapLabTHU/cooragent. src/workflow/agent_factory.py.
  7. LeapLabTHU/cooragent. src/workflow/coor_task.py.
  8. LeapLabTHU/cooragent. src/workflow/graph.py.
  9. LeapLabTHU/cooragent. README_zh.md.

评论

发表回复

人生梦想 - 关注前沿的计算机技术 acejoy.com 🐾 步子哥の博客 🐾 背多分论坛 🐾 知差(chai)网