快速结论:使用 AI Agent (V3) + Google Vertex Chat Model (Gemini) 时,如果模型在同一轮里先输出一段文字再发起工具调用,这段文字在下一次请求的对话历史中会被替换或丢弃;模型可能模仿替换后的合成文本,把 “Calling tools: …” 写进给用户看的回复。优先排查 AI Agent 的步骤构建逻辑(buildSteps),而不是 Vertex 接口本身。
适用环境:n8n AI Agent v3.1(langchain nodes 包,复现提交 ca3e5129e58c 对应 2.47.0)、Google Vertex Chat Model(gemini-3.5-flash,location global,service account,streaming)、Node.js v24.22.0、Simple Memory 或 Postgres Chat Memory;问题与具体操作系统、显卡无关。
最快修复方案:暂无确认的一步修复方案。Issue 中提出的修改思路(在 createEngineRequests 中保留前导文本、在 buildSteps 中回填并删除 “Calling tools” 字符串)尚未合入,只能作为修复方向参考。
注意事项:该问题不影响请求本身,Vertex 响应均为 HTTP 200,因此不能靠报错日志定位;前导文本的替换与丢失每次都会发生,但模型把它抄进用户回复是间歇性的,复测时需要多轮次观察。Issue 已关闭,但讨论内容没有给出已验证的最终修复版本。
问题场景
在 n8n 中搭建 AI Agent (V3/V3.1) 节点,接入 Google Vertex Chat Model(Gemini 3.x),并开启 Chat Trigger 的 streaming。系统提示要求模型“每次调用工具前先用一句话说明要做什么,再在同一轮里调用工具”。当模型按此要求输出“文字 + 工具调用”时,下一轮发给 LLM 的历史记录里,模型自己说过的那段文字被替换为合成的 Calling tools: code_tool, reverse_tool;如果同一轮只有一个工具调用,这段文字则直接丢失。配合 Simple Memory 或 Postgres Chat Memory 时,用户会看到模型在回复中写出 Calling tool: code_tool,或形如 Calling tools: kb_lookupAccording to our policy… 的内容,其中 AI Agent (V3) replaces Gemini’s text before a tool call with synthetic “Calling tools: …” in history; model then copies it into user-facing 是该问题的核心表现。
报错原文
Call 2, request (replayed model turn). The original text is gone and synthetic text is inserted:
model: text("Calling tools: code_tool, reverse_tool") | functionCall(code_tool {"input":"alpha"})[sig:4f88ab57] | functionCall(reverse_tool {"input":"beta"})
Call 2, model response:
text("Calling tool: code_tool") | functionCall(code_tool {"input":"ateb"})[sig:6f2699aa] | text("")
Chat stream received by the client:
I am going to convert 'alpha' to uppercase and reverse the word 'beta' simultaneously.Calling tool: code_toolHere are the results of the operations: ...
原因分析
根据 Issue 复现者的定位,问题出在 packages/@n8n/nodes-langchain/utils/agent-execution/buildSteps.ts:buildSharedGeminiAIMessage() 对并行的 Gemini 工具调用把 content 设为 Calling tools: ${toolNames};buildIndividualAIMessage() 对非 Anthropic 提供商的单工具调用路径返回空 content。同时,createEngineRequests 生成的 action 元数据只携带 thinking 和 signature 信息,buildSteps 没有原始前导文本可用于回放,尽管该文本仍在原始消息日志中。因此模型看到的历史与它实际说出、用户实际看到的并不一致,模型可能模仿合成格式,把 “Calling tools: …” 写入对外回复。
环境排查
- 确认 n8n 中 AI Agent 节点版本为 V3/V3.1,并记录 langchain nodes 包版本(复现环境为 2.47.0)。
- 确认 LLM 节点为 Google Vertex Chat Model,模型为 gemini-3.x 系列,并开启 streaming(复现为 gemini-3.5-flash、location global)。
- 记录 Node.js 版本(复现为 v24.22.0)。
- 确认是否启用了 Simple Memory 或 Postgres Chat Memory,以便判断合成文本是否被写入记忆并在后续轮次回放。
- 开启 HTTP 层请求/响应日志,逐轮检查 model turn 中 text part 与 functionCall 的构成;仅查看节点输出可能看不到被替换的历史内容。
解决步骤
- 先复现并确认:按 Issue 的 workflow 构造“文字 + 平行工具调用”的场景,抓取第二、三次 LLM 请求,确认历史中出现
Calling tools: …或多工具调用时前导文本为空。 - 可优先尝试:若只是需要在记忆回放中避免合成文本污染,可在工作流中更换或关闭相关记忆节点做对照测试;Issue 未验证该办法能彻底解决问题,只能用于确认影响范围。
- 如果使用自部署 n8n,可在本地按 Issue 提出的方向修改:在
createEngineRequests中从消息日志读取前导文本,存入 action 元数据的可选字段;在buildSteps中把它作为共享 Gemini 消息和单工具调用消息的 content,无前导文本时保持为空,并移除Calling tools合成字符串。 - 为并行工具调用和单工具调用两种情况分别补充测试,确认回放的 content 与原始响应一致。
- 修改属于本地补丁,Issue 讨论中未提供合并 PR 或发布版本,升级前需自行评估维护成本。
验证方法
再次执行复现步骤后抓取第二、三次 LLM 请求:model turn 中应保留模型原始前导文本(如 “I am going to convert ‘alpha’…”),不再出现 Calling tools: code_tool, reverse_tool,且单工具调用时该文本不再为空。同时多轮观察 Chat 流式输出,确认回复中不再出现 Calling tool: code_tool 这类被模型模仿的合成文本;使用 Postgres Chat Memory 时,还应确认记忆中没有存下合成文本。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


