STATE≡LAYER
sophia. A RECORD FOR THINKING THINGS

System reference09

Launching a managed agent

A managed launch runs an owner-approved plan end to end: the daemon verifies the pinned harness binary it is about to run, builds a private single-credential config home for the session, delivers the agent's bearer over a one-use local socket instead of argv or environment, and supervises the whole thing as a systemd unit whose terminal you can attach to without gaining any Sophia authority.

Every claim on this page checked against the product source at a pinned revision: 2026-08-19 @ 0c2a08a7.

What this is

A managed launch is Sophia starting an agent for you, rather than you starting an agent and introducing it to Sophia afterwards. The owner picks a workspace and a launch profile (harness, permission profile, tool surface, entity scope, lease duration), approves the launch in the tray, and the daemon does the rest: it verifies the exact harness binary it is about to run, compiles a private launch-local configuration home, hands the agent its credential over a channel no other process can read, and runs the session as a supervised systemd unit with a terminal you can attach to. The pipeline lives in proxy/src/workspaceBroker/ (managedLaunchSupervisor.ts, managedLaunchHost.ts, launchEnvelopeRelay.ts, managedTerminalRelay.ts, and the per-harness adapters).

Why it exists

The ordinary way to wire an agent into anything is a token in a config file plus a PATH lookup, and both halves are wrong for an identity system. A bearer sitting in argv or environment is readable by every process the harness ever spawns, and it outlives the session in shell history and crash dumps. A PATH lookup means the binary you audited and the binary that runs are related by filename only. And a harness started from your real config home inherits your ambient MCP servers, hooks, and project trust decisions, so what the agent can reach is whatever your desktop had accumulated, not what you decided at launch time. The managed pipeline exists to close those three gaps mechanically: the credential never touches argv, environment, or disk; the binary is verified as held bytes, not as a path; and the config the harness boots from is built fresh, per launch, containing exactly what the plan says.

How it works

A launch is an owner decision executed against a bound plan. The launch is requested over the owner-session HTTP route (POST /api/owner/workspaces/:workspaceId/launches, proxy/src/routes/api/ownerWorkspaceIdentityRoutes.ts), waits in pending_trusted_presence until the owner approves it in the tray, and only then starts. The supervisor refuses to spawn unless every field of the approved plan matches the operation it was handed: launch id, planned lease, harness, launch profile and version, the wrapper executable’s digest, and the expected IPC peer digest (managedLaunchRedemptionPayload, managedLaunchSupervisor.ts). A plan that drifted from its approval is a refusal, not a warning. Resuming an existing lease goes back through the same pipeline with the same binding checks: a resume is a launch, not a shortcut.

The binary that runs is the binary that was verified, at pinned bytes and a pinned version. The harness executable is opened and held as a file descriptor while proxy/src/mcp/trustedPresenceLinux.ts checks it: a regular file, no symlink, single hardlink, owned by you, not group or world writable, and structurally a sane ELF (Codex must be static; Claude Code may use only the standard system loader, with RPATH/RUNPATH and loader-audit indirections forbidden). Its SHA-256, device, inode, and size must exactly match the identity recorded when the plan was prepared; any change is managed_harness_identity_changed. The version is then witnessed, not trusted: the daemon executes the held descriptor itself (via /proc/self/fd, so the bytes checked are the bytes run) with --version, and the output must equal the pinned witnessed version, currently codex-cli 0.147.0 and 2.1.222 (Claude Code) (proxy/src/superpowers/harnessRegistry.ts:65,83). A harness you upgraded yesterday does not silently launch today; it fails with unsupported_harness_version until the contract is re-witnessed.

Each launch gets a private config home containing exactly one credential. The adapter (adapters/codex.ts, adapters/claudeCode.ts) builds a fresh overlay directory, mode 0700, owner-checked at every step (adapters/common.ts), and points the harness at it (CODEX_HOME or CLAUDE_CONFIG_DIR). Exactly one file is copied in from your real config home, from a one-entry allowlist: auth.json for Codex, .credentials.json for Claude Code, so the harness keeps its own subscription login and nothing else. Everything else is synthesized: the workspace is pinned to untrusted project trust for Codex; for Claude Code only the two decisions you already made (onboarding completed, this project trusted) are re-stated, because copying the whole state file “would also import ambient MCP definitions, permissions, connector history, and project state” (adapters/claudeCode.ts). The managed config defines a single MCP server: Sophia, through the packaged wrapper. Claude Code additionally launches with --setting-sources user, --mcp-config on the overlay, and --strict-mcp-config, so project-level hooks, skills, and permission files never load. The inherited environment is scrubbed before it reaches the harness: loader controls (LD_*, GLIBC_TUNABLES, GCONV_PATH) and anything shaped like a Sophia credential variable are dropped (sanitizeHarnessEnvironment). And the isolation is evidenced rather than assumed: every real config source the harness could have read is content-hashed before launch and re-hashed after exit, and the pair must validate as untouched (snapshotRealConfigSources, completeIsolationEvidence).

The bearer never rides argv, environment, or disk. The credential handoff is a per-launch unix socket (launchEnvelopeRelay.ts) in a hardened runtime directory. The relay refuses any client whose kernel-reported identity (SO_PEERCRED, plus a hash of the executable behind /proc/<pid>/exe, peerIdentity.ts) is not your uid running the exact packaged wrapper binary the plan named. The launch envelope, carrying a one-use redemption handle, is served exactly once; the handle is overwritten in memory the moment it is consumed, and an unconsumed relay self-destructs after a timeout. The wrapper redeems the handle with the broker, receives the bearer, and proves it against the daemon before serving a single harness request: the daemon must answer with a structured work receipt bound to the exact lease the plan named (wrapper.ts). Only after that proof may the wrapper deposit the verified credential back into the daemon-memory relay, so an identical wrapper subprocess restarted by the same harness can reuse it without a second redemption. The relay’s own contract comment states the invariant: “Nothing is written to disk or placed in argv/environment.” What the agent’s authority then means (profile, entity scope, approval gate) is The security model’s territory; this page is only about how the credential travels.

The session runs as a supervised systemd transient unit, and is verified twice. The supervisor spawns systemd-run --user with Restart=no, KillMode=control-group, a ten-second stop timeout, and BindsTo=sophia-daemon.service (managedLaunchHost.ts), so a stopped daemon cannot leave orphaned managed agents behind. What the unit runs is not a command line the harness could have influenced: it is the packaged host binary plus the path and digest of a one-use manifest file. The host re-verifies everything independently before exec: its own executable identity, the harness, wrapper, and launcher identities byte for byte, and the workspace directory’s device and inode; it consumes the manifest by digest and unlinks it on read, so a manifest cannot be replayed or swapped. On exit, cleanup is evidence-gated: the overlay is deleted only after systemd confirms the unit is actually quiescent (no surviving process in the control group), and the pre/post config hashes are checked before the overlay goes. A unit that cannot be proven quiet keeps its overlay and raises an event instead of sawing a possibly-live process off its config.

The terminal is a relay, not a control plane. The harness runs on a real PTY, and its bytes are republished over a second owner-only unix socket (managedTerminalRelay.ts), whose class comment is the summary: “It carries no Sophia credential.” Attaching requires a 32-byte one-shot token, issued exactly once per launch and compared in constant time; one viewer at a time, and peers are checked by kernel-reported uid like everything else here. While no viewer is attached, output accumulates in a bounded backlog (256 KB) that drops its oldest frames first, so a long-unwatched session may truncate what you see when you finally attach; after a fast startup failure the backlog is deliberately retained for a short grace period so the failure’s output is not destroyed before anyone could read it. An attached viewer is a genuine terminal: keystrokes are forwarded to the PTY, exactly as if you sat down at the session. What it is not is authority: the socket carries terminal bytes only, holds no bearer, and cannot renew, revoke, or terminate anything. Closing the viewer changes nothing about the agent; it keeps running. Stopping it is a separate, explicit owner action that stops the systemd unit and verifies quiescence.

What a launch looks like

# From a registered workspace checkout:
$ sophia agent catalog
Ouroboros-App (ws-1f2ce8)
* Codex reviewer [codex] assistant/core lease 3600s
  Claude implementer [claude-code] full/full lease 7200s

$ sophia agent start --harness codex --seat Reviewer_1
Launch lp-9c41d7 is pending_trusted_presence.
Approve or deny Codex reviewer (Reviewer_1) in the Sophia tray.
Approved. Attaching this terminal to the managed agent…

# The Codex TUI appears here, live. Closing this terminal detaches
# the viewer; the agent keeps running under systemd. Re-attaching is
# not possible for this launch: the attach token was consumed above.

The flags mirror the plan’s axes (--permission, --tool-surface, --scope, --lease, --write-approval), and every one of them is carried into the approved proposal rather than into the process environment (proxy/src/workspaceBroker/agentCli.ts). The launch request itself authenticates with your local owner session key; there is no unauthenticated path to this command.

Boundaries

The verification here is presence and identity, not attestation. The pinned version is witnessed output from a verified binary you own, not a vendor signature, and nothing sandboxes what the harness does inside your OS account once it is running. The isolation evidence proves the launch did not modify your real config homes; it does not prove anything about the model’s behavior in between.

The attached terminal deserves its own honest sentence: attaching lets you type into the session, so it is interaction, not read-only observation. The boundary it enforces is narrower and mechanical: the terminal socket carries no credential and no lifecycle authority, and detaching or losing it never kills the agent.

Capturing a harness’s own conversation state so a session can be resumed mid-thought is in-flight lane work, not part of what this page describes.

This also inherits The security model’s local-trust boundary. The peer checks, held descriptors, and one-use sockets all authenticate your uid to itself across process boundaries; none of this defends against a person who already controls your OS user.