---
title: "Swarms v16 'Overclock': Token Accounting, Decision Models, MCP Deployment, and Runs That Start Clean"
slug: swarms-v16-overclock-token-accounting-decision-models-mcp-deployment-and-runs-that-start-clean
url: https://listedarticles.com/articles/swarms-v16-overclock-token-accounting-decision-models-mcp-deployment-and-runs-that-start-clean
canonical_url: https://www.swarms.ai/blog/swarms-v16-overclock-release
content_type: changelog
language: en
published_at: 2026-10-02T00:00:00.000Z
updated_at: 2026-10-14T14:15:38.349Z
author: "Kye Gomez"
authored_by: human
publisher: "Swarms AI"
publisher_url: https://www.swarms.ai/
topics: ["AI Agents", "Open Source", "Developer Tools"]
license: all-rights-reserved
word_count: 2045
reading_minutes: 9
citation: "Kye Gomez, Swarms AI. \"Swarms v16 'Overclock': Token Accounting, Decision Models, MCP Deployment, and Runs That Start Clean.\" 2 Oct 2026. https://www.swarms.ai/blog/swarms-v16-overclock-release (all-rights-reserved)"
# The full text follows. The web page shows an extract and sends readers
# to the source above; quote the citation and link the canonical URL.
---

# Swarms v16 'Overclock': Token Accounting, Decision Models, MCP Deployment, and Runs That Start Clean

> Swarms v16 Overclock changelog: per-agent token accounting, DecisionModel, MCPDeployer, TreeOfThoughts, cleaner run isolation, and faster tool handling — Sept–Oct 2026 release notes.

# Swarms v16 'Overclock': Token Accounting, Decision Models, MCP Deployment, and Runs That Start Clean

Overclock is four and a half weeks of work: **114 commits between September 1 and October 2, 2026**, across 228 files, **+18,984 / −4,585 lines**. More of those lines went into `tests/` (+6,540) than into `swarms/` itself (+6,409 / −3,803). The suite grew from 762 test functions to 944.

Zena (v14) made the framework observable. Akira (v15) made it honest. Overclock makes it **measurable and fast**.

Five threads run through this release.

The first is **cost**. Before Overclock, an `Agent` had no way to tell you what a run cost. The provider returned exact token counts on every completion, and the framework dropped them. Now `agent.usage` reports provider-billed input, output, cached and reasoning tokens. `SwarmRouter`, `GraphWorkflow` and `HeavySwarm` sum them across every agent they ran, including directors, aggregators and judges that are not in your agent list. `agent.input_tokens` tells you how big the *next* request will be before you send it. Streaming runs, which reported zero, are counted too.

The second is **isolation**. Akira converted every structure onto typed chat turns. Overclock found the next layer down: most structures built their `Conversation` once in `__init__` and never reset it, so **a second `run()` on the same instance served the previous task's transcript as context**, and every batch entry point reused one instance. Twelve structures were fixed, plus three that shared one `Agent` across threads and two that collected results in completion order.

The third is **failures that surface**. When an LLM call failed every retry, `Agent.run()` returned an empty string or the prompt, with no error, and `fallback_models` were never tried. It now raises `AgentLLMError`. A failed tool is no longer blamed on the provider and re-run through the model. A total director outage in `HierarchicalSwarm` is no longer reported as a success. MCP tool errors under mcp 2.x are no longer reported as successes. Each of these returned a plausible value instead of an error.

The fourth is **new capabilities**: `DecisionModel` for typed, calibrated decisions from TypeSafe's Jev and Cloudflare's Clef; `MCPDeployer`, which serves any agent or swarm as an authenticated MCP server; `TreeOfThoughts`; `SwarmRouter(fallback_swarms=...)`; conversations seeded from `messages`; skills from several directories; and a `glob` tool for the autonomous harness.

The fifth is **speed**, which is where the name comes from. Tool handling moved out of `agent.py` into a new `ToolManager` (`agent.py` went from 4,566 to 3,227 lines), and the context compressor stopped tokenizing the whole history on every loop. **A tool turn is about 5× faster on a short conversation and about 65× faster on a long one.**

This post covers all of it. New features and improvements first, then a **day-by-day, commit-by-commit** record of the entire release.


## Getting the Update

```
# pip
pip install -U swarms
# uv
uv pip install -U swarms
# uv, in a project managed by uv
uv add swarms --upgrade
# poetry
poetry add swarms@latest
# pdm
pdm update swarms
```

Pin it if you want reproducible installs:

```
pip install "swarms==16.0.0"
uv pip install "swarms==16.0.0"
```

Confirm what you got. `swarms.__version__` is new in this release:

`python -c "import swarms; print(swarms.__version__)"`

**If you are coming from v15, read Breaking Changes first.** Three defaults changed (`temperature`, `dynamic_tools` and `MCPConnection.transport`), a failed LLM call now raises instead of returning, and the tool methods moved from `Agent` to `agent.tool_manager`.


