GenericAgent Subagent 调用 SOP 全解析:--func 纯函数模式与 --task 持续协作模式的实战指南
【免费下载链接】GenericAgentSelf-evolving agent: grows skill tree from 3.3K-line seed, achieving full system control with 6x less token consumption项目地址: https://gitcode.com/GitHub_Trending/pc/GenericAgent
导读
本文是 GenericAgent 仓库中 memory/subagent.md 这份内部 SOP 的完整技术解读。它面向两类读者:一类是想把 GenericAgent 作为"子代理"(Subagent)批量调用、并行分发任务的编排者,另一类是想理解该 Agent 如何通过文件系统实现跨进程协作的开发者。读完本文,你将掌握--func与--task两种子代理调用模式的区别与适用场景、input/reply/output 文件通信协议、_stop/_keyinfo/_intervene三类干预文件、context.json绝对路径传递机制,以及 Subagent 内部 plan_mode 的正确用法——所有结论均有仓库源码可查证。
一、两种模式总览:一次调用 vs 持续协作
Subagent 的本质是"复用同一个 GenericAgent 主程序,通过命令行参数切换成一次性子任务执行器"。仓库入口 agentmain.py 的参数解析(L208-215)定义了两条核心通道:
| 模式 | 启动命令 | 生命周期 | 适用场景 |
|---|---|---|---|
--func纯函数模式 | python agentmain.py --func prompt.txt [--llm_no N] | 读 prompt → 执行 → 写prompt.out.txt→ 退出 | 单次任务、并行 map、不需要追问 |
--task持续协作模式 | python agentmain.py --task {name} [--input "短文本"] [--llm_no N] | 多轮 reply 往返,直到主 agent 不再回复(10 分钟超时) | 需要多轮反馈、监察、纠偏的长任务 |
从源码看,两种模式共享同一套主循环:agent.put_task(raw, ...)提交任务,随后在一个while循环里消费done事件(agentmain.py),区别只在于是否进入 reply 等待循环。理解了这一点,就理解了整个 SOP 的设计根基。
运行前提
- 两条命令都要求cwd=代码根目录(即仓库根),因为内部通过
script_dir解析temp/等相对位置; --llm_no N用于指定使用第几个 LLM 后端配置,默认0(default=0,见 agentmain.py);--verbose可开启详细输出,用于审查原始数据。
二、--func 纯函数模式:一次执行、写文件、退出
2.1 工作流程
python agentmain.py --func prompt.txt [--llm_no N]执行链路为(对应 agentmain.py 的elif args.func分支):
- 以
prompt.txt内容作为任务输入(infile = args.func); - 结果写入同名前缀的输出文件
prompt.out.txt(outfile = os.path.splitext(args.func)[0] + '.out.txt',即把prompt.txt的扩展名替换为.out.txt); - 写入完成后追加
[ROUND END]标记并直接break退出,不进入 reply 循环——这正是"纯函数"语义:一次输入、一次输出、无副作用追问; - 主 agent 读取
prompt.out.txt后可以自行删除该文件,完成清理。
2.2 前台与后台
- 默认后台启动:当
--func或--task与--nobg同时缺失时,程序会用subprocess.Popen重新拉起一个带--nobg的子进程,并打印PID: <pid>后立即退出(见 agentmain.py)。后台模式下 stdout/stderr 被丢弃(subprocess.DEVNULL),适合并行分发。 --nobg前台同步:加上该参数后,当前终端会阻塞等待结果,适合单次调试、需要同步拿到prompt.out.txt的场景。
2.3 适用场景
- 单次任务:把 prompt 固化为文件,可反复执行、可审计;
- 并行 map:为每个子任务准备独立的 prompt 文件,启动 N 个后台 Subagent,最后统一收集各
.out.txt汇总; - 不需要追问:任务自包含,subagent 无需向主 agent 反向提问。
源码提示:
--func模式与--task模式在提交任务时都会关闭peer_hint(agentmain.py),避免跨会话提示干扰子任务上下文。
三、--task 持续协作模式:基于文件的多人对话
3.1 启动与 input 注入
python agentmain.py --task {name} [--input "短文本"] [--llm_no N]- 任务目录固定为
temp/{name}(script_dir/temp/{args.task},见 agentmain.py); - 带
--input时:自动完成三件事——os.makedirs创建目录、删除该目录下所有旧的output*.txt(避免轮次混淆)、把短文本写入input.txt(见 agentmain.py); - 不带
--input时:适用于长文本场景——先手动把任务描述写入temp/{name}/input.txt,再启动 Subagent; - 严禁
--nobg:持续协作模式必须后台运行,因为前台模式下进程会卡在 reply 等待循环里,阻塞终端。
3.2 通信协议:output.txt → reply.txt 轮次循环
这是整个 SOP 最核心的机制,对应 agentmain.py:
第一轮: 读 input.txt → 执行 → 写 output.txt(末尾含 [ROUND END]) 主agent 读 output.txt → 写 reply.txt(继续指令)或不再写(结束) 第二轮: 检测到 reply.txt → 写 output1.txt 第三轮: → output2.txt …… 依此类推关键细节:
[ROUND END]标记:每次写output*.txt时追加\n\n[ROUND END]\n(agentmain.py),主 agent 以此判断"本轮输出已完整落盘";- reply.txt 驱动继续:Subagent 写完 output 后进入等待循环,
consume_file(d, 'reply.txt')每 2 秒探测一次,最多 300 次(agentmain.py)——即10 分钟超时。超时未收到 reply 则进程退出,会话自然结束; - 轮次递增:每收到一次 reply,输出文件名后缀递增:
output.txt→output1.txt→output2.txt……(nround自增逻辑见 agentmain.py); - 不写 reply = 结束:主 agent 若认为任务完成,只需不再写 reply.txt,Subagent 会在 10 分钟后自动退出,无需显式 kill。
3.3 可选 fork:_history.json 继承对话上下文
若希望新 Subagent 继承此前某次会话的上下文,可将变量history(字符串)写入任务目录下的_history.json。源码侧对应 agentmain.py:
if histfile and os.path.isfile(histfile): agent.llmclient.backend.history = json.loads(open(histfile, encoding='utf-8').read())--task模式默认把_history.json作为历史文件(histfile = histfile or os.path.join(d, '_history.json')),因此只要在启动前把 JSON 放入任务目录,Subagent 就会载入这段历史,实现"从上次断点继续对话"的 fork 效果。
四、三类干预文件:监察者的远程控制台
持续协作模式下,主 agent 不必等轮次结束,可随时通过写干预文件"注入"指令。实现位于 ga.py 的turn_end_callback,每轮结束都会被读取:
| 干预文件 | 作用 | 注入方式(源码) |
|---|---|---|
_stop | 当轮结束后中止当前任务 | consume_file(task_dir, '_stop')命中后触发self.abort()(agentmain.py) |
_keyinfo | 注入 working memory 关键信息 | 以[MASTER]前缀追加到self.working['key_info'](ga.py) |
_intervene | 追加即时指令 | 以[MASTER]前缀拼接到下一轮next_prompt(ga.py) |
需要注意consume_file的读后即删语义(ga.py):文件被读取后立即os.remove,因此每个干预文件都是"一次性指令",写一次生效一次,不会被重复消费;consume_file内部还通过errors='replace'容忍编码问题。
典型用法:主 agent 空闲时读取
output*.txt观察进度,发现偏航就写_intervene纠偏;需要补充背景知识就写_keyinfo;需要终止就写_stop。加--verbose启动 Subagent 可以审查其原始输出数据,便于定位问题。
五、context.json:多文件任务的绝对路径传递机制
当任务涉及多个输入/输出文件时,SOP 要求主 agent 在创建 Subagent 时于任务目录生成context.json,Subagent 启动后第一步必须读取它,且所有文件操作必须使用其中的绝对路径。标准格式示例(原文完整保留):
{ "task": "任务描述", "work_dir": "/absolute/path/to/plan_dir/", "input_files": { "paper_info": "/absolute/path/to/paper_info.txt" }, "output_files": { "pdf": "/absolute/path/to/paper.pdf", "report": "/absolute/path/to/paper_report.md" }, "dependencies": ["paper_info.txt必须存在"] }设计意图很明确:work_dir定位工作目录,input_files/output_files用语义化键名(如paper_info、pdf、report)替代脆弱的相对路径猜测,dependencies声明前置条件。这避免了多文件任务中"路径写错、文件找不到"这类高频故障,也保证了work_dir之外文件(如仓库内素材)的可达性。
六、Subagent 内部 plan_mode:多步骤任务的自我管理
6.1 原则与触发条件
Subagent 本身是完整 agent,不是哑执行器。当它接收的任务包含 3 个以上子步骤、子步骤之间存在依赖关系、或需要 checkpoint 恢复执行时,应在内部创建 plan 管理执行,而非依赖主 agent 逐轮喂指令。源码侧,Agent 每轮都会检查是否处于 plan 模式(_in_plan_mode,见 ga.py),并注入对应提示(如[Plan Hint],见 ga.py)。
6.2 三层协作分工
- 主 agent 创建 Subagent 时:在
input.txt中说明"任务包含多个步骤,建议使用 plan_mode"; - Subagent 内部执行:检测到多步骤任务后,创建
./subagent_plan.md并启用 plan_mode 执行——计划文件即 checkpoint,进程重启后可通过重读该文件恢复; - 主 agent 监控:只关注最终结果(
output*.txt),不关心 Subagent 内部如何分步执行,避免过度耦合。
配合 5.1 节的context.json,多步骤任务的文件传递链路为:主 agent 生成 context.json → Subagent 首步读取 → 全程使用绝对路径 → 最终产物按output_files写回。
七、共通规则:为什么 cwd=temp 与"只给目标"
7.1 所有 agent 的 cwd=temp
所有 Subagent 的工作目录统一为temp/(源码中GenericAgentHandler默认cwd='./temp',见 ga.py),目的是文件共享:主 agent 与多个 Subagent 在同一目录下读写中间文件,天然形成共享总线;同时 task 子目录temp/{name}/又隔离了各 Subagent 的私有轮次文件。
7.2 input 写法:目标 + 约束,而非步骤
SOP 明确要求:给 Subagent 的输入只需"目标 + 约束",因为 Subagent 与主 agent同等智能,过度描述步骤反而会限制其判断空间;大量数据一律给路径,让 Subagent 自行读取,而不是把数据塞进 prompt。这一原则在两个实战场景中体现得尤为充分。
八、场景实战
场景 1:测试模式——行为验证
用途:观察 Subagent 真实行为,反过来修正 RULES / L2 / L3 / SOP 文档质量。
流程:写 prompt → 启动 Subagent → 轮询结果 → 验证 → 清理。
原则:只给目标,不提示位置、不诱导做法;Insight 优先级高于 SOP;Subagent 的 cwd=temp。
两种测试向:
- 测 SOP 质量:input 中指定某个 SOP 名,排除导航干扰——若 Subagent 仍失败,说明是 SOP 本身的问题(表述歧义、步骤缺失);
- 测导航能力:input 只写目标,验证 Subagent 能否自主从 insight 中找到正确 SOP——失败则说明导航信息或 insight 结构需要优化。
这种"测试即开发"的闭环,正是 GenericAgent 自进化机制在 Subagent 层面的体现。
场景 2:Map 模式——并行处理
用途:N 个独立同构子任务并行分发,每个 Subagent 拥有独立上下文,避免交叉污染。
约束(务必遵守):
- 文件系统共享:这是优点,可共享只读素材与汇总目录;
- 键鼠不可共享:多个 Subagent 不能同时操作同一套键鼠设备;
- 浏览器避免同 tab:并行任务若用浏览器,应各用独立 tab/会话,防止状态串扰。
流程:准备 N 个独立输入文件 → 每个任务启动一个 Subagent(--func优先,因其天然无状态、易收集)→ 收集各prompt.out.txt汇总。若个别子任务需要监察纠偏,则改用--task模式并在轮询中利用干预文件。
九、小结:选型决策速查
| 决策点 | 结论 |
|---|---|
| 单次、自包含、无追问 | --func,后台并行,收集.out.txt |
| 需要多轮反馈/监察/纠偏 | --task,绝不加--nobg |
| 长任务描述 | 手动写input.txt后再启动,不用--input |
| 多文件任务 | 首先生成context.json,Subagent 首步读取,全程绝对路径 |
| 需要继承历史对话 | 启动前把 history 写入_history.json |
| 运行时纠偏 | 写_intervene(追加指令)/_keyinfo(注入记忆)/_stop(当轮中止) |
| 多步骤子任务 | input 中建议 plan_mode,Subagent 内部建subagent_plan.md自管 |
本文所有命令与机制均以当前仓库源码为准:参数解析与主循环见 agentmain.py,干预文件注入见 ga.py 与 ga.py,默认工作目录见 ga.py。需要更深入了解 Agent 主循环、工作记忆与提示词注入的读者,可继续阅读同目录下的 llmcore.py 及 memory 目录下其他 SOP 文档(如 plan_sop.md、supervisor_sop.md)以获得完整上下文。
【免费下载链接】GenericAgentSelf-evolving agent: grows skill tree from 3.3K-line seed, achieving full system control with 6x less token consumption项目地址: https://gitcode.com/GitHub_Trending/pc/GenericAgent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考