Documentation Index
Fetch the complete documentation index at: https://docs.benchspan.com/llms.txt
Use this file to discover all available pages before exploring further.
The Anthropic SDK doesn’t have lifecycle hooks, so Benchspan wraps your Claude call with a decorator (Python) or wrapCall helper (TypeScript). Every user and tool message is scanned before the request goes out.
Python
Install
pip install benchspan anthropic
Decorate the call
from benchspan import BenchGuard, InjectionDetectedError
from anthropic import Anthropic
guard = BenchGuard(api_key="ag_live_...", agent="claude-app")
client = Anthropic()
@guard.wrap
def ask_claude(messages):
return client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=messages,
)
try:
response = ask_claude(messages)
except InjectionDetectedError as e:
print(f"Blocked: {e.result.verdict}, score={e.result.score:.4f}")
Use @guard.wrap_async for an async def function.
TypeScript
Install
npm install @benchspan/sdk @anthropic-ai/sdk
Wrap the call
import { BenchGuard, InjectionDetectedError } from "@benchspan/sdk";
import Anthropic from "@anthropic-ai/sdk";
const guard = new BenchGuard({ apiKey: "ag_live_...", agent: "claude-app" });
const client = new Anthropic();
try {
const response = await guard.wrapCall(messages, () =>
client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
messages,
}),
);
} catch (e) {
if (e instanceof InjectionDetectedError) {
console.log(`Blocked: score=${e.result.score.toFixed(4)}`);
}
}
Claude’s tool-use loop means tool outputs flow back into the messages array as tool_result blocks. Pass those through as role: "tool" messages so Benchspan scans them:
# After the first Claude call with tools
for block in response.content:
if block.type == "tool_use":
tool_output = run_tool(block.name, block.input)
messages.append({
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": block.id,
"content": tool_output,
}],
})
# Next ask_claude() call will scan the tool_output before sending
response = ask_claude(messages)
For scanning tool-result blocks specifically, the simplest pattern is an explicit scan right after the tool runs:
tool_output = run_tool(block.name, block.input)
guard.scan(tool_output, role="tool", source=block.name) # raises on injection
messages.append({...tool_result block...})