Codex agent

Run a self-contained OpenAI Codex agent that answers your Chamade DMs and calls — headless, 24/7, one command. No UI, no human in the loop.

Overview

Claude Code wakes on Chamade's push notifications natively (see Claude Code). Codex doesn't — its harness ignores MCP notifications, and there is no way to inject into a live interactive TUI session. So the Chamade npm shim ships an autonomous launcher: it spawns its own codex app-server, manages the task-scoped threads it owns, drives the Chamade push channel, and injects every inbound DM / call event as a Codex turn. The agent replies through the chamade_* tools. This keeps Chamade a router, not a runtime — it pokes a Codex engine, it doesn't host one.

The result is a background agent: someone DMs your connected Telegram / Discord / Teams / … account, Codex answers, you never touch a terminal.

Prerequisites

Quick start recommended

Install the shim and launch the agent. That's it — no codex mcp add step (the launcher injects the Chamade tools into its engine for you).

bash
npm install -g @chamade/[email protected] # first run: register the key, seed the default session, then run chamade-mcp agent run --runtime codex --key chmd_your_key_here --cwd /absolute/project/path

On startup you'll see the agent hash and chamade push session open. Now DM your connected platform and the agent replies on that channel. The Codex engine starts lazily when the first turn arrives.

The key is saved to ~/.chamade/agents/<hash>.json (mode 0600) on first run, so later launches use chamade-mcp agent run --agent <hash> and keep the key off the process arguments. The default instance is https://chamade.io; pass --url only to target a different Chamade deployment.

Configuring Codex (model, sandbox, persona)

Chamade maintains no Codex settings. The agent spawns a standard codex app-server, so everything is inherited from your own Codex config — the same file the codex CLI uses.

toml — ~/.codex/config.toml
model = "gpt-5-codex" model_reasoning_effort = "high" sandbox_mode = "workspace-write" # let it run commands / edit files
The agent's reach is the account's reach

Anyone who can DM the connected account drives the agent at its sandbox_mode level — with workspace-write or danger-full-access, that means running commands and editing files on the host. Scope who can reach the account accordingly: a private bot, your own account, a trusted channel. If it's reachable by people you don't fully trust, drop to read-only.

Slash-commands don't work over a DM. /model, /approvals and friends are a Codex TUI feature; an inbound DM is injected as plain user text, so the agent just talks about /model rather than switching anything. Configure through the TOML, not by messaging the bot.

Want a different config per agent (e.g. one model for your Telegram agent, another for Discord)? Codex profiles aren't available on the app-server, so use a separate Codex home: CODEX_HOME=/path/to/home chamade-mcp agent run --agent <hash>. That directory needs its own config.toml and an auth.json (run codex login there, or symlink ~/.codex/auth.json).

Keeping it running

The agent self-heals while it runs — if the network blips or the Codex engine crashes, it reconnects and resumes its stored sessions in-process, so you don't lose the conversations. The only thing it can't do alone is start itself after a reboot. Three commands cover the lifecycle:

CommandWhat it does
chamade-mcp agent run --agent <hash>Resume the stored agent and all of its sessions lazily. Add --fresh to replace only the default Codex session.
chamade-mcp agent install-service --agent <hash>Write the OS boot-start unit for this agent (systemd --user on Linux, launchd on macOS, guidance on Windows), then print the one-liner to enable it.
chamade-mcp agent stop --agent <hash>Stop exactly that supervisor using its stored PID; no process-name matching.
bash — run at boot (Linux)
chamade-mcp agent install-service --agent <hash> # <hash> is printed at startup systemctl --user daemon-reload systemctl --user enable --now chamade-agent@<hash> loginctl enable-linger $USER # so it runs without an active login journalctl --user -u chamade-agent@<hash> -f # logs

Running several agents (multi-key)

One machine can run many agents — one per key. Each gets its own engine process, session registry, and config entry; everything is derived from the key's <hash>, so they never collide. Select which one a command targets with --agent <hash> (or --key the first time).

bash
# terminal 1 chamade-mcp agent run --runtime codex --key chmd_agent_one --cwd /srv/agent-one # terminal 2 — a second, independent agent chamade-mcp agent run --runtime codex --key chmd_agent_two --cwd /srv/agent-two

A second launch on the same key refuses to start (it would answer every DM twice). Different keys are independent.

How it works

The launcher is part of the @chamade/mcp-server shim. It spawns one lazy codex app-server, injects Chamade's MCP tools scoped to your key via Codex -c config overrides (so each agent replies with its own key), manages task-scoped threads, and drives mcp-remote as the push client on the same channel Claude Code uses. Each session is floor-gated (one turn at a time, queued and coalesced while a turn is in flight) so the agent never writes over an in-flight turn. Voice audio is unchanged — see Voice providers for hosted STT/TTS, or the raw-PCM audio WebSocket.

Interactive use (DMs landing in your live Codex TUI session) is not possible today: Codex spawns a private single-client app-server with no injection hook. The autonomous agent is the supported shape.

Troubleshooting

"codex app-server did not become ready" / engine won't start

The peer gets two replies to every message

The Chamade agent holding this key also has an AI provider configured, so Chamade's built-in dispatcher answers in addition to Codex. Remove the provider from that agent in dashboard → Agents — Codex should be the only brain.

DMs arrive but the agent never answers

Context resets after a restart

Relaunch with chamade-mcp agent run --agent <hash>. Stored sessions resume lazily on their next message; --fresh deliberately replaces only the default Codex session. The boot service uses the same resume command.

Still stuck?

Email [email protected] with the launcher's stderr (it logs each step) and a timestamp — we can correlate against server logs.