Skip to content

Add declarative bring-your-own agent support (#191 Phase 1)#200

Open
JAORMX wants to merge 1 commit into
mainfrom
feat/191-byo-agents-phase1
Open

Add declarative bring-your-own agent support (#191 Phase 1)#200
JAORMX wants to merge 1 commit into
mainfrom
feat/191-byo-agents-phase1

Conversation

@JAORMX

@JAORMX JAORMX commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements Phase 1 of #191 — run arbitrary coding agents from global config with no Go code, no fork, and no Dockerfile in this repo. This is the issue's "first useful iteration" acceptance criteria:

agents:
  aider:
    image: ghcr.io/acme/aider-bbox:latest
    command: ["aider"]
    env_forward: [OPENAI_API_KEY, "AIDER_*"]
    mcp:
      mode: env
$ bbox agents doctor aider
[PASS] config validation: name, image, command, paths, egress all valid
[PASS] required env OPENAI_API_KEY present
$ bbox aider     # boots the image, runs the command

What's included

  • Extended AgentOverride (pkg/domain/config): description, default_env, env_required, credentials.persist, settings entries, per-profile egress_hosts, mcp.mode.
  • Pure mapping + validation: AgentFromOverride (config→agent.Agent) and ValidateCustomAgent are pure, table-tested domain functions. The image-ref parser is injected as a closure from the composition root, keeping go-containerregistry out of the domain layer.
  • Universal BBOX_* env (agent.BuildUniversalEnv) injected into every VM: BBOX_AGENT_NAME, BBOX_WORKSPACE, BBOX_HOME, BBOX_SESSION_ID, BBOX_GIT_TOKEN_AVAILABLE, BBOX_SSH_AGENT_AVAILABLE, plus BBOX_MCP_URL/BBOX_MCP_AUTHZ_PROFILE when MCP is active. Applied after forwarded host vars so it's authoritative. BBOX_MCP_URL uses a new shared config.MCPEndpointPath (/mcp) constant — de-duplicating the path previously hardcoded in the proxy and all five built-in clients.
  • mcp.mode: env: enables the proxy without a config-file injector; the agent discovers it via BBOX_MCP_URL. (mcp.mode: config is rejected with a clear message.)
  • bbox agents list | inspect | doctor: inspect shows field provenance (built-in/global/workspace) and env names only, never values; doctor exits non-zero on invalid config or missing required env. bbox list remains a shared alias.

Defaults & security

  • Safer-than-built-in defaults for custom agents: empty env_forward (forward nothing), egress profile standard (must declare hosts or set permissive), MCP authz safe-tools.
  • Workspace-local .broodbox.yaml is tighten-only: it can never add a custom agent or new credential paths, repoint an existing agent's image/command, or widen env_forward (subset-coverage enforcement prevents secret exfiltration). Credential/settings paths are validated relative and cannot escape the home dir.
  • A guard test pins go-microvm's topology.GatewayIP to the literal pkg/sandbox uses for BBOX_MCP_URL, catching drift.

Out of scope (deliberate follow-ups)

agents import/export, OCI-embedded manifests, mcp.mode: config, agents add/init scaffolding, and trusted host-side plugins.

Verification

  • task fmt clean, task lint 0 issues, full task test (race) passes.
  • End-to-end smoke-tested: agents list shows custom agents; inspect renders provenance + MISSING required-env markers without leaking values; doctor passes with required env set (exit 0), fails without it (exit 1), and rejects mcp.mode: config (exit 1); bbox list unchanged.
  • Strict DDD layering preserved (pure domain mapping/validation; I/O only in infra/cmd).

How it was built

Produced via a multi-agent orchestration loop: architect → implement → 5-axis panel review (architecture / security / correctness / api-ux / tests) → fix, iterated 3 rounds. All findings were resolved; the final state was independently re-verified and reviewed before this PR.

🤖 Generated with Claude Code

Let users run arbitrary coding agents from global config with no Go code,
no fork, and no Dockerfile in this repo — the issue's "first useful
iteration" acceptance criteria:

  agents:
    aider:
      image: ghcr.io/acme/aider-bbox:latest
      command: ["aider"]
      env_forward: [OPENAI_API_KEY, "AIDER_*"]
      mcp:
        mode: env

Then `bbox agents doctor aider` and `bbox aider` work.

Changes:
- Extend AgentOverride with description, default_env, env_required,
  credentials.persist, settings entries, per-profile egress_hosts, and
  mcp.mode. Add AgentFromOverride (pure config->Agent mapping) and
  ValidateCustomAgent (pure load-time checks; image-ref parser injected
  as a closure to keep the domain free of go-containerregistry).
- Inject universal BBOX_* env vars into every VM via
  agent.BuildUniversalEnv, applied authoritatively after forwarded host
  vars. BBOX_MCP_URL uses a new shared config.MCPEndpointPath ("/mcp")
  constant, de-duplicating the path previously hardcoded in the proxy and
  all five built-in clients.
- mcp.mode: env enables the proxy without a config-file injector; the
  agent discovers it via BBOX_MCP_URL. mcp.mode: config is rejected.
- Add `bbox agents list|inspect|doctor`. inspect shows field provenance
  and env names only (never values); doctor exits non-zero on invalid
  config or missing required env. `bbox list` stays a shared alias.
- Safer defaults for custom agents: empty env_forward, egress profile
  standard, MCP authz safe-tools.
- Security: workspace-local config can never add a custom agent or new
  credential paths, repoint an existing agent's image/command, or widen
  its env_forward — tighten-only (mergeAgentOverride). Validate
  credential/settings paths are relative and cannot escape the home dir.
- Add a guard test pinning go-microvm's gateway IP to the literal
  pkg/sandbox uses for BBOX_MCP_URL.

Deferred to follow-ups: agents import/export, OCI-embedded manifests,
mcp.mode: config, agents add/init, and trusted host-side plugins.

Implemented via an architect -> implement -> 5-axis panel review -> fix
orchestration loop.

Fixes #191

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VP887qH8BMW4PMUXBuEqGc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant