在上一章 S01 里我们搭好了 Agent 的最小循环让模型能调用工具、把结果喂回自己继续推理。但当时只有一个bash工具既不安全也不好扩展。这一章 S02我们要解决工具扩展、安全限制、统一分发三大问题实现一句核心原则加一个工具只加一个 handler循环完全不用改。本章核心信息核心闭环把模型意图 → 路由成真实动作工具数量4 个bash /read_file/write_file /edit_file核心思想主循环不变靠分发层扩展能力先把本章所有名词讲明白1. Handler工具处理器每个工具真正执行的代码函数。比如读文件、写文件、执行命令各自有独立的处理逻辑。2. Dispatch Map / 工具路由表一张 “对照表”工具名字 → 对应的处理函数比如模型说要用read_file程序就查表找到run_read执行。3. Harness 层工具调度层统一管理所有工具的中间层负责接收模型调用 → 找到对应工具 → 执行 → 返回结果。4. Path Sandbox 路径沙箱安全限制Agent 只能读写指定文件夹内的文件不能越权访问系统文件防止删库、偷文件。5. Tool Schema工具描述给模型看的 “工具说明书”告诉它这个工具叫什么、需要传什么参数、用来干什么。6. normalize_messages消息规范化把内部消息整理成模型 API 能接受的格式保证工具调用和结果一一对应消息角色不连续重复不携带内部字段导致报错7. turn轮次一轮 模型思考 可能的工具调用 结果返回一轮结束进入下一轮直到任务完成。8. state状态Agent 运行时的全部记忆消息历史、轮次数、继续 / 停止原因。为什么不能只用一个 bash 工具S01 我们只用了bash命令行看起来万能其实隐患巨大cat 读文件可能被截断特殊字符、长文件会导致输出不完整模型拿到错误信息。sed 编辑极易崩溃遇到$ / \等符号命令直接报错。完全没有安全边界模型可以执行任何命令删文件、改系统配置、泄露信息。所以必须拆成专用工具read_filewrite_fileedit_file并加上安全沙箱。本章架构一句话看懂用户输入 → LLM 思考 → 工具分发查表执行→ 结果返回 → 写回消息 → 下一轮工具分发是关键LLM 不需要知道代码怎么实现它只说 “工具名 参数”系统查表找到对应函数执行循环完全不用改。核心实现工具路由表 安全路径1. 路径安全校验沙箱保证 Agent 只能在工作目录内操作def safe_path(p: str) - Path: path (WORKDIR / p).resolve() if not path.is_relative_to(WORKDIR): raise ValueError(f路径超出工作区{p}) return path2. 读文件工具带长度限制def run_read(path: str, limit: int None) - str: text safe_path(path).read_text() lines text.splitlines() if limit and limit len(lines): lines lines[:limit] return \n.join(lines)[:50000]3. 工具路由表核心设计TOOL_HANDLERS { bash: lambda **kw: run_bash(kw[command]), read_file: lambda **kw: run_read(kw[path], kw.get(limit)), write_file: lambda **kw: run_write(kw[path], kw[content]), edit_file: lambda **kw: run_edit(kw[path], kw[old_text], kw[new_text]), }4. 循环中统一分发和 S01 循环几乎一样只是把硬编码改成查表for block in response.content: if block.type tool_use: handler TOOL_HANDLERS.get(block.name) output handler(**block.input) if handler else f未知工具{block.name} results.append({ type: tool_result, tool_use_id: block.id, content: output })关键洞察加工具不用改循环以后你想加新工具比如search_webrun_pythonget_weather只需要两步写一个 handler 函数在TOOL_HANDLERS里加一行映射agent_loop 代码一行不动这就是工业级 Agent 的标准设计。为什么要消息规范化随着工具变多消息会越来越乱工具调用缺结果连续两条 user 消息带内部字段 API 不识别所以必须在发给模型前规范化def normalize_messages(messages: list) - list: # 1. 清理内部字段 # 2. 补齐缺失的 tool_result # 3. 合并连续同角色消息 ...调用模型时这样用response client.messages.create( modelMODEL, systemSYSTEM, messagesnormalize_messages(messages), # 先规范化 toolsTOOLS, max_tokens8000 )S01 → S02 到底升级了什么模块S01S02工具数量1 个bash4 个工具调用硬编码路由表分发安全无路径沙箱消息直接发送规范化后发送扩展性差极强主循环不变不变初学者可以直接试的 PromptRead the file requirements.txt Create a file called greet.py with a greet(name) function Edit greet.py to add a docstring to the function Read greet.py to check the result你会看到Agent 会自主选择工具自动读写编辑完全不用你干预。本章教学边界不搞复杂只抓核心本章不讲权限、不讲缓存、不讲流式、不讲异常恢复。只牢牢抓住三件事Tool Schema给模型看Handler Map给代码分发Tool Result回流到循环只要懂这三点你就掌握了所有 Agent 工具系统的底层结构。一句话总结本章Agent 的能力增长不靠把循环写复杂而靠一层清晰的工具分发层。加工具只加 handler循环永远不动。