模型接上了 Agent 却不动手:编辑器工具调用失效的四类成因与验证方法

2026-08-07

“能聊天”和”能动手”是两条独立的链路,前者通了不代表后者通了。 你把一个自定义模型接进编辑器里的 AI 面板,问它问题它答得头头是道,让它改文件它就开始一本正经地把 diff 打在聊天框里,或者说”我已经修改了 xxx.ts”,可你 git status 一看,什么都没发生。这不是模型偷懒,多数情况下是工具调用这条链路上某一环根本没接通——而这一环的失效方式很安静,不一定报错。

这篇只处理一件事:把”接上了却不动手”拆成四类可分别验证的成因,每类给出你自己能跑出来的复核动作。站内另外三篇的分工是:Agent 工具调错了怎么排查讲的是工具已经调起来了、但参数或对象选错的情形;大模型工具调用是怎么回事讲的是这套机制在模型侧的原理;MCP 常见误解讲的是外挂工具协议层的认知偏差。本篇比它们更靠前一步——工具压根没被调起来的时候,该怀疑哪几处。

一、先把”接上了”和”会动手”拆成两件事

两个概念先摆平。

OpenAI 兼容端点,指一个 HTTP 服务把自己的接口做成和 OpenAI 那套请求/响应格式一样,于是任何按 OpenAI 协议写的客户端都能直接打过去,只需要换个地址和密钥。你在各家编辑器里选的那个 “OpenAI Compatible” 选项,就是让客户端按这套协议发请求。

原生工具调用(native tool calling,也常被叫作 function calling),指模型在响应里返回一段结构化的”我要调用哪个工具、参数是什么”,而不是在正文里用自然语言或自定义标记描述它想干什么。客户端拿到这段结构化输出,才会真的去执行读文件、写文件、跑命令这些动作,再把结果回喂给模型。

关键在于:这两件事分别由不同的一方负责。协议兼容是端点提供方的事,工具调用支持是模型(以及承载它的推理服务)的事。一个端点可以完美兼容 chat completions,但底下那个模型压根不返回工具调用结构——这时候你的对话链路是通的,动手链路是断的。上面那种”它把 diff 打在聊天框里”的表现,正是这种断法的典型外观:模型知道该做什么,但它表达”要做”的方式,客户端不认。

顺着这个划分往下,四类成因分别落在:模型侧、客户端能力声明侧、连接侧、长度参数侧。

二、成因一:所选模型不支持原生工具调用

这是最直接的一类,而且有一家把话说到了明处。

Roo Code 的官方文档在 OpenAI 兼容 provider 这一页写了一句硬限制(以下为官方文档原话):

“Roo Code uses native tool calling exclusively. This is the only supported tool protocol — there is no XML-based fallback.”

按官方文档这个说法,Roo Code 只支持原生工具调用这一种工具协议,没有基于 XML 的回退路径。也就是说,你接进去的模型如果不支持 OpenAI 兼容的 function calling,在这里就是用不了——不是”效果差一点”,是这条路没有。文档同时建议:先去查服务商的文档,确认该模型是否支持工具调用。截至 2026-08-07 官方文档是这么写的,具体以官方文档最新版为准。

为什么值得单独拎出来讲:很多人接自定义端点,是冲着某个便宜或者快的开源模型去的,而”支持 chat completions”和”支持 tools 参数”在服务商的文档里往往是分开两处写的,甚至只在模型详情页的某个能力标记里体现。你只看到”OpenAI 兼容”四个字就往里填,很容易踩中。

怎么验证:不要在编辑器里试,那里变量太多。直接对着你填的那个端点手发一次带工具定义的请求,看响应里有没有工具调用结构。这一步是 OpenAI 兼容协议层面的通用做法,不属于哪一家产品的文档记载。作为端点形态的参照,Groq 官方文档给出的 base URL 是 https://api.groq.com/openai/v1,鉴权走 Authorization 头,格式为 "Authorization: Bearer $GROQ_API_KEY"——你可以照这个形状去理解自己那家服务商的地址与鉴权该怎么组织,但具体值必须以你那家的官方文档为准。

另外一个可参照的说法:goose 的官方文档自述支持 40+ 个 LLM provider,并写了 “works best with Claude 4 models”,给出的理由是这些模型的工具调用能力。这是该文档的说法,不是本文的判断,也不构成推荐——引它是想说明,“模型的工具调用能力”在终端 Agent 这类产品里被当作一个正经的选型维度。

三、成因二:客户端这一侧的能力声明没写对

模型支持是一回事,客户端知不知道它支持是另一回事。配置文件驱动的产品,通常要你在配置里把能力显式写出来。

Continue 的模型配置写在 config.yamlmodels 块下。截至 2026-08-07 官方文档,必填三项是 name(唯一标识)、provider(如 openai、ollama、mistral)、model(具体模型名);可选字段里包含 apiBase(覆盖默认 API 端点)、rolescapabilities(文档举的例子是 tool_useimage_input)、defaultCompletionOptions(temperature、maxTokens、topP 等)、requestOptions(timeout、headers、proxy 等 HTTP 配置)。

这里要格外守住一条:本篇依据的那一页记录里,capabilities 只列了字段名和取值举例,没有逐条说明客户端内部拿它做什么。所以”把 tool_use 写进 capabilities 就能让工具跑起来”这种话,本文不写成事实断言。按字段语义能推出来的判断是:这一项由你来声明该模型具备哪些能力,客户端可能据此决定要不要按对应方式组织请求;实际行为以官方文档为准。

roles 这一项文档写得更实:取值有 chatautocompleteembedrerankeditapplysummarize,默认是 [chat, edit, apply, summarize]。顺带解释两个词:embed 指嵌入,把文本转成向量用于检索;rerank 指重排,对检索回来的候选再排一次序。这两个角色和代码检索相关,和”会不会动手改文件”不是一回事,别混着调。

文档给出的示例可以原样参照:

models:
  - name: GPT-4o
    provider: openai
    model: gpt-4o
    roles:
      - chat
      - edit
    defaultCompletionOptions:
      temperature: 0.7
      maxTokens: 1500

注意这个示例显式写了 roles: [chat, edit]——文档记的是「默认为 [chat, edit, apply, summarize]」,也就是说你一旦自己写了 roles,这一项的取值就以你写的为准,不再是那个默认组合。至于「只声明了 chat 的模型,在需要 editapply 的位置上会怎样」,那是按字段语义推出来的判断,本篇依据的那一页并没有逐条说明客户端拿 roles 做什么,实际行为以官方文档为准。

Zed 走的是 settings.json。官方文档示例(可原样参照):

{
  "language_models": {
    "openai_compatible": {
      "my-provider": {
        "api_url": "https://example.com/v1",
        "available_models": [
          {
            "name": "my-model",
            "display_name": "My Model",
            "max_tokens": 128000
          }
        ]
      }
    }
  }
}

字段含义按文档:api_url 是自定义 base URL;available_models 是模型数组,每项含 name(模型标识)、display_name(界面显示名)、max_tokens(上下文窗口上限);capabilities 对象控制能力开关,包括 tools、images、parallel_tool_calls 等。

把三家横过来看,官方文档层面能对上的一条是:Roo Code 只认原生工具调用且无 XML 回退,Continue 有 capabilities.tool_use,Zed 的 capabilities 含 tools 与 parallel_tool_calls。这三家都在配置层给了一个跟工具调用直接相关的位置,可见它是需要你落到配置里的一项,而不是你只要选对模型就自动带上的。 至于配置里不写会不会走某种自动判定,各家文档在本篇依据的那几页里没有说明,以官方文档为准。可以确定的是:在配置文件驱动的产品里,“我模型明明支持”这句话不足以说明问题——还得去看配置里那一项写没写、写在哪一层。

怎么验证:改配置文件的那一类,验证方式就是拿你自己的配置和官方文档示例逐字段对齐,尤其对齐层级——available_models 是数组、capabilities 是对象,这种结构错了,字段名再对也没用。至于改完之后界面上会不会立刻生效、会不会提示你哪里写错了,以你实际看到的界面为准,本文不做描述。

四、成因三:端点与凭据其实没接通

这一类的迷惑性在于,表现上和”不会动手”很像:Agent 转一圈什么也没做,或者回一句含糊的话。而根子在连接层。

最高频的踩点是 base URL 字段名跨家串台。各家名字完全不同,把 A 家的字段名搬到 B 家的配置里,轻则不生效,重则你在错误的地方查了半天。

配置项(逐字来自官方文档)它是什么填错时大致会怎样出处(见文末来源)
Base URL(Cline / Roo Code / Kilo Code 界面字段)请求要发往的 API 端点请求打不到目标服务,或落到一个非预期的服务上来源 1 / 2 / 3
apiBase(Continue config.yaml覆盖默认 API 端点请求仍走默认端点,你以为换了其实没换来源 4
api_url(Zed settings.json自定义 base URL同上,连接层失败来源 6
OPENAI_HOST(goose 环境变量,另有 OPENAI_BASE_PATH指向自建 / 企业内部的 OpenAI 兼容端点主机与路径两段拆开,只设一段容易拼不出完整地址来源 7
--base-url(Crush 的 provider add 参数)自定义 provider 的端点地址provider 注册出来但打不通来源 8
<PROVIDER_NAME>_API_KEY(Zed 环境变量命名规则)按 provider 名推导出的密钥环境变量名变量名拼错则等同于没提供密钥来源 6
$VAR_NAME / ${VAR_NAME}(Gemini CLI settings.json 插值)配置文件里引用环境变量的写法变量未定义时引用解析不出预期值来源 9

表格里”填错时大致会怎样”这一栏,是 HTTP 与 OpenAI 兼容协议层面的通用机制推理,不是上述任何一家官方文档的记载;各产品实际怎么表现,以官方文档和你实际看到的界面为准。

关于地址要不要带 /v1,官方文档层面能查到的几处是:Cline 文档里的 v0 Quickstart 示例 Base URL 为 https://api.v0.dev/v1(含 /v1),Model ID 为 v0-1.0-md;Kilo Code 文档明确说明 Base URL 接受两种形态,标准形态 https://api.provider.com/v1 和完整端点 https://api.provider.com/v1/chat/completions,第二种是为端点结构非标准的服务商与自建网关准备的;Zed 示例是 https://example.com/v1;goose 则把主机和路径拆成 OPENAI_HOST 与可选的 OPENAI_BASE_PATH 两段。这几家的设计取向明显不同,不能互相套。

密钥存放这一层也有官方口径可依。Zed 文档写得很直:

“Do not put API keys in settings.json.”

凭据走两条路:provider 设置界面,或者环境变量,命名规则是 <PROVIDER_NAME>_API_KEY——provider 名为 my-provider 时对应 MY_PROVIDER_API_KEY。configuration 那一页还有一句原话:“Provider keys saved through Zed are stored in the system keychain, not in settings.json.” 这里的 keychain 指操作系统自带的凭据保管服务,密钥交给它保管、不落到普通配置文件里。

Gemini CLI 走的是另一条路:settings.json 内支持环境变量插值,写 $VAR_NAME${VAR_NAME},加载时自动解析。所谓插值,就是配置文件里只写变量名占位,真实值运行时从环境变量取——这样配置文件可以进版本库,密钥不进。它的 .env 查找顺序是当前工作目录 → 逐级父目录(到项目根或 home 为止)→ 用户 home 的 ~/.env

怎么验证:把 base URL 和密钥抄出来,脱离编辑器,用 curl 直接打一次那个端点。这一步通了,才轮得到怀疑前面三类;打不通,前面全是白排。

顺带一条 Kilo Code 文档里明确写出的提醒:Azure GPT-5 不要用通用的 OpenAI 兼容 provider,要用 Kilo 原生的 azure provider,因为 Azure 会拒绝 max_tokens 参数。这类”某个服务商对某个参数有特殊处理”的情形,是连接层里最难自己想到的一种。

五、成因四:需要你手填的长度参数

这一类不会让工具调用彻底失效,但会让它半路断掉——看起来就像”做了一半不做了”。

多家产品把上下文窗口这件事交给你手填。上下文窗口指模型一次请求里能容纳的 token 总量,输入加输出都算在内。官方文档层面能查到需要手填的地方包括:Cline 的 Model Configuration 区列有 Max Output Tokens、Context Window size、Image Support、Computer Use、Input Price、Output Price;Roo Code 可自定义 Max Output Tokens、Context Window、Image Support、Computer Use、输入/输出价格;Zed 在 available_models 每项里写 max_tokens;aider 则用 .aider.model.metadata.json 给它不认识的模型注册上下文上限与价格,文档示例是:

{
    "provider/model-name": {
        "max_tokens": 4096,
        "max_input_tokens": 32000,
        "max_output_tokens": 4096,
        "input_cost_per_token": 0.00000014,
        "output_cost_per_token": 0.00000028,
        "litellm_provider": "provider",
        "mode": "chat"
    }
}

这段里的数值是官方文档的示例值,不是任何真实模型的报价,别拿去当参考价。

要守住的一条纪律:Cline 与 Roo Code 那几项里,Context Window size、Image Support、Computer Use、Input Price、Output Price,本篇依据的那两页记录里只列了字段名,没有说明客户端内部拿这些数字做什么。所以本文只讲”这一项由你填、填的是什么量纲”,不讲它被用在哪个决策上。要展开也只能标明这是按字段语义推出来的判断:填的是 token 数量的上限,客户端可能据此组织请求;实际行为以官方文档为准。

而”最大输出设得太小会被截断”、“窗口值填得比服务端真实上限大、请求可能被服务端拒”这两条,属于 OpenAI 兼容协议的通用机制推理,不是上述任何一家文档的说法——写在这里是给你一个排查方向,不是给你一个结论。

怎么验证:让 Agent 做一个必然要产出较长内容的动作(比如改一个稍大的文件),观察它是在”没开始”还是在”中途停”。没开始,回到前三类;中途停,才轮到这一类的参数。

六、边界与代价:这套排查法不管什么

按四类成因分头验证,代价和边界都很清楚。

它放弃了”一次定位”。 这是分层排除法,你得从连接层往模型层一层层试,最慢的时候要跑三四轮。想省事的人会更愿意直接换个已知好用的模型试一把——那也是个合理选择,只是换成功了你也不知道原来那个坏在哪。

它不适用于托管模型场景。 你要是用产品自带的托管模型或者官方订阅接进去,base URL、密钥、模型能力都是产品方配好的,这四类里有三类根本不在你手上。Zed 文档列出的模型接入路径共五类:Zed 托管模型、自带 API key、复用已有订阅、网关(OpenRouter / Vercel AI / Amazon Bedrock)、本地模型(Ollama / LM Studio / 自托管)。本篇讲的是自带 key 与自建端点这一侧。

它明确不管这几件事:不管工具已经调起来之后参数选错、对象选错的排查,那是另一篇的范围;不管 MCP 这类外挂工具协议自身的连接问题,那是MCP 常见误解和相关文章的范围;不管本地模型的推理性能与显存问题;也不管各家在权限确认上的设计差异——有的产品会在执行前拦一道,这属于产品行为,以你实际看到的界面为准。

它也不替你判断该用哪家。 各家在配置形态上的取向差得很远:图形界面表单一路(Cline / Roo Code / Kilo Code)、YAML 配置文件一路(Continue 的 config.yaml、aider 的 .aider.model.settings.yml)、JSON settings 一路(Zed 与 Gemini CLI 的 settings.json)、环境变量与 CLI 子命令一路(goose 的 GOOSE_PROVIDERgoose configure、Crush 的 crushrcprovider add)。这四种形态各有各的适配场景,本文不排座次。

七、避坑清单

把”端点兼容”当成”模型支持工具调用”。 会踩是因为两件事在服务商文档里通常分开写,而你只看到”OpenAI 兼容”就下结论了。避法:接之前先按 Roo Code 文档的建议去查服务商文档确认该模型是否支持工具调用;接之后用 curl 发一次带工具定义的请求实测,别在编辑器里猜。

把 A 家的字段名搬到 B 家。 会踩是因为几家的功能高度相似,人脑会自动认为字段名也一样。实际上 Base URL、apiBaseapi_urlOPENAI_HOST--base-url 是五个不同的东西。避法:每换一家,就把该家官方文档的那一页重新打开对一遍字段名,别凭上一家的记忆填。

地址带不带 /v1 全凭手感。 会踩是因为各家示例形态不一致,Kilo Code 甚至明确接受两种形态。避法:以你那家服务商官方文档给出的完整 base URL 为准,再对照你要填的那个客户端的文档示例看该填到哪一层;goose 这种把主机与路径拆成两段的设计,两段都要看清。

把密钥写进会进版本库的配置文件。 会踩是因为配置文件里字段就摆在那儿,顺手就填了。避法:Zed 文档明确写了不要把 API key 放进 settings.json,走 provider 设置界面或 <PROVIDER_NAME>_API_KEY 环境变量;Gemini CLI 提供了 $VAR_NAME 插值,让配置文件能进库而密钥留在环境里。这两条都是可以直接照做的。

写了 roles 却漏了需要的角色。 会踩是因为不写的时候有默认值 [chat, edit, apply, summarize],一旦你为了加一项而显式写出 roles,默认值就不再兜底了。避法:显式写 roles 时,把你需要的角色一次列全,别只写你新加的那个。

改完配置就断定”没生效”。 会踩是因为配置文件类产品的加载时机你未必清楚,而层级写错了字段名再对也是白搭。避法:先拿官方文档示例逐层比对结构(数组是数组、对象是对象),再看行为;界面上有没有提示、什么时候提示,以你实际看到的为准,别把”没看到提示”当成”配置没问题”。

只在编辑器里反复试。 会踩是因为编辑器把连接、能力、参数三层裹在一起,任何一层坏了外观都差不多。避法:坚持”先 curl 打通端点,再回编辑器”这个顺序,能砍掉一半的排查时间。关于连接层之外的成本与预算维度,可以另看Agent 上下文预算怎么算

数据来源与核对日期

本篇涉及的全部产品事实,来自以下官方文档页面,核对日期均为 2026-08-07。文档会更新,请以官方文档最新版为准。

  1. Cline 官方文档(OpenAI 兼容 provider 配置页):https://docs.cline.bot/provider-config/openai-compatible
  2. Roo Code 官方文档(OpenAI 兼容 provider 配置页,native tool calling 那句原话出处):https://roocodeinc.github.io/Roo-Code/providers/openai-compatible
  3. Kilo Code 官方文档(OpenAI 兼容 provider 配置页,Base URL 两种形态与 Azure GPT-5 提醒出处):https://kilo.ai/docs/providers/openai-compatible
  4. Continue 官方文档(config.yaml 参考页,models 块字段与 YAML 示例出处):https://docs.continue.dev/reference
  5. aider 官方文档(模型高级设置页,.aider.model.metadata.json 示例出处;示例中的单价为文档示例值):https://aider.chat/docs/config/adv-model-settings.html
  6. Zed 官方文档(两页,settings.json 示例、API key 不进配置文件那句原话、keychain 那句原话、五类模型接入路径出处):https://zed.dev/docs/ai/use-api-accesshttps://zed.dev/docs/ai/configuration
  7. goose 官方文档(provider 配置页,OPENAI_HOST / OPENAI_BASE_PATHGOOSE_PROVIDER、40+ provider 与 works best with Claude 4 那两句自述出处):https://goose-docs.ai/docs/getting-started/providers/
  8. Crush 官方 README(crushrcprovider add --base-url 示例出处):https://raw.githubusercontent.com/charmbracelet/crush/main/README.md
  9. Gemini CLI 官方文档(配置页,settings.json 位置与 $VAR_NAME 插值、.env 查找顺序出处):https://google-gemini.github.io/gemini-cli/docs/get-started/configuration.html
  10. Groq 官方 API 文档(base URL 与鉴权头格式出处):https://console.groq.com/docs/api-reference

本篇没有写什么,以及为什么。

不写任何产品的价格、免费额度、订阅档位、限速数字。这类数字变动频繁,本次核对也未逐项核实,写出来只会误导你做预算。请以各产品与各服务商官方文档、控制台的实时数据为准。

不写各家的完整模型清单。上面出现的模型 ID 只是官方文档里的示例值,不代表可用清单,也不构成推荐。

不写各家界面长什么样。上述来源记录的是配置层事实,界面元素、菜单层级、提示文案、校验时机都不在其中,本文一律不描述——需要看的时候,以你实际看到的界面为准。

不写”某家没有某项功能”这类绝对否定。本篇只依据上述各页面当天的记录,某项没出现在记录里,不等于该产品没有这项。

不给各家文档或产品排座次。上面提到的设计取向差异,都能在对应文档页里找到依据,但差异不等于优劣,选型请结合你自己的工作流判断。

延伸阅读:同一组里的 聊天能用补全不工作编辑器里AI输出卡住不出字;接完之后照 接完自定义模型别急着干活 逐项过一遍,才算真接通。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。