Protocol specification¶
The mod exposes a minimal HTTP/JSON API on http://127.0.0.1:8723 (default port; configurable). Stable across the 0.x series.
Endpoints¶
| Method + path | Purpose |
|---|---|
GET /health |
Liveness + version metadata. Auth required. |
POST /cmd |
Execute a named command. Auth required. |
GET /capabilities |
Introspect registered commands. Auth required. |
Authentication¶
Every request must present a bearer credential, via either of two headers:
Authorization: Bearer <token> (preferred, v0.3+)
X-WB-Token: <token> (legacy single-tenant, v0.1 / v0.2)
The bridge tries Authorization: Bearer first and falls back to X-WB-Token. Mixing the
two in different requests is fine — the C# server treats them as equivalent.
Legacy single-token mode (default)¶
If no agents.json is present at <worldbox>/BepInEx/config/WorldBoxBridge.agents.json,
the bridge boots with one synthetic agent named "legacy" (role God, full permissions).
Its credential is the random token generated on first launch and stored at
<worldbox>/BepInEx/config/WorldBoxBridge.cfg.
Multi-agent mode (v0.3+)¶
When agents.json exists, every entry registers a distinct bearer. Each authenticated
request inherits the agent's role, optional kingdom_claim, permission bitmask, and
inbox. See multi-agent.md for the full schema and four scenario presets
(PvP / coop / hierarchical / sandbox).
Requests without a valid token return 401 Unauthorized immediately, before any work is
queued.
GET /health¶
Returns a small JSON object useful for connection checks.
{
"ok": true,
"mod_version": "0.3.0",
"worldbox_version": "0.x.x",
"unity_version": "2022.3.60f1",
"assembly_csharp_sha256": "…",
"tick": 12345,
"enabled": true,
"multi_agent": false,
"scenario": "sandbox",
"agent_count": 1
}
multi_agent, scenario, agent_count reflect the active session. With no agents.json deployed the bridge runs in legacy single-tenant mode (multi_agent: false, scenario sandbox, one synthetic "legacy" god agent).
POST /cmd¶
POST /cmd HTTP/1.1
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "<command-name>",
"args": { "<arg>": <value>, ... }
}
Success response¶
Error response¶
{
"ok": false,
"error": {
"code": "GAME_REJECTED",
"message": "spawn 'dragon_red' at (12, 8) failed: tile is water and actor.water_walking = false",
"command": "spawn",
"args": { "entity_id": "dragon_red", "x": 12, "y": 8 },
"exception": {
"type": "System.InvalidOperationException",
"message": "Cannot place water-incompatible actor on water tile",
"stack_top": "WorldBoxBridge.Commands.Action.SpawnCommand.Execute (line 47)"
}
}
}
Error codes¶
| Code | HTTP | Meaning |
|---|---|---|
UNKNOWN_COMMAND |
404 | The name field doesn't match a registered command. |
BAD_ARGS |
400 | Args fail JSON-schema validation. |
UNKNOWN_ASSET |
400 | An asset id (tile_id / entity_id / power_id) doesn't exist in this WorldBox build. Response includes did_you_mean: [...] (Levenshtein top-5). |
OUT_OF_BOUNDS |
400 | Coordinates are outside the current map. |
GAME_REJECTED |
422 | The game accepted the dispatch but the action was logically refused. |
GAME_CRASH |
500 | An exception bubbled up from Assembly-CSharp. Full type + message + stack top in response. |
MAIN_THREAD_TIMEOUT |
504 | Command exceeded 30s on the main thread; it was abandoned. |
UNAUTHORIZED |
401 | Missing or wrong bearer credential. |
DISABLED |
503 | enabled = false in WorldBoxBridge.cfg. The kill-switch is active. |
PERMISSION_DENIED (v0.3+) |
403 | The agent's role lacks the permission this command needs. |
FACTION_SCOPE_VIOLATION (v0.3+) |
403 | A FactionPlayer tried to act on a kingdom it doesn't claim. |
TURN_NOT_YOURS (v0.3+) |
409 | Turn-based mode is active and another agent holds the current slot. |
GET /capabilities¶
Returns the list of registered commands with their JSON Schemas. The Python server consumes this on startup to construct its MCP tools/list response.
{
"mod_version": "0.3.0",
"worldbox_version": "0.x.x",
"unity_version": "2022.3.60f1",
"assembly_csharp_sha256": "…",
"commands": [
{
"name": "spawn",
"category": "action",
"description": "Spawn one or more actors at (x, y).",
"requires_main_thread": true,
"schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", ... }
},
…
]
}
Kill-switch¶
Edit <worldbox>/BepInEx/config/WorldBoxBridge.cfg and set enabled = false. The mod hot-reloads the file every 2 seconds and stops accepting commands. New requests get 503 DISABLED. Set back to true to resume — no restart required.
Stability promise¶
- Endpoint paths, error codes, and the JSON envelope shape are part of the
0.xSemVer contract. - Command inputs and outputs are versioned per command via
capabilities(). Adding a new optional input field is non-breaking; removing or renaming a field is a major bump. - New commands may be added at any minor release.
did_you_meansuggestions and exception detail formatting are best-effort and may evolve.