当Dify、Cursor和一个轻量级Node.js服务共享同一个Vector Engine账号时,一次失败的请求看起来可能比实际情况更扑朔迷离。错误可能在Dify里报一次,在Cursor里换种面目出现,而Node.js服务日志里只留下一个干巴巴的HTTP状态码。如果这些工具都接到同一个OpenAI兼容API网关,真正的问题不是“哪个工具坏了”,而是“每个工具到底发出了怎样的请求”

不妨把Vector Engine看作一个契约很小的LLM API提供层:

  • Base URL:所有工具共用的端点
  • API Key:分配给每个工具或服务的密钥范围
  • 模型名:在Dify、Cursor和Node.js里配置的精确模型路由
  • 请求体形态:messages、tools、temperature以及可选元数据
  • 错误归属:谁来负责检查 model_not_found、401、404、超时和额度耗尽响应

下面展示的是一套轻量级重放检查法,既能防止把密钥泄露到日志里,又能让请求漂移问题一目了然。

第一步:记录请求契约,而不是完整密钥

绝对不要把可用的API密钥直接贴进工单或共享聊天。只应记录密钥的存在状态和一个短指纹。

function keyFingerprint(value) {if (!value) return "missing";return `${value.slice(0, 4)}...${value.slice(-4)}`;const contract = {tool: process.env.TOOL_NAME || "node-service",baseUrl: process.env.VECTOR_ENGINE_BASE_URL,apiKeyFingerprint: keyFingerprint(process.env.VECTOR_ENGINE_API_KEY),model: process.env.VECTOR_ENGINE_MODEL,console.log(JSON.stringify(contract, null, 2));

对于Dify,从提供者设置中复制Base URL、API Key的存在情况和模型名。对于Cursor,同样复制其OpenAI兼容提供者设置。对于Node.js服务,启动时打印这些值,但绝不输出原始密钥。

第二步:从Node.js回放一次小规模的聊天补全请求

使用工具应当遵守的Base URL和模型名,这个脚本可以快速确认Vector Engine能否正常路由模型——在把责任推给Dify或Cursor之前。

const BASE_URL = process.env.VECTOR_ENGINE_BASE_URL;const API_KEY = process.env.VECTOR_ENGINE_API_KEY;const MODEL = process.env.VECTOR_ENGINE_MODEL;async function replay() {if (!BASE_URL || !API_KEY || !MODEL) {throw new Error("缺少Base URL、API Key或模型名");const response = await fetch(`${BASE_URL}/v1/chat/completions`, {method: "POST",headers: {"content-type": "application/json",authorization: `Bearer ${API_KEY}`,},body: JSON.stringify({model: MODEL,messages: [{ role: "system", content: "返回一条简短的健康应答。" },{ role: "user", content: "ping" },],}),const body = await response.json().catch(() => ({}));console.log({status: response.status,model: MODEL,errorCode: body?.error?.code,errorMessage: body?.error?.message,responseId: body?.id,if (body?.error?.code === "model_not_found") {process.exitCode = 2;replay().catch((error) => {console.error(error.message);process.exitCode = 1;

用同一个提供者配置运行这个脚本,你就能弄清真正发出的请求是哪里出了问题。这套检查把“该怪哪个工具”的猜谜,变成了“谁发的请求不匹配”的清晰对比——而这一切,都不需要把密钥暴露在排查日志里。