给代码智能体加一件“新装备”:从零扩展 Code Agent 工具的完整路径

在 Code Agent 的工程实践中,模型本身并不直接“做事”。它通过 Function Calling 选择工具,再由框架执行并返回结果。因此,扩展一个代码智能体,往往不是重新训练模型,而是给它增加新的工具。

Code Agent 的工程实践中,模型本身并不直接“做事”。它通过 Function Calling 选择工具,再由框架执行并返回结果。因此,扩展一个代码智能体,往往不是重新训练模型,而是给它增加新的工具。掘金专栏文章《Code Agent 解剖(20):从零扩展——给 agent 加一个新工具》以 MyCodeAgent 为例,完整拆解了新增工具的流程。

文章指出,从模型视角看,工具只是一个包含名称、描述和参数的 function 定义;从框架视角看,工具则是实现了特定接口的 Python 类。只要完成协议定义、工具实现、注册、提示词接入和测试,一个新能力就可以被 Agent 调用。

工具系统的底层约定:接口与返回结构先统一

在 MyCodeAgent 中,所有工具都继承自 tools/base.py 里的 Tool 基类。基类要求工具实现两个抽象方法:run()get_parameters()。前者负责执行具体逻辑,后者负责向框架描述该工具接受哪些参数。

工具执行结果也有统一格式,即 ToolResult。这是一个不可变的数据类,包含状态、文本摘要、核心数据、错误码、统计信息和上下文字段。文章特别提到,ToolResult 使用 frozen=True,目的是防止工具结果在执行管道中被意外修改。

  • status:表示执行成功、部分成功还是出错。
  • text:给模型阅读的文字摘要。
  • data:工具返回的核心载荷。
  • error_code:仅在错误时提供。
  • stats:记录耗时等统计信息。
  • context:保存当前工作目录、输入参数等上下文。

这种设计的意义在于,框架不需要知道每个工具内部如何工作,只要所有工具都按照同一接口输出结果,Agent 就能统一处理。

以 WordCount 为例:一个新工具如何落地

文章选择了一个简单工具作为示例:统计文件的行数、单词数和字符数。这个工具名为 WordCount,接收一个 path 参数,路径相对于项目根目录。

实现层面,工具类继承 Tool,并在构造函数中传入名称、描述、项目根目录和工作目录。随后,get_parameters() 声明参数信息,run() 执行实际逻辑。

作者在实现中强调了几个工程细节。首先是参数校验在前:如果模型没有传入 path,工具会立即返回清晰的错误信息,而不是继续执行文件 IO。其次是沙箱检查:工具会把传入路径与项目根目录拼接并解析,再通过 relative_to() 判断路径是否逃出项目目录。如果路径越界,会返回访问拒绝错误。

此外,工具还会检查文件是否存在、是否是目录。确认合法后,程序读取文件内容,分别统计行数、单词数和字符数,并通过基类提供的 success_result() 返回标准结果。基类同时提供 partial_result()error_result(),开发者不需要手动构造 ToolResult

注册与提示词:让模型“看见”并“会用”工具

工具类写完后,框架并不会自动识别它。文章要求在 runtime/host.py 的工具注册区导入新工具,并调用 registry.register_tool() 完成注册。注册之后,该工具会出现在 registry.get_openai_tools() 返回的列表中,模型在下一次请求时就能看到对应的 schema。

但“能被调用”不等于“会被正确使用”。模型是否选择某个工具,主要取决于工具描述。文章为此新增了 prompts/tools_prompts/word_count_prompt.py,在里面写明工具用途、适用场景、参数和返回字段。

例如,提示词建议模型在以下情况使用该工具:在决定是否完整读取文件前,先了解文件规模;或者快速概览一个文件的内容体量。示例也给出了调用形式:WordCount(path="src/main.py"),并返回类似“src/main.py: 312 lines, 1847 words, 14203 characters.”的结果。

随后,工具类构造函数中的 description 参数引用这段提示词。文章强调,这个 description 是模型决定是否调用该工具的重要依据。写清楚,模型更容易在合适场景使用;写模糊,模型可能不用,或者误用。

测试闭环:工具不只是能跑,还要可验证

在完成工具实现和注册后,文章要求为新工具编写测试。示例测试覆盖三类情况:正常执行、文件不存在,以及尝试逃出项目目录的沙箱攻击。

在正常执行测试中,测试用临时目录写入一个包含两行文本的文件,然后断言工具返回成功状态,并且行数为 2、单词数为 5,同时检查统计字段存在且耗时不为负。在错误场景中,测试验证未找到文件时返回 ErrorCode.NOT_FOUND,路径逃逸时返回错误状态。

这部分体现的是工具开发的工程底线:Agent 工具并不是单纯的函数封装,它要处理模型给出的不确定输入,也要在文件系统、权限边界和执行结果上保持稳定。测试不是附加项,而是扩展能力的一部分。

对 AI 编程工具链的启示

这篇文章的价值不在于展示一个统计文件行数的工具,而在于把 Code Agent 的能力扩展拆成了可复制的工程路径。它说明,Agent 的工具系统并不神秘:模型看到的是函数描述,框架执行的是接口实现,注册机制负责暴露能力,提示词决定使用边界,测试保证可靠性。

随着 AI 编程助手逐渐从聊天窗口走向真实代码环境,工具扩展能力会成为框架竞争的重要部分。对开发者而言,理解这一链路,也意味着可以把自有项目中的脚本、查询、检索和代码分析能力,逐步接入 Agent,形成更贴近实际开发流程的自动化能力。

原创文章,作者:点点,如若转载,请注明出处:https://www.dian8dian.com/gei-dai-ma-zhi-neng-ti-jia-yi-jian-xin-zhuang-bei-cong-ling

Like (0)
点点的头像点点
Previous 5小时前
Next 3小时前

相关推荐