n8n AI Agent 已连接工具却不调用,直接文本回复与真实 Tool Call 的分支对比 - XBSTACK

n8n AI Agent 不调用工具怎么办?tool_choice、模型兼容与 Memory 排查

Release Date
2026-07-26
Reading Time
9分钟
Content Size
4,657 chars
n8n
AI Agent
Tool Calling
Function Calling
tool_choice
OpenAI Compatible API
Ollama
vLLM
Memory
Debugging
Xiaobai's Note / 实验室笔记

本文使用公开 n8n Issue、官方 Tools Agent 文档和本地确定性请求契约实验。实验没有运行真实 n8n 容器,也没有调用 Mistral、Ollama、vLLM、LM Studio 或任何托管模型 API,因此不能把 20/20 结果解释为真实模型成功率。

n8n AI Agent 不调用工具怎么办?tool_choice、模型兼容与 Memory 排查

n8n 的 AI Agent 已经连上 Code Tool、HTTP Request Tool 或 MCP Tool,System Message 也写了“必须调用工具”,但运行时仍然直接输出一段答案。这类问题不能继续靠加重 Prompt 解决。第一步不是改提示词,而是确认故障发生在哪一层:模型根本没有生成 Tool Call、生成了但 n8n 解析失败、Tool 已执行但结果没有回到 Agent,还是多轮 Memory 把调用过程丢了。

先给结论:Tool 节点在 Execution 中一次都没有亮起,才属于“Agent 跳过工具”;Tool 节点已经运行但报错,则是参数、Schema、凭据或下游接口问题。 对首轮跳过工具的情况,n8n 官方仓库的 Issue #31135 报告了一个具体边界:AI Agent v3 把 tools[] 发给 OpenAI 兼容 Provider,却没有在第一次迭代显式设置 tool_choice: required。对工具调用倾向较弱的模型来说,默认 auto 就意味着“可以直接回答”。

本文把官方报告、本地实验和仍未验证的内容分开。官方 Issue 说明真实用户看到了什么;本地实验只验证“缺少 tool_choicerequired 的请求语义不同”,不把模拟结果冒充 Mistral、Ollama 或 vLLM 的实测成功率。

先用 Execution 判断:到底有没有产生 Tool Call

不要先看 Agent 最终回复。打开本次 Execution,检查 AI Agent、Chat Model 和 Tool 三个节点。

现场说明下一步
Tool 节点完全没有执行模型没有产生可执行 Tool Call,或 Agent 没把调用交给 Tooltool_choice、Provider兼容、工具描述和模型能力
Tool 节点启动后 Schema 报错已经调用,但 arguments 不符合定义查 JSON Schema、required、类型和嵌套结构
Tool 节点执行成功,Agent仍说失败Tool Result 没被正确解析或返回内容不适合模型规范输出结构,检查错误分支与返回体
单轮正常,多轮后不再调用Memory 可能没有持久化 Tool Call/Result查 Memory记录、会话ID和业务状态
某Provider失败,换模型正常Provider只兼容Chat Completions表面格式,Tool Calling实现不完整固定模型与API版本,抓真实请求响应

n8n 官方 Tools Agent 文档说明该节点通过 LangChain 的工具调用接口向模型描述工具和Schema。这个接口能把工具暴露给模型,但是否选择工具仍受请求参数、Provider实现和模型能力影响。Tools AI Agent node

为什么 Prompt 写“必须调用”仍然会被跳过

Prompt 约束的是模型行为倾向,tool_choice 约束的是请求协议。两者不是同一层。

一个典型首轮请求可能包含:

{
  "model": "mistralai/Mistral-Small-24B-Instruct",
  "messages": [
    {"role": "system", "content": "You MUST call get_value."},
    {"role": "user", "content": "What is the value?"}
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_value",
        "parameters": {"type": "object", "properties": {}}
      }
    }
  ]
}

tools 只表示“这些函数可用”。如果没有 tool_choice,多数兼容接口会按 auto 处理,模型仍可选择输出普通文本。大型模型可能从Prompt推断出必须调用,小模型或兼容层则可能直接猜一个答案。

