Anthropic

Wrap your Anthropic client with Rune to scan all tool use blocks in Claude's responses. Same API, same types, with security added transparently.

Installation

Terminalbash
pip install runesec[anthropic]

Quick Start

agent.pypython
from anthropic import Anthropic
from rune import Shield
from rune.integrations.anthropic import shield_client

shield = Shield(api_key="rune_live_xxx")

# Wrap the client — transparent, same API
client = shield_client(
    Anthropic(),
    shield=shield,
    agent_id="analysis-agent",
    agent_tags=["analysis", "prod"],
)

# Use exactly as before
response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Analyze this dataset"}],
    tools=[...],
)

What Gets Scanned

Claude uses tool_use content blocks for function calls. Rune intercepts these and scans:

tool_use blocks

Each tool_use block's name and input parameters are scanned for injection, command injection, and policy violations.

tool_result content

When you send tool results back via tool_result messages, Rune scans them for secrets, PII, and indirect injection.

Text responses

Claude's text content blocks are scanned for data leaks before reaching the user.

Agentic Loop Pattern

For agents that run Claude in a loop (calling tools until the task is complete), the wrapper automatically scans every iteration:

agentic_loop.pypython
messages = [{"role": "user", "content": task}]

while True:
    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=4096,
        messages=messages,
        tools=tools,
    )
    # Rune scans tool_use blocks in each response automatically

    if response.stop_reason == "end_turn":
        break

    # Execute tools and add results
    for block in response.content:
        if block.type == "tool_use":
            result = execute_tool(block.name, block.input)
            messages.append({"role": "assistant", "content": response.content})
            messages.append({
                "role": "user",
                "content": [{"type": "tool_result", "tool_use_id": block.id, "content": result}],
            })
            # Rune scans tool_result content too

Configuration

Optionspython
client = shield_client(
    Anthropic(),
    shield=shield,
    agent_id="my-agent",             # Required: unique identifier
    agent_tags=["prod"],             # Optional: for policy targeting
    block_on_error=False,            # Optional: fail open if Rune unreachable
)

Complete Runnable Example

Copy, paste, and run to verify your Anthropic integration:

anthropic_rune_test.pypython
import os
assert os.environ.get("RUNE_API_KEY"), "Set RUNE_API_KEY"
assert os.environ.get("ANTHROPIC_API_KEY"), "Set ANTHROPIC_API_KEY"

from anthropic import Anthropic
from rune import Shield
from rune.integrations.anthropic import shield_client

shield = Shield()
client = shield_client(Anthropic(), shield=shield, agent_id="anthropic-test", agent_tags=["test"])

response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=256,
    messages=[{"role": "user", "content": "Say hello in French"}],
)
print("Response:", response.content[0].text)
print("Stats:", shield.stats)

Next Steps