Skip to content
UHPUHPDeveloper Guide
Independent resource · Not affiliated with HarnessRouter · Site data checked 18 Sep 2026

Architecture pattern

Containerized subagent execution

Containerizing a child agent is not the same as putting the whole harness in a sandbox. The useful boundary is narrower: the parent model loop can remain on the host while a child tool runtime moves into Docker or Podman under an operator-owned policy that the model cannot weaken.

Verified: Protocol: 2026-09-12Evidence: Qwen Code PR #11711

Containerized subagent execution is an implementation pattern in which a parent harness keeps the model loop, authorization decisions and transcript on the host while selected child-agent tools execute inside an isolated container runtime. It is not a UHP, MCP, ACP or A2A protocol primitive.

Qwen Code PR #11711 is a useful current primary-source example. Merged on 18 September 2026 as 907667bbd61255dee87dc5efc3f8d1ef5b714c66, it adds ordinary-subagent execution through Docker or Podman on Unix hosts while deliberately keeping the parent loop and approval authority outside the container.

The important distinction is:

Parent harness on host
├── model requests
├── transcript
├── authorization / approval decisions
└── child-execution policy
│ typed worker contract
Containerized child runtime
├── file-tool preparation and execution
├── shell processes
├── child-local tool state
└── selected workspace mount

A worktree separates working files. A container can also relocate the child tool lifecycle and process namespace. Neither automatically makes the parent session, approval channel or every nested integration untrusted-code-safe.

Why this is a distinct architecture boundary

Section titled “Why this is a distinct architecture boundary”

Worktree isolation alone does not change who executes commands. A child operating in another worktree can still run shell commands and filesystem APIs with the host user’s permissions. Moving only a shell subprocess is also incomplete if file validation, path resolution, edit preparation, caches and cleanup still happen through host-side tool implementations.

A stronger child-execution boundary therefore has to answer several separate questions:

BoundaryRequired question
Policy ownershipWho is allowed to require or relax container execution?
Tool ownershipWhich preparation, filesystem and shell operations actually move into the container?
Approval ownershipDoes the host still decide whether an operation is authorized?
Workspace exposureWhich host paths are mounted writable, read-only or not at all?
Runtime credentialsWhich environment variables and secrets can cross into the child?
Cleanup ownershipWho owns workers, temporary outputs and mount points after cancellation or failure?
Trust in reportsCan code inside the container forge worker messages or approval-related results?
Fallback semanticsDoes a container failure ever silently retry on the host?

These concerns are implementation-level even when the outer task is exposed through UHP.

PR #11711 makes backend selection an operator/trusted-definition policy, not a model choice.

  • A trusted CLI operator can set QWEN_AGENT_EXECUTION_BACKEND=docker or podman to require containers for ordinary child dispatches.
  • Project .env files and settings cannot activate, replace, delete or relabel that operator requirement. A non-empty file-sourced selector is rejected with remediation to export the value in the launch environment.
  • An agent definition may require executionBackend: container; project declarations require workspace trust.
  • The model receives no backend selector. Omitting or forging invocation arguments cannot downgrade a required container to local execution.
  • Without an operator or definition requirement, ordinary execution remains local.
  • Missing runtime capability, malformed higher-priority definitions and unsupported dispatch paths fail explicitly instead of falling back to the host.

This is a useful general invariant for agent systems: the party being isolated must not control whether the isolation boundary exists.

Qwen’s first implementation deliberately does not move the entire harness into the container.

SurfaceQwen PR #11711 ownership
Parent model loop and model credentialsHost
Approval decisions and invocation guardHost
Parent transcriptHost
Child Read/Write/Edit/Notebook/search preparation and executionContainer worker
Child shell processes and shell-task stateContainer worker/session
Worktree creation and preservationHost
Container worker and output-store cleanupHost-owned lifecycle with bounded retries
Parent ! commands and parent @ expansionHost
Unsupported nested surfacesRefused rather than silently run locally

That division matters when evaluating claims such as “the agent runs in Docker.” In this design, the child tool runtime runs there; the parent harness and authorization plane remain host processes.

The merged design uses a narrow mount model rather than exposing the host environment wholesale.

The selected workspace is mounted, the CLI worker bundle is mounted read-only, and a separate temporary output store is kept outside the writable workspace. The worker receives an explicit environment allowlist and temporary HOME; the host home directory, credential stores, runtime directory and container socket are not intended to be general mounts. Ordinary child operations are offline, while a recognized dependency-installation path uses a separate worker with networking.

Qwen also masks the selected workspace root’s .git entry with an empty read-only mount, including when the entry was initially absent. The goal is to keep child code from modifying root repository metadata or configuration that a later host Git process could interpret. The implementation tracks ownership of a temporary mount-point directory and removes only its own still-empty entry after the last same-process worker releases it.

This boundary has explicit caveats:

  • nested repositories and submodules inside the mounted workspace remain workspace content;
  • container-written files can still affect later host tooling;
  • independent CLI processes do not share cleanup ownership;
  • a hard process exit can leave an empty .git mount-point directory behind;
  • workspaces overlapping the CLI bundle or dependency lookup roots are rejected, including unsafe aliases/links;
  • source/tsc launches and some linked-package layouts are outside the supported installation boundary.

