Conversation
Stage 1 of the agent-collaborator prototype. Gets real agent state out of the tools a team already runs and into the database, deterministically. No world, no realtime, no MCP yet — this exists to answer whether seeing agent state beats reading it before anything expensive gets built. Hooks rather than an MCP tool first: an MCP tool only reports when the model chooses to call it, which degrades during exactly the long tasks you most want to watch. Hooks fire deterministically, and Claude Code's Notification event fires when it is waiting on a human — which is the blocked state a terminal buries. Both end up as adapters onto one ingest endpoint. - agent_spaces / agents / agent_events, deliberately separate from `spaces` (different product, different buyer). RLS on with no policies, so the service role is the only writer. - One write path at /api/agents/ingest, bearer token per space, rate limited. - current_task and event detail are encrypted at rest through the existing encryptContentFields path — they carry repo, branch and command detail. - scripts/mumbl-report.mjs runs inside Claude Code's hook path, so it never blocks and never fails the session: bounded fetch, all errors swallowed, always exits 0. - scripts/agent-space-create.mjs provisions a space and prints the token once. Events are ordered by a reporter-supplied occurred_at, not created_at. Hooks fire faster than the round-trip: five concurrent hooks were inserted in an order that put Stop first. Implausible client clocks fall back to server time. Verified end to end against staging — hook payloads through the reporter to encrypted rows and back out again. Test data removed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Task strings are encrypted at rest, so the Supabase table view shows ciphertext — there was no way to see whether the signal was any good. The watcher is also the control group for the experiment: it is the list the pixel world has to beat. If glancing at a room does not tell you something faster than this text view does, the spatial view is not earning its keep and stage 2 is not worth building. Orders by occurred_at, never created_at. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The demo was one dark room of identical sprites. It is now a walkable office you read as a place: - Six zones on a 1440x960 plate with a camera that follows you: meeting room, bullpen, lounge, cafe, rec room and reception, each with its own floor surface and a name label. - Depth sorting keyed to each object's bottom edge, so you walk behind the tall things and in front of the low ones. - Every agent is a different person. Build, hair, outfit and accessory are independent traits on the 14x20 grid, so no two collaborators are the same sprite recoloured, and each desk carries a personal object. - Proximity interaction: walk up and press E. E, Escape and clicking the agent all drive one open/close state, so they cannot disagree. Palette across the demo and the landing is now soft daylight pastel, with contact shadows to keep the furniture on the floor. The front-page theme is renamed shell-dark -> shell-soft to match what it now is. Two new visuals carry the argument on the landing: a looping animation of the product's loop (ask -> a collaborator walks in -> takes a desk -> working -> done), and a list-vs-room comparison that shows the blocked agent buried in a log and obvious in a room. Both are CSS/SVG and both respect prefers-reduced-motion. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stage 1 of the agent-collaborator prototype. Gets real agent state out of the tools a team already runs and into the database, deterministically.
No world, no realtime, no MCP yet. This stage exists to answer one question before anything expensive gets built: does seeing agent state beat reading it?
Why hooks before MCP
Mumbl will ship an MCP server — it's the breadth play and the line in the pitch. But an MCP tool only reports when the model chooses to call it, which costs tokens and degrades during exactly the long tasks you most want to watch.
Claude Code hooks fire deterministically. In particular
Notificationfires when Claude is waiting on a human — which is theblockedstate, the one a terminal buries and a room can surface. Both end up as adapters onto one ingest endpoint.What's here
0004_agent_presence.sql,0005_agent_event_occurred_at.sqlapp/api/agents/ingest/route.jssrc/server/agentPresence.jsscripts/mumbl-report.mjsscripts/agent-space-create.mjsdocs/agent-presence-stage-1.mdagentsis where a collaborator is now;agent_eventsis what it has been doing. Written together, so the world can never show a state with no trail.Tables are deliberately separate from
spaces— that's the anonymous Slack/room product, and entangling two products with different buyers makes both harder to change.Ordering bug caught during testing
Hooks fire faster than the ingest round-trip. Firing five concurrently,
created_atordering putStopfirst — nonsense. Events now carry a reporter-suppliedoccurredAt; implausible client clocks (>5min future, >24h past) fall back to server time.0005is separate because0004was already applied to staging, and editing an applied migration would leave the two databases silently divergent.Safety properties
current_taskand eventdetailcarry repo, branch and command detail, so both are encrypted at rest via the existingencryptContentFieldspath.Deliberate departure
This is the first thing that will need realtime, which
docs/free-tier-compromises.mdcurrently rules out. Stage 1 doesn't break it yet — flagged in the doc so stage 2 makes that call knowingly.Verified
End to end against staging: real hook payloads → reporter → ingest → encrypted rows → decrypted back out (
"Claude needs your permission to run: npm run deploy"as the blocked reason). Migrations applied to staging; test data removed.npm run buildpasses.0004/0005are on staging only — production not yet migrated.Known limits (documented)
occurred_at🤖 Generated with Claude Code