Rotating a production API key without stopping an agent service creates an overlap window: old and new credentials can authorize work at the same time, while final usage evidence arrives only after a model call. The control decision follows from that constraint. Reserve a conservative amount before dispatch, serialize admission against the account limit, and later reconcile the reservation with the reported usage in an append-only ledger.
Short answer: a pre-call estimate is an admission control; a post-hoc usage report is settlement evidence. An enforceable budget needs both. During rotation, map both credential aliases to one stable account, keep one logical operation ID across retries, and record the credential alias as audit evidence rather than treating it as a second budget.
This is not price prediction. An agent can branch, retry, and invoke tools, so the unknown quantity includes future control flow as well as the next response. The useful promise is narrower: no worker starts a call unless an atomic reservation fits under the applicable, versioned policy.
Should a pre-call cost estimate or post-hoc usage report control admission?
A report describes completed work. By the time it is durable, several workers may have observed the same available balance and dispatched more calls. Suppose a run has 8,000 internal quota units left and eight workers each request a 2,000-unit reservation. Separate reads and writes can admit all eight, although serialized admission should accept four. Every later usage record may be accurate, yet the cap has already failed.
The comparison is therefore about timing and authority, not which number looks more precise.
| Record | Question answered | Available before dispatch? | Safe use |
|---|---|---|---|
| Estimate | May this operation start under this policy? | Yes | Reserve capacity atomically |
| Usage report | What did the completed operation consume? | No | Settle and reconcile |
Trying to make the estimate exact is a category error. Output has not been generated, and the agent's next branch is not known. Build the estimate from bounded inputs available at admission: input size, configured output ceiling, model class, tool allowance, and remaining run envelope. A conservative reservation can reject useful work or hold capacity longer than needed; a loose one admits more work but weakens the cap. That trade-off must be explicit and observable.
Reports have a different kind of precision. Preserve their raw usage dimensions separately from the internal charge produced by a versioned rate card, rounding rule, currency, or quota policy. Recomputing an old charge under a new rule rewrites history. For reconciliation, that is unacceptable.
Make reservation and settlement ledger events
Give each economically distinct operation a stable idempotency key before any external call. Admission appends a reservation event. Completion appends a settlement event. A confirmed cancellation or expired lease appends a release event, while a later correction links to the event it adjusts instead of overwriting it.
Exactly once belongs to the ledger, not the network. A timeout cannot prove that a remote call did not execute. The local store can still make repeated reservation or settlement messages converge by enforcing uniqueness on the logical operation ID and event type. If a retry changes the model class, output ceiling, or tool allowance, it requests different economic authorization and should receive a new operation ID.
The core Go contract can stay small:
package budget
import (
"context"
"errors"
"time"
)
var ErrLimitExceeded = errors.New("budget limit exceeded")
type Reservation struct {
OperationID string
AccountID string
PolicyVersion string
Amount int64
ExpiresAt time.Time
}
type Usage struct {
OperationID string
InputUnits int64
OutputUnits int64
RateVersion string
CredentialRef string // Random internal alias, never the secret value.
}
type Store interface {
Reserve(context.Context, Reservation) error
Settle(context.Context, Usage, int64) error
Release(context.Context, string, string) error
}
Use integer minor units or integer quota units, not floating-point values. Reserve must compare spent + reserved + candidate with the limit and append the event in one serializable transaction, or through an atomic primitive with equivalent semantics. A process-local counter cannot provide that guarantee once multiple workers or regions participate.
No quiet bypass.
If the ledger is unavailable, a hard budget fails closed. “Limit exceeded” is a policy result and can lead to queuing, a smaller bounded request, or a clean stop; “ledger unavailable” is an infrastructure fault. Conflating them makes both operator response and audit review harder.
Keep credential rotation outside the accounting identity
Zero-downtime rotation normally requires a controlled overlap: introduce the new credential, verify its use, and revoke the old credential. OWASP's Secrets Management Cheat Sheet discusses rotation, revocation, least privilege, expiration, and audit concerns; those practices protect credential handling, but a credential is still not a customer account.
Map the old and new secrets to opaque credential references, then map both references to the same stable account. Reservations debit that account. Audit events retain the reference that authorized each operation, so an investigator can reconstruct the cutover without storing a secret in a ledger, log, trace, idempotency key, or error message.
This distinction matters at revocation. A worker authorized by the old key may finish after the key becomes inactive. Its settlement remains valid because it is linked to the existing reservation and logical operation, not to the credential's current status. Requiring an active credential during settlement would strand legitimate reservations during the very overlap the design is meant to support.
Access also needs separation. Permission to retrieve a production secret should not imply permission to inspect budget evidence, and permission to review the ledger should not reveal the secret. Retention must be long enough to meet the organization's contractual and regulatory audit obligations, yet payloads and credentials should not be retained merely because the event store can hold them. There is no universal retention period; the applicable compliance regime and contract determine it.
Treat ambiguity as a recorded state
After a timeout, a call may be known not to have started, known to have completed, or ambiguous. Release immediately only in the first case. Settle in the second. In the ambiguous case, retain the reservation until authoritative evidence, lease expiry, or a documented correction process resolves it; inventing zero usage converts uncertainty into untracked spend.
Useful operational signals include reservation age, settlement lag, estimate-to-actual error, rejected admissions, correction volume, and outstanding reserved amount by policy version. Keep credential references and operation identifiers out of low-control metric labels. Detailed correlation belongs in access-controlled audit records.
For an illustrative policy, a run could have a ceiling of 10,000 internal units, permit at most 1,200 units for one call, and stop admitting steps below 300 uncommitted units. These are test values, not recommended universal settings or prices. Their purpose is to force boundary tests: two workers contending for the final reservation, duplicate settlement delivery, a report that exceeds its reservation, and an expired reservation whose completion arrives late.
Short tests find sharp edges.
Roll out the ledger alongside the key change
Start in shadow mode, computing reservations and recording hypothetical decisions while calls continue under the existing control. Compare estimates with final reports, verify idempotency under duplicate delivery, and confirm that one logical account receives events from both credential aliases. Shadow data may tune future bounds, but it must never rewrite historical decisions.
Next, enforce a generous run ceiling for a limited traffic slice. Rehearse the rotation sequence: reserve under the old alias, introduce the new secret, retry the same logical operation without creating a second reservation, settle the original operation after revocation, and prove that the event chain still names the policy and credential references involved. Expand enforcement only after concurrent admission and ambiguous timeout cases behave as designed.
The decision rule stays compact: estimate to decide, report to settle, and retain both to explain. That arrangement adds transactional contention and temporarily ties up conservative reservations, but it provides the property that matters for a production agent budget during credential rotation: every authorization and adjustment can be reconstructed without splitting the account or pretending a network call happened exactly once.
Sources
References:
- OWASP Secrets Management Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html
Top comments (0)