Status:
draft · Version 0.1 · Filed 2026-04-26Title: Codex App-Server Signal Injection — local receiver bridge for Prism signals
Version
0.1Status
draftSupersedes
SPEC-047Note
This spec replaces Texi’s earlier SPEC-047 draft after Donna reported a spec-number collision. SPEC-047 is marked rejected/superseded; SPEC-048 is the canonical implementation target.Problem
Codex sessions currently receive Prism signals through piggyback delivery: a signal becomes visible only when the receiving Codex agent calls another Prism verb or explicitly pollsprism_signals_pending. The operator goal is stronger: if Desiree sends Texi a signal, Texi should see it in the Codex session without manual polling.
Claude Code has channel-based push. Codex does not have the same channel API. OpenAI Codex provides an experimental local app-server with JSON-RPC methods including thread/inject_items, which can inject items into a loaded Codex thread. That makes app-server the local Codex UI adapter, not Prism’s LAN/global signal router.
Goal
Implement fallback-safe Codex signal push:Sender MCP -> Prism FastAPI -> Receiver MCP -> local Codex app-server -> Codex thread
Prism FastAPI remains the global authenticated signal router. The receiver MCP process bridges from Prism’s session stream to the local Codex app-server.
Non-Goals
- Do not reimplement Codex app-server in Prism FastAPI.
- Do not expose Codex app-server directly on LAN in v1.
- Do not route Prism FastAPI directly to another machine’s
127.0.0.1:<port>. - Do not replace piggyback delivery; it remains the reliability fallback.
- Do not create a general chat proxy between Codex and Prism.
Communication Paths
Texi -> Desiree
- Texi calls
prism_signal(to="Desiree", ...). - Texi MCP sends to Prism FastAPI.
- Prism FastAPI resolves Desiree. If offline, it queues the signal.
- Desiree receives on next bootstrap or Prism verb according to her surface strategy.
Desiree -> Texi Today
- Desiree calls
prism_signal(to="Texi", ...). - Desiree MCP sends to Prism FastAPI.
- Prism resolves Texi’s active session.
- Codex has no push adapter yet, so Texi sees it through piggyback/poll only.
Desiree -> Texi Target v1
- Desiree calls
prism_signal(to="Texi", ...). - Desiree MCP sends to Prism FastAPI.
- Prism FastAPI resolves Texi and publishes onto the existing Prism session stream.
- Texi’s local MCP process receives the signal.
- Texi MCP sees
PRISM_AGENT_SURFACE=codexandPRISM_CODEX_APP_SERVER_URL. AppServerInjectStrategycalls local Codex app-serverthread/inject_items.- Codex app-server injects a model-visible item into Texi’s loaded Codex thread.
- If injection fails, the strategy falls back to piggyback buffering.
Launcher Contract
coder -agent codex gains optional app-server management.
Flags:
-codex-app-server off|local|autodefault:auto-codex-app-server-url URLexplicit override for advanced/debug use- Optional future:
-codex-app-server-port PORT
off: never start or use Codex app-server; piggyback only.local: require a local app-server path; fail or clearly warn if unavailable.auto: try to start/discover local app-server; fall back to piggyback if unavailable.
- Prefer a deterministic local port range for operator/debug visibility.
- If occupied, reuse only when verified as the matching app-server/session, otherwise increment to the next free port.
- Port collision must not break
auto; it falls back or selects another port.
MCP Surface Contract
mcp/agent_surfaces/codex.py owns Codex bootstrap/wrap behavior.
CodexSurface.on_bootstrap(ctx):
- Reads
PRISM_CODEX_APP_SERVER_MODEandPRISM_CODEX_APP_SERVER_URL. - Connects only when mode is not
offand a URL is present/discoverable. - Discovers/records the active loaded thread id if required.
- Stores connection/thread metadata on the surface instance.
- Is non-fatal on failure; logs and stays piggyback.
CodexSurface.signal_strategy():
- Returns
AppServerInjectStrategywhen app-server connection and thread metadata are available. - Otherwise returns
PiggybackStrategy.
CodexSurface.on_wrap(ctx):
- Closes any app-server client handle.
- Clears local thread metadata.
- Does not kill an app-server it did not start.
Strategy Contract
Addmcp/strategies/app_server_inject.py.
AppServerInjectStrategy.deliver(signal):
- Converts Prism signal envelope into a concise Codex-visible item.
- Calls Codex app-server
thread/inject_itemsagainst the active thread. - Returns
Trueon successful injection. - On connection failure, no loaded thread, protocol rejection, or timeout: buffers via piggyback fallback and returns
False.
- source: Prism
- signal type
- sender identity
- signal id
- concise payload summary
- instruction to call
prism_signals_pendingonly if full structured payload is needed
Backend/FastAPI Contract
Prism FastAPI remains the global router. v1 does not require FastAPI to talk directly to Codex app-server. Optional metadata registration may be added later for observability, but signal delivery v1 should not depend on FastAPI-initiated app-server calls.Install Contract
Install changes are capability checks only:- Verify
codexbinary exists when installing Codex support. - Verify
codex app-server --helpincludes--listenbefore advertising app-server injection support. - Continue writing
~/.codex/config.tomlMCP config. - Continue installing
coderlauncher. - Do not start app-server during install.
- Do not reserve ports during install.
Security
- v1 uses loopback only:
ws://127.0.0.1:<port>. - No LAN exposure of Codex app-server in v1.
- Future LAN mode requires explicit operator opt-in and WebSocket auth.
- Prism API key is never passed as a URL query parameter.
- App-server auth tokens/secrets, if used, are local-only and not persisted into Prism logs.
Acceptance Tests
Launcher:coder -agent codex -codex-app-server off -dry-runshows no--remoteand exports modeoff.coder -agent codex -codex-app-server auto -dry-runshows app-server discovery/start plan and fallback behavior.- Fake
codexsmoke verifies child process receivesPRISM_CODEX_APP_SERVER_URLwhen enabled. - Existing Codex CLI mappings remain green:
--cd,--sandbox,--ask-for-approval,--full-auto.
PRISM_AGENT_SURFACE=codex, no app-server URL ->PiggybackStrategy.PRISM_AGENT_SURFACE=codex, fake app-server reachable ->AppServerInjectStrategy.- Fake inject success -> delivered without piggyback buffer.
- Fake inject failure -> buffered for piggyback.
on_bootstrapandon_wrapare idempotent.
- Desiree -> Texi with no app-server still arrives through piggyback/poll.
- Desiree -> Texi with fake/local app-server inject path causes Texi’s Codex thread to receive an injected Prism signal item without manual
prism_signals_pending.
Open Questions
- Whether v1 should launch one app-server per Codex session or share a per-machine app-server. Recommendation: one per coder-launched Codex session.
- Exact app-server JSON-RPC request/response shape for
thread/inject_items; verify against installed Codex CLI generated schema or official docs. - Whether future LAN mode should exist at all, given Prism already has authenticated session stream plus local MCP bridge.

