dystopic docs is in beta — content is actively being added.
dystopic
Reference

Execution modes

The per-tool Simulated / Executed / Live axis — where a tool's response comes from, the public↔SDK-helper↔wire mapping, the legacy aliases, and how default_execution_mode is validated.

Every tool a ported agent can call carries an execution mode. The mode answers exactly one question: where does the tool's response come from? Nothing else about the tool — its input_schema, its ledger adapter, its topology — is decided here. This page is the canonical home for the three modes, the names they go by in public copy, in the SDK, and on the wire, and the rules the platform enforces when you set them.

The axis is a per-tool declaration on a tools_schema entry (default_execution_mode). It is verified against the SDK helpers in dystopic.odyssey.tools and the validator in apps/api/app/schemas/agent.py.

The three modes

There are exactly three declared modes. "Native execution" — an agent running its own un-proxied code in the sandbox — is not a fourth mode; it's simply what happens when a call is never declared or proxied at all.

Public nameSDK helperWire / stored valueWhere the response comes from
Simulated (default)simulated()sandboxThe world engine invents the response from world state and the tool's output_schema. No real calls leave the sandbox.
Executedexecuted()code_interceptedThe tool's real code runs in the sandbox; its data operations execute against the simulated world (the ledger-backed /data plane).
Livelive(*, tool_name, endpoint_id | endpoint_name)passthrough (+ passthrough_binding)Forwarded to a bound live ToolEndpointreal side effects.

Simulated (default)

The world engine answers. Given the current world state and the tool's declared output_schema, the simulator invents a plausible response — no external system is touched. This is the default for any tool you don't annotate, and it's the mode the whole simulated-world regression flow is built around: deterministic, side-effect-free, replayable across a base check and a head check.

from dystopic.odyssey.tools import Tool, simulated

Tool(
    name="get_order",
    input_schema={"type": "object", "properties": {"order_id": {"type": "string"}}},
    output_schema={"type": "object", "properties": {"status": {"type": "string"}}},
    mode=simulated(),  # optional — this is the default
)

Executed

The tool's real code runs inside the sandbox, but its data operations are routed at the platform's ledger-backed /data plane rather than to any real backend. You get the fidelity of running your actual tool logic while keeping the world simulated and the run reproducible. Executed is dashboard-settable — you can flip a tool into this mode from the platform tools table without touching SDK code.

from dystopic.odyssey.tools import Tool, executed

Tool(
    name="compute_discount",
    input_schema={"type": "object", "properties": {"order_id": {"type": "string"}}},
    mode=executed(),
)

Live

The call is forwarded to a bound live ToolEndpoint and produces real side effects against a real system. Because live tools hit the outside world, live() requires keyword arguments — tool_name plus exactly one of endpoint_id / endpoint_name:

from dystopic.odyssey.tools import Tool, live

Tool(
    name="issue_refund",
    input_schema={"type": "object", "properties": {"order_id": {"type": "string"}}},
    mode=live(tool_name="issue_refund", endpoint_name="billing"),
)

live() (and its alias passthrough()) require keyword args. A bare live() / passthrough() raises ValueError — it needs tool_name and one of endpoint_id / endpoint_name. Never call it positionally or empty.

Live tools still participate in the ledger: a ledger adapter on a Live tool records the tool's effect on world state deterministically, exactly as it would for a simulated tool, so behavior-diffing and expected-outcome grading stay consistent across base and head. See ledger adapters for the adapter binding.

Legacy aliases

The 2026-07 vocabulary rename kept the old helper names working:

  • intercepted() is a legacy alias of executed().
  • passthrough(*, tool_name, endpoint_id | endpoint_name) is a legacy alias of live(...) — with the same required kwargs.

Both aliases remain exported from dystopic.odyssey and behave identically to their new names. Lead with executed() / live() in new code; the aliases exist so existing agents keep working.

Setting the mode via default_execution_mode

Under the hood, each tools_schema entry carries a default_execution_mode string. The Tool(...) helper writes it for you, but you can also set it directly — on the tools_schema you pass to create_code_agent(...) / update_code_agent(...), or from the tools table in the dashboard. The validator accepts either vocabulary:

You may writeNormalizes to (stored)
simulated (or omit / null)sandbox
executedcode_intercepted
livepassthrough
legacy sandbox / code_intercepted / passthroughpassed through as-is

An absent or null default_execution_mode defaults to sandbox (Simulated). Anything else is a 422 whose message lists the accepted names. The stored/wire values keep the legacy strings so every existing row and runtime comparison stays byte-identical — the new names are the human-facing surface (dashboard, SDK, error copy).

A raw tools_schema entry (as it travels in the agent payload) looks like this:

{
  "name": "issue_refund",
  "input_schema": { "type": "object", "properties": { "order_id": { "type": "string" } } },
  "default_execution_mode": "live",
  "passthrough_binding": { "tool_name": "issue_refund", "endpoint_name": "billing" }
}

A live entry needs a passthrough_binding (tool_name + one endpoint reference); the live() / passthrough() SDK helpers build it for you. See the tools reference for the full tools_schema field list — including the ledger write policy, adapters, and human-approval gating that ride the same entry.