news 2026/9/13 22:56:57

SWE-agent Tool Bundle 配置详解:从 BundleConfig、Command 到 Argument 的完整实践指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SWE-agent Tool Bundle 配置详解:从 BundleConfig、Command 到 Argument 的完整实践指南

SWE-agent Tool Bundle 配置详解:从 BundleConfig、Command 到 Argument 的完整实践指南

【免费下载链接】SWE-agentSWE-agent takes a GitHub issue and tries to automatically fix it, using your LM of choice. It can also be employed for offensive cybersecurity or competitive coding challenges. [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/sw/SWE-agent

导读

在 SWE-agent 中,Agent 的能力边界由一组可执行工具(tools)决定,而这组工具的组织与管理正是通过Tool Bundle(工具包)机制实现的。本文以仓库文档 docs/reference/bundle_config.md 为主体,结合源码 sweagent/tools/bundle.py、sweagent/tools/commands.py 及仓库内的真实 bundle 配置,系统讲解 Tool Bundle 的配置模型:顶层BundleConfig如何声明工具与状态命令,Command如何定义可执行命令及其签名,Argument如何描述命令参数。读完本文,你将掌握如何阅读、编写、校验和扩展一个 SWE-agent 工具包,为 Agent 定制专属工具集。

一、概念澄清:Tool Bundle 配置 ≠ 工具配置

在深入配置字段之前,必须先厘清一个容易混淆的概念边界。仓库文档在开头就明确提示:

这是用于配置tool bundle的页面,而不是配置 Agent 正在使用的工具的页面。后者请参见 tools configuration。

也就是说,SWE-agent 中"工具"相关的配置分两层:

层级对应文档作用对象核心内容
工具配置(ToolConfig)docs/reference/tools_config.mdAgent 运行时启用哪些 bundle、环境变量、超时、解析函数、过滤规则等
工具包配置(BundleConfig)docs/reference/bundle_config.md(本文)bundle 目录内的config.yaml声明工具命令集合与状态命令

从源码看,二者的关系非常清晰:ToolConfig中有一个bundles: list[Bundle]字段(见 sweagent/tools/tools.py),而Bundle对象在加载时会读取其所在目录下的config.yaml并解析为BundleConfig。因此可以这样理解:bundle 配置是"生产工具"的配方,工具配置是"装配工具"的清单

二、BundleConfig:bundle 配置的顶层模型

BundleConfig定义在 sweagent/tools/bundle.py 中,是整个 bundle 配置文件(config.yaml)对应的 Pydantic 数据模型:

class BundleConfig(BaseModel): tools: dict[str, dict] state_command: str | None = None

它只有两个字段:

  • tools(必填):一个字典,key 是工具(命令)名,value 是对应的Command配置字典。例如searchbundle 的 tools/search/config.yaml 中定义了find_filesearch_dirsearch_file三个工具。
  • state_command(可选):一个特殊的命令名,在每次 Agent 动作之后执行,用于输出环境状态(详见下文第四部分)。

2.1 Bundle 的加载与校验流程

BundleConfig通常不是直接被使用者手动构造的,而是由Bundle模型在加载时自动解析。Bundlevalidate_tools校验器(sweagent/tools/bundle.py#L22-L41)完成了如下步骤:

  1. path转换为绝对路径;
  2. 校验 bundle 目录存在;
  3. 校验目录下存在config.yaml
  4. 读取并yaml.safe_load该文件,构造BundleConfig
  5. 校验hidden_tools(隐藏工具列表)中的每一项都真实存在于tools键集合中,否则抛出ValueError

2.2 hidden_tools:动态隐藏工具

Bundle还支持hidden_tools: list[str]字段,用于在不修改 bundle 配置文件的情况下,屏蔽其中的某些工具。其实现位于Bundle.commands属性(sweagent/tools/bundle.py#L52-L57):

@property def commands(self) -> list[Command]: return [ Command(name=tool, **tool_config.model_dump() if isinstance(tool_config, Command) else tool_config) for tool, tool_config in self.config.tools.items() if tool not in self.hidden_tools ]

注意这里的关键细节:tools中的每个配置字典会被展开为Command(name=tool, **tool_config)构造为命令对象,同时过滤掉hidden_tools中列出的名称。

hidden_tools的用法在测试 tests/test_run_single.py#L48-L63 中有直接体现:Bundle(path=TOOLS_DIR / "windowed", hidden_tools=["scroll_up"])—— 加载windowedbundle 但隐藏其scroll_up工具。这种机制特别适合在不改动公共 bundle 的前提下,为不同任务场景裁剪工具面。

2.3 state_command 属性透传

Bundle通过state_command属性直接透传config.state_command(sweagent/tools/bundle.py#L43-L45),而ToolConfig.state_commands(sweagent/tools/tools.py#L158-L164)会聚合所有 bundle 的 state_command 并在每个动作后依次执行。

三、Command:定义一个可执行命令

Command类是 bundle 中每个工具的核心模型,定义在 sweagent/tools/commands.py#L79-L205。其字段如下:

字段类型默认值含义
namestr必填命令名,Agent 在回复中以此调用工具
docstringstr | None必填命令的人类可读描述,会注入模型提示词
signaturestr | NoneNone自定义调用签名,覆盖默认的name arg1 arg2 ...
end_namestr | NoneNone多行命令的终止标记;一旦设置即表示这是多行命令
argumentslist[Argument][]命令接受的参数列表

3.1 单行命令与多行命令

Commandend_name字段是区分两类命令的关键:

  • 单行命令end_nameNone,命令在一行内完成,如find_filescroll_up
  • 多行命令end_name非空,命令体可以跨越多个行,并以end_name作为终止标记。这类命令的完整定义可以在 sweagent/tools/parsing.py 与 sweagent/tools/utils.py 的解析逻辑中看到:ToolHandler.guard_multiline_input会利用end_name以 heredoc 形式包裹多行参数发送到 bash(sweagent/tools/tools.py#L382-L409)。

ToolConfig.model_post_init会收集所有带end_name的命令,构造multi_line_command_endings字典供解析器使用(sweagent/tools/tools.py#L201-L213)。

3.2 invoke_format:调用格式的生成

Command.invoke_format(sweagent/tools/commands.py#L102-L131)决定了"如何把参数拼进命令字符串"。其逻辑分两种情况:

  1. 提供signature:先校验每个参数名确实以<name>[<name>]{name}--name中的某一种形式出现在签名中,然后通过正则re.sub(rf"\[?<({ARGUMENT_NAME_PATTERN})>\]?", r"{\1}", self.signature)把尖括号占位符替换为 Python format 占位符;
  2. 未提供signature:按默认格式"name {arg1} {arg2} ..."拼接。

以 tools/search/config.yaml 为例:

find_file: signature: "find_file <file_name> [<dir>]" arguments: - name: file_name type: string required: true - name: dir type: string required: false

这里<file_name>(必填)与[<dir>](可选)展示了签名中两种占位符的写法,invoke_format会将其转换为"find_file {file_name} {dir} "

3.3 validate_arguments:编写命令时的自检约束

Command.validate_arguments(sweagent/tools/commands.py#L167-L205)在模型构造时执行多项校验,编写自定义命令时需注意:

  • 必填参数必须在可选参数之前,否则报错Required argument ... cannot come after optional arguments
  • 参数名不得重复
  • 参数名必须匹配正则[a-zA-Z_][a-zA-Z0-9_-]*(sweagent/tools/commands.py#L30);
  • 签名/调用格式中的占位符集合必须与arguments的参数名集合完全一致,否则报错(_extract_keys通过string.Formatter解析出格式字符串中的所有字段名)。

3.4 get_function_calling_tool:与 Function Calling 的桥接

parse_function配置为 function calling 解析器时,Command.get_function_calling_tool(sweagent/tools/commands.py#L133-L165)会把命令转换为 OpenAI 风格的 function schema:

  • 工具名 =command.name
  • 描述 =docstring
  • 每个Argument映射为一个 JSON Schema 属性(含typedescription、可选的itemsenum);
  • required: true的参数进入required列表。

这正是ToolConfig.tools属性(sweagent/tools/tools.py#L193-L195)的实现基础:[command.get_function_calling_tool() for command in self.commands]

四、Argument:参数的类型化描述

Argument类定义在 sweagent/tools/commands.py#L52-L76,为命令参数提供类型化描述,字段如下:

字段类型默认值含义
namestr必填参数名,需匹配[a-zA-Z_][a-zA-Z0-9_-]*
typestr必填参数类型,如"string""integer"
itemsdict[str, str] | NoneNone数组元素类型的描述(如{"type": "string"}
descriptionstr必填参数的人类可读描述
requiredbool必填是否必填
enumlist[str] | NoneNone可枚举的取值白名单
argument_formatstr"{{value}}"参数在命令中的渲染格式,必须使用 Jinja 语法{{value}}而非{value}

argument_format有一个专门的校验器validate_argument_format(sweagent/tools/commands.py#L73-L76),调用 sweagent/utils/jinja_warnings.py 中的_warn_probably_wrong_jinja_syntax来提醒开发者避免误用单花括号。

在实际配置中,enum常用于约束参数取值范围。从源码注释可见其设计意图:它既会进入 function calling schema 的enum字段,帮助模型在结构化输出时只选择合法值。

五、实战:完整的 bundle 配置范例

结合上述三个模型,一个真实且完整的 bundle 配置应同时具备tools与(可选的)state_command。下面以仓库中的 tools/windowed/config.yaml 为例展示全貌:

tools: goto: signature: "goto <line_number>" docstring: "moves the window to show <line_number>" arguments: - name: line_number type: integer description: "the line number to move the window to" required: true open: signature: 'open "<path>" [<line_number>]' docstring: "opens the file at the given path in the editor. If line_number is provided, the window will be move to include that line" arguments: - name: path type: string description: "the path to the file to open" required: true - name: line_number type: integer description: "the line number to move the window to (if not provided, the window will start at the top of the file)" required: false create: signature: "create <filename>" docstring: "creates and opens a new file with the given name" arguments: - name: filename type: string description: "the name of the file to create" required: true scroll_up: signature: "scroll_up" docstring: "moves the window up {WINDOW} lines" arguments: [] scroll_down: signature: "scroll_down" docstring: "moves the window down {WINDOW} lines" arguments: [] state_command: "_state"

这个范例展示了几个常见模式:

  • 无参数命令scroll_upscroll_downarguments为空列表,其docstring中的{WINDOW}由 sweagent/tools/utils.py 的文档生成逻辑结合env_variables渲染(generate_command_docs会把环境变量传入文档模板);
  • 必填/可选参数组合openpath必填、line_number可选,对应签名中<path>[<line_number>]的写法差异;
  • 整数参数line_number的类型是integer,在 function calling schema 中会生成{"type": "integer"}

再对比 tools/diff_state/config.yaml:

tools: {} state_command: "_state_diff_state"

该 bundle 不定义任何工具,只注册一个state_command,用于在每个动作后输出 diff 相关状态——这证明了toolsstate_command是两个正交的维度。

六、state_command:动作后的状态采集机制

state_command是 bundle 配置中一个极易被忽视但作用关键的字段。其工作流程在 sweagent/tools/tools.py#L337-L348 的ToolHandler.get_state中体现:

  1. 依次执行所有 bundle 的state_command
  2. 读取环境中的/root/state.json
  3. 解析 JSON 并返回状态字典,供提示词模板格式化使用。

在 docs/config/tools.md 中给出了经典 SWE-agent 窗口工具的状态命令实现(_state脚本):它通过 registry 读取当前打开的文件,输出{"open_file": ..., "working_dir": ...}这样的 JSON。该状态字典随后可用于模板中的占位符(例如在提示词里展示"当前工作目录"与"当前打开文件")。

state_command也可以叠加多个 bundle 使用:ToolConfig.state_commands会把所有 bundle 的state_command收集起来依次执行,最终合并读取/root/state.json的内容(sweagent/tools/tools.py#L158-L164)。

七、将 bundle 接入 Agent:在 ToolConfig 中装配

了解了 bundle 自身的配置模型后,最后一步是把它接入 Agent。在 Agent 配置(如 config/default.yaml)的tools.bundles中按路径引用即可:

tools: bundles: - path: tools/registry - path: tools/edit_anthropic - path: tools/review_on_submit_m enable_bash_tool: true parse_function: type: function_calling

装配后ToolConfig.commands(sweagent/tools/tools.py#L167-L191)会:

  1. enable_bash_tool为 true,先加入内置的BASH_COMMAND(定义在 sweagent/tools/commands.py#L209-L223,即Command(name="bash", signature="<command>", ...));
  2. 遍历所有 bundle 的命令;
  3. 检测重名工具:同一命令名在不同 bundle 中重复定义会直接抛错,错误信息会指出首次定义与重复定义的来源路径。

ToolHandler._install_commands(sweagent/tools/tools.py#L292-L312)则负责把 bundle 上传到容器,执行install.sh,并逐一校验命令在容器中可用(which <command>)。

八、小结

围绕 docs/reference/bundle_config.md 的三个核心类,本文完成了从理论到实践的完整梳理:

  • BundleConfig(sweagent/tools/bundle.py#L12-L15):bundle 配置文件的顶层模型,tools必填、state_command可选;
  • Command(sweagent/tools/commands.py#L79-L205):定义命令名、文档、签名、多行终止标记与参数,并通过invoke_format生成调用格式、get_function_calling_tool桥接结构化输出,构造时还有严格的参数顺序与签名一致性校验;
  • Argument(sweagent/tools/commands.py#L52-L76):类型化参数描述,支持typerequiredenumitems与 Jinja 风格的argument_format

三个类共同构成了 SWE-agent 工具扩展的"最小可编程单元"。如果你希望新增一个自定义工具,推荐的路径是:先阅读 docs/config/tools.md 了解 bundle 目录结构与装配方式,再参照本文的字段规范编写config.yaml,最后参考 docs/usage/adding_custom_tools.md 的教程完成落地。每一个字段的合法性都由 Pydantic 校验器在加载时守护,出错信息会直接指出问题所在,这让自定义工具的开发过程既灵活又可控。

【免费下载链接】SWE-agentSWE-agent takes a GitHub issue and tries to automatically fix it, using your LM of choice. It can also be employed for offensive cybersecurity or competitive coding challenges. [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/sw/SWE-agent

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 22:51:20

【HarmonyOS 7新能力|007】空间音频入门实战:从能力边界到最小可运行链路

【HarmonyOS 7新能力&#xff5c;007】空间音频入门实战&#xff1a;从能力边界到最小可运行链路 空间音频并不是给左右声道各调一次音量。应用要先描述听者和声源的相对位置&#xff0c;再把位置、方向、播放状态与页面生命周期持续同步给渲染能力。只要坐标轴约定不一致、节点…

作者头像 李华
网站建设 2026/9/13 22:49:05

PLC 快照(Snapshot)机制详解

PLC 快照(Snapshot)机制详解 一、快照的核心设计思想 PLCController 通过周期性轮询将 PLC 的离散信号采集为一份一致性快照,业务流程(如等待条件、联锁判断)只读取快照,而不是直接读 PLC。 这样做的好处: 状态一致性:一次工艺判断中的所有信号来自同一时刻,避免读…

作者头像 李华
网站建设 2026/9/13 22:47:13

.NET并发编程:Task与Thread核心机制与应用场景

1. 理解.NET中的Task与Thread 在.NET开发中&#xff0c;Task和Thread都是用于实现并发编程的重要工具&#xff0c;但它们的设计理念和使用方式有着本质区别。作为一名长期使用.NET进行并发编程的开发者&#xff0c;我经常看到新手混淆这两个概念&#xff0c;导致程序出现性能问…

作者头像 李华
网站建设 2026/9/13 22:44:57

99页全国内部审计数智化转型发展研究报告【附全文阅读】

本报告为中国内部审计协会、信通院联合出品权威调研成果&#xff0c;适配央国企、事业单位内部审计数字化咨询投标与规划编制。基于 2888 份全国调研样本&#xff0c;搭建审计数智化成熟度评估体系&#xff0c;剖析金融、能源、医疗、高校多行业转型现状&#xff0c;梳理顶层规…

作者头像 李华