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.