Mock Data Format Reference

Complete reference for StuntDouble’s data-driven mock format, including input matching operators and dynamic placeholders resolved by register_data_driven() and DataDrivenMockFactory.


Basic Structure

Single Case

{
  "tool_name": [
    {"output": {"key": "value"}}
  ]
}

Multiple Cases with Input Matching

{
  "tool_name": [
    {"input": {"field": "match_value"}, "output": {"result": "matched"}},
    {"input": {"field": {"$gt": 100}}, "output": {"result": "large"}},
    {"output": {"result": "default"}}
  ]
}

Case Fields

Field

Type

Required

Description

input

object

No

Pattern to match. null or omitted = catch-all

output

any

Yes

Value to return (supports placeholders)


Input Matching Operators

Use MongoDB-style operators for flexible pattern matching.

Comparison Operators

Operator

Description

Example

$eq

Exact equality (default)

{"status": {"$eq": "active"}}

$ne

Not equal

{"status": {"$ne": "deleted"}}

$gt

Greater than

{"amount": {"$gt": 1000}}

$gte

Greater than or equal

{"count": {"$gte": 10}}

$lt

Less than

{"age": {"$lt": 18}}

$lte

Less than or equal

{"priority": {"$lte": 5}}

Examples:

{
  "get_bills": [
    {
      "input": {"amount": {"$gt": 5000}},
      "output": {"priority": "high"}
    },
    {
      "input": {"amount": {"$lte": 100}},
      "output": {"priority": "low"}
    }
  ]
}

Set Operators

Operator

Description

Example

$in

Value in list

{"status": {"$in": ["active", "pending"]}}

$nin

Value not in list

{"type": {"$nin": ["deleted", "archived"]}}

Examples:

{
  "get_customer": [
    {
      "input": {"tier": {"$in": ["gold", "platinum"]}},
      "output": {"discount": 0.2}
    },
    {
      "input": {"tier": {"$nin": ["free", "trial"]}},
      "output": {"discount": 0.1}
    }
  ]
}

String Operators

Operator

Description

Example

$contains

String contains substring

{"name": {"$contains": "Corp"}}

$regex

Regular expression match

{"id": {"$regex": "^CUST-\\d+"}}

Examples:

{
  "search": [
    {
      "input": {"query": {"$contains": "invoice"}},
      "output": {"category": "billing"}
    },
    {
      "input": {"id": {"$regex": "^VIP-[A-Z]{3}"}},
      "output": {"tier": "vip"}
    }
  ]
}

Existence Operator

Operator

Description

Example

$exists

Key exists (or not)

{"optional_field": {"$exists": true}}

Examples:

{
  "create_invoice": [
    {
      "input": {"discount_code": {"$exists": true}},
      "output": {"discount_applied": true}
    },
    {
      "input": {"discount_code": {"$exists": false}},
      "output": {"discount_applied": false}
    }
  ]
}

Combined Operators

Multiple operators on the same field use AND logic:

{
  "get_products": [
    {
      "input": {
        "price": {"$gte": 100, "$lt": 500}
      },
      "output": {"category": "mid-range"}
    }
  ]
}

Multiple fields also use AND logic:

{
  "get_orders": [
    {
      "input": {
        "status": "pending",
        "amount": {"$gt": 1000}
      },
      "output": {"priority": "urgent"}
    }
  ]
}

Dynamic Placeholders

Use {{placeholder}} syntax for dynamic values in outputs.

Timestamp Placeholders

Placeholder

Description

Example Output

{{now}}

Current ISO timestamp

2025-01-04T10:30:00

{{today}}

Current date

2025-01-04

{{now + Nd}}

N days from now

2025-01-11 (7 days later)

{{now - Nd}}

N days ago

2024-12-05 (30 days ago)

{{now + Nh}}

N hours from now

Time + hours

{{now + Nw}}

N weeks from now

Date + weeks

{{now + NM}}

N months from now

Date + ~30*N days

{{now + Ny}}

N years from now

Date + ~365*N days

Boundary Timestamps:

Placeholder

Description

{{start_of_day}}

Midnight today

{{end_of_day}}

23:59:59 today

{{start_of_week}}

Monday 00:00:00

{{end_of_week}}

Sunday 23:59:59

{{start_of_month}}

1st of month 00:00:00

{{end_of_month}}

Last day of month 23:59:59

{{start_of_year}}

Jan 1 00:00:00

{{end_of_year}}

Dec 31 23:59:59

Examples:

{
  "create_invoice": [{
    "output": {
      "created_at": "{{now}}",
      "due_date": "{{now + 30d}}",
      "fiscal_year_start": "{{start_of_year}}"
    }
  }]
}

Input Reference Placeholders

Placeholder

Description

{{input.field}}

Value from tool input

{{input.field | default(value)}}

With default if missing

Config Reference Placeholders

Placeholder

Description

{{config.field}}

Value from merged RunnableConfig.configurable data

{{config.field | default(value)}}

With default if missing

{{config.*}} placeholders resolve from the merged configurable data passed to the data-driven mock. If both configurable.field and configurable.config_data.field exist, config_data takes precedence.

