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.
Short answer
Section titled “Short answer”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 mountA 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:
| Boundary | Required question |
|---|---|
| Policy ownership | Who is allowed to require or relax container execution? |
| Tool ownership | Which preparation, filesystem and shell operations actually move into the container? |
| Approval ownership | Does the host still decide whether an operation is authorized? |
| Workspace exposure | Which host paths are mounted writable, read-only or not at all? |
| Runtime credentials | Which environment variables and secrets can cross into the child? |
| Cleanup ownership | Who owns workers, temporary outputs and mount points after cancellation or failure? |
| Trust in reports | Can code inside the container forge worker messages or approval-related results? |
| Fallback semantics | Does a container failure ever silently retry on the host? |
These concerns are implementation-level even when the outer task is exposed through UHP.
Qwen’s operator-owned policy model
Section titled “Qwen’s operator-owned policy model”PR #11711 makes backend selection an operator/trusted-definition policy, not a model choice.
- A trusted CLI operator can set
QWEN_AGENT_EXECUTION_BACKEND=dockerorpodmanto require containers for ordinary child dispatches. - Project
.envfiles 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.
Host versus container ownership
Section titled “Host versus container ownership”Qwen’s first implementation deliberately does not move the entire harness into the container.
| Surface | Qwen PR #11711 ownership |
|---|---|
| Parent model loop and model credentials | Host |
| Approval decisions and invocation guard | Host |
| Parent transcript | Host |
| Child Read/Write/Edit/Notebook/search preparation and execution | Container worker |
| Child shell processes and shell-task state | Container worker/session |
| Worktree creation and preservation | Host |
| Container worker and output-store cleanup | Host-owned lifecycle with bounded retries |
Parent ! commands and parent @ expansion | Host |
| Unsupported nested surfaces | Refused 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.
Workspace, Git and environment boundaries
Section titled “Workspace, Git and environment boundaries”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
.gitmount-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.
Durability and feature gaps
Section titled “Durability and feature gaps”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.
Validation boundary
Section titled “Validation boundary”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.
Relation to UHP and adjacent protocols
Section titled “Relation to UHP and adjacent protocols”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.
Practical review checklist
Section titled “Practical review checklist”When a harness advertises containerized child execution, verify at least:
- Who owns the policy? A model/tool call should not be able to turn a required backend off.
- What actually moved? Confirm file preparation, shell execution and child caches—not only the final command.
- What stays on the host? Identify model credentials, approval decisions, transcript and parent commands.
- What is mounted? Check workspace, HOME, runtime sockets, Git metadata and dependency roots separately.
- What happens on failure? Required isolation should fail closed with no local replay.
- How is the worker authenticated? Process isolation alone is not control-channel integrity.
- Who owns cleanup? Cancellation and partial startup need explicit retained-resource semantics.
- Which features lose parity? Artifact registration, IDE diffing, hooks, MCP/LSP surfaces and nested agents may need explicit refusal.
- What was actually tested? Separate controlled-worker tests from real Docker/Podman/OS evidence.
- What protocol claim is being made? Do not turn an implementation isolation feature into a UHP/MCP/ACP/A2A wire claim.