Repository navigation
feat(sandbox): adopt provider-backed policy composition #2671
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
4a55594
docs: add design spec for provider-backed policy composition
maruiz93 8f2cf5e
docs: add implementation plan for provider-backed policy composition
maruiz93 5ca3d1e
feat(sandbox): add provider profile definitions for policy composition
maruiz93 ed79410
feat(sandbox): add provider definitions for policy composition
maruiz93 1c58f94
refactor(scaffold): register profiles/ and providers/ as layered dire…
maruiz93 bba349e
refactor(sandbox): add ImportProfiles and EnableProvidersV2 functions
maruiz93 823f2ae
feat(sandbox): wire provider profile import into fullsend run
maruiz93 d2c897d
feat(sandbox): declare providers in harness files
maruiz93 3d06617
refactor(sandbox): replace per-agent policies with shared base.yaml
maruiz93 c5789a9
docs(adr): add ADR 0046 for provider-backed policy composition
maruiz93 4930b39
fix(sandbox): add YAML document start markers to profile and provider…
maruiz93 fe6c18b
fix(sandbox): resolve OpenShell CLI compatibility issues
maruiz93 bc1f524
docs: renumber ADR 0055 to 0065 (resolve duplicate with unified-env-v…
maruiz93 95fc2b1
fix(sandbox): make ImportProfiles safe for parallel fullsend run
maruiz93 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,171 @@ | ||
| --- | ||
| title: "65. Provider-backed policy composition" | ||
| status: Accepted | ||
| relates_to: | ||
| - agent-infrastructure | ||
| topics: | ||
| - policy | ||
| - providers | ||
| - composition | ||
| - sandbox | ||
| --- | ||
|
|
||
| # 65. Provider-backed policy composition | ||
|
|
||
| Date: 2026-06-22 | ||
|
|
||
| ## Status | ||
|
|
||
| Accepted | ||
|
|
||
| ## Context | ||
|
|
||
| [ADR 0024](0024-harness-definitions.md) established per-agent harness | ||
| files with a `policy` field pointing to an OpenShell policy YAML. | ||
| Each policy file contains filesystem, process, and network | ||
| restrictions for one agent. | ||
| [ADR 0038](0038-universal-harness-access.md) introduced URL-based | ||
| access for harness resources, and | ||
| [ADR 0045](0045-forge-portable-harness-schema.md) defined | ||
| forge-portable harness composition with `base:` inheritance. Together | ||
| they establish that harness dependencies should be referenceable and | ||
| composable — but neither addresses how provider or profile definitions | ||
| are resolved when a base harness is remote (see [#2672](https://github.com/fullsend-ai/fullsend/issues/2672)). | ||
|
|
||
| In practice, every policy file duplicates the same network rule blocks | ||
| for shared services: Vertex AI inference endpoints, GitHub API access, | ||
| package registries (npm, PyPI, Go modules), and gitleaks binary | ||
| downloads. Six agents × four service groups = the same endpoints and | ||
| binaries repeated in every combination. | ||
|
|
||
| This duplication creates maintenance burden: when a service adds or | ||
| changes endpoints, every policy file must be updated independently. | ||
| The fix.yaml policy comments "Identical to the code agent policy," | ||
| making the redundancy explicit. | ||
|
|
||
| OpenShell v0.0.37 introduced provider-backed policy composition | ||
| (NVIDIA/OpenShell#1037). When a provider is attached to a sandbox and | ||
| has a registered profile, the gateway merges the profile's network | ||
| rules into the effective policy at fetch time under reserved | ||
| `_provider_*` keys. This is additive-only and keeps provider rules | ||
| isolated from user/agent rules. | ||
|
|
||
| ## Options considered | ||
|
|
||
| ### Option 1: Monolithic per-agent policies (legacy approach) | ||
|
|
||
| Each agent has its own policy YAML with all network rules inline. | ||
| Agent designers specify every endpoint and binary in a single file. | ||
|
|
||
| **Pros:** | ||
| - Self-contained — one file per agent, easy to read in isolation. | ||
| - No dependency on providers v2 or OpenShell version. | ||
| - Full control per agent. | ||
|
|
||
| **Cons:** | ||
| - Duplicated network blocks across agents. | ||
| - Maintenance burden grows with agent count and service count. | ||
| - Easy to drift — one agent's policy gets an endpoint fix, others | ||
| don't. | ||
|
|
||
| ### Option 2: Composable policies with agent designer freedom | ||
|
|
||
| Provide composable provider profiles as an option. Agent designers | ||
| choose whether to use providers for network access or keep inline | ||
| network rules. A shared `base.yaml` covers filesystem, landlock, and | ||
| process restrictions. Agents can mix: use providers for common services | ||
| and inline rules for agent-specific endpoints. | ||
|
|
||
| **Pros:** | ||
| - Flexible — agent designers pick the approach that fits. | ||
| - Incremental adoption — no big-bang migration needed. | ||
| - Lowest friction to introduce — no convention change required. | ||
|
|
||
| **Cons:** | ||
| - Two ways to do the same thing — harder to reason about effective | ||
| policy. | ||
| - Duplicated endpoints may reappear if designers don't adopt providers. | ||
| - No single source of truth for a service's endpoints. | ||
|
|
||
| ### Option 3: All network access through providers (chosen) | ||
|
|
||
| Provider profiles are the single mechanism for granting network access. | ||
| Policy files define only non-composable sandbox restrictions: | ||
| filesystem access, landlock, and process identity. A single | ||
| `base.yaml` replaces per-agent policy files for these non-network | ||
| concerns. Harnesses declare which providers they need — each | ||
| contributes network rules via composition. | ||
|
|
||
| **Pros:** | ||
| - Single source of truth per service — endpoint changes update one | ||
| profile. | ||
| - Policy files are small and uniform (no network section). | ||
| - Clear separation: profiles own network access, policies own sandbox | ||
| restrictions. | ||
| - New agents get network access by declaring providers, not copy-pasting | ||
| endpoint blocks. | ||
|
|
||
| **Cons:** | ||
| - Agent designers must understand the provider model. | ||
| - Credential-less providers require a workaround | ||
| ([NVIDIA/OpenShell#1978](https://github.com/NVIDIA/OpenShell/issues/1978)). | ||
|
|
||
| ## Decision | ||
|
|
||
| **Adopt Option 3 as a best practice for fullsend default agents.** | ||
|
|
||
| Harnesses declare providers for network rules and policies control | ||
| filesystem, landlock, and process restrictions only. | ||
|
|
||
| This is a best practice, not an enforcement. Custom agents with | ||
| network rules in their policies continue to work — composition is | ||
| additive, so duplicated rules between providers and policies are | ||
| redundant but harmless. Agent designers who bring their own agents can | ||
| choose whichever approach fits their needs. The default agents serve | ||
| as the reference implementation. | ||
|
|
||
| Six custom profiles ship with the default agents: | ||
|
|
||
| | Profile ID | Service | Access | | ||
| |---|---|---| | ||
| | `fullsend-vertex-ai` | Anthropic API, Google Cloud APIs | read-write | | ||
| | `fullsend-github` | GitHub API, Git transport | read-write | | ||
| | `fullsend-github-ro` | GitHub API, Git transport | read-only | | ||
| | `fullsend-package-registries` | npm, PyPI, Go modules | read-only | | ||
| | `fullsend-gitleaks` | GitHub releases for gitleaks | read-only | | ||
| | `fullsend-github-artifacts` | GitHub Actions artifact download | read-only | | ||
|
|
||
| Custom profiles are used instead of OpenShell built-ins because they | ||
| bundle endpoint combinations specific to fullsend (e.g., | ||
| fullsend-vertex-ai combines Anthropic API + GCP APIs). | ||
|
|
||
| Provider definitions use dummy credentials as a workaround for | ||
| [NVIDIA/OpenShell#1978](https://github.com/NVIDIA/OpenShell/issues/1978) | ||
| — providers exist for network policy contribution only. Credential | ||
| delivery continues via host_files ([ADR 0025](0025-provider-credential-delivery-for-sandboxed-agents.md) tier 4). | ||
|
|
||
| The `providers_v2_enabled` setting and profile imports are managed | ||
| automatically by `fullsend run`. | ||
|
|
||
| ## Consequences | ||
|
|
||
| - Scaffold agents use provider profiles for all network access. Policy | ||
| files contain only filesystem, landlock, and process restrictions. | ||
| - Network rules for each service are defined once in a profile YAML. | ||
| Adding or changing endpoints updates one file. | ||
| - All scaffold agents share a single `policies/base.yaml`. Per-agent | ||
| policy files are eliminated from the scaffold. | ||
| - Custom agents are not required to adopt this pattern. Inline network | ||
| policies continue to work, but the scaffold and guides recommend | ||
| providers as the preferred approach. | ||
| - The building-custom-agents guide is updated to show providers as | ||
| the recommended way to grant network access. | ||
| - Requires OpenShell >= v0.0.37 and the `providers_v2_enabled` gateway | ||
| setting (set automatically). | ||
| - GitHub access is split into read-write (`fullsend-github`) and | ||
| read-only (`fullsend-github-ro`) profiles, matching the access | ||
| levels agents had under the previous per-agent policy model. | ||
| Review and retro agents use the read-only variant. | ||
| - Provider and profile definitions are currently resolved from local | ||
| directories only. Portability for URL-referenced base harnesses | ||
| requires harness-level declaration and URL-based resolution ([#2672](https://github.com/fullsend-ai/fullsend/issues/2672)). | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.