| def run(): |
无参数闭包。捕获外层的 name、system、prompt、sub_tools、sub_handlers。这是 Python 闭包的典型用法——内部函数自动引用外层作用域变量。 |
| messages = [{"role": "user", "content": prompt}] |
Teammate 独立的对话历史,从第一条 user 消息(prompt)开始。与 Lead 的 session_history 完全隔离。 |
| sub_tools = [ |
Teammate 的工具集,比 Lead 小得多:bash(执行命令)、read_file(读文件)、write_file(写文件)、send_message(与 Lead 通信)。没有 task system 和 cron 工具——Teammate 只专注执行,不负责调度。 |
| {"name": "bash", ...}, |
bash 工具:Teammate 的 bash 无 run_in_background 字段(教学版 Teammate 不支持嵌套后台任务,简化设计)。 |
| {"name": "send_message", |
send_message 工具:专用于 Teammate → Lead 通信。schema 中只有 to 和 content,不暴露 from 和 type 参数(由实现层固定)。 |
| sub_handlers = { |
Teammate 的工具处理器字典,对应 sub_tools 的四个工具。 |
| "bash": run_bash, "read_file": run_read, "write_file": run_write, |
直接复用 Lead 的工具函数(闭包引用外层模块级函数)。 |
| "send_message": lambda to, content: (BUS.send(name, to, content), |
lambda 表达式:匿名函数,捕获外层 name(Teammate 名称)。将 from_agent 固定为 name,只暴露 to 和 content 参数。 |
| "Sent")[1], |
元组索引 [1]:(BUS.send(...), "Sent") 是元组字面量。BUS.send() 返回 None(无返回值),[1] 取 "Sent" 字符串作为工具调用结果返回给 LLM。括号内逗号表达式产生元组(Python 中逗号是元组的核心,括号只是分组)。 |
| for _ in range(10): |
有界循环:最多执行 10 轮(10 次 LLM 调用),防止 Teammate 无限运行消耗资源。_:按约定的"不使用的变量"名称,表示循环变量本身不被使用。 |
| inbox = BUS.read_inbox(name) |
每轮开始前检查自己的收件箱(Lead 可能发来新指令)。教学版:先读 inbox,如有消息则注入对话,然后继续 LLM 调用。 |
| if inbox: |
空列表为 falsy,有消息才注入。 |
| messages.append({"role": "user", |
以 user 角色注入 inbox 消息,使 LLM 知晓 Lead 发来的新信息。 |
| "content": f"<inbox>{json.dumps(inbox)}</inbox>"}) |
用 XML <inbox> 标签包裹 JSON 序列化的消息列表。混合格式(XML 外层 + JSON 内容)便于 LLM 识别边界。json.dumps(inbox) 将 list[dict] 序列化为 JSON 字符串。 |
| try: |
捕获 LLM API 错误,任何异常都 break 退出循环(Teammate 会在 finally 阶段发送最终摘要)。 |
| response = client.messages.create( |
使用全局 client 调用 Anthropic API。Teammate 与 Lead 共用同一个 Anthropic 客户端实例(线程安全,HTTP 连接池支持并发)。 |
| model=MODEL, system=system, messages=messages[-20:], |
messages[-20:]:切片取最近 20 条消息(Python 负索引从末尾计数)。Lead 用完整 messages,Teammate 用滑动窗口——Teammate 任务专一,历史无需太长,也节省 token。 |
| except Exception: |
捕获所有异常(含网络错误、rate limit 等)但不打印错误(避免后台线程日志混乱),直接 break 退出 for 循环。 |
| break |
退出 for 循环,执行循环外的"发送最终摘要"逻辑。 |
| messages.append({"role": "assistant", "content": response.content}) |
将 LLM 回复追加到 Teammate 的对话历史。 |
| if response.stop_reason != "tool_use": |
LLM 停止工具调用(发出文本回复)→ 任务完成或 LLM 认为无需继续,break 退出 for 循环。 |
| break |
自然结束,后续发送最终摘要。 |
| results = [] |
本轮工具调用结果列表。 |
| for block in response.content: |
遍历 LLM 回复内容,找出 tool_use block。 |
| if block.type == "tool_use": |
过滤:只处理工具调用 block(可能有 text block 混在其中)。 |
| handler = sub_handlers.get(block.name) |
从 Teammate 专属的 sub_handlers 查找处理器(不用 Lead 的 TOOL_HANDLERS)。 |
| output = handler(**block.input) if handler else "Unknown" |
三元表达式:找到 handler 则调用(** 解包参数),否则返回 "Unknown"(Teammate 工具集小,遇到未知工具不应崩溃)。 |
| results.append({"type": "tool_result", |
构造 tool_result,格式与 Lead 相同(Anthropic API 要求)。 |
| "tool_use_id": block.id, |
与 LLM 请求的 block.id 对应,API 用于关联请求与结果。 |
| "content": str(output)}) |
str(output):强制转为字符串(output 可能是 None 或其他类型),Anthropic API 的 content 字段要求 str。 |
| messages.append({"role": "user", "content": results}) |
将工具结果以 user 消息形式追加(Anthropic 协议要求)。 |