Skip to main content
Best for: teams already using the Claude Agent SDK and wanting native protection without changing runtimes.

Install

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

Net-new VerifiedX code

This is the actual VerifiedX delta in an existing Claude Agent SDK query setup.
from verifiedx import claude_query, init_verifiedx

verifiedx = init_verifiedx()

async for message in claude_query(
    prompt=prompt,
    verifiedx=verifiedx,
    options=options,
):
    ...
That is the important part. Your existing prompt, tools, MCP servers, system prompt, permission mode, and max-turn configuration stay the same.
In Python, if you prefer to wrap an existing callable instead of swapping imports, use attach_claude_query(...). In TypeScript, withVerifiedXClaudeQuery(...) is the wrapper surface.
Your native tool surface is the config. VerifiedX uses your existing tool names, descriptions, schemas, MCP servers, built-ins, and approval flow as the source of truth for what to preflight.

Full example

import os

from claude_agent_sdk import ClaudeAgentOptions, create_sdk_mcp_server, tool
from verifiedx import claude_query, init_verifiedx

@tool(
    "lookup_workflow",
    "Look up an internal workflow before changing state.",
    {"workflow_id": str},
)
async def lookup_workflow(args: dict[str, str]) -> dict:
    return {
        "content": [
            {
                "type": "text",
                "text": '{"ok": true, "workflow": {"workflow_id": "%s", "status": "pending_review"}}'
                % args["workflow_id"],
            }
        ]
    }

@tool(
    "set_workflow_status",
    "Update internal workflow status.",
    {"workflow_id": str, "status": str, "reason": str},
)
async def set_workflow_status(args: dict[str, str]) -> dict:
    return {
        "content": [
            {
                "type": "text",
                "text": (
                    '{"ok": true, "workflow_updated": {"workflow_id": "%s", "status": "%s", "reason": "%s"}}'
                    % (args["workflow_id"], args["status"], args["reason"])
                ),
            }
        ]
    }

support_ops = create_sdk_mcp_server(
    "support_ops",
    tools=[lookup_workflow, set_workflow_status],
)

verifiedx = init_verifiedx()

options = ClaudeAgentOptions(
    tools=[],
    mcp_servers={"support_ops": support_ops},
    system_prompt="Use tools instead of prose for operational work.",
    permission_mode="bypassPermissions",
    model=os.environ.get("ANTHROPIC_MODEL", "claude-sonnet-4-6"),
    max_turns=20,
)

async for message in claude_query(
    prompt="CASE-7003: For workflow WF-1002, inspect it and then update it to awaiting_human because billing verification is missing.",
    verifiedx=verifiedx,
    options=options,
):
    print(message)
Do not use raw install_runtime(...) or bindHarness(...) for this path. Keep the native Claude Agent SDK query surface and wrap that directly.

Composed systems

If this Claude run 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 Claude 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):
    async for message in claude_query(
        prompt=prompt,
        verifiedx=verifiedx,
        options=options,
    ):
        ...
Upstream context is supporting workflow context from outside the current run. It is not proof that this run already executed any local action.

What the adapter already captures

Once attached, VerifiedX appends native Claude Agent SDK hooks into your existing query options and protects the SDK surface you already use. That includes:
  • Prompt submission through UserPromptSubmit
  • Tool boundaries through PreToolUse, PostToolUse, and PostToolUseFailure
  • Permission flow through PermissionRequest and PermissionDenied
  • Stop events through Stop
  • Lifecycle summaries through Notification, PreCompact, SessionStart, SessionEnd, StopFailure, SubagentStart, and SubagentStop
  • Custom Claude Agent SDK tools and MCP-backed tools
  • Mutating built-ins such as Bash, Write, Edit, MultiEdit, and NotebookEdit as direct protected boundaries
  • Read-like built-ins such as Read, Glob, Grep, WebFetch, and WebSearch as support inputs in run history
Read stays a read-only support input here. It is captured truthfully as file_read, not misclassified as a memory write.

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 step is blocked during PreToolUse, VerifiedX returns native Claude hook output with a block decision and deny signal instead of throwing. The side effect does not execute, and Claude gets the reason plus safe-next-step guidance so it can keep moving toward the same goal when possible.

Production-style validation coverage

The Claude Agent SDK validation paths in this repo cover real workflows including:
  • Clean durable memory writes
  • Clean record mutations
  • Clean internal workflow updates
  • Multi-step internal runs across retrieval, mutation, memory, and internal notification
  • External email attempts that replan into safer internal Slack fallbacks
  • Repeated adversarial external-email attempts that should not keep pushing the same unsafe action
  • Built-in Bash local journal updates
  • Built-in Write local note creation
  • Built-in Edit local note mutation after a Read prerequisite step

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 direct Claude / Anthropic adapter outside the Claude Agent SDK, see the Anthropic pages.