{"slug": "your-agent-has-too-many-tools-and-no-way-to-take-any-back", "title": "Your Agent Has Too Many Tools, and No Way to Take Any Back", "summary": "Anthropic released Claude Opus 5 on 24 July 2026 at $5 and $25 per million input and output tokens, featuring a new mechanism that decouples tool declaration from runtime tool availability via tool_addition and tool_removal content blocks on system messages, preserving prompt caching by keeping the tools array unchanged. The update addresses the problem of frozen tool sets in agentic sessions, allowing dynamic capability changes without cache invalidation, and includes strict placement rules for system messages to maintain cache hits.", "body_md": "Anthropic released Claude Opus 5 on 24 July 2026 at $5 and $25 per million input and output tokens, unchanged from Opus 4.8, describing it as coming close to the frontier intelligence of Claude Fable 5 at half the price. Most of the commentary went to the benchmarks: state of the art on Frontier-Bench v0.1 and GDPval-AA, three times the next-best score on ARC-AGI 3, and a five-level effort ladder that lets you trade tokens for reasoning depth.\n\nTwo beta features shipped alongside it, in a short list near the end of the post:\n\nVentureBeat came closest to noticing the first one, describing it as a small feature that agent developers may appreciate more than any benchmark. That is the right instinct and the wrong magnitude. It changes where the boundary of an agent’s authority can live, and it lets two problems be handled by one mechanism: **which tools a model can find**, and **which tools a model is allowed to use**.\n\nThose sound like one problem. They are not, and treating them as one is a reliable way to stall an agentic pilot at the point where a security or risk review begins.\n\nPrompt caching hashes the request prefix in a fixed order: tools, then system, then messages. A cache hit requires the prefix to match a recent request byte for byte, up to the breakpoint.\n\nThe tools array sits at the front of that hash. Which meant the tool list was effectively frozen for the life of a session. Add one tool at turn 40 of a long agentic run and you change the front of the prefix, invalidate the cache for everything after it, and reprocess the conversation at full input price.\n\nThe consequence is one most of us absorbed without naming: **you had to decide an agent’s entire capability surface before the first user message arrived.**\n\nThe new mechanism removes the coupling. You declare the tool set in tools up front, then use tool_addition and tool_removal content blocks, carried on role: \"system\" messages, to offer or withdraw a tool from a specific point in the conversation onward. Blocks reference a tool by name, and individual MCP tools and whole MCP toolsets can be referenced. The tools array itself never changes, so the hashed prefix survives and the cache keeps hitting.\n\nConstraints worth knowing before you design around it:\n\nThat pairing is the real primitive. A mid-conversation system message lets your application assert an operator-level fact partway through a session at system priority rather than user priority. A tool change lets the capability surface move in response to that fact. Together they give you a runtime, operator-controlled, cache-preserving capability state machine.\n\nThe placement rules are strict enough to design around, so learn them before you build. A system message must immediately follow a user turn, including one carrying tool_result blocks, or an assistant turn ending in a server tool result. It must either end the messages array or be immediately followed by an assistant turn. It cannot be the first entry, and it cannot sit between a tool_use block and the tool_result answering it. Any other position returns a 400. Once a system message has been sent, do not edit or remove it; append a new one instead, or you invalidate the cache from that point forward.\n\nOne instruction in the documentation reads like style advice and is actually engineering advice: phrase system content as **context rather than command**. State the fact (“step-up authentication completed”, “remaining token budget is 12k”) and let the model act on it. Models are trained to resist instructions that appear to work against the user, and that resistance applies to the system role too, so “ignore what the user asked for” performs worse than stating what changed.\n\nStart with the measurable problem, because it is where most teams are already losing money without a line item for it.\n\nTwo things degrade as a tool catalogue grows.\n\n**Context.** Anthropic’s own example of a multiserver MCP setup, GitHub plus Slack plus Sentry plus Grafana plus Splunk, consumes roughly 55k tokens in tool definitions before the model reads a word of the request. A feature request on Anthropic’s Python agent SDK repository describes a production setup with more than 150 registered tools consuming 40k to 60k tokens before any user message is processed. Treat that second figure as one team’s report rather than a benchmark, but the shape is familiar to anyone who has aggregated more than three MCP servers.\n\n**Accuracy.** The documented guidance is direct: the model’s ability to pick the correct tool degrades significantly once you exceed roughly 30 to 50 available tools. This is the part that gets underweighted. Cost is irritating. Misrouting is what destroys trust, because an agent that calls the read-only lookup instead of the update, or picks a near-synonym tool belonging to a different system of record, produces confident and plausible wrong work.\n\nThe mechanism for this is the tool search tool with deferred loading. You mark tools defer_loading: true. They are sent to the API but kept out of context. The model sees only the search tool plus whatever you left resident. When it needs a capability it searches the catalogue across tool names, descriptions, argument names and argument descriptions, and the API returns matching tool_reference blocks that expand into full definitions in place.\n\nThe published figures, with their provenance, since you will be asked:\n\nThe documented decision rule is to use it at ten or more tools, or above 10k tokens of definitions, or when aggregating multiple MCP servers, and to skip it below ten tools or when every tool is used on every request.\n\nNow the part that matters for the rest of this piece. **Tool search optimises for relevance. It says nothing about permission.** It is model-driven, semantically ranked, and nondeterministic in the way retrieval always is. That is what you want for discovery across a wide surface. It is not what you want as the last thing standing between a model and an action that moves money, changes an entitlement, or writes to a system of record.\n\nIf search is your only filter, every privileged tool in the catalogue is one plausible query away from being in context, and its availability is a function of phrasing and embedding proximity. That is not a control, and no reviewer should accept it as one.\n\nUnder a frozen tool list, an agent that can issue a refund at any point in a session can issue one at every point in that session. The available controls were:\n\nLeast privilege, which every other part of the enterprise already runs on, was **inexpressible at the model boundary.** You could ask a model not to reach for a capability. Withholding it and keeping the session meant paying a full cache invalidation every time the answer changed.\n\nRuntime tool gating makes the control structural. The reachable action space becomes a function of verified state.\n\nA generic shape, for a customer-facing transactional agent:\n\n**Session start, identity unverified**\n\nOffered: verify_identity, search_public_kb\n\nWithdrawn: everything account-scoped\n\n**Identity verified**\n\nOffered: get_account, get_order_history, check_eligibility\n\nWithdrawn: verify_identity\n\n**Eligibility check clean**\n\nOffered: modify_order, issue_credit_under_threshold\n\nWithdrawn: check_eligibility\n\n**Change committed**\n\nOffered: send_confirmation\n\nWithdrawn: modify_order, issue_credit_under_threshold\n\n**Value above threshold**\n\nOffered: nothing new\n\nWithdrawn: routed to a human queue\n\nThat flow is an authorisation state machine. Every transition is a decision your application made, from state your application verified, at a moment you can timestamp.\n\nFour properties follow, and they are the ones that get an agentic system through a control review.\n\n**1. Grants become events rather than configuration.** Every addition and removal is a decision you can log: tool name, direction, the state that justified it, the check or actor that produced that state, the turn index. That answers the question reviewers actually ask, which is not “what did the model do” but “what was the model able to do, and who decided that”.\n\n**2. Separation of duties becomes enforceable.** Some tools should never be offered to a model under any state. That belongs in a deny list inside your own code, not in a sentence in a system prompt. A rule such as “no single automated actor both approves and executes above threshold X” maps onto a gating policy and does not map onto prompt text at all.\n\n**3. Blast radius is bounded per turn instead of per session.** The question stops being “what can this agent do” and becomes “what can this agent do right now”. That is a smaller number and a far easier one to defend.\n\n**4. Withdrawal is real, and it is not amnesia.** This is the failure mode to design for. Removing a tool stops it being offered from that point onward. The earlier tool_use and tool_result blocks stay in history, and the model can still reason about a capability it no longer holds. Expect attempts, and expect occasional claims that an action was completed. Two mitigations: align every withdrawal with a clear state transition, and state that transition in a mid-conversation system message (\"the order modification step is complete; modification tools are no longer available\"). Then evaluate for it, because no public benchmark covers this behaviour.\n\nThe documentation warns against placing untrusted content in system messages, because system content carries operator authority. The consequence extends further than the warning states.\n\nIf your gating logic is influenced by retrieved documents, tool output, or model-inferred intent, then **prompt injection becomes privilege escalation.**\n\nAn injected instruction that makes a model produce embarrassing text is a content incident. An injected instruction that persuades your orchestrator to offer the refund tool is a control failure with a number attached. That gap opens the moment capability becomes dynamic.\n\nThe rule short enough for a code review checklist: **gating decisions derive only from trusted application state.** Verified authentication results. Deterministic policy checks executed outside the model. Records read through a path the model did not influence. Never free text the model produced, and never content the model read.\n\nDiscovery and authorisation have different failure modes and now have different primitives. Composing them is the architecture.\n\n**Tool search with ****defer_loading**\n\nDecided by the model, through semantic search. Optimises for relevance and context economy. Fails by misrouting to a plausible wrong call. Weakly auditable, because a ranking is not a justification. Fits wide read-only and low-consequence surfaces.\n\n**tool_addition / ****tool_removal**\n\nDecided by your orchestrator, deterministically. Optimises for policy, authorisation and business process. Fails by denying an action, and the agent replans. Strongly auditable, because every grant is a logged decision. Fits money, entitlements, PII and systems of record.\n\nThe composition rule, in one line: **search decides what the model can find; your broker decides what the model can do.** Do not let the first mechanism stand in for the second.\n\nThat yields a three-tier tool topology worth adopting as a default.\n\n**Tier 1, resident.** The three to five tools used on nearly every turn. Never deferred, never gated. They live in the cached prefix and stay there.\n\n**Tier 2, discoverable.** The long tail of read-only and low-consequence capability, all defer_loading: true. The model finds these itself. Breadth is not a problem here, and this is where the 10,000-tool headroom gets spent.\n\n**Tier 3, gated.** Every write, every irreversible action, every value transfer, every PII-scoped read. Declared up front so the prefix stays stable, but not offered until your broker grants it, and withdrawn as soon as the step completes. Tier 3 should not be reachable by search, because availability here is a policy decision rather than a relevance decision.\n\nOne detail to verify before you commit to a design: confirm whether a tool declared in tools is callable before any tool_addition block refers to it, or whether it must be offered explicitly. The implementable pattern under either semantics is to withdraw the Tier 3 set at the start of the session and grant on verified state. Test it against the beta rather than inferring it from the launch post, including mine.\n\nA sketch of the one component this needs:\n\n```\nclass CapabilityBroker:    \"\"\"Owns the mapping from verified state to the offered tool set.    Emits tool_addition / tool_removal blocks. Logs every decision.    Never reads model output or tool output as an input to a decision.    \"\"\"    def next_tool_changes(self, state) -> list[dict]:            # `state` holds only verified facts: authentication results,            # deterministic policy outcomes, records read through paths            # the model did not influence.            grants, revocations = self.policy.evaluate(state)            for tool in grants:                assert tool not in self.never_offer_to_model   # SoD deny list                self.audit.record(                    action=\"grant\", tool=tool,                    justified_by=state.evidence_for(tool),                    turn=state.turn,                )            # symmetrical logging for revocations            return self.to_blocks(grants, revocations)        def degraded_mode(self, state) -> list[dict]:        # Beta unavailable, or unsupported model or platform:        # resend the tools array for the current tier set and accept        # the cache miss. Correctness must not depend on a beta header.        return self.full_tool_array(state)\n```\n\nTwo properties of that sketch matter more than its details. It is the only component that emits tool changes, so there is one place to audit. And it has a degraded path, because correctness should not depend on a beta header being available on whichever platform you are running on this quarter.\n\n**This does not solve catalogue scale on its own.** Mid-conversation tool changes still require the tool set declared in tools, paid for once in the prefix and then cached. Deferred loading is what handles breadth. Neither replaces the other.\n\n**Beta, and uneven across platforms.** Header-gated, with Bedrock support for tool changes limited to Opus 5. Check current availability, model support and header requirements for your own platform before planning around either feature, including whether tool search requires a beta header where you run.\n\n**The economics are conditional.** If your sessions are short and stateless, cache preservation is a rounding error and the cost argument mostly disappears. The governance argument survives, but the number you take to a budget conversation should come from long-horizon, stateful, high-tool-count work, because that is where it is real.\n\n**You will need evaluations that do not exist yet.** Capability transitions are a new behaviour class. At minimum: correct behaviour on the turn a tool appears, correct behaviour on the turn one is withdrawn, and no claims of having performed an action the model could not perform.\n\nRead this one as governance rather than reliability.\n\nThe mechanism is reasonable. Flagged requests route to another model rather than being blocked. Anthropic expects Opus 5’s cyber classifiers to intervene around 85% less often than Fable 5’s, and in Claude.ai, Claude Code and Claude Cowork, flagged requests fall back to Opus 4.8 by default, with the same fallback available on the API.\n\nThe detail worth pausing on is in the footnotes of the launch post. For the Frontier-Bench v0.1 effort plot, Anthropic states that the results come from an internal run and that Opus 4.8 served as fallback on safety-classifier refusals for both Opus 5 and Fable 5. The share of the plotted result produced by the older model is not given. That is a disclosed limitation on one chart, not a scandal, and the vendor documented it. But it demonstrates the mechanic precisely: once fallbacks are on, a reported number can include work done by a model other than the one named.\n\nWhich is why the engineering position is straightforward:\n\nA reliability feature that hides which model produced a response creates an audit gap, and audit gaps surface at the worst possible time.\n\nThe release cadence makes the point on its own. Fable 5 and Mythos 5 arrived in early June, Sonnet 5 at the end of June, Opus 5 on 24 July. Whatever capability gap you are designing around this month will have moved before your programme ships.\n\nWhat does not move that fast is whether the platform lets you express the controls your business already requires, without discarding the session or the cache every time the answer changes. Capability scoping tied to verified state is one of those primitives, and for the first time it is available at runtime and cheap enough to use per turn.\n\nIt arrived as the second bullet in someone else’s launch post. That is usually where the parts you have to build on are.\n\n[Your Agent Has Too Many Tools, and No Way to Take Any Back](https://pub.towardsai.net/your-agent-has-too-many-tools-and-no-way-to-take-any-back-d05cd29ae169) was originally published in [Towards AI](https://pub.towardsai.net) on Medium, where people are continuing the conversation by highlighting and responding to this story.", "url": "https://wpnews.pro/news/your-agent-has-too-many-tools-and-no-way-to-take-any-back", "canonical_source": "https://pub.towardsai.net/your-agent-has-too-many-tools-and-no-way-to-take-any-back-d05cd29ae169?source=rss----98111c9905da---4", "published_at": "2026-07-27 16:01:02+00:00", "updated_at": "2026-07-27 16:14:53.033570+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "ai-agents", "ai-products", "ai-tools"], "entities": ["Anthropic", "Claude Opus 5", "Claude Fable 5", "VentureBeat", "GitHub", "Slack", "Sentry", "Grafana"], "alternates": {"html": "https://wpnews.pro/news/your-agent-has-too-many-tools-and-no-way-to-take-any-back", "markdown": "https://wpnews.pro/news/your-agent-has-too-many-tools-and-no-way-to-take-any-back.md", "text": "https://wpnews.pro/news/your-agent-has-too-many-tools-and-no-way-to-take-any-back.txt", "jsonld": "https://wpnews.pro/news/your-agent-has-too-many-tools-and-no-way-to-take-any-back.jsonld"}}