Runtimes
A runtime is an external AI coding CLI that APX can invoke headlessly on behalf of an agent.
You use apx run to delegate a prompt to one of these tools; APX builds the system prompt, spawns
the CLI, captures its output, and stores a session record. The external tool drives the actual
model interaction, file edits, and shell commands — APX records the envelope.
This is distinct from apx exec, which calls an LLM engine directly inside APX without spawning
any external process. See Engines for that path.
Supported runtimes
Section titled “Supported runtimes”| Runtime ID | Binary | What APX spawns |
|---|---|---|
claude-code | claude | Headless -p mode; receives the agent’s system prompt via --append-system-prompt; returns structured JSON including a session_id that links to the Claude Code transcript |
codex | codex | codex exec --sandbox workspace-write --skip-git-repo-check; system prompt is prepended to the user prompt (no dedicated --system flag in exec mode) |
opencode | opencode | opencode run; system prompt prepended to prompt body |
aider | aider | aider --message --yes-always --no-auto-commits; non-interactive, no auto-commits |
cursor-agent | cursor-agent | --print --output-format text --trust --force; headless print mode |
gemini-cli | gemini | --prompt --output-format text --approval-mode yolo; headless prompt mode |
qwen-code | qwen | --output-format text --approval-mode yolo; system prompt via --append-system-prompt |
Check what’s installed
Section titled “Check what’s installed”Before picking a runtime, confirm which CLIs are available on the current machine:
apx env detect$ apx env detect RUNTIME: ✓ claude-code claude 1.0.44 ✓ codex codex 0.12.3 ✓ opencode opencode 0.3.1 · aider aider (not found) · cursor-agent cursor-agent (not found) ✓ gemini-cli gemini 0.2.0 ENGINE: ✓ ollama ollama 0.5.4 TOOL: ✓ git git 2.45.2 ✓ rg rg 14.1.0
The output groups results by category: runtime, engine, and tool. A runtime missing from
the list is not installed — install its binary first, then re-run apx env detect.
Running an agent
Section titled “Running an agent”apx run <agent> --runtime <id> "<prompt>" [--timeout <seconds>] [--project <name|id|path>]Examples:
# Full code review via Claude Codeapx run reviewer --runtime claude-code "Review the diff in src/ for memory leaks"
# Refactoring task via Codex with a longer timeoutapx run cody --runtime codex "Refactor parseAgentsMd to use a state machine" --timeout 600
# One-liner with OpenCodeapx run sofia --runtime opencode "Add JSDoc to every exported function in lib/"$ apx run reviewer --runtime claude-code 'Review this diff' • injecting reviewer system prompt into claude-code • project: Acme Store (#2) cwd: ~/code/acme-store I reviewed the diff. Three findings: 1. cart.js:42 — total is recomputed inside the render loop; hoist it. 2. checkout.js:88 — Stripe webhook signature is never verified. 3. tests are missing for the empty-cart path. I'd block the merge on #2 until the signature check lands. # claude-code | exit 0 | session: ~/.claude/projects/...../a1f3c92e.jsonl
Options
Section titled “Options”| Flag | Description |
|---|---|
--runtime <id> | Required. One of the runtime IDs in the table above |
--timeout <seconds> | Maximum wall-clock time before APX kills the subprocess |
--project <name|id|path> | Pin to a specific project; defaults to the current directory |
How APX injects the system prompt
Section titled “How APX injects the system prompt”When you run apx run, APX:
-
Reads the agent’s definition from
.apc/agents/<slug>.mdplus runtime memory from~/.apx/projects/<apx_id>/agents/<slug>/memory.mdand any loaded skills to build the full system prompt. -
Calls
buildAgentSystem({ invocation: "runtime", runtime: "<id>" })— the same builder used byapx execandapx chat, but with theruntimeinvocation tag so prompts can branch. -
Passes the result to the CLI’s system-prompt injection mechanism (e.g.
--append-system-promptforclaude-codeandqwen-code, or prepended to the prompt body for runtimes that lack a dedicated flag). -
Captures stdout. If the output includes a line starting with
APC_RESULT:, that value is stored as the session’s structured result field. -
Writes a session file at
~/.apx/projects/<apx-id>/agents/<slug>/sessions/<date>-<runtime>-<id>.mdwith a frontmatter link back to the external tool’s own transcript path (when the runtime provides it).
Session records and resuming
Section titled “Session records and resuming”After apx run completes, APX creates a session record:
# ~/.apx/projects/<apx-id>/agents/reviewer/sessions/2026-05-27-claude-code-abc123.md---runtime: claude-codesession_id: abc123external_session_path: /Users/me/.claude/projects/<encoded-cwd>/abc123.jsonl---The external_session_path points to the external tool’s own transcript. You can read, summarize,
or continue from it using the session commands:
# List recent runtime sessions for an agentapx session list reviewer
# Summarize what happened in a sessionapx session resume <id> --summary
# Read the raw transcriptapx session get <id> --full
# Continue the session in Claude Code's native CLIapx session resume <id> --continueStructured results with APC_RESULT
Section titled “Structured results with APC_RESULT”If you want APX to capture a machine-readable value from the external runtime, instruct the model (via the prompt) to print on its last line:
APC_RESULT: <one-line value>APX parses this and stores it as the session’s result field, which other routines or the
super-agent can read.
Delegating from the super-agent (call_runtime)
Section titled “Delegating from the super-agent (call_runtime)”apx run is a command you type. But the super-agent itself can also decide, mid-conversation, to
hand a task off to an external runtime — it has a call_runtime tool for exactly that (same
runtime IDs, same spawn logic as above). This is what happens when you ask the agent on Telegram,
web, or apx exec to “have Claude Code refactor this” or “run this through Codex”.
Synchronous vs. background delegation
Section titled “Synchronous vs. background delegation”A call_runtime call can either block the current turn until the runtime finishes, or launch the
runtime detached and let the turn end immediately:
- Synchronous (blocking) — the default on surfaces with no way to deliver a late result (web,
desktop,
apx exec). The tool call doesn’t return until the runtime process exits, and the runtime’s output comes back as this turn’s tool result. - Background (async) — the default on Telegram, because a runtime like
claude-codecan run for minutes to over an hour, and blocking would freeze the super-agent and hold the “typing…” indicator the whole time. In background mode,call_runtimespawns the runtime detached and returns immediately with{ status: "launched", background: true, apc_session: "<id>" }. The agent replies right away (e.g. “lo lancé, te aviso”) and the turn ends — the runtime keeps working in the background.
Background mode is only available when there’s a channel to deliver the result to later (see
Callback delivery (A2A) below); today that means a Telegram chat. The
model can still force a blocking call on Telegram by passing background: false — useful when it
needs the runtime’s output inside the same turn for an immediate follow-up.
Timeout also shifts with the mode: a foreground call defaults to 300s before APX sends SIGTERM;
a background call defaults to 3600s (1 hour), since detached runs are expected to take longer.
Either can be overridden per call.
Callback delivery (A2A)
Section titled “Callback delivery (A2A)”When a background run finishes, its result has to reach the user without anyone waiting on it. APX delivers it in one of two ways:
- A2A report (preferred) — the result is fed back into a fresh super-agent turn as an internal report (tagged so it reads as an agent-to-agent hand-off, not a user message). The super-agent relays it to the user in its own voice, and can chain a next step if the task isn’t done. This is what happens on Telegram: the finished run re-enters the conversation and the agent sends a new message summarizing it.
- Direct channel send (fallback) — if the A2A path isn’t wired up or fails, APX sends a plain message to the originating chat instead: a ”✅ finished” or “⚠️ failed” line followed by the runtime’s result, with no super-agent rephrasing.
Durable delivery across daemon restarts
Section titled “Durable delivery across daemon restarts”Launching a background run also writes a small pending-callback record (~/.apx/pending-callbacks/ <apc_session>.json) — an IOU noting which chat is owed the result. If the daemon that launched the
run dies before the runtime finishes (a crash, a git pull + restart, or a delegated task that
restarts the daemon), that in-memory callback would normally be lost. Instead, a reconciler runs at
daemon boot and on a 30-second interval, checks each pending callback’s session record, and once the
session shows the run completed, delivers the result as a direct channel send and removes the IOU.
This also covers the case where the external runtime itself proactively closed its APX session
(e.g. via apx session close) rather than APX’s own process wait detecting the exit.
The two delivery paths don’t double up: the reconciler gives the live in-process delivery a grace window before it will deliver the same callback itself.
run vs. exec
Section titled “run vs. exec”apx run | apx exec | |
|---|---|---|
| What runs | External CLI (claude, codex, …) | Direct LLM call inside APX |
| File edits / shell | Yes — the external CLI can write files and run commands | No — read-only LLM response |
| Model choice | Controlled by the external CLI’s own config | Controlled by --model or the agent’s configured model |
| Session transcript | Stored both in APX and in the external tool’s own path | Stored in APX conversations only |
| Use when | You need full coding-agent capabilities (edits, terminal) | You need a quick answer or one-shot generation |
Related
Section titled “Related”- Engines — direct LLM calls with
apx execandapx chat - Configuration —
~/.apx/config.jsonreference