Skip to content

Serve Environment work over the Link - #529

Merged
SaladDay merged 13 commits into
aos/cutoverfrom
aos/agent-host-owner
Oct 7, 2026
Merged

SaladDay merged 13 commits into
aos/cutoverfrom
aos/agent-host-owner

Conversation

@SaladDay

@SaladDay SaladDay commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

On an agent host, a Session's Environment work now goes through one Environment owner, which works in the sandbox over its own Link attachment.

What changes

  • Environment owner on the agent host. It uses File and Process services, under the bind's grant, and handles:

    • runtime_prepare: it installs Skills, plugins and capability snapshots, and runs setup steps as Process operations named by the transfer ID;
    • directory reads, file writes and output export.

    Before an Executor starts, it fills LocalEnvironment.Skills, MCP and CapabilityRoot with paths in the sandbox. If it cannot observe the outcome of a mutation, it quarantines itself until the home is removed.

  • Dispatch. Environment admission is per Session, and owners drain on release. The owner's outcomes are part of the dispatch contract, and SessionEnvironments is gone.

  • One composition. Each Environment owner declares its environment composition once, and the registry composes it with the Harness's own declaration once. ViewCapabilities, the discovery mutations and the CLI export derivation are gone. Capability installation rules move out of the local-directory helpers in agentcapabilities.

  • Typed failures. A workspace_write or runtime_prepare that cannot reach the sandbox before any effect ends rejected/resource_unavailable, through one error, dispatch.ErrEnvironmentUnavailable. unknown is kept for outcomes that really are uncertain.

  • Plugin MCP credentials. A plugin whose MCP server declares literal http_headers, or a stdio server that takes Environment credentials, is refused before anything is staged. The check uses one predicate shared with mcp_binding.

  • Docs. docs/runtime-protocol.md and contracts/agents-api/harness-onboarding.md, with zh.

Review

A blind review found two major issues, both fixed here with tests:

  • a failure before any effect was reported as unknown, which blocked the Router;
  • the plugin credential check missed stdio servers.

Also fixed: a second composition, a test-only production field, guest rules that were copied instead of shared, and a stale comment. The real-Harness Skill Turn is deferred to C4b phase 3. Two follow-ups are recorded for PR5 and PR6: one preparation transfer per connection, and the export walk that PR6 deletes.

Checks

  • Go tests: focused tests for agenthost, dispatch, agent/..., localworkspace, agentcapabilities, cli and processbroker; -race -count=50 on the changed dispatch and agenthost tests.
  • Gated agent-host suite: all 18 tests pass in a throwaway container, with no skips.
  • Builds: darwin and windows builds and vet.
  • Make: make check-names check-docs check-ci.
  • Real-Harness qualification: a Claude SDK run through scripts/qualify-agent-host.sh with MiniMax passes.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

@SaladDay
SaladDay merged commit 4ee6933 into aos/cutover Oct 7, 2026
1 check passed
@SaladDay
SaladDay deleted the aos/agent-host-owner branch October 7, 2026 21:35
The owner contract now holds its result types, workspace errors and a
typed initialization failure, so a second owner returns every outcome
without importing localworkspace. The export bound and empty-write
filter move to the Router, and Binding.Resolve replaces the CLI and
test copies of the resolver.
Busy checks for runtime_prepare, workspace_write, workspace_export and
execution_prepare now look only at the Session's own work, so another
Session's Executor never blocks an Environment; the aggregate slots
stay. Shutdown and quiescence drain the owners of unreleased
assignments, and release cleanups of one assignment run one at a time,
so a retry never closes an owner concurrently.
The Runtime's Environment owner declares which Environments it serves, and
agent.Registry.Register composes that with the Harness's own declaration.
Views no longer carry a second capability declaration, adapters no longer
load the local binding to declare capabilities, and the CLI no longer derives
read preparation and export at heartbeat.
The installation, snapshot, manifest, marker, tool-environment, setup
argument and MCP credential rules become functions over file lists and
values, so an owner that reaches the installation through File applies
the same rules. The os.Root helpers stay as thin wrappers for the guest.
Each Session bound to the agent host gets one Environment owner with its
own Link attachment. It applies runtime_prepare to the sandbox through File
and Process, prepares each Executor's request with sandbox paths, serves
workspace reads, Files create and outputs export, and quarantines itself
after a mutation whose effect is unknown. Dispatch loses the
SessionEnvironments mode, which no owner backed.
The owner no longer repeats dispatch's state-key check: dispatch resolves it from the Session's assignment and checks the key before any writable preparation.
A runtime_prepare whose owner could not attach, open the Process service or have a step admitted ended unknown, which kept the Router's transfer slot and fenced every later transfer. Such a failure has no effect, so the owner now returns dispatch.ErrEnvironmentUnavailable, which also replaces the workspace write's unavailable error, and the Router ends it rejected with resource_unavailable.
The agent host installed a plugin whose stdio MCP server declares env_vars, which admission then rejects for every execution of the Session. The owner now refuses it before staging, through the predicate that also sets a binding's environment_configuration authority.
Config.Harnesses was composed when its kinds were registered and again by the agent host's Registry. Because composition only narrows, a registry built on a host without a local workspace lost local Environments for good. Config.Harnesses now holds the declarations as adapters state them, and Registry composes them once with the Environments the agent host serves.
The agent host copied the guest's workspace path rule, export bounds and setup kill grace. localworkspace now exports each once, uses its one path rule in its three checks, and the agent host reads them from there. The processbroker comment no longer lists TMPDIR among the sandbox values.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant