Implementation Plan: Phase 4 — Runtime Dependency Loading
Context
Phases 1-3 require all dependencies to be declared statically in the harness YAML. Phase 4 adds runtime dependency loading: agents can discover and fetch additional skills during execution based on the specific problem they encounter.
Design
Harness schema additions
yaml
agent: agents/code.md
skills:
- skills/base
- https://github.com/fullsend-ai/library/tree/abc123/skills/rust#sha256=<tree-hash>...
allowed_remote_resources:
- https://github.com/fullsend-ai/library/
allow_runtime_fetch: true # opt-in (default: false)
max_runtime_fetches: 10 # rate limit per agent runIn-sandbox fetch subcommand
The fullsend fetch-skill subcommand reuses the existing fullsend binary already in the sandbox. When the agent runs it:
- Agent calls:
fullsend fetch-skill https://github.com/fullsend-ai/library/tree/abc123/skills/python-linting#sha256=<tree-hash>... - Subcommand sends HTTP request to runner via
FULLSEND_FETCH_URLwith bearer token fromFULLSEND_FETCH_TOKEN - Runner validates URL against
allowed_remote_resources - Runner uses forge API to list and fetch the skill directory (skills are directories, requiring
ListDirectoryContentsandGetFileContentAtRef) - Runner verifies tree hash (hash covers entire directory tree)
- Runner stores in cache via
CachePutDirand uploads directory tree to sandbox - Subcommand returns the sandbox-local skill directory path
Security constraints
- Runtime fetch is opt-in per harness (
allow_runtime_fetch: true) - All URLs must match
allowed_remote_resourcesprefixes - Integrity hash required on all URLs (tree hash for skill directories)
- Rate limited:
max_runtime_fetches(default 10) per agent run - Skills are directories -- requires forge API access (same as static resolution)
- Non-forge HTTPS URLs are rejected for skills (no HTTP directory listing standard)
- All fetched skills pass security scanning pipeline
- Audit log records all runtime fetches with
fetch_type: "runtime"
Implementation steps
PR 1: Runner-side fetch service (#2173, merged)
- HTTP service implementing
fetchsvc.ServicewithServeHTTPhandler - Request/response protocol: URL -> local path or error
- Rate limiting enforcement via atomic counter
- Forge API integration for skill directory fetching (reuses Phase 1 forge client)
- Audit logging with
fetch_type: "runtime"
PR 2: In-sandbox fetch subcommand (#2223)
fullsend fetch-skillsubcommand reusing the existing fullsend binary in the sandbox- Runner starts HTTP server on dynamic TCP port with per-run bearer token auth (ADR-0046)
FULLSEND_FETCH_URLandFULLSEND_FETCH_TOKENenv vars injected during bootstrap- Reports errors to stderr, success path to stdout
- Returns the sandbox-local skill directory path (not a single file path)
PR 3: Harness schema and CLI integration
- Add
allow_runtime_fetchandmax_runtime_fetchesto harness schema - Validation: reject runtime fetch fields if
allowed_remote_resourcesis empty - Gate fetch service startup behind
allow_runtime_fetch
Verification
- Agent can fetch a skill directory at runtime matching allowed prefix
- Fetch of URL outside allowed prefix is rejected
- Fetch without hash is rejected
- Rate limit enforcement: 11th fetch fails
allow_runtime_fetch: falseblocks all runtime fetches- Audit log records runtime fetches
- Fetched skill directory structure is preserved in sandbox (SKILL.md plus companion files)
- Non-forge HTTPS URLs are rejected with clear error message