Containerization reduces exposure; it does not make writable workspace content harmless.

Fail closed when composition is unsupported

Section titled “Fail closed when composition is unsupported”

The first Qwen backend is intentionally narrower than every subagent path in the product. When container execution is required, unsupported compositions such as Teams, Arena, some workflows/external executors and retained tool-capable resumes refuse instead of running the same work locally.

This is an important safety property. A system that says “container required” but transparently falls back to host execution after runtime failure has converted an isolation requirement into a preference.

The same rule applies to operation replay. Worker failure must not automatically replay a possibly state-changing operation on the local backend.

Cancellation and cleanup are part of the security model

Section titled “Cancellation and cleanup are part of the security model”

Isolation resources are stateful. Cancellation can happen while a worker is being created, while permission preparation is waiting, during tool execution, or during removal. The Qwen design therefore treats cleanup as owned state rather than a best-effort final callback.

Relevant properties include bounded release deadlines, idempotent release, no cross-request cancellation, retention of ownership when cleanup fails, and retry of failed removal without reopening execution. Session shutdown starts disposal but remains bounded; if cleanup does not finish, diagnostics identify retained containers and temporary directories instead of claiming success.

This produces a general rule: a failed cleanup must not be reported as released ownership. Otherwise later sessions can race with resources that still exist.

The critical trust caveat: container does not equal hostile-code-safe mediation

Section titled “The critical trust caveat: container does not equal hostile-code-safe mediation”

The merged Qwen design explicitly documents a significant limitation: the worker protocol currently shares its UID/PID namespace with tool subprocesses and is not authenticated against them. If hostile code inside the container can reach that endpoint and produce a valid forged reply, it can influence preparation parameters, confirmation details, permission-related results and tool results.

That means the current implementation should not be described as providing trustworthy approval/reporting mediation against hostile in-container code. Endpoint and payload identity separation remains open upstream.

This distinction is easy to miss:

  • filesystem/process relocation can be real;
  • host credentials can remain withheld;
  • local fallback can be prevented;
  • and yet the host↔worker control channel can still be insufficiently authenticated for an adversarial child.

A container boundary and a trusted control channel are separate security properties.

Some host-coupled features do not automatically survive relocation into a child container. In the reviewed Qwen implementation, automatic session artifact registration is unavailable in container subagents. Files remain in the workspace, but the worker must not claim that those files were registered as host session artifacts. File-history checkpoints, host-path IDE diffs and some host-side path-triggered behaviors are similarly outside the first container tool registry.

This is preferable to fabricating parity. A relocated child should expose the features it can preserve and explicitly refuse or downgrade unsupported host integrations.

PR #11711 contains substantial unit, controlled-worker and CLI verification, plus independent Linux Docker and rootful/rootless Podman evidence for an earlier policy revision at e544823995. Upstream is explicit that later review fixes received local controlled-worker verification and still need native-runtime revalidation.

Accordingly, the verified claim is implemented container execution with bounded primary-source evidence, not blanket native-runtime certification of every final merged path on every platform.

Current platform boundary in the merged design:

  • Linux: real Docker and rootful/rootless Podman evidence exists for the earlier reviewed policy revision; later fixes retain a native-runtime revalidation caveat.
  • macOS: local build/typecheck and controlled CLI/worker verification are reported; this is not equivalent to the Linux native-container evidence.
  • Windows: backend disabled for this implementation; no native container execution claim.

Containerized subagents answer an inside-the-harness execution question. UHP answers an external harness task/session question. MCP exposes tools/resources/context, while ACP can participate in harness composition and session integration. None of those protocols automatically specifies how a harness must confine an internal child process.

A UHP server can therefore expose the same external Task API while its underlying harness uses local children, worktrees, containers, remote workers or a mixture. Conformance to the external protocol should not be presented as proof of any particular internal sandbox strength.

For related boundaries, see Profile isolation, Harness composition, Remote harness execution, Security and Qwen Code.

When a harness advertises containerized child execution, verify at least:

  1. Who owns the policy? A model/tool call should not be able to turn a required backend off.
  2. What actually moved? Confirm file preparation, shell execution and child caches—not only the final command.
  3. What stays on the host? Identify model credentials, approval decisions, transcript and parent commands.
  4. What is mounted? Check workspace, HOME, runtime sockets, Git metadata and dependency roots separately.
  5. What happens on failure? Required isolation should fail closed with no local replay.
  6. How is the worker authenticated? Process isolation alone is not control-channel integrity.
  7. Who owns cleanup? Cancellation and partial startup need explicit retained-resource semantics.
  8. Which features lose parity? Artifact registration, IDE diffing, hooks, MCP/LSP surfaces and nested agents may need explicit refusal.
  9. What was actually tested? Separate controlled-worker tests from real Docker/Podman/OS evidence.
  10. What protocol claim is being made? Do not turn an implementation isolation feature into a UHP/MCP/ACP/A2A wire claim.