这也是 Issue #31135 提出的核心:只在第一次迭代强制工具调用,拿到 Tool Result 后恢复 auto,让模型生成最终回复。若每一轮都保持 required,Agent可能反复调用工具而无法结束。

缺少 tool_choice 时模型直接回复,设置 required 后返回 Tool Call 的请求契约对比

本地实验:只验证请求契约,不伪造模型跑分

实验目录:

experiments/n8n-ai-agent-tool-choice/

实验使用一个确定性 OpenAI 兼容 Provider Fixture。它故意遵循一条简单规则:

  • 请求有工具但没有 tool_choice: required:返回普通文本;
  • 请求显式要求 required:返回结构化 Tool Call。

同一请求重复20次:

场景运行次数Tool Call普通文本
首轮缺少 tool_choice20020
首轮代理注入 required20200

这里的20/20是确定性Fixture的契约测试,不是任何真实模型的准确率。它只证明:当Provider把缺失值视为auto时,Prompt不能替代协议参数;代理确实能改变请求语义。

同时验证了三个安全边界:

  1. 请求没有工具时不注入;
  2. 调用方显式设置none或指定工具时不覆盖; 3.历史消息已经包含Assistant Tool Call时,视为后续迭代,不再强制。

核心逻辑如下:

def should_force_tool_use(payload):
    tools = payload.get("tools") or []
    if not tools:
        return False

    for message in payload.get("messages") or []:
        if message.get("role") == "assistant" and (
            message.get("tool_calls") or message.get("function_call")
        ):
            return False

    return payload.get("tool_choice") in (None, "auto")

完整请求样本、验证结果和5项单元测试都保存在实验目录中。

如何在不改 n8n 源码的情况下临时处理

最稳妥的长期方案是等待上游修复,并在升级前后抓取真实请求验证。若当前生产流程必须使用某个兼容Provider,可以在n8n和Provider之间增加一个窄代理:

n8n AI Agent
  -> OpenAI-compatible proxy
     -> 检查 tools
     -> 检查是否首轮
     -> 仅首轮注入 tool_choice=required
  -> Provider

代理必须满足:

  • 只允许受控上游和模型;
  • 不记录API Key和完整敏感Prompt;
  • 限制请求体大小、超时和并发;
  • 对显式none、指定函数和后续迭代保持原样;
  • 记录是否注入、模型名、Tool数量和去敏请求哈希;
  • 可以通过开关快速回滚。

不要用 Code 节点随意改一段未知JSON后直接转发。若代理无法准确识别Agent迭代,可能把第二轮也强制成Tool Call,引发重复发送、重复退款或死循环。

请求已经有 Tool Call,为什么 Tool 仍不执行

这时tool_choice已不是主因,继续检查以下四项。

同一 n8n AI Agent 请求在 OpenAI、兼容 Provider 与本地小模型中的工具调用可靠性差异

Tool Schema 是否真的被Provider支持

公开Issue中存在Gemini返回参数后,n8n报Received tool input did not match expected schema的案例。常见原因包括:

  • Schema要求对象,模型输出字符串;
  • required字段与实际参数不一致;
  • 嵌套对象或数组被兼容层扁平化;
  • 枚举值超出范围;
  • Tool Workflow的输入字段名与声明不同。

先把工具收敛成无参数常量函数,再逐步增加参数。若无参工具都无法调用,优先查Provider和请求契约;若无参成功、复杂Schema失败,再查参数定义。

工具名称和描述是否互相竞争

Issue #15883 记录了相同输入有时调用一个、有时两个工具的现象。多个工具描述高度相似时,模型缺乏稳定路由依据。

工具名称应表达动作和对象,例如:

get_customer_order_status
create_customer_refund_draft
send_refund_confirmation_email

不要同时提供customer_toolsupport_toolorder_helper这类模糊名称。描述里要写清输入、输出、是否有副作用和什么时候禁止调用。

含糊的工具名称和相似描述会让模型无法稳定选择,清晰命名与合法 JSON Schema 能提高调用可靠性

Provider是否只“兼容接口”,并不兼容完整Tool Calling

