10 · hosted seat

Claude endpoints: a cached seat

Any role can be staffed by Claude through Anthropic's API. On api.anthropic.com darkmux speaks Anthropic's native Messages API, so prompt caching covers every turn of the agent loop: each turn reads the conversation before it from the cache instead of sending it again at full price. darkmux reports tokens; the rate is between you and Anthropic.

Set it up

Put the API key in the Keychain. Only the item's name goes in any file.

security add-generic-password -a "$USER" -s darkmux-anthropic -w

Declare the endpoint once under endpoints in ~/.darkmux/profiles.json, and a profile whose model names it:

{ "endpoints": {
    "claude": { "url": "https://api.anthropic.com/v1",
                "auth": { "type": "bearer", "keychain": "darkmux-anthropic" } } },
  "profiles": {
    "claude-seat": { "models": [ { "id": "claude-sonnet-5-5", "n_ctx": 200000, "endpoint": "claude" } ] } } }

Then point a role at the seat. Any role works; this one makes Claude the reviewer:

darkmux config set role_profiles.reviewer claude-seat

darkmux doctor -v lists the endpoint with the dialect it resolved. Captured on the operator's machine, trimmed to one endpoint:

✓ endpoints   `claude-sonnet`: unmanaged, api.anthropic.com, messages, credential from
              Keychain `darkmux-anthropic`; limits 100000000 tokens per 30d · waits at most
              30m; calls run one at a time (no limits.concurrent_calls); budget wait, early
              warning at 80%: spent 38492046 tokens in 1613 calls over the last 30d

messages is the part that matters. You do not declare it: an endpoint on api.anthropic.com with no dialect gets it. Declaring another dialect there sends the OpenAI-compatible layer, which neither caches nor reports caching, and doctor warns with the edit to undo it.

What is cached

Two things, both automatic. The system prompt and the tool definitions carry their own cache breakpoint, so every dispatch of a role shares them. The conversation is cached as it grows, so each turn of a dispatch reads everything before it from the cache and pays full input price only for what is new. An agent loop resends its whole conversation every turn, which is why the second part is most of the effect.

Anthropic keeps an entry for five minutes after its last use, so turns and dispatches that follow each other closely keep reading it. A long pause starts a fresh entry.

Budgets

A budget sits on the endpoint, beside url and auth. The numbers are yours; darkmux ships none.

"limits": { "window": { "period": "30d", "tokens": <tokens> },
            "policy": "wait", "max_wait": "30m", "warn_at": 0.8 }

Reading the numbers

Every model call writes a telemetry.tokens flow record. prompt_tokens is every input token the call sent, cached_tokens the part read from the cache, and cache_write_tokens the part written to it. One dispatch, turn by turn:

jq -r --arg s review-1791622322-7977d4.adhoc.reviewer.test-gap-u-0001 \
  'select(.action=="telemetry.tokens" and .session_id==$s)
   | [.payload.turn_seq, .payload.prompt_tokens, .payload.cached_tokens] | @tsv' \
  ~/.darkmux/flows/2026-10-10.jsonl
1	11475	7112
2	27260	11471
3	30783	27258
4	29455	11471

Verbatim, captured 2026-10-10: a Claude Sonnet 5.5 reviewer unit in a PR review.

Turn 1 read the shared system prompt and tools. Turns 2 and 3 read everything before them. Turn 4 read only the head, because something earlier in its conversation changed and the cache matches an exact prefix. A dispatch's --json envelope carries cached_tokens summed over its calls, and the fleet view's token readout shows cached tokens beside the rest. Multiply by your own rates to see what that is worth to you.