Agent programs and connected agents
Agent programs as the storyteller
Since server 0.22.0, a program already installed and signed in on the server's machine can narrate: Claude Code, Codex, opencode or Grok Build. It runs on its own plan, and the server never asks for, reads or stores its key. Inside the Docker image only when the program is built into it (below), and not on Android.
Setting it up
- Admin, Server settings, Agent lists the four with what this machine has: installed, signed in, and how well each is locked down (its own tools removed, or boxed in).
- Pick one. Choose a story model and a lighter bookkeeping model from what the program offers, and an effort level.
- Press Test the table: one tiny real turn that checks every step, from starting the program to a tool call and back. Claude Code and opencode are proven; Codex and Grok Build are marked untested until a test passes on your machine.
- Decide who may use it: every campaign on the server, or only campaigns an administrator leads. Campaigns then choose The server's agent in their Settings tab, or the server's default provider is set to it.
- Optionally Paint a test picture. A program with its own image tool (Codex, Grok Build) is offered as an image backend only after one real picture succeeds.
How it is contained
- The program is started with none of its own tools: no shell, no files, no web, none of your MCP servers or settings. Its only tools are the Dungeon Master's, served by the server's own MCP endpoint on a token that works from this machine only and dies with the turn.
- It plays inside the same DM loop as the built-in storyteller: the server rolls every die, the per-turn caps apply, physical dice park the turn, and the narration guard checks its prose.
- The program never sees the server's secrets: not the database key, not provider keys, not accounts.
- Concurrency (1 to 8 turns at once, default 2) and a per-turn timeout (60 to 900 seconds, default 240) are settings. The admin page shows the plan's usage when the program reports it.
Codex is boxed in with the settings Codex honours (shell, image viewer and sub-agents off, read-only, approvals refused), and the admin card names any setting the installed Codex no longer recognises. Codex may call the table's own tools without asking.
In Docker
A container cannot start programs on its host, so the program must be inside the image: put AGENT_PROGRAMS=@openai/codex (or @anthropic-ai/claude-code, @opencode/cli; npm's opencode-ai is opencode 1.x, which is not supported) in .env, run docker compose up -d --build, then sign in once with docker compose exec open-dungeon-master codex login --device-auth. The sign-in lives in the odm-home volume and survives updates.
The desktop app exposes the same door on its Story AI screen for the device world; see Bring your own agent.
Connected agents
The other direction: a player's own MCP client (Claude Code, Codex, or anything that speaks MCP) acts as that player over /api/mcp. Settings, Connected agents:
- Create a grant. Tick the scopes it may use: read (campaigns and the chronicle), play (act as your character), characters (manage your library), campaigns (create and manage your campaigns), dm (run a table where you hold the seat).
- Optionally pin it to one campaign.
- Copy the token, shown once, into the client's MCP configuration with the server's
/api/mcpaddress.
Every tool the agent gets is a web route called as you, so it can do exactly what you can in the browser and nothing more: never keys, backend URLs, accounts, the admin panel or backups. Revoke a grant any time; changing your password disconnects every agent. The server caps the number of grants per user. The guided setup's last question shows the one line for your program and lights up when the agent's first call arrives.
A connected agent can read a long campaign whole: every tool result stays valid JSON under its size cap with a note naming what was cut, the campaign read puts the safety pause, DM status, caps and pending rolls first, the transcript comes a page at a time, a character is read as the table holds it, and it can read and answer the Dungeon Master's whispers. A player's agent can level its character the way the level-up dialog does: odm_level_up_options reads what the next level offers, and odm_level_up takes it, refusing an unearned level or an illegal pick with the reason. When the table waits for everyone, odm_pass passes the agent's beat, and its posts are no longer refused as stale while the table gathers. A player's agent can also be woken by a signed decision webhook when a decision is its to make; the repository documents the receiver setup for Codex and for a Claude Code routine.
On a world hosted from the desktop or Android app and shared online, Settings, Connected agents also shows an assistant link: one lasting address that ChatGPT, Claude, Grok or Meta Muse saves as a custom connector. It follows the world to every new share address and goes through the project's relay, which limits each world's traffic.
Waking a player's agent
A decision webhook can push opportunities to a player receiver. The administrator registers receiver addresses under Server settings, Player agents; Connected agents offers a receiver file and setup instructions for an eligible connection. The Codex receiver resolves npm's Windows launcher and can recover a lock left by a process that has stopped. A webhook-driven agent is also woken once for each level its character earns (level_up_available), behind the table's own decisions.
For an agent that cannot accept incoming requests, the administrator can enable Allow poll links (off by default). Create a connection that can play one campaign, then use Make a poll link in Connected agents. The secret link is shown once and reports the character's current opportunities. A hook checks it periodically and wakes the agent when wake is true and fingerprint has changed. Use a poll link or a receiver for a connection. Revoking the connection or disabling poll links stops the link; replacing it invalidates the old one.
Both at once
The two are independent. A table can have the server's agent narrating while a player's connected agent plays their rogue, each held to its own scope. The repository's agent-harness document has the protocol details for people running their own programs.