Skip to content

Default mode template replay still classified as overage for high-volume OC agent traffic #23

@belangertrading

Description

@belangertrading

Environment

  • Dario: 3.4.1 (also reproduced on 3.4.0)
  • Claude Code: 2.1.104
  • Platform: Linux x64 (Ubuntu VPS)
  • OpenClaw: 2026.4.9
  • Device identity: detected
  • OAuth: valid (token expires ~8h from testing)

Problem

Running OpenClaw agents through dario in default mode. Simple curl tests consistently get billing: five_hour. Actual OC agent requests always get billing: overage. We never got a single non-overage request from OC regardless of what we changed.


Complete Debugging Trail

Step 1: cache_control fingerprint hypothesis

Built a Bun strip proxy (:3455 → :3456) that recursively removed all cache_control fields from request body and stripped prompt-caching-* from anthropic-beta headers before forwarding to dario.

Result: still overage. Dario's template injection adds cache_control back in anyway. We were stripping what dario intentionally adds.


Step 2: SDK headers fingerprint hypothesis

Captured exact headers OC was sending to dario:

x-stainless-arch, x-stainless-helper-method, x-stainless-lang, x-stainless-os
x-stainless-package-version: 0.73.0, x-stainless-runtime-version: v22.22.2
anthropic-dangerous-direct-browser-access: true
user-agent: Anthropic/JS 0.73.0

Stripped all of these at the strip proxy before forwarding to dario.

Result: still overage.


Step 3: Verified final headers reaching Anthropic

After stripping at proxy level + dario template replay, headers forwarded to Anthropic were clean:

{
  "accept": "application/json",
  "anthropic-beta": "fine-grained-tool-streaming-2025-05-14",
  "anthropic-version": "2023-06-01",
  "content-type": "application/json",
  "user-agent": "Mozilla/5.0"
}

No SDK fingerprints, no cache headers. Result: still overage.


Step 4: curl vs OC agent isolation test

Same proxy setup, same endpoint. Curl always got five_hour. OC always got overage.

Observable differences:

Property curl test OC agent
Messages 1 155+
Body size ~500 bytes ~295KB
Tools 0–10 10
Streaming yes/no yes
Extended thinking yes/no yes
Conversation history none full multi-turn

Step 5: Tool count reduction

OC normally sends all available tools (50+). We added a hard limit to restrict OC to exactly 10 tools per request — matching what a typical Claude Code session sends.

Result: still overage. Tool count is not the trigger.


Step 6: context-1m pattern (misleading correlation)

Observed this in dario logs:

#10 POST /v1/messages
#10 context-1m rejected (400) — retrying without it
#11 billing: five_hour ✅
#11 POST /v1/messages
#11 context-1m rejected (400) — retrying without it
#12 billing: five_hour ✅
#12 POST /v1/messages
#12 no rejection
#13 billing: overage ❌

Looked like context-1m was the trigger. Patched dario to remove context-1m-2025-08-07 from the default beta string entirely.

Result: still overage. The five_hour results on retry were coincidental — possibly a brief window of Max plan capacity, not caused by removing context-1m.


Step 7: --passthrough mode

Tried thin proxy mode — OAuth swap only, no CC template injection.

Result: 100% overage, worse than default mode. Confirmed template injection helps but isn't sufficient for our traffic.


Step 8: --cli mode

This worked. No overage entries whatsoever. But --cli was removed in 3.4.1.


Step 9: OAuth profile bypass (unrelated bug, discovered during debugging)

OC agents had stored anthropic:claude-cli OAuth profiles. OC uses stored OAuth profiles over models.json baseUrl, meaning requests bypassed dario entirely and hit Anthropic directly. Cleared all OAuth profiles from all agents to ensure routing through dario.

This was a real bug but not related to the overage issue.


Step 10: Version updates

Updated dario 3.4.0 → 3.4.1 and Claude Code 2.1.101 → 2.1.104. No change in billing behavior.


Step 11: credentials clientId issue (discovered at end)

After extended testing, dario's token refresh started failing:

Refresh attempt 1/3 failed: HTTP 400 — Client with id [uuid] not found

Claude Code credentials at /root/.claude/.credentials.json contain no clientId field in the claudeAiOauth object. Dario's refresh needs the clientId. Access token still valid for several hours but will expire without refresh working.


Summary: Why It Doesn't Work

After exhaustive testing we believe the issue is server-side session-level classification at Anthropic, not client-side headers or request fields.

Evidence:

  1. Curl requests through the exact same proxy → five_hour
  2. OC agent requests through the same proxy → overage
  3. Every client-side variable we could control made no difference
  4. The only thing curl and OC differ on is conversation length, token throughput, and multi-turn session behavior

Our theory: Anthropic's billing classifier looks at aggregate session behavior (token volume per session, request frequency, conversation depth) rather than per-request headers. A single-turn curl request looks like a human. A 155-message multi-turn agent session with continuous streaming looks like an automated workload — which is exactly what Extra Usage billing is designed to capture.

The --cli mode worked because it doesn't use the API at all — it shells to the Claude Code CLI binary, which is a completely different code path that Anthropic's API billing classifier never sees.


Workaround

Migrating to openclaw-claude-bridge (shinglokto/openclaw-claude-bridge) which shells directly to claude --print with persistent sessions — same approach as the old --cli mode but built properly with tool support, session memory, and a dashboard.

Metadata

Metadata

Assignees

No one assigned

    Labels

    wontfixThis will not be worked on

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions