Skip to main content
Best for: teams using Claude through the Anthropic SDK directly.

Install

pip install verifiedx
This page assumes your app already uses anthropic in Python or @anthropic-ai/sdk in TypeScript.

Net-new VerifiedX code

This is the actual VerifiedX delta in an existing Claude Messages tool loop.
from verifiedx import (
    attach_anthropic,
    create_anthropic_tool_dispatcher,
    init_verifiedx,
)
from verifiedx.anthropic_direct import (
    assistant_message_param as anthropic_assistant_message_param,
)

verifiedx = init_verifiedx()
client = attach_anthropic(client, verifiedx=verifiedx)
dispatch_tool_uses = create_anthropic_tool_dispatcher(
    verifiedx=verifiedx,
    tools=TOOLS,
    tool_handlers=HANDLERS,
)

# Inside your existing loop:
messages.append(anthropic_assistant_message_param(message))
tool_results = dispatch_tool_uses(message)
if tool_results:
    messages.append({"role": "user", "content": tool_results})
That is the important part. The rest of the full example below is your normal Anthropic client, tool-definition, tool-handler, and message-loop code that you likely already have.
Your native tool surface is the config. VerifiedX uses your existing tool names, descriptions, schemas, and native Claude Messages tool loop as the source of truth for what to preflight. If you want explicit actions and memories dictionaries, use the raw runtime instead.

Full example

import os

from anthropic import Anthropic
from verifiedx import (
    attach_anthropic,
    create_anthropic_tool_dispatcher,
    init_verifiedx,
)
from verifiedx.anthropic_direct import (
    assistant_message_param as anthropic_assistant_message_param,
)

TOOLS = [
    {
        "name": "lookup_workflow",
        "description": "Look up an internal workflow before changing state.",
        "input_schema": {
            "type": "object",
            "properties": {"workflow_id": {"type": "string"}},
            "required": ["workflow_id"],
        },
    },
    {
        "name": "set_workflow_status",
        "description": "Update internal workflow status.",
        "input_schema": {
            "type": "object",
            "properties": {
                "workflow_id": {"type": "string"},
                "status": {"type": "string"},
                "reason": {"type": "string"},
            },
            "required": ["workflow_id", "status", "reason"],
        },
    },
]

def lookup_workflow(args):
    return {
        "ok": True,
        "workflow": {
            "workflow_id": args["workflow_id"],
            "status": "pending_review",
        },
    }

def set_workflow_status(args):
    return {
        "ok": True,
        "workflow_updated": {
            "workflow_id": args["workflow_id"],
            "status": args["status"],
            "reason": args["reason"],
        },
    }

verifiedx = init_verifiedx()
client = attach_anthropic(
    Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"]),
    verifiedx=verifiedx,
)

dispatch_tool_uses = create_anthropic_tool_dispatcher(
    verifiedx=verifiedx,
    tools=TOOLS,
    tool_handlers={
        "lookup_workflow": lookup_workflow,
        "set_workflow_status": set_workflow_status,
    },
)

messages = [
    {
        "role": "user",
        "content": "Update workflow WF-1002 to awaiting_human because billing verification is missing.",
    }
]

while True:
    message = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1200,
        system="Use tools instead of prose for operational work.",
        messages=messages,
        tools=TOOLS,
    )

    messages.append(anthropic_assistant_message_param(message))

    tool_results = dispatch_tool_uses(message)
    if not tool_results:
        break

    messages.append({"role": "user", "content": tool_results})
Do not use raw install_runtime(...) or bindHarness(...) for this path. Keep the native Anthropic Messages API surface and use the Anthropic direct adapter.

Composed systems

If this Claude Messages loop is part of a larger multi-agent or agent+human workflow, pass upstream context into VerifiedX so the current run has better system and situational awareness before it takes a high-impact action. This is useful when a supervisor agent, parent workflow, or human reviewer already has context that the current run should use before taking action. VerifiedX does not require a fixed schema for this. Pass the upstream context you already have in any JSON-serializable shape.
upstream = {
    "source": "workflow_supervisor",
    "workflow_id": "WF-2203",
    "approval_status": "approved_with_follow_up",
    "human_review": {
        "reviewer": "ops_lead",
        "result": "approved",
    },
    "prior_agent_output": {
        "summary": "Billing verification is complete.",
    },
}

with verifiedx.with_upstream_context(upstream):
    message = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1200,
        system="Use tools instead of prose for operational work.",
        messages=messages,
        tools=TOOLS,
    )

    tool_results = dispatch_tool_uses(message)
Upstream context is supporting workflow context from outside the current run. It is not proof that this run already executed any local action.

Async tool handlers

If your tool handlers are async, use the async dispatcher in Python:
tool_results = await dispatch_tool_uses.async_dispatch(message)
In TypeScript, the dispatcher is already async:
const toolResults = await dispatchToolUses(message);

Streaming

The adapter works with the normal Anthropic streaming surfaces too:
  • client.messages.create(...)
  • client.messages.stream(...)
  • client.messages.create(..., stream=True) in Python
  • client.messages.create({ ..., stream: true }) in TypeScript
That includes native tool-history capture from streamed tool_use output while preserving the native stream shape.

What the adapter already captures

Once attached, VerifiedX already captures and protects the native Anthropic Messages surface, including:
  • Native tool_use history
  • Native server_tool_use history
  • Client-executed custom tools through the Anthropic tool dispatcher
  • Built-in mutating memory, text-editor, and bash tool uses when present
  • Prompt context from the Messages window across turns
  • Normal continuation turns in direct tool loops
  • Managed and raw streaming tool selections
Provider-executed server tools such as native web fetch, web search, code execution, and tool search stay in run history as native support inputs. You do not dispatch those yourself.

What to expect at runtime

Protected boundaries can return:
  • allow
  • allow_with_warning
  • replan_required
  • goal_fail_terminal
Every outcome includes a structured decision receipt. If a client-side tool is replanned, the side effect does not execute. The dispatcher returns Anthropic tool_result blocks containing the blocked result shape, including ok: false, blocked: true, boundary_outcome, safe_next_steps, and decision_receipt, so Claude can keep moving toward the same goal safely.

Pricing note

One protected action check equals one real boundary preflight. Taint, event ingest, execution reports, and decision reads are all included at that price. The Free Sandbox includes every language, provider, framework, and adapter. VerifiedX does not replace your orchestrator or human workflow. It returns receipts your system can keep local, route downstream, or pass upstream.
For the raw runtime reference, see the Python SDK and TypeScript SDK. For the Claude Agent SDK surface, see the Claude Agent SDK page.