Examples:

{
  "get_customer": [{
    "output": {
      "id": "{{input.customer_id}}",
      "query_time": "{{now}}",
      "name": "Customer {{input.customer_id}}"
    }
  }]
}

With defaults:

{
  "search": [{
    "output": {
      "query": "{{input.query | default('*')}}",
      "limit": "{{input.limit | default(10)}}"
    }
  }]
}

Generator Placeholders

Placeholder

Description

Example Output

{{uuid}}

Random UUID

a1b2c3d4-e5f6-7890-abcd-ef1234567890

{{random_int(min, max)}}

Random integer

42 (for range 1-100)

{{random_float(min, max)}}

Random float (2 decimals)

47.53

{{choice('a', 'b', 'c')}}

Random choice from list

b

{{sequence('prefix')}}

Incrementing ID

prefix-001, prefix-002

{{random_string(length)}}

Random alphanumeric

xK9mP2qR

Examples:

{
  "create_invoice": [{
    "output": {
      "id": "{{uuid}}",
      "invoice_number": "{{sequence('INV')}}",
      "verification_code": "{{random_string(8)}}",
      "priority_score": "{{random_int(1, 10)}}"
    }
  }],
  "get_status": [{
    "output": {
      "status": "{{choice('pending', 'processing', 'complete')}}",
      "progress": "{{random_float(0, 100)}}"
    }
  }]
}

Complete Examples

Customer Service Mock

{
  "get_customer": [
    {
      "input": {"customer_id": {"$regex": "^VIP"}},
      "output": {
        "id": "{{input.customer_id}}",
        "tier": "platinum",
        "discount": 0.25,
        "account_manager": "dedicated"
      }
    },
    {
      "input": {"customer_id": {"$regex": "^CORP"}},
      "output": {
        "id": "{{input.customer_id}}",
        "tier": "enterprise",
        "discount": 0.15,
        "account_manager": "team"
      }
    },
    {
      "output": {
        "id": "{{input.customer_id | default('UNKNOWN')}}",
        "tier": "standard",
        "discount": 0,
        "account_manager": null
      }
    }
  ]
}

Invoice Creation Mock

{
  "create_invoice": [
    {
      "input": {"amount": {"$gt": 10000}},
      "output": {
        "id": "{{uuid}}",
        "invoice_number": "{{sequence('INV')}}",
        "amount": "{{input.amount}}",
        "customer_id": "{{input.customer_id}}",
        "created_at": "{{now}}",
        "due_date": "{{now + 45d}}",
        "status": "pending_approval",
        "requires_approval": true
      }
    },
    {
      "output": {
        "id": "{{uuid}}",
        "invoice_number": "{{sequence('INV')}}",
        "amount": "{{input.amount}}",
        "customer_id": "{{input.customer_id}}",
        "created_at": "{{now}}",
        "due_date": "{{now + 30d}}",
        "status": "created",
        "requires_approval": false
      }
    }
  ]
}

Bills Query Mock

{
  "list_bills": [
    {
      "input": {"status": "overdue", "amount": {"$gt": 5000}},
      "output": {
        "bills": [
          {"id": "B-001", "amount": 7500, "status": "overdue", "days_overdue": 45},
          {"id": "B-002", "amount": 12000, "status": "overdue", "days_overdue": 30}
        ],
        "total_overdue": 19500,
        "priority": "CRITICAL"
      }
    },
    {
      "input": {"status": "overdue"},
      "output": {
        "bills": [
          {"id": "B-003", "amount": 250, "status": "overdue", "days_overdue": 5}
        ],
        "total_overdue": 250,
        "priority": "normal"
      }
    },
    {
      "input": {"status": {"$in": ["paid", "processing"]}},
      "output": {
        "bills": [],
        "message": "No action required"
      }
    },
    {
      "output": {
        "bills": [],
        "message": "No matching bills"
      }
    }
  ]
}

Matching Precedence

Cases are evaluated in order. First match wins:

{
  "tool": [
    {"input": {"specific": "value"}, "output": "first"},   // Checked first
    {"input": {"field": {"$gt": 0}}, "output": "second"},  // Checked second
    {"output": "default"}                                   // Catch-all (always last)
  ]
}

Best practice: Order cases from most specific to least specific, with catch-all last.

No-Match Behavior

When no case matches and no catch-all is present, the behavior depends on how the mock was registered:

Configuration

No-match result

echo_input=True

Returns the input kwargs as-is

fallback=value

Returns the fallback value

Catch-all case (no input key)

Returns catch-all output

None of the above

Raises InputNotMatchedError

InputNotMatchedError ensures broken mock specs are caught early rather than producing plausible-looking but incorrect data. To opt into lenient behavior, add a catch-all case or set fallback= when registering.


Validation

Required Fields

  • output is always required

  • input is optional (omit for catch-all)

Type Coercion

Numeric comparisons support string-to-number coercion:

{
  "input": {"amount": {"$gt": 1000}},  // Works with "1500" or 1500
  "output": {...}
}

Null Handling

  • null input pattern = match any input

  • $exists: false = field is missing or null

  • $exists: true = field is present and not null