AI Codex
Claude APIimplementation

Define tools mid-conversation: the inline-tools beta and how it keeps your cache warm

In brief

Since September 22, 2026, a mid-conversation system message can carry a full tool definition — or a whole MCP server's toolset — with the inline-tools-2026-09-15 beta header. You can add a tool, change its schema, or connect a server partway through a session without editing the tools array, so the prompt cache and preserved thinking stay intact. Working code and the rules that trip people up.

8 min read·Tool Use

Contents

Sign in to save

On September 22, 2026, alongside Claude Opus 5.5, Anthropic added a beta that lets you define a tool inside the conversation itself. With the inline-tools-2026-09-15 beta header, a tool_addition block in a mid-conversation system message can hold a complete tool definition. With the mcp-client-2026-09-15 header as well, it can connect an MCP server's whole toolset.

This article covers why that matters, the request shapes, and the placement rules that cause most 400 errors.

The problem it solves

The Messages API sends the full conversation on every request. The tools array sits near the start of that request. Two things depend on the start staying identical from one turn to the next:

  1. Prompt caching. The cache matches on an exact prefix. Change one character in tools and every token after it is reprocessed at full price. On a long agent session that can be most of the bill. See prompt caching.
  2. Preserved thinking. On Opus 5.5 and Fable 5.1 (for accounts created on or after August 31, 2026), the API rejects a replayed thinking block if anything before it changed, including tools.

So agents that discover mid-session that they need a new tool had two bad options: define every possible tool up front (slower, costlier, and more ways for the model to pick the wrong one), or edit tools and pay for a cache miss.

Mid-conversation tool changes, in beta since July (mid-conversation-tool-changes-2026-07-01), partly fixed this. You could add or remove tools between turns, but only by reference: the tool had to be declared already, for example as a deferred tool. The new beta removes that limit. The full definition can arrive in the message.

The request shape

A mid-conversation system message is a {"role": "system"} entry in messages. To add a tool inline, its content is a tool_addition block whose tool is a tool_definition:

import anthropic

client = anthropic.Anthropic()

db_query = {
    "name": "db_query",
    "description": "Run a read-only SQL query against the analytics database.",
    "input_schema": {
        "type": "object",
        "properties": {"sql": {"type": "string"}},
        "required": ["sql"],
    },
}

response = client.beta.messages.create(
    model="claude-opus-5-5",
    max_tokens=4096,
    betas=["inline-tools-2026-09-15"],
    tools=[],  # unchanged from earlier turns, so the cached prefix still matches
    messages=[
        {"role": "user", "content": "How many orders shipped yesterday?"},
        {
            "role": "system",
            "content": [
                {
                    "type": "tool_addition",
                    "tool": {"type": "tool_definition", "definition": db_query},
                }
            ],
        },
    ],
)

On the next turn you send the same messages plus the new ones. The system message stays where it is, in history, so the tool remains available from that point on.

Removing a tool

Removal is by reference, using the July beta's tool_removal block:

{
    "role": "system",
    "content": [
        {"type": "tool_removal", "tool": {"type": "tool_reference", "name": "db_query"}}
    ],
}

Changing a tool's schema

To change a tool, add a new definition under the same name in a later system message. Use this when a user grants a new permission partway through ("you can now write, not just read") or when you move a server tool to a newer version. Nothing earlier in the conversation changes, so the cache and thinking chain survive.

Adding an MCP server mid-conversation

With both beta headers, the definition can be an MCP toolset. Declare the server in mcp_servers as usual, then switch it on in the conversation when the task calls for it:

response = client.beta.messages.create(
    model="claude-opus-5-5",
    max_tokens=4096,
    betas=["inline-tools-2026-09-15", "mcp-client-2026-09-15"],
    mcp_servers=[
        {
            "type": "url",
            "url": "https://mcp.example.com/calendar",
            "name": "calendar",
            "authorization_token": CALENDAR_TOKEN,
        }
    ],
    tools=[],
    messages=[
        {"role": "user", "content": "What's on my calendar tomorrow?"},
        {
            "role": "system",
            "content": [
                {
                    "type": "tool_addition",
                    "tool": {
                        "type": "tool_definition",
                        "definition": {"type": "mcp_toolset", "mcp_server_name": "calendar"},
                    },
                }
            ],
        },
    ],
)

for block in response.content:
    if block.type == "mcp_tool_listing":
        print(block.mcp_server_name, [t.name for t in block.tools])

The response includes an mcp_tool_listing block recording which tools the server returned. Keep it in history like any other content block.

Placement rules

Most errors come from putting the system message in the wrong spot. It must:

  • come immediately after a user message (a message holding tool_result blocks counts),
  • come before an assistant message, or be the last entry,
  • not be the first entry in messages,
  • not sit between a tool_use and its tool_result.

In an agent loop, the natural spot is right after you append the tool results for a turn, before you call the API again.

Limits

After any message, the request fails with available_tools_limit_exceeded if you exceed 10,000 tools defined after the first user message, 10,000 deferred tools, or 4 MB of tool definitions. Few applications will hit these, but an agent that adds a tool per step in a long loop can. Remove tools you no longer need.

Model support and availability

Mid-conversation system messages work on Fable 5.1, Mythos 5.1, Fable 5, Mythos 5, Opus 5.5, Opus 5, and Opus 4.8. They are not available on Sonnet 5. The inline-tools beta is on the Claude API.

When to use it

  • Progressive disclosure. Start an agent with three tools and add more as the task narrows. Fewer tools per turn means fewer wrong picks and a smaller prompt.
  • Permission escalation. Add a write tool only after a human approves it, and remove it when the step is done.
  • Late-connected systems. Connect the calendar or CRM server only when a user asks about it, instead of paying for its tool list on every turn.

Pair this with compaction on demand for long sessions and per-message effort for hard steps. All three follow the same rule: append to the conversation instead of editing it, and the cache keeps paying off.

Related tools

Weekly brief

For people actually using Claude at work.

Each week: one thing Claude can do in your work that most people haven't figured out yet — plus the failure modes to avoid. No tutorials. No hype.

No spam. Unsubscribe anytime.

What to read next

Picked for where you are now

All articles →