Repository navigation
plat 683
github-actions[bot] edited this page Oct 7, 2026
·
3 revisions
| Field | Value |
|---|---|
| State | fixed on main |
| Priority | P1 |
| Product | app |
| Area | accounts |
| Summary | Admins set a per-person daily and weekly token limit on the shared server accounts; at the limit new turns on a server account are refused, own accounts keep working. |
Owner request (2026-10-07), mainly for Excellence: people share the admin
(server) provider accounts (global:<provider>), and one person can use up
the shared plan for everyone. There was no per-person cap.
-
Limits live on the person's
config/users.jsonrecord astoken_limits: {daily, weekly}(absent or 0 = unlimited, the default). An admin edits them through the existingPUT /api/admin/users/{id}withtoken_limits(replaces both).GET /api/admin/usersreturns each person's limits and current usage (token_usage). -
What counts: tokens in the cost ledger (
_system/costs.sqlite) whoseaccount_idstarts withglobal:, for that person'suser_id. The ledger already recorded the account on every LLM-call event (costobserver.WithAccountin handleQuery, delegation, Relays and the workflow orchestrator, so Code, Crew, Goals workflows, Relays and Brain chats are all covered); nothing new had to be recorded. A token is input (cached input counted once, as the ledger'sinput_tokens) plus output; reasoning is inside output for the CLIs that report it. Own accounts and accounts shared by another user have their own IDs and never count. New:costledger.Ledger.AccountTokensand an index on(user_id, occurred_at). - Windows: calendar day and Monday-start week, both UTC (there is no server timezone setting); the UI says UTC.
-
Enforcement:
admitProviderAccount(server-account branch) refuses when the principal is at or over either limit, with "You have used your daily limit of N tokens on the shared accounts (resets at 00:00 UTC). Use your own account or ask an admin to raise it." (weekly: "resets Monday 00:00 UTC"). That one admission runs for every turn in handleQuery and for every model start (llmguard.WithServerAccountAdmission→ResolveConnection), so all products are covered. Usage is cached per person for 20 s. A ledger read error logs and admits (budget control, not a security gate). - Running turns finish: nothing stops a turn already running. A model that starts inside a running turn (for example a sub-agent) on a server account is admitted again and can be refused once the limit is reached.
-
Scheduled and triggered runs count toward the run's identity (the
scheduler's
OwnerUserID,workflowExecutionOwnerUserID). Decision: a run whose workflow runs on a server account while that identity is over a limit is refused before it starts and recorded as failed with the limit message (scheduledRunTokenLimitRefusalinrunJob). A workflow set to its owner's own account is not refused. -
UI: Access → Users has a "Shared-account tokens (UTC)" column with Daily and
Weekly fields (empty = unlimited; accepts 500k / 5M) and the person's use today
and this week. The Models panel (
WorkModelsPanel) shows the person's own use against their limits when a limit is set (GET /api/me/token-usage), amber from 80%, red at the limit. - Code:
agent_go/cmd/server/token_limits.go,user_directory.go,provider_accounts.go,scheduler.go,pkg/costledger;frontend/src/components/admin/UsersAdminPanel.tsx,components/providers/SharedTokenUsageNotice.tsx,utils/tokenLimits.ts. - Test:
TestTokenLimitsCountAndCapServerAccountsOnly(own-account use does not count; over the limit a server turn and a scheduled server run are refused, the own account and an unlimited person are not).
- Not deployed. Verify live on Excellence after deploy: set a small daily limit on a test person, run a Code turn on the server account, see the refusal; the same person's own account still runs.
- The 80% warning is shown in the Models panel only, not as a chat banner.
- Live input typed into an already running server-account session is not re-checked (it is part of the running turn).
Owner: people should see it where they type. The chat input toolbar shows a small chip next to Attach (e.g. "1.2M/5M today", the tighter of the two limits; amber from 80%, red at the limit; both limits and resets in the tooltip). Hidden when no limit is set. The Models panel notice stays.
Each shared account now also has its own per-person limit with per-person overrides; the limit above stays as the overall cap. See PLAT-693.
Auto-synced from docs/ on main. Edit there, not here.