Skip to content

feat: headless sandboxes and an MCP server to drive PentAGI without an LLM key - #475

Open
IshanKulkarni02 wants to merge 1 commit into
vxcontrol:mainfrom
IshanKulkarni02:feat/pentagi-mcp-headless-sandbox
Open

IshanKulkarni02 wants to merge 1 commit into
vxcontrol:mainfrom
IshanKulkarni02:feat/pentagi-mcp-headless-sandbox

Conversation

@IshanKulkarni02

Copy link
Copy Markdown

What

Adds a flow mode with no agent loop and no LLM provider behind it: a Docker sandbox (same hardened docker.WorkerSpec agents get) that a caller drives directly, so PentAGI's Docker sandboxing is usable with zero LLM provider configured. Alongside it, mcp/ is a small stdio MCP server wrapping both this new surface and the existing flow API, so a tool like Claude Code can drive a PentAGI instance over MCP — the motivating use case.

New REST endpoints (reusing the existing terminal tool's exec/file plumbing, not new exec logic):

POST    /sandboxes/
DELETE  /sandboxes/{sandboxID}
POST    /sandboxes/{sandboxID}/exec
GET/PUT /sandboxes/{sandboxID}/file

Design choices (happy to revisit)

  • One migration adds flows.headless; model_provider_name/model_provider_type carry inert 'headless'/'custom' placeholders rather than a new PROVIDER_TYPE enum value, so GraphQL/gqlgen/frontend stay untouched. A headless flow is a real row in flows (shows up in the normal flows list/UI), but LoadFlowWorker skips it on restart — it never had a FlowWorker to rebuild.
  • /sandboxes/* reuses the existing flows.* privileges rather than adding a new privilege namespace.
  • mcp/ is a standalone Node project (own package.json: @modelcontextprotocol/sdk, zod, both MIT), not wired into frontend/'s dependency tree or the existing license-scan scripts — let me know if you'd rather it live elsewhere or be folded into an existing scope.

I know examples/proposals/mcp_client_integration.md stages MCP work carefully given PR #268's review history (no implicit lifecycle state, explicit operator visibility/control) — that RFC is about the other direction (PentAGI as an MCP client calling external tools). This is PentAGI as something an MCP client drives, a narrower surface, but I'm glad to split this into smaller slices if that's preferred.

Testing

No existing test suite covers this (new feature), but it's verified live, not just compiled:

  • Full lifecycle against a real local Postgres + Docker: create → exec → file read/write → survives a server restart → stop → container actually removed.
  • Driven through real MCP tools/call requests end-to-end, not just the REST layer.
  • Found and fixed two real bugs this way before they shipped: a route that silently no-op'd DELETE (redirect instead of deleting), and an empty placeholder value that 500'd GET /flows/ for every flow once a headless one existed — both now pinned by regression tests (shown failing before the fix, per this repo's testing conventions).
  • go build ./..., go test ./..., go vet ./..., and golangci-lint run (v2.12.2) all clean.
  • swag/gqlgen: no schema change, so only swagger was regenerated (pinned swag v1.8.7 to match the committed output, not @latest, which silently produced an empty paths list on this toolchain — worth knowing about independent of this PR).

Not done here

  • No frontend UI for sandboxes (they're reachable via REST/MCP only; they do show up in the existing flows list/API since they're real flow rows).
  • No installer wizard changes (nothing to configure — no new provider, no new env var).
  • Open to feedback on whether /sandboxes is the right name/shape, or whether this belongs behind a feature flag given it's a new unauthenticated-by-default (well, same Bearer-token auth as everything else) way to get arbitrary command execution in a container — same privilege model as flows, but worth a second look given the dual-use nature of this tool.

🤖 Generated with Claude Code

…n LLM key

Adds a flow mode with no agent loop and no LLM provider behind it: a
flows.headless row plus a real Docker container (same hardened
docker.WorkerSpec agents get), reached through new REST endpoints that
reuse the existing terminal tool's exec/file plumbing directly.

- POST   /sandboxes/                  create
- DELETE /sandboxes/:sandboxID        stop + remove container
- POST   /sandboxes/:sandboxID/exec   run a command
- GET/PUT /sandboxes/:sandboxID/file  read/write a file

Migration adds flows.headless; model_provider_name/model_provider_type
carry inert 'headless'/'custom' placeholders rather than a new
PROVIDER_TYPE enum value, keeping GraphQL/gqlgen/frontend untouched.
LoadFlowWorker skips headless flows on restart (they never had a
FlowWorker to rebuild). Regression tests pin both bugs found while
testing this live: a route that silently no-op'd DELETE, and an empty
placeholder that 500'd GET /flows/ for every flow once a headless one
existed.

mcp/ is a stdio MCP server (Node, @modelcontextprotocol/sdk) wrapping
both the new sandbox endpoints and the existing flow API, plus a
pentagi skill, so Claude Code can drive a PentAGI instance directly.

Verified live against a local Postgres + Docker: create, exec, file
read/write, restart-survival, and stop, through real MCP tool calls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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