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, opens one thread 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/mcp-server # start a fresh agent on a key (registers it, then runs) chamade-mcp --codex-spawn --key chmd_your_key_here

On startup you'll see the engine port, the thread id, and chamade push session open. Now DM your connected platform — the agent logs ◀ dm_chat from … on telegram: "…" and replies on that channel within a few seconds.

The key is saved to ~/.chamade/codex/<hash>.json (mode 0600) on first run, so later launches don't need --key. 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 --codex-resume …. 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 the same thread in-process, so you don't lose the conversation. The only thing it can't do alone is start itself after a reboot. Two commands cover the lifecycle:

CommandWhat it does
chamade-mcp --codex-spawnStart on a fresh thread (like codex). Use the first time, or to deliberately start over.
chamade-mcp --codex-resumeResume the stored thread (like codex resume) — keeps the agent's context across restarts. This is what a service should run.
chamade-mcp --install-serviceWrite 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.
bash — run at boot (Linux)
chamade-mcp --install-service --agent <hash> # <hash> is printed at startup systemctl --user daemon-reload systemctl --user enable --now chamade-codex@<hash> loginctl enable-linger $USER # so it runs without an active login journalctl --user -u chamade-codex@<hash> -f # logs

Running several agents (multi-key)

One machine can run many agents — one per key. Each gets its own engine port, its own thread, and its own 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 --codex-spawn --key chmd_agent_one # terminal 2 — a second, independent agent chamade-mcp --codex-spawn --key chmd_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 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), opens one thread, and drives mcp-remote as the push client on the same channel Claude Code uses. Inbound events are 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

Use --codex-resume (not --codex-spawn) to continue the stored thread. A thread that never ran a turn has no saved state and correctly falls back to a fresh one. The boot service (--install-service) already uses resume.

Still stuck?

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