深度解析:子任务 Prompt 的构建机制——从源码到执行
深度解析:子任务 Prompt 的构建机制
从源码到执行——主/子智能体 Prompt 的对比与 Tool/Skill 注入时机
01 引言:为什么需要理解 Prompt 构建
在 buddyMe 这样的多智能体系统中,Prompt 不只是"给 AI 的一段话"——它是整个系统的控制平面。Prompt 的构建方式决定了:
- 智能体能做什么(能力边界)
- 智能体怎么做(行为规范)
- 智能体在什么约束下做(安全规则)
理解 Prompt 的构建机制,就是理解这个系统的"灵魂"是如何被注入的。
02 整体架构概览
buddyMe 采用主-子智能体(Orchestrator-Worker)架构:
拥有全局视野、完整记忆、全量工具/技能
关键设计理念:主智能体是"指挥官",子智能体是"特种兵"。指挥官拥有全局视野,特种兵只聚焦单一任务。
03 主智能体 Prompt 的构建
主智能体的 Prompt 由以下几个层次组成:
3.1 基础系统提示词
- 角色定义:作为用户的全能助手,负责理解需求、规划任务
- 完整技能列表:所有可用 Skills 的名称和描述
- 完整工具列表:所有可用 Tools 的定义(JSON Schema)
- 全局上下文:项目工作空间路径、环境信息等
3.2 记忆系统注入
# 伪代码示意 system_content = base_system_prompt system_content += format_memory(we_md_content) # 循环记忆 system_content += format_recent_summary(recent_logs) # 近期摘要
3.3 任务规划能力
# 主智能体内部逻辑(伪代码) def plan_subtasks(user_request): steps = decompose(user_request) # 每个 step 包含: # - 动作类型:SEARCH / CREATE / EDIT / VERIFY # - 可选的 SKILL 标记 # - 依赖关系(前序步骤) return steps
3.4 主智能体 Prompt 的特征总结
| 特征 | 说明 |
|---|---|
| 上下文范围 | 全局:完整对话历史、所有记忆 |
| 工具访问 | 全量:所有 Tools + 所有 Skills |
| 生命周期 | 长驻:贯穿整个对话会话 |
| 自主性 | 高:可规划、调度、决策 |
| Token 预算 | 充裕:无严格上限 |
04 子任务 Prompt 的构建
子任务的 Prompt 构建是本文的核心。它并非主智能体 Prompt 的简单子集,而是一次精心设计的重构。
4.1 SUB_AGENT.md —— 子任务的行为宪法
子任务 Prompt 的核心是 SUB_AGENT.md 文件,它定义了子任务执行者的完整行为规范。注意文件头部的关键注释:
agent.py 读取并注入子任务的 system_content,用 11 和 97500 填参。
这两个数字是核心参数:11 是单个子任务最多调用工具的轮次上限,97500 是输出字符数的上限。它们并非硬编码在模板中,而是由 PromptBuilder.load_sub_agent_prompt(max_steps=11, max_output=97500) 在运行时通过 .format() 填入,保持模板通用性。
4.2 子任务 Prompt 的十层组装
子任务的 system_content 由以下十层按顺序拼接:
4.3 逐层解析
第一层:SUB_AGENT.md(行为宪法)
这是子任务 Prompt 的"地基",确立了身份定位("你是子任务执行者")、6 条安全红线和 4 条执行纪律。
第二层 & 第九层:技能列表的双重注入
技能匹配规则在 Prompt 中出现了两次——一次在 SUB_AGENT.md 之后,一次在文件输出规则之后。这种"双重注入"确保无论 LLM 的注意力如何分布,都能看到技能匹配规则。
第三层:当前子任务描述
由主智能体在任务规划阶段生成,直接告诉子任务执行者"你要做什么",例如:
当前子任务: [EDIT] 搜索并提取主/子智能体源码,填充 Prompt 构建差异及 Tool/Skill 注入时机的代码片段与文字解析
第四层:已生成文件列表
让子任务执行者知道前置步骤已经产出了什么,避免重复工作。随着子任务逐个完成,这个列表不断更新。
第五层:验证任务说明(仅 VERIFY 类型)
【验证任务】
1. 用 read_file 读取已生成的文件
2. 检查结构完整性
3. 发现问题用 edit_file 修复
4. 无问题则输出文件路径和功能说明
5. 禁止重新搜索
第六~八层:环境 + 规则 + 禁止事项
环境信息(工作空间路径)、文件输出规则、以及最关键的禁止事项:严禁修改 subtask_results.json。
第十层:近期摘要
提供历史上下文,帮助子任务执行者理解项目的整体背景。
05 核心差异对比
| 维度 | 主智能体 | 子任务执行者 |
|---|---|---|
| 身份 | 全能助手、任务规划者 | 单一任务执行者 |
| Prompt 来源 | 动态构建(对话历史 + 记忆 + 系统提示) | 模板化构建(SUB_AGENT.md + 任务描述 + 上下文注入) |
| 上下文 | 完整对话历史 | 精选摘要 + 当前任务描述 |
| 工具访问 | 全量 | 按类型筛选(research/build/verify) |
| 技能访问 | 全量 | 全量(但受任务范围限制) |
| 自主性 | 可规划、调度、决策 | 只执行分配的任务 |
| 轮次限制 | 无严格限制 | 最多 11 轮工具调用 |
| 输出限制 | 无严格限制 | 不超过 97500 字符 |
| 生命周期 | 贯穿会话 | 单次任务 |
| 安全约束 | 通用安全规则 | 更严格:禁止修改 subtask_results.json 等 |
设计哲学差异
需要维护全局状态
需要协调多个子任务
只需关注当前上下文
在严格约束下高效执行
Prompt 模板化 vs 动态化
主智能体的 Prompt 是高度动态的——随着对话进行,上下文不断增长,记忆不断累积。
子任务的 Prompt 是半模板化的——SUB_AGENT.md 是固定模板,但以下部分是动态注入的:
# 子任务 Prompt 构建伪代码 def build_subagent_prompt(task_description, generated_files, recent_summary): prompt = read_file("SUB_AGENT.md") # 固定模板 prompt += format_skill_rules() # 固定规则 prompt += f"当前子任务: {task_description}" # ← 动态注入 prompt += format_generated_files(generated_files) # ← 动态注入 prompt += format_env_info() # 固定环境 prompt += format_output_rules() # 固定规则 prompt += format_prohibitions() # 固定禁止项 prompt += format_skill_list() # 固定列表(二次注入) prompt += format_recent_summary(recent_summary) # ← 动态注入 return prompt
06 Tool 与 Skill 的注入时机
这是理解整个系统运作的关键。Tool 和 Skill 的注入发生在不同阶段,服务于不同目的。
6.1 Tool 的注入时机
Tools(基础工具)如 read_file、write_file、edit_file 是在 API 调用层面注入的:
tools 参数中。这意味着 LLM 在理解工具时,依赖的是 API 层面的结构化定义,而非 Prompt 中的自然语言描述。
api_request = {
"model": "deepseek-v4-pro",
"system": system_content, # Prompt 文本
"tools": [ # Tool 定义(独立于 Prompt)
{ "name": "read_file", "description": "...", "input_schema": {...} },
{ "name": "write_file", "description": "...", "input_schema": {...} },
{ "name": "edit_file", "description": "...", "input_schema": {...} },
{ "name": "invoke_skill", "description": "...", "input_schema": {...} },
],
"messages": [...]
}
6.2 Skill 的注入时机
Skills(技能)的注入更为复杂,分为两个阶段:
system_content,告诉 LLM "你有这些技能可用,匹配时调用 invoke_skill 激活"
invoke_skill → 系统返回该 Skill 的完整执行指令 → LLM 按指令执行
6.3 注入时机完整时序图
6.4 为什么 Tool 和 Skill 分开注入?
类比:给工人发工具箱
类比:给工人发专业培训教材
分开注入的好处:
- Token 效率:不需要一开始就加载所有 Skill 的完整指令
- 按需加载:只有匹配的 Skill 才会被激活,减少噪音
- 灵活性:可以动态添加新 Skill 而不改变基础架构
07 完整生命周期时序图
以下是一个子任务从创建到完成的完整生命周期:
Step 1: SEARCH Step 2: CREATE Step 3: EDIT Step 4: VERIFY
08 总结与思考
核心设计原则
SUB_AGENT.md 提供稳定的行为框架,动态部分(任务描述、上下文)按需填充
身份层(你是谁)→ 安全层(不能做什么)→ 执行层(怎么做)
基础能力始终可用(API 层注入),专业知识按需激活(Prompt 声明 + 运行时加载)
关键规则(如技能匹配)在 Prompt 中重复出现,确保注意力覆盖
参数化设计的精妙
SUB_AGENT.md 通过 .format(max_steps=11, max_output=97500) 实现参数化,这意味着:
- 可以根据不同任务类型调整工具调用上限
- 可以根据模型上下文窗口调整输出限制
- 模板本身保持通用性
从"我"的视角看
作为子任务执行者,我看不到主智能体的完整对话历史,但我有:清晰的 task goal、严格的安全边界、必要的上下文(近期摘要、已生成文件)、完整的工具和技能访问能力。
这种设计让我能够专注而高效地完成单一任务,而不被全局复杂性所干扰。
潜在改进方向
- 上下文传递优化:当前前置步骤的结果以简短文本传递,可能丢失细节。可以考虑结构化的结果传递机制。
- Skill 懒加载:当前所有 Skill 的描述都写入 Prompt,占用 Token。可以只注入与当前任务相关的 Skill 子集。
- 自适应轮次限制:不同复杂度的任务可能需要不同的工具调用上限,可以根据任务类型动态调整。