Backends¶
All agent sessions in Houmao are executed by a backend. Each backend implements the InteractiveSession protocol, providing a uniform interface for prompt delivery, interruption, and termination regardless of the underlying agent tool or execution mode.
The canonical backend list is defined by the BackendKind literal type in src/houmao/agents/realm_controller/models.py. Adding a new backend requires updating BackendKind, wiring the backend through launch_plan.py, and implementing the InteractiveSession protocol.
BackendKind¶
BackendKind = Literal[
"local_interactive",
"claude_headless",
"codex_headless",
"kimi_headless",
"codex_app_server", # unmaintained: blocked at launch with an explicit error
"cao_rest",
"houmao_server_rest",
]
Backend dispatch¶
flowchart LR
LP["LaunchPlan<br/>.backend"]
LI["LocalInteractiveSession<br/>persistent TUI in tmux pane<br/>send_prompt via tmux paste<br/>captures pane output"]
CH["ClaudeHeadlessSession<br/>claude -p per turn<br/>JSON streaming output<br/>--continue for resume"]
CX["CodexHeadlessSession<br/>codex exec --json per turn<br/>resume via thread_id"]
KH["KimiHeadlessSession<br/>kimi -p per turn<br/>--session <session_id>"]
LEG["Legacy/internal backends<br/>cao_rest / houmao_server_rest<br/>rejected for new public launches"]
UNM["Unmaintained backends<br/>codex_app_server<br/>blocked at launch with an explicit error"]
LP -->|local_interactive| LI
LP -->|claude_headless| CH
LP -->|codex_headless| CX
LP -->|kimi_headless| KH
LP -.->|legacy manifests only| LEG
LP -.->|blocked| UNM
Backend reference¶
local_interactive (primary)¶
Source: backends/local_interactive.py
The primary backend for interactive agent sessions. The agent runs as a real interactive CLI process inside a tmux pane, preserving the tool's native user experience (colors, interactive prompts, streaming output). Maintained local interactive tools are Claude Code, Codex, and Kimi Code.
- Session class:
LocalInteractiveSession - Prompt delivery: via tmux paste-buffer with bracketed paste and a separate final submit key.
- Relaunch continuation: provider-native startup arguments are applied before respawning the TUI in tmux window
0. - Interrupt: Escape is the primary interrupt/cancel key for maintained TUI providers, including Kimi Code.
- Role injection: tool-dependent; see Role Injection.
- Use case: development, debugging, and any workflow where direct interactive access to the agent is valuable.
Kimi Code local interactive¶
Kimi local interactive support starts the interactive kimi TUI under backend local_interactive; it does not reuse or rename kimi_headless.
- Process recognition: live process inspection treats both
kimi-codeandkimias supported Kimi TUI process names. - Role injection: Kimi Code 2.1.1 or later loads the complete composed Houmao prompt from managed
$KIMI_CODE_HOME/SYSTEM.mdbefore TUI startup. Houmao preserves Kimi's built-in prompt with${base_prompt}and does not submit a role chat turn. - Model selection: launch-owned Kimi model selection is projected as
--model <alias>for fresh and resumed Kimi TUI startup. - Update suppression: managed Kimi TUI launches set
KIMI_CODE_NO_AUTO_UPDATE=1so startup does not stop on the interactive update preflight. - Managed skills: Houmao does not add managed
--skills-dirarguments to Kimi TUI launches. The maintained--skills-dir <KIMI_CODE_HOME>/skillsprojection remains Kimi headless prompt-mode behavior. - Unattended prompt mode: for maintained Kimi Code 2.1.1 or later, launch policy writes the migration marker and
default_permission_mode = "auto"fallback, canonicalizes permission inputs, appends one native--auto, and pre-seeds the provider workspace-trust record for the launch working directory so startup does not stop on the "Trust this folder?" modal. The ready TUI is already unattended;as_isleaves provider approval and trust behavior unchanged. - Relaunch continuation:
tool_last_or_newmaps tokimi --continue;exactmaps tokimi --session <session_id>. The runtime never uses barekimi --sessionfor managed relaunch because that opens Kimi's interactive picker. - Resume behavior: Kimi Code 2.1.1 or later accepts native
--autowith--continueand--session <session_id>. Houmao strips conflicting caller permission flags, preserves the resolved resume selector, verifies and repairsSYSTEM.md, and appends one strategy-owned--auto;--model <alias>remains allowed.
claude_headless¶
Source: backends/claude_headless.py
Runs Claude Code CLI in headless mode (claude -p --verbose). Output is captured programmatically rather than displayed in an interactive terminal.
- Session class:
ClaudeHeadlessSession(extendsHeadlessInteractiveSession) - Resume:
--continueresumes the provider's latest stored conversation;--resume <session_id>resumes an exact provider session. - Role injection: when the role prompt is non-empty, Houmao passes
--append-system-prompt <prompt>and sends one bootstrap message on the first turn. Empty prompts skip both startup inputs. - Use case: automated pipelines, batch processing, and non-interactive agent orchestration.
codex_headless¶
Source: backends/codex_headless.py
Runs Codex CLI in headless mode (codex exec --json). Produces structured JSON output for programmatic consumption.
- Session class:
CodexHeadlessSession(extendsHeadlessInteractiveSession) - Resume:
resume --lastasks Codex to continue its latest stored chat;resume <session_id>resumes an exact provider session. - Role injection: when the role prompt is non-empty, Houmao passes
-c developer_instructions=<prompt>. Empty prompts skip the developer-instructions flag. - Use case: automated pipelines, structured output processing, and non-interactive agent orchestration.
kimi_headless¶
Source: backends/kimi_headless.py
Runs Kimi Code CLI in prompt mode (kimi -p <prompt> --output-format stream-json).
- Session class:
KimiHeadlessSession(extendsHeadlessInteractiveSession) - Auth lanes: managed Kimi homes use
KIMI_CODE_HOMEand support OAuth material through projectedconfig.tomlpluscredentials/kimi-code.json, or env-model material through allowlistedKIMI_MODEL_*values. - Managed skills: Houmao-owned Kimi skills project into top-level
skills, and managed launches pass--skills-dir <KIMI_CODE_HOME>/skillsso they do not depend on user-global skill discovery. - Resume:
--continueasks Kimi to continue the latest stored session for the working directory;--session <session_id>resumes an exact provider session. Resume stays bound to the same recorded working directory/project context. - Role injection: managed-home native
SYSTEM.md, verified before each fresh or resumed provider start. A promptless build removes a stale file. - Use case: automated pipelines and non-interactive agent orchestration for Kimi Code.
Managed Kimi support starts at version 2.1.1 and has no upper version limit. Both Kimi backends force KIMI_CODE_LEGACY_FLAG=0, reject explicit or project agent profiles that outrank SYSTEM.md, and reject any ${identifier} token in the complete effective prompt before provider launch.
Kimi validation checklist¶
- OAuth lane: create or import a Kimi auth bundle with
config.tomlandcredentials/kimi-code.json, build or launch a managed Kimi home, and confirmKIMI_CODE_HOMEpoints at that constructed home. - Env-model lane: create a Kimi auth bundle with
KIMI_MODEL_NAMEandKIMI_MODEL_API_KEY, build or launch a managed Kimi home, and confirm those env vars are exported without depending on user-global~/.kimi-code. - Skill projection: inspect the constructed home and confirm selected and Houmao-owned skills land under
skills/. - Native prompt projection: inspect
SYSTEM.md, confirm it starts with${base_prompt}, compare its recorded effective and rendered SHA-256 digests, and confirm the first user prompt is substantive work rather than role delivery. - First-turn capture: verify the first
stream-jsonKimi turn emits asession.resume_hintevent and that Houmao persists itssession_idinto the managed session manifest. - Resume behavior: send a follow-up Kimi prompt from the same working directory and confirm Houmao launches
kimi --session <persisted-session-id> -p <prompt> --output-format stream-json; changing the working directory should fail explicitly. - Local-interactive unattended posture: launch fresh, latest-resume, and exact-resume Kimi TUI sessions with
operator_prompt_mode = unattended; confirm each effective command contains one strategy-owned--auto, the migration picker is suppressed, and no confirmation appears before managed prompts.
codex_app_server (unmaintained, blocked)¶
Source: backends/codex_app_server.py (retained as dead code)
Runs Codex in app-server mode over a stdio JSON-RPC channel. This backend has not been qualified against current Codex releases and is unmaintained: launch requests and retained manifests naming codex_app_server are rejected with an explicit unmaintained-backend error, and no Codex process is started.
- Migration: use
codex_headlessfor structured non-interactive sessions orlocal_interactivefor tracked TUI sessions. - Role injection (historical): native developer instructions (same as
codex_headless).
cao_rest (legacy/internal)¶
Source: backends/cao_rest.py
Legacy backend that delegated session management to an external REST API. Public operator starts for this backend are retired and fail with migration guidance.
- Role injection: profile-based injection via the external server.
- Note: standalone operator use of
backend='cao_rest'is retired in favor of maintainedhoumao-mgrlocal/headless flows andhoumao-passive-serverAPI workflows.
houmao_server_rest (legacy/internal)¶
Source: removed public backend implementation; retained manifests are rejected before new session creation.
Legacy old-server-backed path. New runtime manifests with this backend are not supported.
- Role injection: profile-based injection via the server.
- Note: use maintained local/headless runtime backends or passive-server-owned headless launch APIs.
Headless backend base class¶
The maintained native headless backends (claude_headless, codex_headless, kimi_headless) share a common base class: HeadlessInteractiveSession.
This base class manages:
- tmux-backed process execution: even in headless mode, the agent process runs inside a tmux pane for uniform process management, signal delivery, and output capture.
- Resumable session state via
HeadlessSessionState, which tracks: session_id— backend-specific session/thread identifier for resume.turn_index— number of prompt turns completed in this session.role_bootstrap_applied— whether the first-turn role bootstrap message has been delivered.
This shared infrastructure ensures consistent behavior across headless backends for concerns like process lifecycle, output buffering, and session persistence.
Relaunch Chat-Session Mapping¶
Tmux-backed relaunch accepts a relaunch-only chat-session selector. It does not affect first launch and is distinct from gateway prompt-control chat-session selectors.
| Tool | Local interactive latest | Local interactive exact | Native headless latest | Native headless exact |
|---|---|---|---|---|
| Claude Code | claude --continue |
claude --resume <session_id> |
claude -p --continue <prompt> |
claude -p --resume <session_id> <prompt> |
| Codex | codex resume --last |
codex resume <session_id> |
codex exec resume --last <prompt> |
codex exec resume <session_id> <prompt> |
| Kimi Code | kimi --continue |
kimi --session <session_id> |
kimi --continue -p <prompt> |
kimi --session <session_id> -p <prompt> |
When the relaunch selector is omitted, the runtime uses new and starts a fresh provider chat. When a local interactive relaunch resumes an existing provider chat, bootstrap-message role injection is not replayed into that chat.
InteractiveSession protocol¶
All backends implement the InteractiveSession protocol:
class InteractiveSession(Protocol):
def send_prompt(self, prompt: str) -> list[SessionEvent]: ...
def interrupt(self) -> SessionControlResult: ...
def terminate(self) -> SessionControlResult: ...
def close(self) -> None: ...
See Session Lifecycle for details on how the protocol is used.
See also¶
- Launch Plan — how backend-specific launch plans are composed
- Role Injection — per-backend role injection strategies
- Session Lifecycle — how backends are used within the session lifecycle