## New Features

### Token accounting: `agent.usage`, `router.usage`, and `agent.input_tokens`

**The headline capability of Overclock.** The provider returns exact token counts on every completion, and LiteLLM normalises them to one shape for every provider. Until this release they were discarded, so there was no way to ask an agent what a run had cost.

```
from swarms import Agent
agent = Agent(agent_name="Analyst", model_name="gpt-5.4", max_loops=1)
agent.input_tokens   # size of the next request: system prompt, memory, tool schemas
agent.run("Summarise the latest FOMC statement in three bullets.")
agent.usage
# {'input_tokens': 1204, 'output_tokens': 87, 'cached_tokens': 1024,
#  'reasoning_tokens': 0, 'total_tokens': 1291}
```

`usage` is summed over every LLM call the agent has made, including the tool-summary call each loop makes. `cached_tokens` is the part of the input served from the provider's prompt cache, and `reasoning_tokens` is the part of the output a reasoning model spent thinking. The property returns a copy, so callers cannot corrupt the running total. Take a snapshot before and after a run to isolate one run's cost from the agent's lifetime total.

`input_tokens` answers a different question: how big the agent's next request will be, measured with `count_tokens` under the agent's own `model_name`, so the tokenizer matches the model. It counts the system prompt, the whole `short_memory` and any tool schemas, and it costs no API call.

