Skip to content

feat(box): berthd agent-host keeps a structured agent alive, and a log of everything it says - #75

Merged
sean-brydon merged 1 commit into
mainfrom
agent-host
Oct 13, 2026
Merged

sean-brydon merged 1 commit into
mainfrom
agent-host

Conversation

@sean-brydon

Copy link
Copy Markdown
Collaborator

Phase 2 of design/structured-agents/plan.md. Nothing uses it yet, so this PR changes no behaviour; the Claude driver (phase 3) is the first user.

berthd agent-host --dir D [--socket S] [--cwd W] -- COMMAND runs as the agent's tmux session program:

  • Owns the agent's stdin and stdout. The agent survives berthd restarts, upgrades and dropped links, because tmux keeps the host alive and berthd just attaches again.
  • Keeps its own log. D/events.jsonl is append-only and numbered (seq). It holds agent stdout (JSON kept as-is, other lines as text), what was written to stdin, stderr, and started/exited host entries. Streamed partials are kept, which the agents' own transcripts lose when killed mid-turn. A line cut short by a crash is dropped on reopen, and a host started again in the same folder carries the numbering on (resume).
  • Socket. D/host.sock takes JSON-line calls: attach (from a seq, gap-free between replay and live, ending after exited; a reader that falls 1024 behind is let go and attaches again), write (one JSON line to stdin, logged first, non-JSON refused) and stop.
  • Stop. It closes stdin, then sends SIGTERM to the process tree, then SIGKILL to the tree. The tree is collected before the first signal, so a tool's child in its own session is killed too; the spike found plain SIGKILL leaves Bash children running.
  • Shutdown. Closing the tmux session (SIGHUP) or SIGTERM stops the agent first. Readers get the exited entry before the host exits.

Tests cover the logged exchange, gap-free late attach, the log outliving the host, a second host carrying the log on, killing a setsid child that ignores SIGTERM, a cut-short log line, and a slow reader. I also ran it end to end against real claude -p --input-format stream-json --output-format stream-json --include-partial-messages (haiku): write, then attach until result, then stop, with exit 0 and a 30-entry log.

The plan's SQLite conversation index moves to phase 3, which is the first thing with data to put in it.

Checks run: go vet ./... (plus GOOS=linux), and go test -race for ./cmd/... and ./internal/agenthost (-count=5 on the new package).

🤖 Generated with Claude Code

…g of everything it says

`berthd agent-host --dir D -- COMMAND` runs as a tmux session's program
and owns the agent's stdin and stdout. Everything that passes between
them, streamed partials included, goes into the conversation's own
append-only events.jsonl. A unix socket serves "attach from seq N" with
nothing missed, plus write and stop. A stop closes stdin, then sends
SIGTERM, then kills the whole process tree, including what tools started
in sessions of their own. A host started again in the same folder carries
the log on. No driver uses it yet; the Claude driver is next
(design/structured-agents/plan.md, phase 2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
berth Ready Ready Preview Oct 13, 2026 11:48am UTC
berth-docs Ready Ready Preview Oct 13, 2026 11:48am UTC

Request Review

@sean-brydon
sean-brydon merged commit c8e8d34 into main Oct 13, 2026
8 checks passed
@linear-code

linear-code Bot commented Oct 13, 2026

Copy link
Copy Markdown

ENG-6000

This branch was successfully deployed

2 active deployments
Preview – berth-docs — a8735db4 Deployed Oct 13, 2026 by vercel[bot]
Preview – berth — a8735db4 Deployed Oct 13, 2026 by vercel[bot]
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