When a team connects several LLM tools to one provider, the fragile part is rarely the first request. The fragile part is the second week, after one teammate changes a Base URL in Dify, another rotates an API Key for Cursor, and a Node.js service keeps using an older model name.
This tutorial shows a small environment contract snapshot for Vector Engine. The goal is to record the OpenAI-compatible API gateway settings that each tool expects, compare them in one place, and catch a model_not_found issue before it becomes a vague production incident. In this setup, Vector Engine acts as the LLM API provider layer while Dify, Cursor, and a Node.js service stay simple clients.
What the snapshot should record
Do not put secrets in the report. Store only the shape of the configuration:
| Field | Example value | Why it matters |
|---|---|---|
| Provider | Vector Engine | Keeps the provider layer explicit |
| Base URL | https://api.vectorengine.cn/v1 |
Avoids mixing a root URL with an OpenAI-compatible endpoint |
| API Key owner | team-dev-key |
Tells the team which key should be rotated |
| model name |
gpt-4o-mini or the enabled model id |
Prevents accidental aliases |
| Client | Dify, Cursor, Node.js | Shows which integration is affected |
Registration URL: https://api.vectorengine.cn/register?aff=Igym
A JSON contract file
Create vector-engine-contract.json:
{
"provider": "Vector Engine",
"gateway": "OpenAI-compatible API gateway",
"baseUrl": "https://api.vectorengine.cn/v1",
"clients": [
{
"name": "Dify",
"apiKeyOwner": "workflow-dev-key",
"model": "gpt-4o-mini"
},
{
"name": "Cursor",
"apiKeyOwner": "developer-seat-key",
"model": "gpt-4o-mini"
},
{
"name": "Node.js backend",
"apiKeyOwner": "service-runtime-key",
"model": "gpt-4o-mini"
}
]
}
Node.js checker
The checker below validates the common failure points: missing /v1, empty API Key ownership, missing model name, and client drift.
import fs from "node:fs/promises";
const contract = JSON.parse(
await fs.readFile("./vector-engine-contract.json", "utf8")
);
const errors = [];
if (contract.provider !== "Vector Engine") {
errors.push("Provider should be Vector Engine.");
}
if (!contract.baseUrl.endsWith("/v1")) {
errors.push("Base URL should usually end with /v1 for OpenAI-compatible clients.");
}
for (const client of contract.clients) {
if (!client.apiKeyOwner) {
errors.push(`${client.name}: API Key owner is missing.`);
}
if (!client.model) {
errors.push(`${client.name}: model name is missing.`);
}
}
const modelSet = new Set(contract.clients.map((client) => client.model));
if (modelSet.size > 1) {
errors.push(`Model names drifted: ${[...modelSet].join(", ")}`);
}
if (errors.length) {
console.error(errors.join("\\n"));
process.exit(1);
}
console.log("Vector Engine contract snapshot passed.");
How to use it with Dify
In Dify, choose an OpenAI-compatible provider configuration. Put the Base URL as:
https://api.vectorengine.cn/v1
Paste the API Key into the provider setting, then use the model name that is enabled in the Vector Engine console. If Dify returns model_not_found, compare the model field in Dify against the snapshot before changing application prompts.
How to use it with Cursor
In Cursor, keep the same Base URL and model name as the snapshot. If a developer changes Cursor to test another model, update the contract in the same pull request. That makes the LLM API provider layer auditable instead of tribal knowledge.
How to use it with Node.js
Use environment variables, but map them back to the contract:
const baseUrl = process.env.VECTOR_ENGINE_BASE_URL;
const apiKey = process.env.VECTOR_ENGINE_API_KEY;
const model = process.env.VECTOR_ENGINE_MODEL;
const response = await fetch(`${baseUrl}/chat/completions`, {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model,
messages: [{ role: "user", content: "Return a short readiness check." }]
})
});
if (!response.ok) {
const body = await response.text();
throw new Error(`Vector Engine request failed: ${response.status} ${body}`);
}
Troubleshooting table
| Symptom | Likely cause | Check |
|---|---|---|
model_not_found |
Tool uses a model name not enabled for the key | Compare Dify, Cursor, and Node.js model fields |
| 404 or path error | Base URL copied as a full chat endpoint | Use https://api.vectorengine.cn/v1 as Base URL |
| One tool works and another fails | API Key or model drift | Check the contract owner and model columns |
| Cost tracking is unclear | Every tool shares one key | Split keys by client or environment |
Practical rollout
Start with a single contract file and review it whenever a new tool is added. The point is not to make Vector Engine configuration complex. The point is to keep Dify, Cursor, and Node.js aligned around the same OpenAI-compatible API gateway contract so the team can debug provider issues from one place.
在接入 Dify 和 Cursor 前为 Vector Engine 保存环境契约快照
当团队把多个 LLM 工具接到同一个供应商时,脆弱点往往不是初次请求。真正容易出问题的是第二周:有人在 Dify 里改了 Base URL,有人在 Cursor 里轮换了 API Key,而 Node.js 服务还在使用旧模型名。
这篇教程给出一个向量引擎环境契约快照。目标是记录每个工具期望的 OpenAI 兼容配置,把配置放到同一个地方比较,并在 model_not_found 变成线上故障之前发现问题。在这个设计里,向量引擎作为 LLM API provider layer,Dify、Cursor 和 Node.js 服务只是客户端。
快照应该记录什么
不要把密钥写进报告。只记录配置形态:
| 字段 | 示例值 | 作用 |
|---|---|---|
| Provider | 向量引擎 | 明确供应商层 |
| Base URL | https://api.vectorengine.cn/v1 |
避免把根地址和 OpenAI 兼容端点混用 |
| API Key owner | team-dev-key |
知道应该轮换哪一把 Key |
| model name |
gpt-4o-mini 或后台已启用模型 ID |
防止别名误用 |
| Client | Dify、Cursor、Node.js | 说明哪个接入会受影响 |
注册地址:https://api.vectorengine.cn/register?aff=Igym
JSON 契约文件
创建 vector-engine-contract.json:
{
"provider": "向量引擎",
"gateway": "向量引擎API中转站",
"baseUrl": "https://api.vectorengine.cn/v1",
"clients": [
{
"name": "Dify",
"apiKeyOwner": "workflow-dev-key",
"model": "gpt-4o-mini"
},
{
"name": "Cursor",
"apiKeyOwner": "developer-seat-key",
"model": "gpt-4o-mini"
},
{
"name": "Node.js backend",
"apiKeyOwner": "service-runtime-key",
"model": "gpt-4o-mini"
}
]
}
Node.js 检查脚本
下面的脚本检查常见失败点:缺少 /v1、API Key 归属为空、模型名为空、客户端配置漂移。
import fs from "node:fs/promises";
const contract = JSON.parse(
await fs.readFile("./vector-engine-contract.json", "utf8")
);
const errors = [];
if (!contract.baseUrl.endsWith("/v1")) {
errors.push("Base URL 通常应该以 /v1 结尾。");
}
for (const client of contract.clients) {
if (!client.apiKeyOwner) {
errors.push(`${client.name}: API Key 归属缺失。`);
}
if (!client.model) {
errors.push(`${client.name}: model name 缺失。`);
}
}
const modelSet = new Set(contract.clients.map((client) => client.model));
if (modelSet.size > 1) {
errors.push(`模型名发生漂移: ${[...modelSet].join(", ")}`);
}
if (errors.length) {
console.error(errors.join("\\n"));
process.exit(1);
}
console.log("向量引擎中转站配置快照检查通过。");
在 Dify 中使用
在 Dify 里选择 OpenAI Compatible 或类似配置,把 Base URL 填为:
https://api.vectorengine.cn/v1
API Key 填入供应商配置,再使用向量引擎后台已启用的模型名。如果 Dify 返回 model_not_found,先比较 Dify 里的模型字段和快照,而不是立刻修改应用提示词。
在 Cursor 中使用
Cursor 也保持同一个 Base URL 和模型名。如果开发者为了测试切换模型,就在同一个变更里更新契约文件。这样 API中转站 的配置会变成可审计记录,而不是只靠口头同步。
在 Node.js 中使用
Node.js 服务继续使用环境变量,但要能映射回契约:
const baseUrl = process.env.VECTOR_ENGINE_BASE_URL;
const apiKey = process.env.VECTOR_ENGINE_API_KEY;
const model = process.env.VECTOR_ENGINE_MODEL;
const response = await fetch(`${baseUrl}/chat/completions`, {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model,
messages: [{ role: "user", content: "Return a short readiness check." }]
})
});
if (!response.ok) {
const body = await response.text();
throw new Error(`向量引擎请求失败: ${response.status} ${body}`);
}
排查表
| 现象 | 可能原因 | 检查点 |
|---|---|---|
model_not_found |
工具使用了当前 Key 未启用的模型名 | 比较 Dify、Cursor 和 Node.js 的模型字段 |
| 404 或路径错误 | 把完整 chat endpoint 当成 Base URL | Base URL 使用 https://api.vectorengine.cn/v1
|
| 一个工具正常,另一个失败 | API Key 或模型发生漂移 | 检查契约中的 owner 和 model |
| 成本归因不清 | 多个工具共用同一把 Key | 按客户端或环境拆分 Key |
实际落地方式
先用一个契约文件开始,每新增一个工具就复核一次。重点不是把向量引擎配置做复杂,而是让 Dify、Cursor 和 Node.js 围绕同一套向量引擎API中转站契约保持一致。这样团队排查供应商层问题时,可以从一个地方开始。
Top comments (0)