Skip to content

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.

Runtime IDBinaryWhat APX spawns
claude-codeclaudeHeadless -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
codexcodexcodex exec --sandbox workspace-write --skip-git-repo-check; system prompt is prepended to the user prompt (no dedicated --system flag in exec mode)
opencodeopencodeopencode run; system prompt prepended to prompt body
aideraideraider --message --yes-always --no-auto-commits; non-interactive, no auto-commits
cursor-agentcursor-agent--print --output-format text --trust --force; headless print mode
gemini-cligemini--prompt --output-format text --approval-mode yolo; headless prompt mode
qwen-codeqwen--output-format text --approval-mode yolo; system prompt via --append-system-prompt

Before picking a runtime, confirm which CLIs are available on the current machine:

Terminal window
apx env detect
apx
$ 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
apx env detect — shows installed runtimes, local LLM runners, and tools

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.

Terminal window
apx run <agent> --runtime <id> "<prompt>" [--timeout <seconds>] [--project <name|id|path>]

Examples:

Terminal window
# Full code review via Claude Code
apx run reviewer --runtime claude-code "Review the diff in src/ for memory leaks"
# Refactoring task via Codex with a longer timeout
apx run cody --runtime codex "Refactor parseAgentsMd to use a state machine" --timeout 600
# One-liner with OpenCode
apx run sofia --runtime opencode "Add JSDoc to every exported function in lib/"
apx
$ 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
apx run in progress — external Claude Code session with injected system prompt
FlagDescription
--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

When you run apx run, APX:

  1. Reads the agent’s definition from .apc/agents/<slug>.md plus runtime memory from ~/.apx/projects/<apx_id>/agents/<slug>/memory.md and any loaded skills to build the full system prompt.

  2. Calls buildAgentSystem({ invocation: "runtime", runtime: "<id>" }) — the same builder used by apx exec and apx chat, but with the runtime invocation tag so prompts can branch.

  3. Passes the result to the CLI’s system-prompt injection mechanism (e.g. --append-system-prompt for claude-code and qwen-code, or prepended to the prompt body for runtimes that lack a dedicated flag).

  4. Captures stdout. If the output includes a line starting with APC_RESULT:, that value is stored as the session’s structured result field.

  5. Writes a session file at ~/.apx/projects/<apx-id>/agents/<slug>/sessions/<date>-<runtime>-<id>.md with a frontmatter link back to the external tool’s own transcript path (when the runtime provides it).

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-code
session_id: abc123
external_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:

Terminal window
# List recent runtime sessions for an agent
apx session list reviewer
# Summarize what happened in a session
apx session resume <id> --summary
# Read the raw transcript
apx session get <id> --full
# Continue the session in Claude Code's native CLI
apx session resume <id> --continue

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”.

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-code can 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_runtime spawns 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.

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:

  1. 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.
  2. 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.

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.

apx runapx exec
What runsExternal CLI (claude, codex, …)Direct LLM call inside APX
File edits / shellYes — the external CLI can write files and run commandsNo — read-only LLM response
Model choiceControlled by the external CLI’s own configControlled by --model or the agent’s configured model
Session transcriptStored both in APX and in the external tool’s own pathStored in APX conversations only
Use whenYou need full coding-agent capabilities (edits, terminal)You need a quick answer or one-shot generation
  • Engines — direct LLM calls with apx exec and apx chat
  • Configuration~/.apx/config.json reference