sipi.bot integration
sipi.bot + Anthropic Claude API
Integrate sipi.bot with the Anthropic Claude API. Every messages.create call passes through a policy check that enforces per-token cost ceilings, per-conversation velocity caps, and tool-use transaction limits before the request is sent.
Where the money actually goes
Nothing in a Claude integration looks like a purchase. There is no checkout, no
merchant, no invoice at the moment of spend — there is a messages.create
call that returns some tokens and quietly adds a line to your monthly bill. That is
what makes it easy to overspend: the expensive call and the cheap call are the same
function with different arguments.
Cost on the Claude API is a function of input tokens, output tokens, and the model you picked. The input side is the part people underestimate. In a tool-use loop the entire conversation so far is re-sent on every turn, so a ten-turn agent does not cost ten times a one-turn agent — it costs considerably more, because turn ten carries the transcript of turns one through nine. A loop that never converges is the classic runaway shape here.
The estimate problem, stated honestly
You cannot know what a Claude call costs until it returns and you read
usage. A firewall that runs before the call therefore cannot
evaluate the true cost — it evaluates your estimate of it. This is a real limitation
and worth being clear about rather than papering over.
The workable approach is to check the ceiling, not the expectation. You know
max_tokens before you call, and you know your input length. Price the
worst case and submit that as the amount. A policy that approves the worst case is
safe by construction; a policy tuned to the average will let the tail through.
Then reconcile. After the response
lands, submit the real figure from usage as a second, recorded
evaluation. The pre-call check is your brake; the post-call record is what makes the
daily ceiling and the audit trail accurate.
Wrapping messages.create
The hook point is the client call itself. Estimate, check the decision, and only then let the request through.
import requests, anthropic
client = anthropic.Anthropic()
def guarded_message(**kw):
worst_case = estimate_usd(kw["model"], kw["messages"], kw["max_tokens"])
d = requests.post(
"https://sipi.bot/v1/transactions/evaluate",
headers={"Authorization": f"Bearer {SIPI_KEY}"},
json={"amount": worst_case, "merchant": "anthropic", "category": "llm",
"description": f"{kw['model']} max_tokens={kw['max_tokens']}"},
timeout=5,
).json()
if d["decision"] != "APPROVED":
raise RuntimeError(f"{d['decision']}: {d['reason']}")
return client.messages.create(**kw)
The response carries decision (APPROVED,
BLOCKED or FLAGGED), a reason, the rules in
triggered, and a transaction_id for the audit trail. Handle
all three decisions — an agent that only understands APPROVED will treat
a block as a crash.
Rules that carry weight here
| Rule type | What it does on this integration |
|---|---|
daily_total | The one that matters most. Token spend is many small charges, and no single call looks alarming — only the sum does. |
velocity | Catches the non-converging tool-use loop, which fires many calls in quick succession rather than one large one. |
per_transaction | Guards against a single call with a huge context or an over-generous max_tokens. |
approval_threshold | Escalates to a human instead of hard-blocking — the right default for long-context batch work. |
merchant_allow has little to do on a single-provider integration.
It earns its place once the same agent can also reach OpenAI, a search API and a
cloud account, and you want to constrain which of them it may spend on.
What the check cannot see
- Anthropic's own meter. sipi.bot evaluates the number you submit; if your estimate is wrong, the policy is wrong in the same direction.
- Prompt-caching economics. A cache write costs more than a normal input token and a cache read costs far less, so a naive per-token estimate misprices both.
- Whether the output was any good. A blocked call and a wasted call cost the same to prevent, but only one of them is a spend problem.
Questions people actually ask
Does this add latency to every Claude call?
It adds one HTTP round trip before the request. That is real, but it is small next to the multi-second generation it precedes. If you cannot accept it on a hot path, check at the start of a task rather than on every individual message.
What happens if sipi.bot is unreachable?
That is your decision to make explicitly, and you should make it before you ship. Failing open keeps the agent running and drops the guarantee; failing closed keeps the guarantee and stops the agent. Pick per environment — most people fail closed in production and open in development.
Can I attribute spend to individual agents?
Yes — register each one and send its own key, so the daily ceiling and the audit trail are per agent rather than per account.