Three gaps were closed after the first version landed (#2190):

- **Streaming runs reported zero.** A stream carries no usage unless you ask for it. The wrapper now sends`stream_options={"include_usage": True}` and records the provider's trailing usage-only chunk.
- **Reasoning tokens were invisible.** In the PR's example, 11 of a reply's 23 output tokens were reasoning. They are now reported separately.
- **OpenAI's reasoning-era models rejected the request.**`o1` /`o3` /`o4` and the`gpt-5` family refuse`max_tokens` and want`max_completion_tokens` , and`drop_params` could not help because litellm lists both keys as supported. The wrapper now sends the key each model accepts.

The same shape works one level up, on every structure that owns agents:

```
from swarms import Agent, SwarmRouter
agents = [
    Agent(agent_name="Researcher", model_name="gpt-5.4-mini", max_loops=1),
    Agent(agent_name="Writer", model_name="gpt-5.4-mini", max_loops=1),
]
router = SwarmRouter(agents=agents, swarm_type="HierarchicalSwarm")
router.run("Write a one-page brief on HBM supply constraints.")
router.usage   # summed over every agent the swarm ran, director included
```

`router.usage` (#2160) adds up your agents **and** any agent a built swarm holds on its own: a `HierarchicalSwarm` director, a `MixtureOfAgents` aggregator, a judge. Those are not in `router.agents`, but their spend is part of the run. Agents are deduplicated by identity, so one that appears in both places is counted once.

`GraphWorkflow.usage` (#2365) collects agents once across the whole graph, including subgraphs, so an agent that backs two nodes is counted once. `HeavySwarm.usage` (#2366) also counts question generation, which runs on a bare `LiteLLM` rather than an `Agent` and so was in nobody's `Agent.usage`. Runnable walkthroughs are in `examples/single_agent/utils/agent_usage.py` and `examples/multi_agent/swarm_router/swarm_router_usage.py`.


### `DecisionModel`: typed, calibrated decisions from TypeSafe and Cloudflare

A new kind of model joins the framework. A decision model does not generate text. It answers typed questions about a state with calibrated probabilities, so your code can branch on the answer and on how sure the model is.

| Question type | Asks | Returns | 
|---|---|---|
| Choice | Pick one option from a set | `choice` ,`probabilities` ,`confidence` | 
| Score | Rate against ordered levels | `score` ,`legend` ,`probabilities` ,`confidence` | 
| Noul | Is this statement true? | `noul` , from 0 to 1 | 

```
from swarms import DecisionModel, get_decision_models
model = DecisionModel()                    # TypeSafe Jev, reads TYPESAFE_API_KEY
clef = DecisionModel(model_name="clef")    # Cloudflare Workers AI
result = model.run(
    state={"message": "Checkout has been failing for every customer for an hour."},
    questions={
        "team": {
            "type": "choice",
            "instructions": "Which team should handle this?",
            "criteria": {"billing": "Payments", "technical": "Outages and errors"},
        },
        "urgent": {"type": "noul", "instructions": "Is this urgent?"},
    },
)
answers = result["answers"]
if answers["team"]["confidence"] < 0.5:
    print("Send to a human.")
print(answers["team"]["choice"], answers["urgent"]["noul"])
get_decision_models()
# ['jev-latest', 'jev-preview', 'jev-1.13.0', 'clef', 'clef-flash']
```

Every question is answered in one request, so a router, a guardrail and a scorer cost one call between them. TypeSafe's `jev-latest` is the default. Switching to Cloudflare's Clef is only a model-name change: names starting with `clef` route to Workers AI, read `CLOUDFLARE_ACCOUNT_ID` and `CLOUDFLARE_AUTH_TOKEN` from the environment or `.env`, and unwrap Workers AI's `result` envelope, so you get the same response shape either way. `get_decision_models()` merges the built-in names with each provider's live model list when its credentials are set.

There are single-question helpers (`choice`, `score`, `noul`), an async `arun`, retries with backoff that honour `retry-after`, and checks on both ends: questions are validated before they are sent, and every question must come back with an answer of its own type. Another provider plugs in through `base_url`, `endpoint` and `api_key_env`, or by overriding `build_headers`, `build_payload` and `parse_response`. The client calls the HTTP APIs directly with `httpx`, so there is no new dependency.

Nine examples ship in `examples/decision_models/`, including a decision model as the director of a `HierarchicalSwarm`, a 500-resume screening funnel that sends only the shortlist to LLM agents, a calibrated judge for a model ensemble, a debate referee that stops when no new arguments appear, and guardrails on a `GroupChat` (#2416).


### `MCPDeployer`: serve any agent or swarm as an authenticated MCP server

Swarms could consume MCP servers. It could not easily *be* one. `MCPDeployer` turns one or more agents, swarms or callables into an MCP server with an auth layer in front of it.

```
from swarms import Agent, MCPDeployer
agent = Agent(agent_name="Researcher", model_name="gpt-5.4", max_loops=1)
MCPDeployer(agent, api_keys=["sk-local-dev"], port=8000).run()
```

Another agent connects to it like any other MCP server:

```
from swarms import Agent, MCPConnection
client = Agent(
    agent_name="Client",
    model_name="gpt-5.4",
    max_loops=1,
    mcp_url=MCPConnection(url="http://127.0.0.1:8000/mcp", api_key="sk-local-dev"),
)
```

The first argument is one target, a list, or a dict of tool name to target. A target is an `Agent`, any structure with a `run()` method (`SequentialWorkflow`, `SwarmRouter`, ...), or a plain callable. Each becomes its own MCP tool with a `(task, img)` schema. Auth is layered: a custom `auth` callable, a `token_verifier` for OAuth, or static `api_keys` / `api_key_env`, with `allow_anonymous` and `public_paths` for the cases that need them. Duplicate names and unservable entries raise at construction, not at first call (#2219).

`timeout=` now really times out a blocking target (#2374). `anyio.to_thread.run_sync` shields its wait from cancellation unless told otherwise, so the deadline fired, the wait ignored it, and the late result came back as a success. Examples are in `examples/mcp/mcp_deployer/`, and both READMEs gained a "Serve an Agent as an MCP Server" section.


### `TreeOfThoughts`: search instead of answering in one pass

An implementation of Tree of Thoughts (Yao et al., 2023) joins `swarms.agents`. Instead of answering in one pass, it grows a tree of partial solutions and searches it.

```
from swarms import TreeOfThoughts
agent = TreeOfThoughts(
    model_name="gpt-5.4",
    search_algorithm="bfs",          # or "dfs", with backtracking
    generation_strategy="propose",   # or "sample", one call per candidate
    evaluation_strategy="value",     # or "vote", compare candidates
    thought_description="One arithmetic operation on two remaining numbers.",
    evaluation_criteria="Can the numbers left still reach exactly 24?",
)
answer = agent.run("Use 4, 9, 10 and 13, each once, with + - * / to make 24.")
agent.last_result.steps   # the best path; .root is the whole tree
agent.usage               # tokens across every call the search made
```

Four steps repeat: generate `num_thoughts` candidate next steps, score each from 0 to 1 and prune below `value_threshold`, search breadth-first with a beam of `breadth` or depth-first with backtracking, and write the final answer from the best path. `max_expansions` caps the cost.

Every model output is a function call validated against a Pydantic schema, with `$ref` inlined, because with nested `$ref` fields Claude Haiku 4.5 invented its own field names and every generator call failed validation. Each call runs on a fresh, stateless `Agent`, so evaluations never see each other's context, and calls at the same depth run concurrently. The prompts contain nothing task-specific: `thought_description` and `evaluation_criteria` adapt the search to a domain (#2379).


### `SwarmRouter(fallback_swarms=...)`: try the next architecture when one fails

`SwarmRouter` ran exactly one swarm type. If it raised, the run was over, and a caller wanting `HierarchicalSwarm` with `SequentialWorkflow` behind it had to build two routers and hand-write the retry.

```
from swarms import SwarmRouter
router = SwarmRouter(
    agents=agents,
    swarm_type="HierarchicalSwarm",
    fallback_swarms=["SequentialWorkflow", "ConcurrentWorkflow"],  # tried in order
)
result = router.run(task)
router.active_swarm_type   # which swarm actually served the run
router.fallback_attempts   # [{"swarm_type": ..., "error": ...}] for each that failed
```


*(Excerpt of release notes; full changelog at canonical URL.)*
