Skip to content

Code mode: out-of-process code-runner and backend executor client #1361

Closed

Description

@helpcodeai

Summary

Add an out-of-process code-runner and the backend client that drives it, as the foundation for code mode (executing short JS programs that orchestrate several MCP tool calls in one round trip). This issue tracks the runner subsystem and the transport client only; the execution-path, schema, governance and Cloud pieces are tracked in the linked issues.

Design

  • Runner (deploy/code-runner/): one container, long-lived supervisor (PID 1, root) that spawns one Deno subprocess per run under an unprivileged uid with a cleared environment. The subprocess runs user code with every Deno permission denied and an import map that blocks every file:/node:/npm:/remote specifier. The only way out is the amcp bridge (search/describe/run), shuttled back to the backend over a WebSocket. No egress, no filesystem, no env, no secrets in the child.
  • Backend client (CodeExecutorService): opens the WebSocket per run, answers each bridge call via the existing executeTool under the caller's role scope, enforces transport-level ceilings, and refuses when no runner is configured or reachable (never runs in-process).

Security model (defence in depth)

Deno --deny-* flags + --no-remote/--no-npm/--cached-only; an import map that closes the import-based file reads (import(..., {with:{type:'text'|'json'}}), relative imports, new Function, data:/blob: chains) that --deny-read alone does not stop; setpriv to an unprivileged uid; env -i so the run token is never in the child environment; container read_only + cap_drop: ALL (only SETUID/SETGID) + no-new-privileges.

Verification

deploy/code-runner/test.sh: 19/19 containment assertions (fetch, file read, env, subprocess, FFI, node:fs, node:child_process, /proc/self/environ, text/json/relative/new Function imports all denied; compute/bridge/console allowed; timeout kills; errors propagate) and the end-to-end WebSocket path. Verified on denoland/deno:debian-2.9.8.

Status

Implemented and verified on branch helpcodeai/code-mode, OFF by default (CODE_RUNNER_URL unset; code-runner compose profile). No schema change. Backend: tsc clean, eslint clean, unit tests pass.

Deployment behaviour

  • Self-hosted: COMPOSE_PROFILES=code-runner + CODE_RUNNER_URL=ws://code-runner:8777.
  • Cloud: dedicated service (wiring tracked separately).
  • Both: unreachable runner ⇒ code mode unavailable, runs refused.

Activity

  1. helpcodeai commented on Oct 31, 2026

    @helpcodeai
    ContributorAuthor

    Implemented on branch helpcodeai/code-mode (commit 6d872de). The code-runner (Dockerfile, supervisor, harness, import map) and the backend CodeExecutorService are in place and off by default. Containment + bridge verified with deploy/code-runner/test.sh (19 containment assertions + the end-to-end WebSocket path) on deno 2.9.8. Done.

  2. helpcodeai commented on Oct 31, 2026

    @helpcodeai
    ContributorAuthor

    Delivered in PR #1366 (merged into main as be4742a). Code mode ships off by default; the agent-proposal follow-up is tracked in #1369, and the Cloud runner operations in this issue remain operational/out-of-repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions