StuntDouble Documentation

Tool Mocking Framework for AI Agent Testing


What is StuntDouble?

StuntDouble is a Python framework for mocking AI agent tool calls. Just like a stunt double performs risky scenes in place of an actor, StuntDouble lets you test your AI agents without the risk, cost, and unpredictability of production APIs.

┌─────────────────────────────────────────────────────────────────────────────┐
│                                                                             │
│     Production                              Testing with StuntDouble        │
│     ──────────                              ────────────────────────        │
│                                                                             │
│     Agent ──▶ Real API ──▶ $$$              Agent ──▶ StuntDouble ──▶ Mock  │
│               ↓                                       ↓                     │
│          Slow, Flaky,                            Fast, Reliable,            │
│          Unpredictable                           Deterministic              │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Motivation

The Problem

AI agents rely heavily on external tools—APIs for customer data, billing systems, communication services, and more. Testing these agents presents unique challenges:

Challenge

Impact

API Costs

Every test run hits real APIs, accumulating costs

Slow Execution

Network latency makes test suites painfully slow

Non-Deterministic

Real data changes, causing flaky tests

Environment Dependencies

Tests require production-like environments

Risk of Side Effects

Tests might accidentally send emails, create invoices

The Solution

StuntDouble provides transparent tool mocking that intercepts tool calls and returns controlled responses:

┌─────────────────────────────────────────────────────────────────────────────┐
│                                                                             │
│                        Before StuntDouble                                   │
│                        ─────────────────                                    │
│                                                                             │
│     ┌─────────┐     ┌──────────────┐     ┌────────────────┐                │
│     │  Agent  │────▶│ list_bills() │────▶│  Real API      │                │
│     └─────────┘     └──────────────┘     │  • Slow        │                │
│                                          │  • Costly      │                │
│                                          │  • Flaky       │                │
│                                          └────────────────┘                │
│                                                                             │
│                        After StuntDouble                                    │
│                        ─────────────────                                    │
│                                                                             │
│     ┌─────────┐     ┌──────────────┐     ┌────────────────┐                │
│     │  Agent  │────▶│ StuntDouble  │────▶│  Mock Function │                │
│     └─────────┘     └──────────────┘     │  • Instant     │                │
│                           │              │  • Free        │                │
│                           │              │  • Controlled  │                │
│                           ▼              └────────────────┘                │
│                     scenario_metadata?                                      │
│                     ├── YES ──▶ Return mock                                │
│                     └── NO  ──▶ Call real tool                             │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Key Features

Feature

Description

🚀 LangGraph Native

Per-invocation mocking via RunnableConfig—no global state

Transparent Mocking

Wrap tools once, toggle between real and mock

🔄 Zero Code Changes

Agent code remains unchanged, production-ready

🔍 Smart Input Matching

Operators like $gt, $in, $regex for conditional mocking

Dynamic Outputs

Placeholders for {{now}}, {{input.id}}, {{uuid}}

🔗 Fluent Builder API

Chainable mock registration: mock("tool").when(...).returns(...)

📝 Call Recording

Capture and assert on tool calls with CallRecorder

🔐 Signature Validation

Catch mock/tool signature mismatches at registration or runtime

🪞 MCP Tool Mirroring

Auto-generate mocks from MCP server schemas

🔑 Context-Aware Mocks

Access runtime config (user ID, headers) in mock factories

Getting Started

Quick Example

Best for LangGraph agents. Per-invocation mocking via RunnableConfig.

from langgraph.prebuilt import ToolNode
from stuntdouble import (
    mockable_tool_wrapper,
    default_registry,
    inject_scenario_metadata,
)

mock = default_registry.mock  # Fluent builder on default registry

# Register mocks on the default registry (fluent API)
mock("list_bills").returns({"bills": [{"id": "B001", "amount": 500}]})

# Build graph with native ToolNode + mockable wrapper
builder.add_node("tools", ToolNode(tools, awrap_tool_call=mockable_tool_wrapper))

# Invoke with mocks via config
config = inject_scenario_metadata({}, {
    "scenario_id": "landing-page-demo"
})
result = await graph.ainvoke(state, config=config)

Benefits:

  • ✅ Fully concurrent—each request gets its own mocks

  • ✅ No global state or environment variables

  • ✅ Native ToolNode integration—minimal code changes

  • ✅ Call recording for test assertions

  • ✅ Signature validation to catch config errors early

LangGraph Integration Guide

Auto-Generate Mocks from MCP Servers

Already using an MCP server? StuntDouble can auto-discover its tools and generate mock implementations, which you can then use in your LangGraph agent workflow:

from stuntdouble.mirroring import ToolMirror

mirror = ToolMirror()
mirror.mirror(["python", "-m", "my_mcp_server"])
tools = mirror.to_langchain_tools()

MCP Mirroring Guide

Installation

# Using uv (recommended)
uv add stuntdouble

# Using pip
pip install stuntdouble

# Using Poetry
poetry add stuntdouble

For MCP mirroring support, install the optional extra:

pip install "stuntdouble[mcp]"

Documentation Structure

Support

For questions or feedback, please open an issue on the repository.