Repository navigation
Add a per-call spend threshold (claude --max-budget-usd) and report call cost - #241
Merged
Merged
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bf29bbb782
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
tzhouam
added a commit
that referenced
this pull request
Sep 30, 2026
Two defects found by the commit gate while integrating #241: - claude_code formatted the threshold with `.4f`, moving the boundary: 0.00001 became "0.0000" (no threshold) and 0.12345 became "0.1235" (a higher one). budget_arg() now emits the float's shortest round-trip decimal in plain notation, rejects non-positive/non-finite values, and is tested on tiny thresholds. - runtime.trace_recorder dropped max_budget_usd (and cost_usd), so production traces never persisted them. They now land in the model_call record's result (null when unset/unknown), including transport-failure records; tested through the real recorder and TraceStore. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tzhouam
added a commit
that referenced
this pull request
Sep 30, 2026
Two defects found by the commit gate while integrating #241: - claude_code formatted the threshold with `.4f`, moving the boundary: 0.00001 became "0.0000" (no threshold) and 0.12345 became "0.1235" (a higher one). budget_arg() now emits the float's shortest round-trip decimal in plain notation, rejects non-positive/non-finite values, and is tested on tiny thresholds. - runtime.trace_recorder dropped max_budget_usd (and cost_usd), so production traces never persisted them. They now land in the model_call record's result (null when unset/unknown), including transport-failure records; tested through the real recorder and TraceStore. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tzhouam
force-pushed
the
kb/init-spend-cap
branch
from
September 30, 2026 10:57
7b55056 to
aa65de7
Compare
…all cost kb init's budget_usd must be a hard ceiling (design v3, sol-approved), but max_tokens is no spend bound for CLI transports (they ignore it), and the claude CLI checks --max-budget-usd only after each API request completes: it stops the NEXT request, it cannot cut the current one short. So this is a stop threshold, not a cap, and is named that way; the hard ceiling is the caller's reservation of threshold + one request's worst case (kb init budget, later PR). - providers: complete() takes max_budget_usd; HarnessTransport.stops_at_spend (default False) says whether the CLI starts no further request once the call's spend reaches it. Only claude-code does (--max-budget-usd); a call the CLI ends on its budget comes back with stop_reason "max_budget" and no text. The CLI's total_cost_usd is reported as usage["cost_usd"]. No transport may advertise a hard per-call cap (regression test). - kb_service.models: call_json(max_budget_usd=...) refuses before dispatch when the transport cannot stop at a threshold, treats a call stopped at it as ModelUnavailable, and surfaces ModelReply.cost_usd (also in the trace record). Callers without a threshold are unchanged: the kwarg is never sent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two defects found by the commit gate while integrating #241: - claude_code formatted the threshold with `.4f`, moving the boundary: 0.00001 became "0.0000" (no threshold) and 0.12345 became "0.1235" (a higher one). budget_arg() now emits the float's shortest round-trip decimal in plain notation, rejects non-positive/non-finite values, and is tested on tiny thresholds. - runtime.trace_recorder dropped max_budget_usd (and cost_usd), so production traces never persisted them. They now land in the model_call record's result (null when unset/unknown), including transport-failure records; tested through the real recorder and TraceStore. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The zcode provider (#238) landed after the spend-threshold change and kept the old complete() signature. ModelGateway already refuses a threshold for transports that cannot stop at one before dispatch, so nothing broke, but every transport now takes max_budget_usd; zcode accepts and ignores it (stops_at_spend stays False). A test now checks every transport class, so the next provider cannot miss it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tzhouam
force-pushed
the
kb/init-spend-cap
branch
from
September 30, 2026 14:31
aa65de7 to
e0903e7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part 3b/9 of kb init (design v3, sol-approved): the building block for making
budget_usda hard ceiling.Why
kb init reserves spend before each model call.
max_tokenscan't bound spend for CLI transports (they ignore it). The claude CLI's--max-budget-usdis checked after each API request completes (see Anthropic'sclaude-agent-sdk-pythonexamplemax_budget_usd.py). It stops the next request and can't cut the current one short. So it's a stop threshold, not a hard cap, and this PR names it that way. The hard ceiling is the caller's reservation of threshold + one request's worst case (kb init budget, a later PR).What
complete()takesmax_budget_usd.HarnessTransport.stops_at_spend(default False) says whether the CLI starts no further API request once the call's spend reaches the threshold.ClaudeCodeTransportsets it (--max-budget-usd). A call the CLI ends on its budget comes back withstop_reason="max_budget"and no text.total_cost_usdis reported asReply.usage["cost_usd"].ModelGateway.call_json(..., max_budget_usd=None)refuses before dispatch when the transport can't stop at a threshold (fail-closed).ModelUnavailableand is recorded as a failure.ModelReply.cost_usdis new; the trace record gainscost_usd+max_budget_usd.providers/{base,claude_code,codex,cursor,deepseek}.md,kb_service.md.Tests
test/test_kb_spend_cap.py(new, offline fake CLI):stop_reason="max_budget"handlingstops_at_spendModelReplyand the tracecheck_spec_freshness --strict, knowledge linters.Review gate
The commit gate (gpt-6-astra-high) first flagged that the original
supports_spend_cappromised a hard cap the CLI can't give. I reworked it to threshold semantics, and the gate approved it on iteration 2.🤖 Generated with Claude Code