Configure agents, presets, transport

Detect installed agent CLIs, pick launch presets, and choose how each one authenticates and talks to Orchemax.

Goal#

Tell Orchemax which coding-agent CLIs are on your machine, how to launch each one (headless dispatch vs. native TUI), which credentials it should use, and — for the few that support it — how to drive it over the Agent Client Protocol (ACP) instead of scraping a subprocess pipe.

Steps#

  1. Scan your PATH for known agent CLIs (Claude, OpenCode, Cursor, Codex, Copilot, …):

    orch agents scan
    

    Writes a snapshot; does not touch orch.yaml yet.

  2. Review what was found:

    orch agents show
    
  3. Apply new detections to orch.yaml (never overwrites presets you already edited):

    orch agents apply
    
  4. Presets live in two maps in orch.yaml:

    • agents.cmds.<preset> — headless BYO template used by dispatched workers, e.g. claude -p "{{prompt}}". Built-ins ship for copilot, claude, opencode, grok, kimi, commandcode, agy, codex and cursor.
    • agents.interactive.<preset> — native TUI launch used by orch <preset> (no prompt required), e.g. codex, cursor-agent, claude, opencode --hostname 127.0.0.1 --port {{notify_port}}.
    • agents.workers — optional cheap-worker roster the Chair prefers when spawning (agent CLI + gateway model). List order is preference. Workers are metered by orch.agents.concurrent. Open Chairs are metered by orch.agents.max (Starter 2, Professional 5, Team 10). MCP-only Chairs do not consume the worker meter.

    Leave it off with an empty list or omit the key (Chair then uses its own agent). A fresh orch setup seeds agents.auth so plan-login vs API-key seats are explicit.

    Pi (workers on external LLMs): put agent: pi on the roster or spawn dispatch_worker {agent: "pi", model: "..."}. Orchemax automatically installs and manages Pi whenever you use workers powered by different LLMs from the primary seat (pinned @earendil-works/pi-coding-agent under machine-home tools/pi/<version>; Node ≥ 22.19). The worker runs in its own worktree, so only its own model is billed for that subtask and the Chair's window does not grow with it. Per-seat token counts are in /app/board. Skip auto-install with ORCH_SKIP_PI_ENSURE=1.

    agents:
      auth:
        cursor: account          # plan login — no gateway API key
        claude: account
        codex: account
        agy: account
        gemini: account
        opencode: gateway        # API-key / BYO → local gateway
        openclaude: gateway
        commandcode: gateway
        pi: gateway
      workers: []                # or fill: agent + optional model/tier
      # opt-in cheap workers, e.g.:
      # workers:
      #   - agent: pi
      #     model: deepseek-v4.1-flash
      #     name: cheap-pi
      #     tier: cheap
    

    Interactive Cursor flags (--approve-mcps --trust) live in the built-in preset — override only if you need different flags:

    agents:
      interactive:
        cursor: cursor-agent --approve-mcps --trust
    

    Optional worker roster (placeholders like your-*-here never spawn):

    agents:
      workers:
        - agent: claude
          model: sonnet              # vendor LLM default (account lane)
          name: plan-login
          tier: account
        - agent: opencode
          model: deepseek-v4-flash   # gateway LLM → orchemax/<id>
          name: api-key
          tier: cheap
    
    • tier: account — vendor plan login; model is the vendor default LLM; no API key. Roster tier / optional auth: drives credential mode on spawn.
    • tier: cheap (gateway) — gateway picks upstream keys; OpenCode-family default provider account is orchemax. Mix account + gateway rows freely.
    • Workers are secondary work inside one project. Other open project Chairs → bus to_project (see Same CLI, many projects), not stand-in workers.

    entitlements_status.workers shows the live roster to the Chair. dispatch_worker {agent, model, prompt} can pass both from that list.

    Edit either map directly in orch.yaml to add a CLI Orchemax doesn't know about, or to change an existing template. Dispatching a recognized CLI preset that has no agents.cmds.<preset> entry fails loudly to the Chair (preset "<preset>" has no headless command: set agents.cmds.<preset>) instead of silently running the stub agent — add the entry to fix it.

    A headless preset must also actually load Orchemax's own MCP server from the worktree (.cursor/mcp.json / .mcp.json / .orch/mcp.json), not just run — otherwise every worker-side tool (msg_send, verify_report, lock_acquire, symbols) is dead for the whole session.

    orch agents apply runs category fine-tunes from the agent catalog (traits): GEMINI.md pointers, login-auth notes, headless flags (--add-dir, --approve-mcps), and the next step when USER-scope wire is required. It never writes user-home configs without consent.

    Category Effect Agents (examples)
    Project MCP Loads worktree .mcp.json / .cursor/mcp.json cursor, copilot, claude, opencode
    Global MCP (USER) One machine-wide entry — needs consent agy
    Auth login Do not put an API key in keys.env agy, gemini
    Headless --add-dir Pin writes to the worktree agy
    Headless --approve-mcps Project MCP loads without a UI cursor
    Interactive --approve-mcps --trust Skip Cursor’s MCP approval whitelist TUI on orch cursor cursor
    Tool auto-approval Suppress confirmation prompts (governed by Orchemax) agy, cursor, opencode

    copilot reads workspace .mcp.json on its own; cursor needs --approve-mcps on interactive and headless (its project MCP server otherwise sits "not loaded (needs approval)", and the interactive approve TUI often freezes — see common-seat-tune-ups and troubleshooting.md). agy reads no per-workspace MCP file at all — it has one machine-global config — so Orchemax registers a single global entry only when you ask:

    orch guard wire --agy --scope user --allow-user-scope
    

    That runs agy mcp add orch <orch executable> mcp, which agy documents as "add or update": re-running replaces the orch entry and leaves your other MCP servers alone. orch setup does not do this (USER-scope is never part of setup). After orch agents apply, if agy was among the applied agents, the CLI prints that wire command. The entry deliberately carries no workspace arguments — every agy worker on the machine shares it, and orch mcp works out which workspace it belongs to from ORCH_CONFIG (dispatch injects it into every worker, along with ORCH_SESSION for the worker's identity), falling back to walking up from the working directory. Two workers in two different workshops can therefore use the one entry at the same time.

    Check it with agy mcp list (orch stdio enabled …). If it is missing or disabled, an agy worker still runs and still exits 0 — with zero Orchemax tools and nothing in its log to say so — so Orchemax closes the session guardrails: fail with orch MCP unavailable in worker — run orch guard wire --agy --scope user --allow-user-scope.

    agy also needs --add-dir "{{worktree}}" in its headless preset (it ships that way): agy does not treat its working directory as the workspace, and without the flag it writes the worker's files into its own ~/.gemini/antigravity-cli/scratch/ and leaves the worktree untouched.

    Tool execution permissions & prompt suppression: Because Orchemax already governs worktree isolation, .sandbox/, and verification gates, child agent CLIs run with auto-approval flags so unattended dispatches and interactive seats are not interrupted by confirmation prompts on every tool call. For Antigravity, Orchemax injects --dangerously-skip-permissions into both headless workers and orch agy interactive seats. Cursor interactive uses --approve-mcps --trust; headless also --force (and --output-format json). OpenCode uses run --auto. Any BYO CLI can specify its own non-interactive flags under agents.interactive.<preset> and agents.cmds.<preset> (vendor allowlists often re-prompt when Orchemax rewrites MCP config — see common-seat-tune-ups).

  5. Choose the credential mode per preset with agents.auth.<preset>:

    • account — the agent keeps its own plan login (Cursor, Claude Pro/Max, Codex, …); Orchemax injects only its own ORCH_GATEWAY_* vars, never provider keys. The gateway does not carry model traffic.
    • gateway — the agent authenticates with Orchemax's virtual key and model traffic routes through the local gateway (API-key / BYO seats only: OpenCode, OpenClaude, Command Code, BYOK, …).

    Defaults: codex and cursor are account. claude is gateway only when an Anthropic passthrough key is configured, otherwise account. Other BYO / API-key seats tend to gateway (OpenAI-compat is the default wire).

    Wire the gateway by protocol, not per CLI name:

    Protocol Command
    Account / plan (Cursor, Claude plan, Codex) — (keep vendor login)
    OpenAI-compat (OpenCode, OpenClaude, Command Code, BYOK, …) orch gateway connect / openai
    OpenCode file write (optional) orch gateway connect opencode --allow-user-scope
    Anthropic Messages (Claude + API key) orch gateway connect anthropic

    Full matrix: gateway-keys-and-connect.md.

    agents.route.<preset> is the related switch for CLIs that read a config file of their own, currently OpenCode. Unset, a dispatched OpenCode worker gets an Orchemax-owned OPENCODE_CONFIG pointed at the local gateway only when that gateway has a live provider (ai.mode: live plus at least one provider key); otherwise the log records route: opencode-native (workspace gateway has no live provider) and the CLI keeps its own config, which Orchemax never writes. Force either side with:

    agents:
      route:
        opencode: gateway   # or: native
    

    Starting the proxy is not consent to edit your profile: orch gateway run never writes ~/.config/opencode/opencode.json nor the User ORCH_GATEWAY_KEY. Those belong to orch setup and orch guard wire --opencode --scope user --allow-user-scope, which back up what they touch to <file>.bak-<timestamp>.

  6. For CLIs that expose an Agent Client Protocol server mode — currently gemini (gemini --acp) and opencode (opencode acp) — set:

    agents:
      transport:
        gemini: acp
    

    ACP makes tool calls and permission prompts visible to Orchemax instead of scraping stdout. Any other preset stays on the default subprocess transport; agents.acp.<preset> holds the invocation Orchemax runs to put the CLI into ACP mode (built-in for gemini/opencode, empty for everything else — a preset with no ACP entry cannot use transport: acp).

  7. Set run limits:

    agents:
      timeout_sec: 600        # hard wall-clock cap per run (0 = default)
      idle_timeout_sec: 0     # kill if no stdout/stderr for this long; 0 = the built-in default (420s), negative = off
    

AGENTS.md — one instruction file for every CLI#

orch init, orch project add, and orch setup write a compact (under 1.5 KB) AGENTS.md at the root of every registered project: the project's locale/code_lang, which guard.* gates are on, the item-144 sandbox rule, and how to reach Orchemax (the orch MCP server, or the orch CLI). Content lives inside an <!-- orch:begin --> … <!-- orch:end --> block, so a re-run always refreshes it without touching anything you add outside the markers.

Every managed CLI reads it, project scope only:

  • Codex, OpenCode — read AGENTS.md natively; nothing else to wire.
  • Claude Code — the project's CLAUDE.md carries an @AGENTS.md include.
  • Cursor — .cursor/rules/orch.mdc (alwaysApply: true) points at it.
  • Copilot — .github/copilot-instructions.md points at it.
  • Gemini / agy — GEMINI.md points at it.

Check what each CLI is actually reading with:

orch harness scan

which prints one row per CLI per project — the file it reads, and whether that file still points at AGENTS.md.

Verify#

orch <preset>

launches the native TUI for that preset. For a headless dispatch, check .orch-agent.log in the session's worktree for the resolved command and any permission/timeout exit codes (124 = agents.timeout_sec/idle timeout, 126 = a headless permission prompt Orchemax couldn't answer).

Undo#

Remove the preset's entry from agents.cmds / agents.interactive, or reset agents.auth.<preset> / agents.transport.<preset> to unset to fall back to the defaults above.

  • Configure agents
  • Common seat tune-ups — terminal UI Orchemax owns, OpenClaude model pinning, dontAsk vs bypassPermissions, Notification wire, turn caps
  • ../talk-to-orch/connect-openclaude-gateway.md — OpenClaude recipe.
  • troubleshooting.md — worker permission timeouts.