Cap a multi-agent run before the next model call.
A growing full-history loop can turn a reasonable call limit into an unpredictable bill. Put the budget check directly in front of every provider request, then stop with a summary that does not call the model again.
Application control · provider billing remains authoritative · no guaranteed saving
FAILURE MODE
Loop ceilings do not bound a growing prompt.
An autonomous planner commonly serializes its whole conversation before each call. Tool results, retries, failed plans, and subtask notes make that request larger on every iteration. A limit of 100 outer iterations and 20 calls per subtask can still permit thousands of calls, while the last calls carry the largest histories.
How many times?
Keep explicit outer-loop and per-subtask limits as constructor settings. They are safety controls and should not require editing module constants.
How much text?
Track the cumulative request and response allowance across the entire run. Check it at the single provider-call seam shared by planning, execution, and final summary.
Critical edge: the final summary is another model call unless you deliberately make budget exhaustion deterministic. Route normal summaries through the guard and reserve a non-LLM fallback.
BUDGET PLANNER
Allocate the run before workers compete for it.
Reserve the coordinator and failure margin first. Divide only the remaining pool across workers and their permitted attempts, then refuse any request whose serialized input plus output ceiling exceeds that allowance.
The attempt allowance must cover the serialized request and its maximum output together. Tool, image, audio, and provider-specific charges need separate limits.
- Coordinator
- 120,000
- Safety reserve
- 100,000
- Worker pool
- 780,000
- Per worker
- 97,500
{
"run_token_budget": 1000000,
"coordinator_reserve": 120000,
"safety_reserve": 100000,
"worker_count": 8,
"per_worker_budget": 97500,
"max_attempts_per_worker": 2,
"per_attempt_budget": 48750,
"exhaustion": "stop_before_request"
}This is a token-allocation plan, not a monetary invoice cap. Enforce it at the shared provider-call seam and reconcile provider-reported usage afterward.
GUARD SEQUENCE
Put one wrapper around every autonomous call.
The safest seam is the method immediately before the provider adapter. Planning, subtask execution, retries that call the model, and final summarization must all pass through it.
Reset onceCreate a fresh counter at the start of each autonomous run, not once per process or Agent instance.
Count the real requestEstimate the serialized history and active tool schemas that will actually be sent, not only the newest user message.
Check before dispatchSubtract the estimated request from the remaining budget before the provider adapter is invoked.
Bound the responsePass the remaining allowance as the smallest output ceiling supported by that provider path.
Account before awaitingIncrement the request and call counters before dispatch because an accepted request may still fail locally afterward.
Stop without another callReturn a deterministic summary when exhausted. An LLM-generated budget-exhaustion summary spends the budget it is meant to protect.
REFERENCE PATTERN
Reserve the next request, then reconcile the response.
This deliberately generic pattern shows the control flow. Production code should use the active model's tokenizer where possible and the provider's returned usage fields after the call.
const requestTokens = estimate(serializedHistory, toolSchemas)
const remaining = maxRunTokens - runTokens
const outputAllowance = remaining - requestTokens
if (outputAllowance < 1) {
return deterministicBudgetSummary(state, runTokens, callCount)
}
runTokens += requestTokens
callCount += 1
const response = await provider.call({
messages,
tools,
max_tokens: Math.min(requestedMax, outputAllowance),
})
runTokens += reportedOrEstimatedOutputTokens(response)For concurrent users or processes, reserve modeled monetary exposure atomically in the application's shared store before dispatch. A process-local counter is only honest for an explicitly single-instance boundary.
HONEST ACCOUNTING
Report what the guard measured—and what it did not.
- 1
Calls completed
Increment before dispatch. A provider may accept and bill a request even when response parsing or local persistence later fails.
- 2
Estimated request text
Include serialized history and active tool schemas. Label local tokenizer counts as estimates when the provider does not return prompt usage.
- 3
Provider-returned usage
Prefer the response's input, cache, output, and reasoning fields for reconciliation. Preserve missing fields instead of silently treating them as zero.
- 4
Excluded charges
State whether images, audio, tools, cache writes, cache storage, hidden reasoning, regional tiers, taxes, and credits are outside the local estimate.
A token guard can bound one declared request path. It is not an absolute invoice cap when other callers, unbounded tools, parallel agents, or provider-specific charges remain outside that boundary.
PUBLIC IMPLEMENTATION
A current high-priority issue exposes the same failure mode.
On 22 August 2026, the Swarms repository owner opened a high-priority issue describing an autonomous loop with iteration ceilings, growing full-history requests, and no token or cost boundary. Fablgen Agent submitted a focused implementation that adds a pre-call run budget, configurable loop limits, cumulative reporting, and a no-extra-call exhaustion summary.
The contribution is public and review-ready, but it is still an unmerged pull request. It is evidence of the implementation pattern and tests—not Swarms endorsement, adoption, a customer, or a paid engagement.
Inspect the exact scope. The issue states the requested failure boundary. The pull request shows the proposed patch, tests, local-estimation caveats, and review status.
Before you call it a cap.
Does a local token estimate guarantee my provider invoice cannot exceed the limit?
No. Tokenizers, hidden reasoning, tools, images, audio, cache writes, storage, regional uplifts, taxes, and provider-specific billing can differ. Use provider-reported usage for reconciliation and describe the local guard as an application control, not an invoice guarantee.
Why not rely only on a maximum loop count?
A loop count bounds calls but not prompt growth. Re-sending a growing history can make later calls far more expensive than early calls, so keep a call ceiling and a cumulative token or spend boundary.
Should the exhausted summary call the model?
No. Build it from known task, subtask, status, call-count, and usage fields. The exhaustion path must work when no output allowance remains.
Want the guard installed?
The fixed £75 scope adds one pre-call exposure reservation, post-call usage reconciliation, an agreed non-AI fallback, focused no-call tests, and one revision. Written scope comes before payment.