Anthropic SDK#
Base URL: http://127.0.0.1:8787/anthropic. Do not add /v1: the SDK adds /v1/messages itself.
You can also set it with ANTHROPIC_BASE_URL.
Connect#
import anthropic
client = anthropic.Anthropic(
base_url="http://127.0.0.1:8787/anthropic",
# api_key defaults to ANTHROPIC_API_KEY; on a team server, pass your lp_... key
default_headers={
"X-Lockpin-Task": "fix-login-bug",
"X-Lockpin-Budget-Usd": "0.50",
},
)
msg = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Fix the login bug"}],
)
To name the task per call instead of per client:
client.messages.create(..., extra_headers={"X-Lockpin-Task": "summarise-logs"})
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
baseURL: "http://127.0.0.1:8787/anthropic",
// apiKey defaults to ANTHROPIC_API_KEY; on a team server, pass your lp_... key
defaultHeaders: { "X-Lockpin-Task": "fix-login-bug", "X-Lockpin-Budget-Usd": "0.50" },
});
The SDK sends the key as x-api-key. A Lockpin team server reads an lp_... key from that header,
so nothing else changes on a team server.
The two headers:
Header |
What it does |
|---|---|
|
Names the task. Calls with the same name share one budget. |
|
The task’s budget in USD. It can only lower the budget below |
Lockpin removes every X-Lockpin-* header before the call goes to Anthropic. See
Budgets and tasks for the other headers.
Prompt cache#
Anthropic caches nothing unless a call asks for it. When a task’s previous call was less than 5
minutes ago, Lockpin adds the cache marker to calls that have none, and the reply carries
X-Lockpin-Cache-Marker: added. -auto-cache-marker=false turns this off.
When the cap hits#
The SDK raises an error with status 402 and does not retry it. In Python it is
anthropic.APIStatusError; in TypeScript it is Anthropic.APIError with status === 402. The
response body has error.type == "budget_exceeded" and a lockpin object with the numbers:
try:
msg = client.messages.create(...)
except anthropic.APIStatusError as e:
if e.status_code == 402: # budget reached: wrap up with what you have
print(e.response.json()["lockpin"]) # {'task': ..., 'spent_usd': ..., 'budget_usd': ...}
return partial_result
raise
The call never reached Anthropic, so it cost nothing.
Models#
A model with no price is refused with HTTP 400 unknown_model. lockpin providers -models lists
the priced ones. To add one, see Prices.
Verify#
After one call, the meter shows it under the task you named. Non-streaming replies carry
X-Lockpin-Cost-Usd, X-Lockpin-Spent-Usd and X-Lockpin-Remaining-Usd.