OpenAI兼容通常只说明URL和部分字段相似,不保证:

  • tool_choice全部枚举都支持;
  • 并行Tool Call支持;
  • 流式增量参数格式一致;
  • JSON Schema 2020-12兼容;
  • Tool Call ID和Tool Result关联正确;
  • 多轮消息保留完整。

必须抓请求和响应,不要只看Provider宣传页。固定模型版本和Provider版本,保存一份最小成功样本。

Tool返回是否足够结构化

Tool返回长段自然语言、HTML或巨大JSON时,Agent可能解析失败或忽略关键字段。生产工具最好返回稳定结构:

{
  "ok": true,
  "data": {"value": 42},
  "error": null,
  "audit_id": "tool-20260726-001"
}

让模型读取明确的okdata,同时保留审计ID供Execution追踪。

为什么多轮后会“声称调用了工具”

Issue #14361 报告Simple Memory和Postgres Memory只保存输入与最终输出,没有保存Tool Call和Tool Result。模型后续看到的是:用户要求执行,Assistant文字上说“已经完成”,用户又继续对话;它看不到中间真实调用,于是可能学会只复制“已完成”的文本模式。

Tool Result 没有写入 Memory 时,下一轮 AI Agent 可能根据文本历史伪造连续性

排查方法:

  1. 查看Memory后端实际保存的消息类型;
  2. 确认Tool Call ID、参数摘要和Tool Result是否存在;
  3. 不把“Assistant声称成功”当成业务事实;
  4. 订单ID、审批ID、任务状态等关键数据写入数据库,而不是只依赖对话Memory;
  5. 每次写操作返回审计ID,并在下一轮需要时重新查询权威状态。

Memory用于帮助模型理解对话,不应成为支付、订单、邮件和部署是否执行成功的唯一账本。

一套从快到慢的排查顺序

1. 看 Execution:Tool 节点是否启动
2. 只保留一个无参数常量 Tool
3. 固定同一个输入重复运行 10 次
4. 抓 Provider 的原始请求与响应
5. 检查 tools 与 tool_choice
6. 换一个已知支持 Tool Calling 的模型做对照
7. 逐步恢复 Schema、多个工具和 Memory
8. 检查 Tool Result 与跨轮状态
9. 写入业务审计ID和幂等键

每次只改变一个变量。一次同时换模型、改Prompt、改Schema和换Memory,最终即使成功,也无法知道真正修复了什么。

可复现实验代码已同步到公开 GitHub 目录。它不需要 API Key,可直接重跑请求契约和 5 项单元测试。

最终判断

n8n AI Agent不调用工具并不是一个单一Bug。首轮tool_choice缺失、Provider兼容不完整、模型工具选择能力、Schema错误、工具描述冲突和Memory丢失都可能产生相似表象。

最重要的判断标准不是Agent回复里有没有“我已调用”,而是Execution中是否存在真实Tool Call、Tool节点是否执行、结果是否持久化、外部副作用是否有审计记录。Prompt只能影响模型,不能代替协议约束和业务证据。

继续阅读:n8n AI Workflow 错误处理、重试与成本监控AI Agent Tool Use:工具注册、参数校验与调用审计自托管 n8n AI Workflow 部署指南

专题入口 / AI Workflow Hub

继续按 n8n 生产排障链路读

自托管、Queue Mode、Webhook、错误处理和案例文统一沉淀到 Workflow 专题页:部署文做主力页,案例文做长尾页,对比文承接工具选择流量。

下一步阅读

返回专题入口 →
小白

小白

Full-Stack AI Engineer

小白,全栈 AI 工程师,持续构建生产级 Agent 系统、产品工具与独立软件资产。

了解小白与 XBSTACK →

喜欢这篇文章?
加入小白实验室的周刊

每期只整理 AI 工程变化、真实故障、可复现实验、值得尝试的工具和 XBSTACK 新资产,不做泛新闻汇总,也不为周更凑数。

Comments

参与讨论

问题、验证与勘误

登录后可发表评论。所有新评论先进入审核;审核期间仅评论者本人和管理员可见,通过后才公开。

登录评论 审核后公开
正在加载评论区…