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
- Node.js 22+ (the agent uses Node's built-in WebSocket).
- Codex CLI installed and logged in — run
codex loginonce. The launcher spawns a realcodex app-server, so it needs valid Codex auth in~/.codex. - A Chamade agent key (
chmd_…) from dashboard → Agents, with at least one platform connected. - That Chamade agent must have no AI provider configured. Codex is the brain here. If the agent holding the key also has a provider (Anthropic, OpenAI, …) set in the dashboard, both Codex and Chamade's built-in provider will answer the same DM — double replies.
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).
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.
- Model, reasoning effort, personality — set
model,model_reasoning_effort,personalityin~/.codex/config.toml. The agent picks them up on its next turn. - What the agent can do — governed by
sandbox_mode. Wiring Codex to a chat is usually about getting work done — running commands, editing files — soworkspace-write(Codex's agentic default) ordanger-full-accessis what you want. Pickread-onlyonly when you specifically want a read/answer-only assistant. - Persona / instructions — drop an
AGENTS.mdin the agent's working directory (set it withCHAMADE_CODEX_CWD=/path). Codex discovers it the same way it does for the CLI.
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:
| Command | What it does |
|---|---|
chamade-mcp --codex-spawn | Start on a fresh thread (like codex). Use the first time, or to deliberately start over. |
chamade-mcp --codex-resume | Resume the stored thread (like codex resume) — keeps the agent's context across restarts. This is what a service should run. |
chamade-mcp --install-service | 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. |
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).
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
- Codex not logged in — run
codex loginand confirm~/.codex/auth.jsonexists. codexnot on PATH of the shell that launched the agent (common under a service). Use an absolute path or ensure the unit's environment includes it.- The
could not find bubblewrap on PATHline is a harmless warning — Codex falls back to a bundled sandbox.
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
- Confirm the agent is live — the log should end with
autonomous agent liveandchamade push session open. - Check the key is in scope for the account: the agent holding it must be active and a member of the connected platform in dashboard → Agents.
- An
already running for this keymessage means another instance owns the lock — only one agent per key.
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.
