Swarm Cost Optimization
Swarms amplify token cost because the same conversation is replayed across multiple turns and (potentially) multiple agents. Augments gives you five composable levers and one absolute safety net.
The Five Levers
| Lever | Mechanism | Layer | Applies to |
|---|---|---|---|
| Per-tool result cap | FunctionTool.max_result_tokens | Tool | A single tool's JSON output |
| Per-handoff history cap | HandoffConfig.budget | Handoff | History carried across a handoff edge |
| Swarm-wide switch cap | SwarmConfig.max_handoffs | Swarm | Total agent switches in the run |
| Swarm-wide token cap | SwarmConfig.max_total_tokens | Swarm | Cumulative LLM tokens across the swarm |
| Per-turn context size | SharedContextStrategy | Swarm | Messages sent to each agent per turn |
Absolute safety net: RunConfig.max_total_turns (not
swarm-specific) stops runaway loops. It defaults to 500 β a bounded,
cost-conservative default; production deployments can override
(raise or lower) for their workload. Set to None explicitly only
when you genuinely want unbounded multi-agent turns.
Minimal-Cost Starter Template
from augments.adk.run.config import RunConfig
from augments.adk.run.runner import Runner
from augments.adk.swarms import (
Swarm, SwarmConfig, SharedContextConfig, SharedContextStrategy,
LLMHandoffPolicy,
ExplicitDoneTermination, MaxTurnsTermination, TokenBudgetTermination,
)
swarm = Swarm(
members=(author, reviewer, auditor),
entry=author,
policy=LLMHandoffPolicy(),
termination=(
ExplicitDoneTermination() # primary stop
| MaxTurnsTermination(20) # soft cap
| TokenBudgetTermination(80_000) # cost cap
),
config=SwarmConfig(
max_handoffs=10,
max_total_tokens=80_000,
shared_context=SharedContextConfig(
strategy=SharedContextStrategy.SCOPED, # default, but stated for clarity
),
),
)
result = await (
Runner.configure()
.with_config(RunConfig(max_total_turns=50)) # absolute safety net
.swarm(swarm)
.arun("Refactor this module.")
)SharedContextStrategy β the biggest lever
| Strategy | What each agent sees | Typical use |
|---|---|---|
SCOPED (default) | Its own scratch + the explicit handoff message | Production default β no hidden broadcast |
LAST_N | Last N items of the shared history | When agents need a rolling view but not full history |
SUMMARIZED | Compacted summary + preserved recent items | Long runs where the full trail matters |
FULL_BROADCAST | Every item every agent ever produced | AutoGen parity β debugging only, not production |
Guideline: if you find yourself paying for "the other agents' tool
results" every turn, you're probably on FULL_BROADCAST when you
meant SCOPED.
Where Each Lever Wins
FunctionTool.max_result_tokens
A noisy tool (e.g. get_full_order_history) will bloat every
downstream replay. Cap the tool output, not the conversation.
HandoffConfig.budget
When agent A hands off to B, you can trim what B inherits. Reuses the
existing handoff budgeting pipeline β the swarm driver calls the same
prepare_handoff_input path.
SwarmConfig.max_handoffs
Policy-independent switch cap. Distinct from max_total_turns because
a single agent can take many turns between switches.
SwarmConfig.max_total_tokens
Cumulative across the whole swarm run. Checked at the top of each
turn; stops cleanly with StopReason(kind="max_total_tokens").
SharedContextStrategy
The cheapest lever of all because it's per-turn. Moving from
FULL_BROADCAST to SCOPED can cut replay cost by an order of
magnitude on long runs.
How the Levers Interact
Think of the run as a nested envelope:
RunConfig.max_total_turns (absolute safety net β never skip)
βββ SwarmConfig.max_total_tokens (cost envelope)
βββ SwarmConfig.max_handoffs (switch envelope)
βββ TerminationCondition (explicit stop)
βββ Per-turn:
βββ SharedContextStrategy (input size)
βββ HandoffConfig.budget (handoff carry-over)
βββ FunctionTool.max_result_tokens (tool results)
A healthy production swarm trips ExplicitDoneTermination first β
every other layer is a safety rail, not the expected exit.
Default safety net: when you don't pass
termination, a swarm getsDEFAULT_TERMINATIONβExplicitDoneTermination() | MaxTurnsTermination(25). The explicit-done contract is unchanged; the 25-turn cap only bounds runs whose members never callswarm_done. Pass your owntermination=to tune it.
Debugging High-Cost Runs
- Inspect
result.state.cumulative_usage(orresult.per_member_usagefor the per-agent breakdown) β which agent burned tokens? - Inspect
result.handoff_countβ too many switches usually means the policy isn't converging. - If
FULL_BROADCASTorLAST_N, trySCOPEDand see if quality actually drops. - If a single agent's turn is huge, check which tool's output is dominating β cap it.
- If tokens explode late in the run, add
TokenBudgetTerminationwith a soft cap beforeMaxTurnsTermination.
See Also
docs/swarms/swarms.mdβ overview and when to use a swarmdocs/swarms/policies.mdβ how each policy affects cost