在同一台机器上的两个 Agent 之间,通过 HTTP 传递任务和结果。
- Agent1 提交任务,等待或补取结果。
- Agent2 接收任务、完成工作,再交回结果。
serve是常驻中继,只保存和转发文本,不执行任务。watch是一次性后台等待进程:先输出信息,再退出,由宿主的后台任务完成通知唤醒 Agent2。
AgentChat 不包含模型,也不会自动执行任务、调用 reply 或重启 watch。这些动作由 Agent2 按输出指引完成。
在包含 run.py 的项目目录下执行以下命令。需要 Python,以及项目列出的依赖:
python -m pip install -r agentchat/requirements.txt通信地址固定为 http://127.0.0.1:18765,不提供自定义地址、端口或 Token 参数。只适用于本机通信,不要将中继暴露到不可信网络。
Agent2 的宿主必须支持:启动后台任务,并在任务结束后恢复 Agent 会话、提供该任务的输出。 仅仅把进程放到操作系统后台,并不等于宿主能唤醒 Agent。若宿主不支持这项能力,不能依靠 watch 实现自动唤醒。
宿主应让 serve 长期运行,并允许每次后台 watch 完整运行 9 分钟,不要让任务工具较短的默认时限提前杀死它。宿主任务工具的时限与 AgentChat 命令行参数是两回事。
给 Agent 使用的具体操作规程见项目根目录 SKILL.md。安装技能时,将其放入宿主支持的技能目录;命令仍应在本项目目录中执行,不是在技能安装目录中执行。
通过宿主的后台任务工具,分别启动以下两个进程;不要把它们串成一个前台命令:
python run.py serve确认中继启动成功并仍在运行后,再启动另一个后台任务:
python run.py watch确认 watch 已作为后台任务运行,再结束 Agent2 当前会话,交还控制权给宿主。不要在前台等它退出,也不要为了等通知持续轮询后台状态。
serve 只需启动一次;每次 watch 结束后,需要由 Agent2 重新启动新的 watch。
python run.py send --text "请处理这个任务"该命令默认等待结果,成功时标准输出就是 Agent2 交回的结果。
watch 输出“收到任务 #N”、任务正文和后续指引,然后以退出码 0 退出。Agent2 读取输出,完成任务,再交回结果。下面的 1 必须替换为本次输出中的实际任务 ID:
python run.py reply --id 1 --text "实际处理结果"长结果可以先写入 .tmp/结果.md,再发送文件内容:
python run.py reply --id 1 --file .tmp/结果.md确认回复成功后,通过宿主工具重新启动一个后台任务:
python run.py watch然后结束当前会话,等待下一次通知。不要每轮重启 serve。
当前使用场景中,后台等待超过 10 分钟后再结束,宿主可能无法恢复 Agent2。为提前产生一次完成通知,watch 每次启动后最多等待 9 分钟。
没有任务时的流程:
- 本次
watch启动,从零计时。 - 满 9 分钟后,输出“保活唤醒”“这不是任务”和重新启动
watch的指引。 - 刷新输出,以退出码
0退出。 - 宿主恢复 Agent2;Agent2 不执行任务、不调用
reply,只重新后台启动python run.py watch。 - 新进程从零开始下一轮 9 分钟计时,Agent2 再结束会话。
保活和收到任务的退出码都是 0,必须阅读输出区分,不能只判断退出码。
watch 不会自行创建下一个进程。进程内部的临时通信失败重试,也不会重置本进程的计时。9 分钟是后台接单阶段的保活周期,不是任务执行时限;处理任务期间,已经退出的 watch 不会继续计时或产生通知。
保活依赖宿主实际发出完成通知;若宿主提前终止进程或不能恢复会话,本工具不能保证 Agent2 在线。
以下是全部 6 个子命令。所有子命令均支持 --help;没有列出的业务参数不应使用。
| 命令 | 业务参数 | 行为 |
|---|---|---|
serve |
无 | 启动常驻中继 |
watch |
无 | 收到任务或满 9 分钟后,先输出指引再退出 |
send |
--text、--file、--detach |
提交任务;默认等待结果 |
reply |
--id(必填)、--text、--file |
为指定任务交回结果 |
wait |
--id(必填)、--timeout |
等待或补取指定任务的结果 |
stop |
无 | 停止中继;只在明确需要结束服务时使用 |
send 和 reply 都可以通过 --text "内容" 或 --file 路径 提供文本,建议每次只选择一种。若同时指定,当前实现优先读取文件。
--file 只读取文件内容,不会创建或删除该文件;--file - 表示读取标准输入。两种参数都未指定时,也可以从管道输入文本。文件优先按 UTF-8 读取,兼容 UTF-8 BOM,解码失败时按 GBK 读取。程序输出固定为 UTF-8。
临时任务文件、结果文件放在 .tmp/,需要时先通过宿主文件工具创建目录。
如果调用方不能让一个命令持续运行约 20 分钟,使用:
python run.py send --text "请处理这个任务" --detach命令立即返回,任务 ID 写在标准错误中的“已提交 #N”提示里;不要把这条提示误当作提交失败。随后使用实际 ID:
python run.py wait --id 1send 的默认结果等待上限是 20 分钟,不提供命令行配置。wait 默认也等待 20 分钟,固定每 2 秒查询一次;只有 wait 保留等待时长参数,单位为秒:
python run.py wait --id 1 --timeout 60wait 只查询已有任务,不会再次提交。超时不取消任务;中继未重启时,迟到的 reply 仍可被后续 wait 取回。没有明确证据表明提交失败时,不要直接重发同一任务。
python run.py --help
python run.py --version
python run.py send --help
python run.py stopstop 会终止中继,不应在每次回复或保活时执行。
| 场景 | 退出码 | 下一步 |
|---|---|---|
watch 收到任务 |
0 |
完成任务 → reply 成功 → 后台启动新 watch → 结束会话 |
watch 九分钟保活 |
0 |
不调用 reply;后台启动新 watch → 结束会话 |
watch 启动时无法连接中继 |
5 |
检查原 serve 的后台状态与输出;恢复中继后重挂 watch |
watch 运行中连续通信失败 3 次 |
4 |
检查连接与中继状态;修复后重挂,不当作正常保活 |
send 或 wait 等结果超时 |
3 |
保存任务 ID,用 wait --id N 补取,不直接重发 |
send 或 wait 的通信等请求错误 |
4 |
阅读错误详情;不能据此断定任务未提交 |
reply 被中继拒绝或通信失败 |
1 |
查看具体错误;未确认成功前不声称已交回 |
| 命令或参数不合法 | 2 |
按当前命令表修正,不是“没有任务” |
watch 运行中若通信失败,在剩余生命周期内重试:首次失败后等待最多 2 秒,第二次失败后等待最多 4 秒,连续第三次失败就报错退出。达到九分钟期限时转为保活退出,不额外延长等待。程序不自动重启 serve。
reply 的错误中,404 表示当前中继没有这个任务 ID;409 表示已经回复过,不能重复提交。中继仍运行时先查看其输出,不要盲目启动第二个 serve,更不要为排障随意停止现有中继。
serve将任务写入其当前工作目录的data/i{id}.md,将结果写入data/o{id}.md。send在自己的当前工作目录记录已知任务 ID 对应的输入;阻塞等待成功时也记录结果。分离提交和超时返回时只有输入,wait目前不会补写发送端的结果文件。- 路径固定为各进程当前工作目录下的
data/,没有目录配置或禁用记录选项。希望共用一份记录时,所有命令从同一项目目录执行。 data/只是日志,不是传话渠道。接任务看watch输出,取结果用send或wait,不要扫描日志当作消息队列。- 任务队列和可查询结果保存在中继内存中。重启
serve会丢失这些状态;已有日志不会恢复任务。编号会根据现有日志文件名接着分配,这不代表旧任务仍能查询。 - 日志可能包含完整任务与结果,不要将敏感内容写入不可信目录。
九分钟保活没有新增命令行参数:直接运行 python run.py watch,不需要传入时长或重启选项。
代码内部的 client.next_task() 增加了可选的 timeout 入参,用于限制本次网络请求的等待时间;这是 Python 内部接口,不是 watch 的命令行参数。