Repository navigation
Telegram shopper: check only the platform Gemini cap with recorded spend on - #1885
Merged
Merged
Conversation
The Telegram shopper belongs to no tenant, and a check without a tenant applies the per-tenant Gemini cap to every tenant's spend combined. With recorded-spend controls on, that total is real: once all tenants' router Gemini spend reached the per-tenant cap ($10 by default) in a UTC day, every Telegram buyer turn failed until the day rolled over. - With AGENTICORG_RECORDED_SPEND_CONTROLS_ENABLED on, run_shopper checks only AGENTICORG_GEMINI_PLATFORM_DAILY_USD_CAP through the new assert_under_gemini_platform_cap(), which fails closed like the combined check. Off, it calls assert_under_gemini_cap() as before. - assert_under_gemini_cap() delegates its platform half to the new function with the same checks, order and messages, so router calls without a tenant keep both caps. - Unit tests cover the platform check and both shopper branches. A Postgres replay has two tenants' recorded spend pass the per-tenant cap: the shopper still answers, and is refused at the platform cap.
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. |
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.
Summary
The Telegram shopper (
core/commerce/network_telegram.py,run_shopper) belongs to no tenant. Before every buyer turn it callsassert_under_gemini_cap(0.0)without a tenant, and that check applies the per-tenant Gemini cap (AGENTICORG_GEMINI_DAILY_USD_CAP, default $10) to every tenant's spend combined.With
AGENTICORG_RECORDED_SPEND_CONTROLS_ENABLEDon (#1869, and now on in production), that combined total is real. So once all tenants' Gemini calls through the router add up to $10 in a UTC day, every Telegram buyer gets "Sorry, something went wrong on my side" until the day rolls over. The bot itself is not what spends that $10. Its own model calls go through LangChain, not the router, so they are never recorded.This PR holds the shopper to the platform cap (
AGENTICORG_GEMINI_PLATFORM_DAILY_USD_CAP, default $100) only.assert_under_gemini_platform_cap()incore/llm/router.py: the platform half of the existing check, moved into its own function. It still fails closed, and a cap of0still turns it off.assert_under_gemini_cap()is unchanged in behaviour: it now calls the new function for its platform half, with the same checks, order and messages. Router calls without a tenant keep both caps.run_shopper: with the flag on, it calls the platform-only check. With the flag off, it callsassert_under_gemini_cap(0.0)exactly as main does (AGENTS.md: the change sits behind the existing default-off flag).Verdict (bug-fix checklist)
DailyBudgetExceeded: spent $1.2000 of $1.19/day.Not merged and not deployed. Production has the flag on, so this takes effect on the next deploy with no env change. Rolling back means routing traffic back to the previous revision; there is no migration and no new setting.
Sibling paths
assert_under_gemini_capthroughLLMRouter._call_gemini): unchanged. They keep the per-tenant cap applied to the platform total as well as the platform cap. Loosening those is a separate decision.core/llm/router.py(_call_gemini) andcore/commerce/network_telegram.py(run_shopper) are the only two. No other code calls it.Residuals
AGENTICORG_NETWORK_TELEGRAM_CHAT_LIMIT_PER_HOUR,AGENTICORG_NETWORK_TELEGRAM_GLOBAL_LIMIT_PER_MINUTE). Recording LangChain-path spend would be its own change.assert_under_gemini_cap. They pass with the default settings CI uses. With the flag forced on in the environment, they would reach the real platform check, as other suites on main already would.Test plan
tests/unit/test_network_telegram_spend_cap.py(new) covers:0turns it off, with no spend lookup;tests/integration/test_llm_daily_spend_postgres.py: the new Telegram replay against Postgres, plus the existing cap, budget and migration tests.tests/integration/test_lead_delivery_postgres.pycovers the flag-off path. 12 passed.grantex_agent_httpsig. On SQLAlchemy 2.0 / Python 3.14, the cap and Telegram set passed (61).ruff check ., mypy on the touched modules (same four missing-package import notes as main) and the enterprise stability gates.SKIP_UI=1 bash scripts/preflight.sh): 12 of 13 steps passed, including ruff, mypy and bandit on the whole tree, the secret scan and the enterprise stability gates. The pytest step had 16,511 passed, 13 failed and 10 errors. I reran those 8 test files on this PR's base (61824fe), and the same 13 tests fail and the same 10 error there, so this change causes none of them. They come from the local Windows environment: for example, the local venv haslanggraph-checkpoint-postgres3.0.5, where the tests expect 3.2.0. CI'sunit-testsjob runs the same suites and passed on this commit.