GenAgent.Backend implementation backed by CodexWrapper.
CodexWrapper 0.5.3 streams NDJSON while closing CLI stdin. This
backend forwards translated events as they arrive, so
handle_stream_event/2 can observe progress during a turn.
Session continuation
Codex reports its persistent thread identifier as thread_id in the
first thread.started event of a turn, not in the terminal
turn.completed event. The EventTranslator captures it and
injects it into the :result event as session_id. This backend's
update_session/2 then records it on the session struct, and the
next turn is dispatched via ExecResume with that id.
terminate_session/1 has no native process to close. GenAgent cancels
its prompt task on interrupt, watchdog, stop, or agent death, but the
default Port runner closes pipes without guaranteeing that the CLI and
its subprocesses have exited. Choose a runner with process-group
termination when OS-level settlement is required.
Options accepted by start_session/1
Config-level (forwarded to CodexWrapper.Config.new/1):
:binary,:working_dir(aliased as:cwd),:env,:timeout,:verbose
Exec-level (forwarded to CodexWrapper.Exec):
:model,:sandbox,:approval_policy,:full_auto,:dangerously_bypass_approvals_and_sandbox,:skip_git_repo_check,:ephemeral,:config_overrides,:enabled_features,:disabled_features,:images,:output_schema
Options that cannot be preserved on exec resume (:cd,
:add_dirs, :search) are rejected by
start_session/1. Use :working_dir / :cwd for a directory that
persists across turns. Session options are translated into supported
resume arguments; :sandbox and :approval_policy use config
overrides because resume does not accept their exec flags.
Backend-only:
:exec_fn-- a 2-arity function(prompt, session) -> {:ok, Enumerable.t()} | {:error, term()}that replaces the defaultExec/ExecResumedispatch. Intended for tests.
Codex has no equivalent of Claude's --system-prompt; if you need
system-level instructions, pass them via AGENTS.md in the working
directory or through Codex's configuration layer.
Summary
Types
@type t() :: %GenAgent.Backends.Codex{ config: CodexWrapper.Config.t(), exec_fn: (String.t(), t() -> {:ok, Enumerable.t()} | {:error, term()}), exec_opts: keyword(), thread_id: String.t() | nil }