---
title: "Create a Dojo sim session and begin the runner (\"Begin Sim\")."
method: POST
path: "/sim/sessions"
tags: ["Dojo"]
---

# Create a Dojo sim session and begin the runner ("Begin Sim").

`POST /sim/sessions`

## Request

- Base URL: `https://api.mnemom.ai/v1`
- URL: `https://api.mnemom.ai/v1/sim/sessions`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-Mnemom-Api-Key`

Creates a `dojo_sim_sessions` row for the agent + scenario and starts the server-side runner (a per-session Durable Object that drives the Agent Smith ↔ agent loop and survives the human closing the tab). The runner resolves the agent's gateway compute key server-side BY `agent_id` (via the agent↔TryMeConfig link from onboarding) — the cleartext key never travels in the request. Emits SimEvents readable via `GET /v1/sim/{session_id}/stream`. MNE-531.

This operation returns `409` for THREE distinct causes; branch on the stable `error.code`, NEVER on the status alone (a client that assumes 409 means "a session is already running" will offer a force-end remedy that cannot help, succeeds at ending nothing, and loops):

- `active_sim_session` — the agent already has a `pending`/`running`/`paused` session. `error.details.session_id` carries the BLOCKING session's id so the client can stop that session directly. It is omitted (no `details` at all) on the DB unique-constraint backstop path, where a concurrent create raced the pre-check and the racing session's id is not known.
- `dojo_provider_key_missing` — no dojo provider key resolves for the agent's provider. An admin must set it (`/admin/dojo`) and the agent must be bound to its Try-Me config. Force-ending sessions does nothing for this.
- `agent_unnamed` — `agents.name` is empty for this agent, and the sim needs a name to spar as it. Remedy: `PUT /v1/agents/{id}` with `{"name": "…"}` (2-32 chars, letters/digits/hyphens), then retry. Names are normally written at birth from the gateway's `x-mnemom-agent` header, but birth is NOT the only writer — do not send the operator back through birth for an agent that already exists. Force-ending sessions does nothing for this.

An unrecognised or absent code on a 409 should fall back to displaying `error.message` verbatim rather than assuming any of the above.

Every spar turn is charged in µ to the agent's billing account, so Begin Sim first reads that account's balance from billing (plans do not matter): no µ billing account → `402 dojo_billing_unconfigured`, balance at or below zero → `402 dojo_balance_depleted` (both carry `error.details.top_up_url`, the deployment's web app billing page — `https://www.mnemom.ai/settings/billing` in production — and a plain `error.message` starting "Out of µ — recharge at <that page>."), billing unreachable → `503 dojo_balance_unverified` (fail closed). No session is created in any of these cases. The runner re-reads the balance before each turn (a funded read is trusted for 30 seconds) and the gateway checks every agent call, so a run that runs out of µ mid-session stops at once, before another Agent Smith turn, and completes with `outcome.ended` `balance_depleted` or `billing_unconfigured` (or `billing_unverified` when the balance could not be checked: try again in a minute), after one `system` `rating` SimEvent carrying `ended`, `message` and `top_up_url`. Other gateway refusals of the agent's call also end the run at once, with their own `ended` and a plain `message` but no `top_up_url` (recharging is not the remedy): `account_suspended` (a suspended account), `billing_refused` (any other billing refusal), and `dojo_refused` (a Dojo rule: `403 dojo_claim_required`, or `400 dojo_model_unpinned` / `dojo_model_not_allowed` / `dojo_max_tokens_exceeded` / `dojo_invalid_body` / `dojo_multiple_completions`).

## Request body

- object
  - `agent_id` string, required: Prod agent id to spar (the runner resolves its compute key server-side).
  - `scenario_id` string, required: dojo_scenarios.id (e.g. 'db-shepherd').
  - `mode` 'auto' | 'manual'
  - `max_turns` integer
  - `reviewer_kind` 'builtin_opus' | 'human': The review policy for this run's Safe House review-holds (Wave 4 §13). 'builtin_opus' (default) resolves synchronously; 'human' routes a hold to the human-tier resolve endpoint. Assigns the sim agent to the corresponding STANDING, non-weakenable team-scope review-policy team before the run starts — this is owner-authoritative policy, never a per-agent card upsert the agent could weaken.
  - `capture_payloads` boolean: Mnemom-staff only: arm raw-payload capture for the debug export BEFORE the run starts, so payloads are captured from turn 1 (MNE-923). Honored only when the caller is a platform admin (capture is staff-only); ignored otherwise.

## Response `201`

Session created and runner started.

- object
  - `session_id` string, uuid, required
  - `agent_id` string, required
  - `scenario_id` string, required
  - `mode` 'auto' | 'manual', required
  - `state` string, required

## Other responses

- `400`: Bad request
- `401`: Authentication required
- `402`: No µ to spar with: `dojo_billing_unconfigured` (no µ billing account) or `dojo_balance_depleted` (balance used up). `error.details.top_up_url` is the deployment's web app billing page (`https://www.mnemom.ai/settings/billing` in production). No session was created.
- `403`: Forbidden
- `404`: Resource not found
- `409`: Resource conflict — the request cannot proceed because of a current state conflict (e.g., resource already exists, version mismatch, in-flight idempotency key with a different body).
- `429`: Rate-limit exceeded. The global per-IP limiter (100 requests/minute, applied to every `/v1/*` route) rejected this request. Back off until the window resets — `Retry-After` carries the cooldown in seconds and `X-RateLimit-Reset` the absolute reset time.
- `500`: Server error — request was well-formed but the server failed to fulfill it. Typically a downstream dependency (DB / RPC / external API) returned an unexpected error.
- `502`: Server error — request was well-formed but the server failed to fulfill it. Typically a downstream dependency (DB / RPC / external API) returned an unexpected error.
- `503`: An upstream dependency is currently unavailable. The request was not processed; retry after the cooldown window.

---

[API](https://skmtc.dev/mnemom/apis/mnemom-api.md) · [All operations](https://skmtc.dev/mnemom/apis/mnemom-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mnemom/apis/mnemom-api/revisions/274b7a6ea182?raw)
