Repository navigation
fix(harness): record each Claude turn once, never the CLI's estimate, and date the price table (TH-9057, TH-9039) - #274
Open
khushalsonawat wants to merge 6 commits into
Conversation
…ate, and date the price table The CLI reports running totals within one connection, and the kit added each one, so a stage that sent a second message counted its earlier turns again. The simulated customer, one message per line, was billed (N+1)/2 times its true tokens. Each result now records its own counts: the difference from the connection's last totals, or, on a resumed connection's first result, the per-query usage, since SDK 0.2.176 on carries the old totals over a resume. A cost the kit can't price is now unpriced, never the CLI's estimate (about 7x Gemini's rate). The price table becomes dated rows, re-checked by 2027-03-31; the three Flash models double on 2027-01-01, per Google's Vertex pricing page. CI now runs these tests, so the check-by date turns it red from 2027-03-01. TH-9057 TH-9039 Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
5 of 10 tasks
cdileep23
requested changes
Nov 11, 2026
…K, pin today's prices, price on UTC days Review on #274 (Dileep). A recorded turn below the query's own usage now takes the totals whole, so totals that restarted and came back above the baseline, or a CLI that reports each query on its own, can't under-record. CI reruns the Claude cost tests on the SDK version uv.lock pins, which the hosted image uses. Today's prices are checked in CI against a committed copy of the gateway's rows at 9ec5f9fb1, not only beside a future-agi checkout. Prices switch on the UTC day, as the platform's dated rows do. TH-9057 TH-9039 Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
… the date weekly Past CHECK_BY a Gemini model kept no price, so every turn in a running release went unpriced. It now bills at its latest row's rate and warns once per model per UTC day. A model with no row, or a day before its first row, still reports no cost and counts in unpriced_turns. The re-check date no longer runs on PRs. A weekly scheduled workflow, price-check-by.yml, runs it from a month before CHECK_BY. It fails if the test is skipped, and a separate notify job opens or updates one issue on a scheduled failure. A PR test pins the workflow, its env var and the test's skip together. Refs: TH-9057 Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
khushalsonawat
changed the base branch from
dev
to
feat/TH-8804-source-subfolder
November 11, 2026 17:43
…nto feat/TH-9057-claude-cost Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
…ts it This PR now goes into #225's branch, where the reading took the difference of Claude's running totals itself (_own). The Claude backend now reports each turn's own figures, so the reading counted half: a two-turn reading recorded 0.07875 instead of 0.1575. The reading keeps each turn as reported; the two #225 tests that fed running totals feed per-turn figures; _gemini_priced reads current_rates, since the table is dated rows. Refs: TH-9057 Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
… day and the weekly workflow Refs: TH-9057 Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
This branch has not been deployed
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.
Description
The kit's record of what a run used gets two fixes.
The platform bills the simulated customer's tokens and authoring tokens from these figures. Before this change, a 10-line simulated conversation recorded 5.5× its true tokens. No company has been invoiced for environments yet, so there are no past bills to correct.
Type of Change
Changes
backends/claude.py).usage. SDK 0.2.176 and later carry the old process's totals over a resume, while the locked 0.2.156 restarts them.cost_usd=None(counted inunpriced_turns), never the CLI'stotal_cost_usd. For a Gemini model the CLI's figure was about 7× our price.backends/vertex_gemini.py).(input, output, first_day, last_day), andCHECK_BY = "2027-03-31".current_rates(name, today=None)returns today's rates, whatever the row order. Code that read the table by position should use it.agentcc-gateway/internal/modeldb/litellm.json(future-agi9ec5f9fb1, 2026-11-02);CHECK_BY, a model keeps its latest row's price and logs a WARNING once per model per UTC day, so a running release keeps counting cost. A model with no row, or a day before its first row, stays unpriced and counts inunpriced_turns.vertex_gemini._today(), as the platform's dated rows are.tests/harness/fixtures/litellm_vertex_prices.json, the gateway's 18 vertex rows at future-agi9ec5f9fb1) pins today's rates in CI.claude.py): when a turn's running-total count falls below the query's own usage, the totals are taken whole.sdk-smoke.ymladdstest_spend.pyandtest_claude_cost.py, andtest_ci_runs_these_testsfails if either is dropped. A second step rerunstest_claude_cost.pyon the SDK versionuv.lockpins (0.2.156), the one the hosted image installs.price-check-by.yml(Mondays 06:00 UTC), runs the check-by test and goes red from 2027-03-01. It fails if the test is skipped, and a separatenotifyjob, the only one withissues: write, opens or updates one issue on a scheduled failure. A PR test pins the cron, the env var, the node id, the skip condition and the notify job. GitHub runs schedules on the default branch only, so it starts after this reachesmain.test_claude_cost.py(new):Stage, a resume andrun/conversation.py's customer;test_spend.py:CHECK_BY, and a model with no row staying unpriced;CHECK_BY, including the "no current price" warning;test_vertex_gemini_backend.py: one test that priced gemini-3.7-flash without a date now pins it.The integration with #225 (TH-8804), now in this PR
This PR targets #225's branch, so the double subtraction is fixed here (
be64c352, after merging the basec0e51b7ein67b52516):agent_reading.py:_ReadingStage._own, therunning_totalsflag and their baselines are removed. A turn is added as the backend reports it, since this PR's Claude backend already reports per-turn figures.test_agent_reading.py: the three tests that fed running totals now feed per-turn figures, with the same expected totals._gemini_pricedusescurrent_rates.test_a_claude_reading_adds_per_turn_figures_as_they_come, now runs. It failed on the merge before the fix (0.07875 against 0.1575) and passes after.Fixed after the review rounds (named as asked)
Plan review round 1 (not clear). Fixes:
Plan review round 2 (clear). Fixed with no further round:
current_rates;Change review round 1 (not clear: CI ran none of these tests). Fixes:
Change review round 2 (clear). Fixed with no further round:
These were checked by planted bugs, not by another round.
Known limits and open items
complete: falseitem (feat(harness): build an agent from a repo's subfolder #225). On feat(harness): build an agent from a repo's subfolder #225, a reading whose turns include an unpriced one writescomplete: falseincost.json. After this change, that happens only for a model missing from the price table. The CLI's estimate no longer counts as priced, which is what the ticket asks. How the platform bills an incomplete reading isn't on future-agi dev, so this is left for feat(harness): build an agent from a repo's subfolder #225's landing.usagedoesn't carry them: up to a third of that turn in a probe. Only hosted chat resumes, and chat usage isn't billed. If that result has nousageat all, it records 0 and logs a warning.Testing
Run locally under a memory cap, after the last pushed change (
ffa61b78):Python 3.12.3 (SDK 0.2.176):
test_spend.pyandtest_claude_cost.py: 43 passed, 3 skipped (the tripwire, the local-only agreement test, and the check-by test, which runs only in the weekly workflow). WithALK_PRICE_CHECK_BY=1, the check-by test passes.The locked SDK 0.2.156:
test_claude_cost.py: 19 passed, 1 skipped.test_vertex_gemini_backend.py(19 passed): not in CI. Itstest_provider_429_exhausts_bounded_retriesfails the same way on the base (c0e51b7e, Python 3.12.3), so the file isn't added tosdk-smoke.yml.CI's whole pytest list, in a CI-like environment on Python 3.12 (a reviewer's run, before the weekly-workflow change): green.
The agreement test, run by hand against litellm.json at
9ec5f9fb1: all 18 rows match.Planted bugs:
Reviews: two plan review rounds and two change review rounds, each with two fresh reviewers. Dileep's review fixes and the CHECK_BY change had their own change review, with two reviewers (both clear). A fix-only check of the commits made after those clears (
a232700b, and the Lows inffa61b78), with two reviewers: clear, no High. It found one Medium and five Lows, all guards no test pinned (the locked-SDK rerun step, two weaker forms of the per-query guard, a non-UTC zone, and the price-check-by workflow's checkout andif:). They are fixed in5e45ac81.The last fix-only check, two reviewers, covered
be64c352and5e45ac81: clear, no High. It covered the integration fix and those guards. Owl's six plants are caught, and the locked SDK 0.2.156 gives 23 passed. It found 2 Mediums and 4 Lows, left for a follow-up commit with its own check:continue-on-error,if,shell) with the test still green;_gemini_pricedbreaks after 2027-04-01;importorskipcould hide an import fault;ClaudeSessioninto the reading;CI
clean-installon the pull_request run fails one speed budget,test_contract_model.py::test_a_crafted_file_of_block_comments_does_not_hold_up_the_check[a-file-of-openers](0.5 s), at about 0.54–0.66 s. That file isn't in this PR. The base fails it on its own push run,477efe88(https://github.com/future-agi/agent-learning-kit/actions/runs/43169044737, 0.84 s, plustest_a_quote_that_grows_when_normalised_costs_little). This PR's own push run passes (https://github.com/future-agi/agent-learning-kit/actions/runs/43171616440).Failures that predate this change:
test_terminal_save_closes_adk_invocation_in_its_original_contextcases, andtests/test_harness.py::test_hosted_claude_session_uses_durable_resume_and_restricted_tools;test_provider_429_exhausts_bounded_retries.All of them fail the same way on untouched dev in the same environment.
Related Issues
Refs: TH-9057
Refs: TH-9039
Related: #225 (TH-8804), TH-9508, TH-9510