Agent API over unix socket (labctl LAB_URL unix://) #201

Closed
opened 2026-07-22 11:43:31 +02:00 by dominik.polakovics · 1 comment

What to build

Move the agent surface off loopback TCP: the server additionally listens for /agent/v1 on a unix domain socket at <state-dir>/agent.sock, and labctl learns a unix scheme for LAB_URL (e.g. unix:///run/lab/agent.sock). Spawned runs get the unix LAB_URL by default. This is the transport the container runner will bind-mount into instances; it must also work for today's host-spawned runs, end to end (labctl issue/pr/secret commands + pre-push scan).

The web UI / human HTTP surface stays on its existing TCP listener; only the agent API is dual-listened. Socket file mode must restrict access to the lab user; recreate stale sockets on boot.

Acceptance criteria

  • Server serves /agent/v1 on <state-dir>/agent.sock in addition to the existing TCP listener; socket is 0700-owned by the service user and safely recreated on restart
  • labctl accepts LAB_URL=unix:///abs/path (all subcommands, including secret exec and secret scan) with unchanged behavior for http URLs
  • spawnEnv passes the unix LAB_URL to new runs; a full host-mode run works end to end over the socket (issue view/comment, pr create, pre-push scan)
  • Tests cover unix-scheme parsing, HTTP-over-UDS round trip against a test server, and socket recreation
  • docs/ops.md documents the socket and the LAB_URL scheme

Blocked by

None - can start immediately

## What to build Move the agent surface off loopback TCP: the server additionally listens for /agent/v1 on a unix domain socket at `<state-dir>/agent.sock`, and labctl learns a unix scheme for LAB_URL (e.g. `unix:///run/lab/agent.sock`). Spawned runs get the unix LAB_URL by default. This is the transport the container runner will bind-mount into instances; it must also work for today's host-spawned runs, end to end (labctl issue/pr/secret commands + pre-push scan). The web UI / human HTTP surface stays on its existing TCP listener; only the agent API is dual-listened. Socket file mode must restrict access to the lab user; recreate stale sockets on boot. ## Acceptance criteria - [ ] Server serves /agent/v1 on `<state-dir>/agent.sock` in addition to the existing TCP listener; socket is 0700-owned by the service user and safely recreated on restart - [ ] labctl accepts `LAB_URL=unix:///abs/path` (all subcommands, including secret exec and secret scan) with unchanged behavior for http URLs - [ ] spawnEnv passes the unix LAB_URL to new runs; a full host-mode run works end to end over the socket (issue view/comment, pr create, pre-push scan) - [ ] Tests cover unix-scheme parsing, HTTP-over-UDS round trip against a test server, and socket recreation - [ ] docs/ops.md documents the socket and the LAB_URL scheme ## Blocked by None - can start immediately
Author
Owner

This was generated by AI during triage.

Agent Brief

Category: enhancement
Summary: Serve /agent/v1 on a unix domain socket and teach labctl a unix:// LAB_URL scheme; spawned runs default to the socket.

The issue body's "What to build" and acceptance-criteria checklist are the authoritative spec (grilled 2026-07-22). This brief adds the interface map and scope fences.

Current behavior:
The /agent/v1 tree is one handler (built by the agent-API package's New(...)/Handler(), guarded by run-token AuthMiddleware) mounted on the same TCP listener as the human/web surface. The labURL helper resolves the URL handed to runs with precedence AgentURL → BaseURL → http://127.0.0.1:<port> loopback, and spawnEnv emits it as LAB_URL. labctl only speaks http/https.

Desired behavior:
The same agent handler is additionally served on a unix socket at <state-dir>/agent.sock (mode restricted to the service user; stale socket unlinked and recreated on boot). labctl accepts LAB_URL=unix:///abs/path in every subcommand — including secret exec and secret scan, which the pre-push guard hook shells out to — with http(s) behavior unchanged. spawnEnv hands new runs the unix URL by default; the web/human TCP surface is untouched.

Key interfaces:

  • The agent-API Handler() — reuse the one mux on a second listener; do not duplicate routes. Run-token auth must apply identically over the socket.
  • The labURL resolution precedence — extend so the socket becomes the default agent URL for spawned runs while explicit AgentURL config still wins.
  • labctl's HTTP client — a unix scheme should route through a transport whose dialer connects to the socket path; one shared client seam so all subcommands inherit it.
  • Socket lifecycle on the server: create in the state dir with restrictive permissions, remove a stale socket file before Listen.

Acceptance criteria: the checklist in the issue body.

Out of scope:

  • The container runner and any mount wiring (#205) — this issue must work end to end for today's host-spawned runs.
  • Moving the web UI / human HTTP surface off TCP.
  • Any change to the run-token auth model.
> *This was generated by AI during triage.* ## Agent Brief **Category:** enhancement **Summary:** Serve /agent/v1 on a unix domain socket and teach labctl a `unix://` LAB_URL scheme; spawned runs default to the socket. The issue body's "What to build" and acceptance-criteria checklist are the authoritative spec (grilled 2026-07-22). This brief adds the interface map and scope fences. **Current behavior:** The /agent/v1 tree is one handler (built by the agent-API package's `New(...)`/`Handler()`, guarded by run-token `AuthMiddleware`) mounted on the same TCP listener as the human/web surface. The `labURL` helper resolves the URL handed to runs with precedence AgentURL → BaseURL → `http://127.0.0.1:<port>` loopback, and `spawnEnv` emits it as `LAB_URL`. labctl only speaks http/https. **Desired behavior:** The same agent handler is additionally served on a unix socket at `<state-dir>/agent.sock` (mode restricted to the service user; stale socket unlinked and recreated on boot). labctl accepts `LAB_URL=unix:///abs/path` in every subcommand — including `secret exec` and `secret scan`, which the pre-push guard hook shells out to — with http(s) behavior unchanged. `spawnEnv` hands new runs the unix URL by default; the web/human TCP surface is untouched. **Key interfaces:** - The agent-API `Handler()` — reuse the one mux on a second listener; do not duplicate routes. Run-token auth must apply identically over the socket. - The `labURL` resolution precedence — extend so the socket becomes the default agent URL for spawned runs while explicit AgentURL config still wins. - labctl's HTTP client — a `unix` scheme should route through a transport whose dialer connects to the socket path; one shared client seam so all subcommands inherit it. - Socket lifecycle on the server: create in the state dir with restrictive permissions, remove a stale socket file before Listen. **Acceptance criteria:** the checklist in the issue body. **Out of scope:** - The container runner and any mount wiring (#205) — this issue must work end to end for today's host-spawned runs. - Moving the web UI / human HTTP surface off TCP. - Any change to the run-token auth model.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/coding-lab#201
No description provided.