Skip to content

feat: support provider attach and detach for running sandboxes #1171

@johntmyers

Description

@johntmyers

Problem Statement

Issue #1081 adds a custom provider profile registry, but sandbox provider attachments are still effectively fixed at sandbox creation time. The next provider v2 chunk from #896 should let operators and agents attach or detach providers from a running sandbox and have the effective policy update reflect the sandbox's current provider set.

This is the runtime lifecycle step needed after profile import/export: create or import a profile, create a provider of that profile type, attach that provider to a sandbox, verify the profile-generated policy layer appears, detach it, and verify the effective policy returns to the previous state.

Credential injection needs an explicit boundary in this issue. Attaching a provider to a running sandbox should affect new process/session launches that resolve provider env from the sandbox's current attachments, but it should not attempt to mutate the environment of already-running processes. Existing long-running harnesses such as Codex, Claude, or OpenClaw may need to be relaunched by the user to observe newly attached provider credentials.

Related: #896, #1081, #1170

Proposed Design

Add a gateway and CLI surface for mutating a sandbox's attached provider list after creation. The attachment should be provider-record based, not a raw profile id, because the current model stores providers separately from profiles and derives profile policy from Provider.type.

Suggested CLI shape:

openshell sandbox provider list <sandbox>
openshell sandbox provider attach <sandbox> <provider-name>
openshell sandbox provider detach <sandbox> <provider-name>

Equivalent API shape could be explicit RPCs such as:

ListSandboxProviders
AttachSandboxProvider
DetachSandboxProvider

or an update operation with attach/detach semantics, as long as it avoids accidental full replacement of the provider list.

Expected behavior:

  • Attach validates that the sandbox exists.
  • Attach validates that the provider exists.
  • Attach is idempotent when the provider is already attached.
  • Detach validates that the sandbox exists.
  • Detach is idempotent or returns a clear not-attached result; choose the convention that best matches nearby APIs.
  • Attach/detach updates the persisted sandbox provider list using the existing sandbox object/schema.
  • Effective policy composition remains JIT and reads the current provider list from storage.
  • When providers_v2_enabled is true, attaching a provider whose Provider.type maps to a built-in or custom profile adds that profile-generated policy layer on the next running policy/config refresh.
  • Detaching that provider removes the profile-generated policy layer on the next running policy/config refresh.
  • When providers_v2_enabled is false, attach/detach should update the provider list without adding provider-profile policy layers.
  • Attach/detach must not mutate environment variables for already-running sandbox processes.
  • New sandbox exec/shell/harness process launches after attach should resolve provider env from the current persisted sandbox provider list.
  • New sandbox exec/shell/harness process launches after detach should not receive provider env for the detached provider.
  • Existing credential injection remains the mechanism in both modes for this issue. Do not introduce profile-defined credential injection here.
  • If the current launch path only resolves provider env once at sandbox startup, add the smallest refresh/fetch point needed so future process launches observe attach/detach without requiring a full sandbox restart.

Running sandbox behavior is the key acceptance path. If the supervisor already refreshes policy/config periodically or on demand, use that mechanism. If not, add the smallest gateway-to-supervisor notification or refresh trigger needed so a running sandbox observes provider attachment changes without restart. The same current-attachment invariant should be used for future process/session launches that perform provider env resolution.

Alternatives Considered

  • Attach raw profile ids to sandboxes. This does not match the current schema or provider credential model; sandboxes attach provider names, and profile policy is derived through Provider.type.
  • Fold this into profile import/export. That would make feat: support custom provider profile import and export #1081 too broad and mix registry management with running sandbox lifecycle behavior.
  • Mutate environment variables for already-running processes. This is not reliable for normal Unix process environments and would create confusing behavior for long-running agent harnesses.
  • Add a harness restart primitive in this issue. That may be useful later, but attach/detach can be shipped with clear semantics for new process/session launches first.
  • Wait for profile-defined credential injection. Policy attach/detach and the existing credential-injection boundary can be validated independently now, while profile-defined credential injection can remain a later provider v2 chunk.

Definition of Done

  • Gateway exposes an attach provider operation for existing sandboxes.
  • Gateway exposes a detach provider operation for existing sandboxes.
  • Gateway exposes a way to list providers attached to a sandbox, or reuses an existing sandbox get/list response clearly enough for CLI UX.
  • Attach validates sandbox existence and provider existence.
  • Attach/detach preserve existing sandbox fields and mutate only the attached provider list.
  • Attach/detach do not create duplicate provider entries.
  • Attach/detach semantics are documented in API/handler tests, including idempotency or clear errors.
  • CLI supports attaching a provider to a sandbox.
  • CLI supports detaching a provider from a sandbox.
  • CLI supports listing attached providers for a sandbox or clearly shows attachments through an existing command.
  • With providers_v2_enabled=false, attach/detach does not add provider-profile policy layers.
  • With providers_v2_enabled=true, attaching a provider backed by a built-in profile adds that provider profile policy layer on the next effective policy/config fetch.
  • With providers_v2_enabled=true, attaching a provider backed by a custom profile adds that custom provider profile policy layer on the next effective policy/config fetch.
  • Detaching a provider removes that provider profile policy layer on the next effective policy/config fetch.
  • Test coverage includes the full lifecycle: create/import profile, create provider, create sandbox, capture baseline effective policy, attach provider, verify policy includes provider layer, detach provider, verify policy returns to baseline.
  • Running sandbox behavior is covered by an integration test or the closest available supervisor/config-refresh test.
  • Existing provider credential injection behavior is unchanged by this issue.
  • Existing running process environments are not mutated by attach/detach.
  • New sandbox exec/shell/harness process launches after attach resolve provider env from current sandbox attachments.
  • New sandbox exec/shell/harness process launches after detach do not receive provider env for the detached provider.
  • Tests document the credential-env boundary: already-running process env is unchanged where testable, while future launches use current attachments.

Non-Goals

  • Do not implement profile-defined credential injection in this issue.
  • Do not implement OAuth refresh or token-store refresh in this issue.
  • Do not mutate environment variables of already-running sandbox processes.
  • Do not add a harness restart/relaunch primitive in this issue.
  • Do not add a new sandbox profile attachment field unless the existing provider-name attachment model proves insufficient.
  • Do not persist composed effective policy revisions; effective policy should remain derived from current inputs.
  • Do not change default provider behavior when providers_v2_enabled is false.
  • Do not update published docs or architecture docs in this issue; docs can be swept separately.

Agent Investigation

PR #1170 establishes the custom profile registry and confirms custom profiles participate in JIT policy composition when referenced by the current sandbox provider list. The missing lifecycle surface is mutating that provider list after sandbox creation and proving a running sandbox observes policy changes when providers are attached or detached.

Credential injection currently has process-environment constraints independent of provider profiles. This issue should preserve the current injection mechanism, make future process/session launches consult the current sandbox attachments, and explicitly avoid promising runtime env mutation for processes that are already running.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    In progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions