Sandbox Mode
Run agents against integrations without touching production — using vendor sandboxes, the Fruxon simulator, or a read-through hybrid — and choose per test where each connection goes
Every Fruxon integration can be exercised in Sandbox Mode — an isolated, side-effect-free way to call tools during development, evaluation, and CI. Sandbox Mode is resolved at the tenant credential layer: each connection (an integration config in Integrations) carries its own saved sandboxMode, so a single agent can mix sandboxed and live tools in the same run by binding different steps to different configs of the same integration.
A test can also route each connection its own way for that run only, without changing what's saved on the connection. See Route connections per run.
Why it exists
Real APIs are flaky, non-idempotent, and cost money. Agents that depend on Salesforce, HubSpot, Stripe, or your warehouse can't be reliably evaluated against the live thing — every eval run pollutes prod, burns credits, and produces results you can't reproduce.
Sandbox Mode solves that by giving every integration a stable, side-effect-free substitute. You build, evaluate, and CI-gate against substitutes; you ship against the real APIs.
Two execution modes
A run has an execution mode, PRODUCTION or SANDBOX. You set it with mode when you test a draft (draft:test, draft:streamTest, or draft:queueTest), and it defaults to PRODUCTION. A deployed run through :execute or :stream ignores mode and always uses production credentials.
| Mode | Behavior |
|---|---|
PRODUCTION | Every tool call uses live credentials. Default for normal runs. |
SANDBOX | Each connection uses its saved sandbox strategy. A connection with no sandbox saved is simulated. |
Turns in a sandbox session are contained the same way, whatever their mode. That covers the debug console, the studio's Conversation and Trigger chats, a forked conversation, and Improvements' Try it. Which runs are sandbox runs lists every kind.
Sandbox strategies (per connection)
Each connection carries a sandboxMode setting with one of four values. To set it, open the connection in Integrations, expand Advanced on its Overview tab, pick a Sandbox routing, and publish.
| Value | In the UI |
|---|---|
NONE | None — production only |
SIMULATED | Simulated |
VENDOR | Vendor sandbox |
READ_THROUGH | Read-through |
VENDOR — use the vendor's own sandbox
Routes tool calls to the vendor's sandbox or test environment using sandboxVariant credentials on the config. Best when the vendor provides a high-fidelity sandbox (Salesforce Sandbox orgs, Stripe test mode, HubSpot developer accounts).
You're responsible for the sandbox account; Fruxon just routes traffic. On the Overview tab you can enter the sandbox's connection parameters under Vendor sandbox parameters. Its auth credentials are set through the API.
A VENDOR connection with no sandbox credentials saved counts as having no sandbox. A sandbox run treats it like NONE, and an evaluation refuses it.
SIMULATED — use the Fruxon integration simulator
Tool calls never leave Fruxon. The integration simulator intercepts each call and serves it from a persistent simulated store kept per connection.
The simulator behaves like the real API:
- Real-shape IDs. A simulated Salesforce account ID is prefixed
001…, a Salesforce lead00Q…, a Stripe customercus_…. Some IDs are minted sequentially (PROJ-1,PROJ-2), others randomly — either way the shape matches what the live API returns. - Stateful entities. Create a contact in one tool call, look it up by ID in the next — the simulator remembers it for the duration of the run (and across runs, scoped to that connection). Entities are soft-deleted (tombstoned), so a
Deletefollowed by aListbehaves like the real API. - Operation-aware. Each tool is classified by operation (
List,Read,Create,Update,Delete,Action) and entity type, so the simulator knows what kind of result to construct. - Identity and reference rules. Update and delete calls resolve their target by the same identity params the real API uses; cross-entity references (a deal's
companyId) are validated against the simulated store.
Best for integrations without a usable vendor sandbox, or when you need offline, isolated CI runs with no external dependencies.
READ_THROUGH — read from production, write to the simulator
A hybrid for read-first agents. Read operations (List, Read) hit the real production API with live credentials. Write operations (Create, Update, Delete, Action) are routed to the Fruxon simulator so the agent's full flow completes without touching real data.
In a sandbox run, a tool that has no sandbox classification is treated as a write and simulated. Fruxon never guesses that an unknown call is a safe read.
Best when evaluation quality depends on real production data — GitHub commits, live database queries, current Stripe customers — but you still want write-side safety. Both revisions in an evaluation read the same live data, so their behavioral comparison stays fair.
NONE — no sandbox configured
NONE means the connection has no sandbox, and it's what a new connection starts with. A connection whose setting was never saved (UNSPECIFIED) behaves the same way.
What happens to a NONE connection depends on the run:
| Run | A NONE connection |
|---|---|
| Production run | Uses its live credentials, as always |
| Studio or console sandbox test, forked conversation, Try it | Simulated, unless you choose Live (production) for it on that test |
| Automation stage test, Improvements' Test the change | Read through: real reads, simulated writes |
| Evaluation | The run refuses to start |
A sandbox run sends a NONE connection's writes to production only when you choose Live (production) for that connection. A run that reads it through still reads live data with its production credentials.
Evaluation runs refuse to start when any integration that the deployed or candidate revision uses is left at NONE, or set to VENDOR with no sandbox credentials. The run is rejected up front with an error naming exactly which configs to switch to VENDOR (with sandbox credentials), SIMULATED, or READ_THROUGH. The evaluation would simulate such an integration rather than reach production, so the refusal isn't what keeps your data safe. It tells you the integration was never really exercised, instead of handing you a verdict built on simulated answers you didn't ask for.
Which runs are sandbox runs
For each connection, a sandbox run uses, in order:
- The choice made for that run, if any.
- The connection's saved sandbox:
SIMULATED,READ_THROUGH, orVENDORwith sandbox credentials. - Otherwise, the run's default.
| Run | How you start it | Default for a connection with no sandbox | Choices per connection |
|---|---|---|---|
| Studio test, Single run | The sandbox toggle in the Agent Studio test chat | Simulated | Simulated, Read-through, Live (production) |
| Studio test, Conversation or Trigger | The chat itself, while Live delivery is off | Simulated | Simulated, Read-through, Live (production) |
| Debug console | Open debug console | Simulated | Simulated, Read-through, Live (production) |
| Forked conversation | Test from here on a message | Simulated | Simulated, Read-through, Live (production) |
| Try a change | Try it on an Improvements card | Simulated | Simulated, Read-through, Live (production) |
| Automation stage test | Test this stage | Read-through | Simulated, Read-through |
| Test on past conversations | Test the change on an Improvements card | Read-through | SIMULATED or READ_THROUGH, through the API only |
| Evaluation | Evaluations → New Run | The run is refused | Not offered |
A turn you send to a sandbox session through the API or the Python SDK gets the same default. The server applies it, whatever the client.
Runs that a sandbox run starts, such as a consult or a delegation, are contained the same way. Your per-connection choices are carried to them. A run they don't reach, such as a relay, gets the default instead, so a connection you set to Live is simulated there rather than the other way round.
A Conversation or Trigger chat with Live delivery on isn't a sandbox run. Everything the agent does in it is real, and it takes no per-connection choices.
Route connections per run
A per-run choice applies to that test only. Nothing is saved on the connection.
In Agent Studio
In the test chat, a Single run has a toggle beside the composer that switches between production and sandbox. In production, the banner above the chat reads Production — Live credentials for all N integrations.
In sandbox, and in any Conversation or Trigger chat without Live delivery, the banner reads Sandbox, with a verdict such as All 3 integrations isolated from production. Click the banner to see one row per connection, each with a menu:
| Option | Where the connection goes |
|---|---|
| Simulated (default), or the saved mode, such as Read-through (default) | Its saved sandbox, or the simulator when it has none |
| Simulated | The Fruxon simulator |
| Read-through | Real reads, simulated writes |
| Live (production) | Its production credentials. Writes are real. |
When any connection is set to Live, the banner says how many integrations will hit production. An integration with no connection behind it can't be routed. The banner names it and says it will run against production.
In the debug console
The debug console, where Try it opens, lists the connections the agent's deployed revision uses under Integrations on this test, with the same menu. A connection that only a draft or a proposed change uses isn't listed, and is simulated by default.
In the automation stage debugger
The Debug drawer has a Connections section with the same menu, minus Live. A connection with no sandbox shows Read-through (default). A stage test can't route a connection to live, because the ledger wouldn't know about a write the test made, and the real run would make it again.
In a sandbox session, real sends to channels and memory writes stay blocked. What can still change something real is a connection you set to Live (production), and a built-in tool that changes the workspace itself. Confirm writes (Confirm tool writes in the studio's run settings) holds those calls until you approve them. Reads and simulated calls run straight through. In the debug console it's on by default for a forked conversation and for Try it.
Through the API
Each endpoint below takes a map from connection ID (the tenantConfigId an agent's integration slot points at) to a mode.
| Endpoint | Field | Modes you can choose |
|---|---|---|
POST …/agents/{agent}/revisions/{revision}/draft:test, draft:streamTest, draft:queueTest | sandboxRouting | SIMULATED, READ_THROUGH, NONE (Live) |
POST …/fruxon/sessions/{session}/turns, POST …/fruxon/sessions/{session}:fireTrigger | sandboxRouting | SIMULATED, READ_THROUGH, NONE (Live) |
POST …/recommendations/{recommendation}:compare | sandboxRouting | SIMULATED, READ_THROUGH |
POST …/stageTests | routing | SIMULATED, READ_THROUGH |
VENDORcan't be chosen per run. A vendor sandbox needs the connection's own sandbox credentials, so you choose it on the connection.- Routing a draft test makes it a sandbox run, even with
modeleft atPRODUCTION. Every connection you leave out is simulated unless it has a sandbox saved. - A session turn or fire on a Live-delivery session is refused if it carries
sandboxRouting. A Live session already reaches every connection with its production credentials. - Only route connections the run uses. A draft test, a comparison, or a stage test that names a connection its revisions don't use gets a
400. On a session turn, such a choice routes nothing. :executeand:streamignore routing. A deployed run can't be rerouted by its request body.
How to run an agent in sandbox mode
In Agent Studio, switch the test chat's toggle to sandbox, or use a Conversation chat. Before you send, the banner shows where each connection will go.
Through the API, set mode to SANDBOX on a draft test request (POST …/agents/{agent}/revisions/{revision}/draft:test), and add sandboxRouting for any connection you want routed differently:
{
"mode": "SANDBOX",
"parameters": { "message": "Find leads created this week and create a follow-up task." },
"sandboxRouting": {
"8b0e6c2a-3f4d-4e21-9a7c-5d1f0b2e4c11": "READ_THROUGH"
}
}Each connection the agent uses resolves on its own: the run's choice, then its saved sandbox, then the simulator.
Choosing a strategy
Use this table as a starting point. Most teams end up with a mix.
| Situation | Recommended strategy |
|---|---|
| Vendor offers a usable sandbox (Salesforce, Stripe, HubSpot) | VENDOR |
| No vendor sandbox, or you want fully offline, isolated runs | SIMULATED |
| Agent reads live data and the eval depends on that realism | READ_THROUGH |
| Internal databases (Postgres, MongoDB) — point at a staging instance | VENDOR |
| Integrations that the agent uses but you don't yet trust to be safe | SIMULATED |
Leaving a connection at NONE is enough for studio and console tests, which simulate it. Evaluations need one of the other three.
Coverage
Most built-in integrations ship with a sandbox classification for each tool. It's the metadata that tells the simulator each tool's operation, entity type, identity params, and ID shape. A tool with no classification is treated as a write under READ_THROUGH.
What sandbox mode is not
- It is not a load- or performance-testing tool. The simulator is built for correctness and isolation, not throughput, and its store is shared across concurrent sessions on the same connection.
- It does not record or replay live API traffic. Each simulated call constructs its result from the tool's classification, not from a captured trace.
- It is not a substitute for production observability. Simulated results are synthesized from each tool's classification — real-shaped, but not real — so they won't surface issues that only show up against live data.
Related
- Sandbox Workspace — seed, inspect, snapshot, diff, and revert the simulated store that backs
SIMULATEDandREAD_THROUGH - Integrations Overview — the full list of integrations
- Evaluations — every integration an evaluation touches needs a saved sandbox, or the run won't start
- Improvements — Try it and Test the change, and how each routes connections
- Automations — test one stage in the sandbox before you turn it on