caveman-setup
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseYou are wiring this repository through the Caveman gateway. Caveman is a
byte-preserving LLM proxy: in record mode it measures what your app sends and
what it costs, and changes nothing else. Your job is a minimal, verified
integration — not a refactor.
The prompt that sent you here provides four values. Refer to them as:
- — the gateway base URL (e.g.
GATEWAYorhttps://gateway.caveman.so)http://127.0.0.1:8787 - — the gateway auth secret (treat like any API key: env var only, never committed, never printed in full)
CAVE_API_KEY - —
PROVIDER_KEYS(provider keys live encrypted in Caveman Cloud) orstored(this app sends its own provider key per request)byok - — the dashboard base URL (e.g.
DASHBOARD)https://app.caveman.so
If any value is missing, stop and ask for it. Do not guess a URL or mint a key.
你正在将此仓库通过Caveman网关进行连接。Caveman是一款保留字节完整性的LLM代理:在记录模式下,它会统计应用发送的内容及其成本,但不会更改任何其他内容。你的任务是完成最小化的可验证集成——而非重构。
触发此任务的提示词提供了四个值,命名如下:
- — 网关基础URL(例如
GATEWAY或https://gateway.caveman.so)http://127.0.0.1:8787 - — 网关认证密钥(需像对待其他API密钥一样处理:仅存于环境变量,绝不提交到代码仓库,绝不完整打印)
CAVE_API_KEY - —
PROVIDER_KEYS(提供商密钥加密存储在Caveman Cloud中)或stored(应用每个请求自行发送其提供商密钥)byok - — 控制台基础URL(例如
DASHBOARD)https://app.caveman.so
若任何值缺失,请停止操作并询问用户补充。请勿猜测URL或生成密钥。
Rules (non-negotiable)
规则(不可协商)
- Coherent integration. Wire every live LLM callsite through existing configuration and responsible seams. Touch each layer correctness requires. No drive-by refactors or formatting sweeps; add an abstraction only when it clarifies ownership or lowers lifecycle cost.
- Secrets stay in env vars. goes into the env file the repo already uses (
CAVE_API_KEY,.env, …). If that file isn't gitignored, add it to.env.localand say so. Never hardcode the key in source..gitignore - Report only what you observed. The final report states the HTTP status and usage numbers from the real verification response — never assumed success. If verification fails, report the failure template instead.
- Record mode only. You are adding measurement. You do not enable any optimization, and you do not claim any savings — verified savings are $0 until an optimizer is explicitly turned on and passes its eval gate.
- Provider keys are not your business. With you never see one. With
PROVIDER_KEYS: stored, the app's existing provider key stays exactly where it already is.byok
- 连贯集成:将每个活跃的LLM调用点通过现有配置和可靠的连接层进行连接。仅修改确保正确性所需的层级。请勿随意重构或格式化代码;仅当抽象能明确归属或降低生命周期成本时才添加抽象。
- 密钥仅存于环境变量:需存入仓库已使用的环境文件(
CAVE_API_KEY、.env等)。若该文件未被加入.env.local,请将其添加至.gitignore并告知用户。绝不要在源代码中硬编码密钥。.gitignore - 仅报告实际观测结果:最终报告需包含真实验证响应的HTTP状态和使用数据——绝不要假设操作成功。若验证失败,请使用对应的失败模板进行报告。
- 仅启用记录模式:你仅需添加统计功能。请勿启用任何优化功能,也不要宣称任何成本节省——在优化器被明确启用并通过评估之前,已验证的节省金额为0美元。
- 提供商密钥无需你处理:若为模式,你不会接触到任何提供商密钥;若为
PROVIDER_KEYS: stored模式,应用现有的提供商密钥需保留在原位置。byok
Step 1 — Find every live LLM callsite
步骤1 — 找到所有活跃的LLM调用点
Read dependency files (, , ,
, lockfiles) and search the source for LLM clients:
package.jsonrequirements.txtpyproject.tomlgo.mod- SDK imports: ,
openai,@anthropic-ai/sdk,anthropic+ai(Vercel),@ai-sdk/*,langchain*,litellm/google-genai,@google/genai,crewai,pydantic_ai/openai-agentsagents - Raw HTTP to ,
api.openai.com,api.anthropic.comgenerativelanguage.googleapis.com - Existing base-URL env vars: ,
OPENAI_BASE_URL,OPENAI_API_BASE,ANTHROPIC_BASE_URL,GEMINI_BASE_URLGOOGLE_GEMINI_BASE_URL
List what you found (file:line per callsite) before changing anything. If you
find no LLM callsites, stop and report the "nothing to wire" template at
the end of this file — do not invent an integration.
读取依赖文件(、、、、锁定文件)并在源码中搜索LLM客户端:
package.jsonrequirements.txtpyproject.tomlgo.mod- SDK导入:、
openai、@anthropic-ai/sdk、anthropic+ai(Vercel)、@ai-sdk/*、langchain*、litellm/google-genai、@google/genai、crewai、pydantic_ai/openai-agentsagents - 直接调用HTTP接口:、
api.openai.com、api.anthropic.comgenerativelanguage.googleapis.com - 已存在的基础URL环境变量:、
OPENAI_BASE_URL、OPENAI_API_BASE、ANTHROPIC_BASE_URL、GEMINI_BASE_URLGOOGLE_GEMINI_BASE_URL
在进行任何修改前,列出所有找到的内容(每个调用点的文件:行号)。若未找到任何LLM调用点,请停止操作并使用本文末尾的“无调用点可连接”模板进行报告——请勿凭空创建集成。
Step 2 — Pick the app slug
步骤2 — 选择应用标识(slug)
One slug names this app in the gateway path: . Derive it from
the package/module name (e.g. , ). Grammar:
lowercase first, then , max 64 chars. Spend for this
whole app groups under that slug on the dashboard.
GATEWAY/w/<app>support-botacme-api[a-z0-9][a-z0-9._-]使用一个标识在网关路径中命名此应用:。从包/模块名称衍生(例如 、)。命名规则:首字符为小写,其余字符可为,最长64字符。此应用的所有支出将在控制台中归为此标识下。
GATEWAY/w/<app>support-botacme-api[a-z0-9][a-z0-9._-]Step 3 — Wire each callsite
步骤3 — 连接每个调用点
The pattern is always the same: base URL → the gateway with ,
plus one auth header. Gateway auth is
( also works where a header is awkward).
With , also send .
/w/<app>x-cave-api-key: CAVE_API_KEYAuthorization: Bearer CAVE_API_KEYPROVIDER_KEYS: byokx-cave-upstream-key: <the provider key the app already uses>Two facts that make the wiring safe (both are gateway-enforced, not hopes):
the gateway rebuilds upstream auth headers from scratch, so a client's
/ value is never forwarded to the provider; and with
, upstream auth comes from the encrypted connection server-side. So in
mode, where an SDK insists on an api-key parameter, set it to the
Cave key — it authenticates the gateway and goes no further.
Authorizationx-api-keystoredstoredExact shapes (use the one matching each callsite — these are the product's
published recipes, not suggestions):
OpenAI SDK (TS) — Chat Completions and Responses both route through:
ts
const client = new OpenAI({
baseURL: `${process.env.CAVE_GATEWAY_URL}/w/<app>/openai/v1`,
apiKey: process.env.OPENAI_API_KEY, // byok: unchanged · stored: use CAVE_API_KEY
defaultHeaders: {
"x-cave-api-key": process.env.CAVE_API_KEY!,
// byok only:
"x-cave-upstream-key": process.env.OPENAI_API_KEY!,
},
});OpenAI SDK (Python) — same shape: ,
.
base_url=f"{gw}/w/<app>/openai/v1"default_headers={"x-cave-api-key": ..., "x-cave-upstream-key": ...}Anthropic SDK (TS/Python) — the SDK appends itself. The
header is required here in both modes (this SDK's own key
param rides , which is not a gateway-auth header):
/v1/messagesx-cave-api-keyx-api-keypython
client = anthropic.Anthropic(
base_url=f"{os.environ['CAVE_GATEWAY_URL']}/w/<app>",
api_key=os.environ["ANTHROPIC_API_KEY"], # byok: unchanged · stored: use CAVE_API_KEY
default_headers={
"x-cave-api-key": os.environ["CAVE_API_KEY"],
# byok only:
"x-cave-upstream-key": os.environ["ANTHROPIC_API_KEY"],
},
)Vercel AI SDK — ${gw}/w/<app>/openai/v1; Anthropic models via
${gw}/w/<app>/v1.
createOpenAICompatible({ baseURL: , headers: { "x-cave-api-key": ... } })createAnthropic({ baseURL: , headers: { ... } })LangChain / LangGraph — ; . LangGraph inherits whatever model you pass it.
ChatOpenAI(base_url=f"{gw}/w/<app>/openai/v1", default_headers={...})ChatAnthropic(base_url=f"{gw}/w/<app>", default_headers={...})LiteLLM — per call +
, or fleet-wide in the LiteLLM proxy .
api_base=f"{gw}/w/<app>/openai/v1"extra_headers={...}config.yamlRaw HTTP / anything else — swap the host, keep the provider's native path:
(OpenAI protocol) or
(Anthropic protocol), add the header(s).
GATEWAY/w/<app>/v1/chat/completionsGATEWAY/w/<app>/v1/messagesConcretely, with slug and the hosted gateway, an OpenAI-SDK base
URL reads . And in
mode, drop every line entirely — it is byok-only.
support-bothttps://gateway.caveman.so/w/support-bot/openai/v1storedx-cave-upstream-keyFor frameworks not listed (google-genai, crewai, pydantic-ai, openai-agents),
fetch the matching page under — same origin
this skill came from — and follow it.
<docs origin>/docs/integrations/Add to the repo's env file (and reference from code — no literals):
CAVE_GATEWAY_URL=<GATEWAY>
CAVE_API_KEY=<CAVE_API_KEY>连接模式始终相同:基础URL → 带有的网关,加上一个认证头。网关认证头为(若头信息设置不便,同样有效)。若为模式,还需发送。
/w/<app>x-cave-api-key: CAVE_API_KEYAuthorization: Bearer CAVE_API_KEYPROVIDER_KEYS: byokx-cave-upstream-key: <应用已使用的提供商密钥>以下两个特性确保连接的安全性(均由网关强制保障,而非依赖假设):网关会重新构建上游认证头,因此客户端的/值绝不会转发给提供商;若为模式,上游认证信息来自服务器端的加密连接。因此在模式下,若SDK强制要求api-key参数,可将其设置为Cave密钥——该密钥仅用于网关认证,不会被进一步传递。
Authorizationx-api-keystoredstored具体实现方式(选择与每个调用点匹配的方式——这些是官方发布的配置方案,而非建议):
OpenAI SDK(TS) — 聊天补全和响应均通过以下方式路由:
ts
const client = new OpenAI({
baseURL: `${process.env.CAVE_GATEWAY_URL}/w/<app>/openai/v1`,
apiKey: process.env.OPENAI_API_KEY, // byok模式:保持不变 · stored模式:使用CAVE_API_KEY
defaultHeaders: {
"x-cave-api-key": process.env.CAVE_API_KEY!,
// 仅byok模式需要:
"x-cave-upstream-key": process.env.OPENAI_API_KEY!,
},
});OpenAI SDK(Python) — 格式相同:,。
base_url=f"{gw}/w/<app>/openai/v1"default_headers={"x-cave-api-key": ..., "x-cave-upstream-key": ...}Anthropic SDK(TS/Python) — SDK会自行追加。此处两种模式均需头(此SDK自身的key参数通过传递,并非网关认证头):
/v1/messagesx-cave-api-keyx-api-keypython
client = anthropic.Anthropic(
base_url=f"{os.environ['CAVE_GATEWAY_URL']}/w/<app>",
api_key=os.environ["ANTHROPIC_API_KEY"], // byok模式:保持不变 · stored模式:使用CAVE_API_KEY
default_headers={
"x-cave-api-key": os.environ["CAVE_API_KEY"],
// 仅byok模式需要:
"x-cave-upstream-key": os.environ["ANTHROPIC_API_KEY"],
},
)Vercel AI SDK — ${gw}/w/<app>/openai/v1;Anthropic模型通过${gw}/w/<app>/v1配置。
createOpenAICompatible({ baseURL: , headers: { "x-cave-api-key": ... } })createAnthropic({ baseURL: , headers: { ... } })LangChain / LangGraph — ;。LangGraph会继承你传入的任何模型配置。
ChatOpenAI(base_url=f"{gw}/w/<app>/openai/v1", default_headers={...})ChatAnthropic(base_url=f"{gw}/w/<app>", default_headers={...})LiteLLM — 每次调用时设置 + ,或在LiteLLM代理的中全局配置。
api_base=f"{gw}/w/<app>/openai/v1"extra_headers={...}config.yaml原生HTTP / 其他情况 — 替换主机地址,保留提供商的原生路径:(OpenAI协议)或(Anthropic协议),添加对应的头信息。
GATEWAY/w/<app>/v1/chat/completionsGATEWAY/w/<app>/v1/messages举个具体例子,若标识为且使用托管网关,OpenAI SDK的基础URL应为。在模式下,请完全删除所有行——该配置仅适用于byok模式。
support-bothttps://gateway.caveman.so/w/support-bot/openai/v1storedx-cave-upstream-key对于未列出的框架(google-genai、crewai、pydantic-ai、openai-agents),请从此技能来源的同一域名下的页面获取对应配置方案并遵循执行。
<docs origin>/docs/integrations/将以下内容添加至仓库的环境文件(并在代码中引用——请勿使用字面量):
CAVE_GATEWAY_URL=<GATEWAY>
CAVE_API_KEY=<CAVE_API_KEY>Step 4 — Verify with one real request
步骤4 — 通过真实请求验证
The user pasted the setup prompt to authorize exactly this: one small
verification request. Send it now — do not pause to ask permission for it.
An integration that ends unverified because you hesitated is a worse outcome
than one tiny request; finishing the verification and the report autonomously
is the point of this skill.
Send one minimal request through the wiring you just built — the app's own
cheapest path if it has a script for it, otherwise curl on the path matching
the protocol you just wired with the app's own model and a small cap
( ≤ 32):
max_tokensbash
undefined用户粘贴设置提示词即明确授权执行此操作:发送一个小型验证请求。立即发送——无需暂停询问许可。因犹豫导致未完成验证的集成,比发送一个微小请求的结果更差;自主完成验证和报告是此技能的核心目标。
通过你刚搭建的连接发送一个最小化请求——若应用有对应的脚本则使用应用自身的最低成本路径,否则使用curl命令匹配你刚配置的协议路径,使用应用自身的模型并设置较小的上限( ≤ 32):
max_tokensbash
undefinedOpenAI-protocol wiring:
OpenAI协议连接:
curl -sS "$CAVE_GATEWAY_URL/w/<app>/v1/chat/completions"
-H "x-cave-api-key: $CAVE_API_KEY"
-H "content-type: application/json"
-d '{"model":"<model the repo already uses>","max_tokens":16,"messages":[{"role":"user","content":"ping"}]}'
-H "x-cave-api-key: $CAVE_API_KEY"
-H "content-type: application/json"
-d '{"model":"<model the repo already uses>","max_tokens":16,"messages":[{"role":"user","content":"ping"}]}'
curl -sS "$CAVE_GATEWAY_URL/w/<app>/v1/chat/completions"
-H "x-cave-api-key: $CAVE_API_KEY"
-H "content-type: application/json"
-d '{"model":"<仓库已使用的模型>","max_tokens":16,"messages":[{"role":"user","content":"ping"}]}'
-H "x-cave-api-key: $CAVE_API_KEY"
-H "content-type: application/json"
-d '{"model":"<仓库已使用的模型>","max_tokens":16,"messages":[{"role":"user","content":"ping"}]}'
Anthropic-protocol wiring:
Anthropic协议连接:
curl -sS "$CAVE_GATEWAY_URL/w/<app>/v1/messages"
-H "x-cave-api-key: $CAVE_API_KEY"
-H "anthropic-version: 2023-06-01"
-H "content-type: application/json"
-d '{"model":"<model the repo already uses>","max_tokens":16,"messages":[{"role":"user","content":"ping"}]}'
-H "x-cave-api-key: $CAVE_API_KEY"
-H "anthropic-version: 2023-06-01"
-H "content-type: application/json"
-d '{"model":"<model the repo already uses>","max_tokens":16,"messages":[{"role":"user","content":"ping"}]}'
(byok: add `-H "x-cave-upstream-key: $PROVIDER_KEY"`.) This is one real,
billable provider request — that is the point: real traffic, real measurement.
Read the response. Success = HTTP 200 with a `usage` block. Anything else =
the matching failure template below.curl -sS "$CAVE_GATEWAY_URL/w/<app>/v1/messages"
-H "x-cave-api-key: $CAVE_API_KEY"
-H "anthropic-version: 2023-06-01"
-H "content-type: application/json"
-d '{"model":"<仓库已使用的模型>","max_tokens":16,"messages":[{"role":"user","content":"ping"}]}'
-H "x-cave-api-key: $CAVE_API_KEY"
-H "anthropic-version: 2023-06-01"
-H "content-type: application/json"
-d '{"model":"<仓库已使用的模型>","max_tokens":16,"messages":[{"role":"user","content":"ping"}]}'
(byok模式:添加 `-H "x-cave-upstream-key: $PROVIDER_KEY"`。)这是一个真实的、需付费的提供商请求——核心目的是:真实流量,真实统计。
读取响应结果。成功=HTTP 200且包含`usage`块。其他情况=使用下方对应的失败模板。Step 5 — Report
步骤5 — 生成报告
End with exactly this shape, values filled from what you actually did and saw:
undefined最终输出需严格遵循以下格式,填充你实际执行和观测到的值:
undefinedCaveman is live in this repo
Caveman已在本仓库中启用
Wired: <n> callsite(s) in <n> file(s)
- <file> — <one-line what changed> App slug: <app> — spend for this app groups under it Verified: HTTP 200 · model <model> · <in> in / <out> out tokens (one real request) Mode: record — measured only. No model-visible bytes changed, no optimization enabled. Verified savings are $0 until you turn an optimizer on and it passes its eval gate. That honesty is the product.
See the dollars: <DASHBOARD>/traces — your request is the top row, priced from
the public catalog. <DASHBOARD>/getting-started flips to "First request received."
Want spend split by workflow (e.g. support-reply vs nightly-digest), not just
by app? Say "discover workflows" — I'll fetch <docs origin>/docs/discover-workflows.md
and label every callsite by the job it does.
undefined已连接:<n>个调用点,分布在<n>个文件中
- <文件> — <一行描述修改内容> 应用标识:<app> — 此应用的所有支出将归为此标识下 已验证:HTTP 200 · 模型<model> · <输入Token数>输入 / <输出Token数>输出(一次真实请求) 模式:记录——仅统计。未修改任何模型可见的字节,未启用任何优化。在你启用优化器并通过评估之前,已验证的节省金额为0美元。诚信是本产品的核心。
查看支出详情:<DASHBOARD>/traces — 你的请求位于顶部,费用基于公开价目表计算。<DASHBOARD>/getting-started会显示“已收到第一个请求”。
希望按工作流(例如支持回复 vs 夜间摘要)拆分支出,而非仅按应用拆分?请说“discover workflows”——我会获取<docs origin>/docs/discover-workflows.md并为每个调用点标记其对应的任务。
undefinedFailure templates (use verbatim, filled in — never soften)
失败模板(严格使用原文,填充对应内容——绝不弱化表述)
- Nothing to wire: "I found no LLM callsites in this repo (searched SDKs,
raw provider HTTP, base-URL env vars). If this repo runs a coding agent
rather than shipping LLM code, use instead — see <DASHBOARD>/getting-started."
caveman wrap <agent> - Gateway unreachable: "The verification request could not reach GATEWAY (<error>). Wiring is in place but unverified — nothing will be measured until the gateway is reachable. Check the URL and network, then re-run the verification curl above."
- 401 cave_invalid_api_key: "The gateway rejected CAVE_API_KEY. Mint a new key at <DASHBOARD>/getting-started and update the env file; the wiring itself is unchanged."
- 404 cave_route_not_found: "The gateway matched no route — usually a malformed /w/<app> slug (lowercase [a-z0-9] first, then [a-z0-9._-], max 64) or a path that doesn't match the SDK's protocol. Fix the URL and re-verify."
- Provider error (4xx/5xx via gateway): report status + body verbatim; the gateway is reachable and auth passed, the upstream call failed — usually a provider key or model-name issue in the app itself.
Never report success on any of these. An unverified integration is reported as
unverified.
- 无调用点可连接:“我在此仓库中未找到任何LLM调用点(已搜索SDK、原生提供商HTTP接口、基础URL环境变量)。若此仓库运行的是编码Agent而非LLM代码,请使用替代——详见<DASHBOARD>/getting-started。”
caveman wrap <agent> - 网关无法访问:“验证请求无法连接到GATEWAY(<错误信息>)。连接已配置但未验证——网关恢复可访问前无法进行统计。请检查URL和网络,然后重新运行上述验证curl命令。”
- 401 cave_invalid_api_key:“网关拒绝了CAVE_API_KEY。请在<DASHBOARD>/getting-started生成新密钥并更新环境文件;连接配置本身无需修改。”
- 404 cave_route_not_found:“网关未匹配到路由——通常是标识格式错误(首字符为小写[a-z0-9],其余字符可为[a-z0-9._-],最长64字符)或路径与SDK协议不匹配。请修正URL后重新验证。”
/w/<app> - 提供商错误(网关返回4xx/5xx):如实报告状态码和响应体;网关已可访问且认证通过,但上游调用失败——通常是应用自身的提供商密钥或模型名称问题。
请勿在上述任何情况下报告成功。未验证的集成需如实报告为未验证。