Where your house keeps its memories. One live page per household that every family member, and every family member's AI agent, can read from and write to. Built for the WebMCP Challenge.
Every home has one person who knows everything: the furnace filter size, the plumber who does not overcharge, where the water shutoff is, who is taking Mom to cardiology on Thursday. When that person is busy, away, or gone, the household goes blind. Attic gives the house itself the memory, and lets agents do the tedious part: filing things as you mention them, and answering when someone asks.
- Open the live URL, click Walk through the Hensley House. A furnished demo home is created for you; no sign-up.
- Come in as Dana. The cutaway house lights up: every lamp is one thing the house knows, in the room it belongs to. The care circle (Mom, the dog) has appointments, meds, and two rides nobody has claimed yet.
- Ask your agent, in ChatGPT's browser or Chrome with WebMCP on: "what needs doing this week? I can take Mom to cardiology." It reads the house, claims the ride, and a receipt lands on the page with an Undo button. Everyone else in the house sees it live.
- No WebMCP browser handy? Open the Agent tab and click Run a simulated agent. It calls the same tool code a real agent would, labeled in its own color, and you can undo anything it does.
The house registers 17 imperative tools with document.modelContext.registerTool, plus 3 declarative form tools (<form toolname>), plus 2 tools on the landing page so an agent can create or open a house for you.
document.modelContext.registerTool({
name: 'remember',
description: 'File something new into the house: a fact, a contact, a maintenance note, a reminder. Pick the room it belongs to.',
inputSchema: { type: 'object', properties: { title: {...}, details: {...}, room: {...}, remind_on: {...} }, required: ['title'] },
annotations: { readOnlyHint: false },
async execute(input, { signal }) {
// same WebSocket op channel the UI uses; returns a receipt id the agent can undo
},
}, { signal });| Tool | Annotation | What it does |
|---|---|---|
attic_overview |
read | Rooms, counts, care circle, who is in the house, what is urgent |
search_house_memory, read_room, whats_coming_up, care_circle, whos_here, recent_activity |
read | Answer questions from the house |
remember, update_memory |
write | File and correct knowledge; a light appears in the room live |
forget |
consequential | Remove a memory (agent is told to confirm first; undoable) |
add_care_person, add_care_task, care_journal |
write | Grow and annotate the care circle |
add_medication |
consequential | Add a medication to someone's card: health information a family acts on |
claim_care_task, complete_care_task |
write | "I'll take Mom on Thursday": claims it for you, family sees it live |
undo_last_action |
write | Reverse the last undoable action by anyone, by receipt id |
come_in (form) |
Enter the house as a family member, by name | |
rename_house (form) |
Rename the house; the form stays mounted so an agent finds it without a click | |
add_memory (form) |
The add-memory panel, fillable by an agent the way a person fills it |
Three things make the tool layer more than a bolt-on:
- Receipts and undo. Every mutating call returns a receipt id and a record id. The Durable Object stores an inverse op with each log entry, so
undo_last_action(or the Undo button any family member sees) reverses exactly that change, agent or human, and everyone's page updates. - Same channel as the UI. Tools send the same ops the buttons send. The server validates, persists, and broadcasts a human-readable cause (
Marcus's agent claimed "Cardiology follow-up"), which drives the receipt bar, the light that turns on in the room, and the presence chips. - Multi-human, multi-agent. Presence is per person and marks whose agent has acted recently.
whos_heretells an agent who else is home.
web/src/
webmcp.js tool definitions (schemas, annotations, execute) + registration
store.js WebSocket client, shared bridge used by both UI and tools
simulate.js the on-page simulated agent (calls the real tool execute())
HouseView.jsx single-screen house: cutaway left, rail right (Rooms / Family / This week / Agent)
HouseSVG.jsx the cutaway house, lamps, presence, agent light
Care.jsx care circle: people, tasks, meds, journal
Landing.jsx landing page with the two starter tools
worker/index.js Cloudflare Worker + HouseDO Durable Object: op reducer, inverse ops, log, presence, broadcast
tests/ Playwright (Chrome channel) + raw protocol tests, WebMCP polyfill harness
A house is a Durable Object addressed by an unguessable slug. No accounts, no tracking: the URL is the key you hand to family.
npm install
npm run build # vite -> dist/
npx wrangler dev # http://localhost:8787With wrangler dev running on :8787, in a second terminal:
npm test # all three suites in order
node tests/protocol.test.mjs # raw WebSocket protocol against the Durable Object:
# hello/presence, op -> state+cause, undo via inverse op, errors
node tests/webmcp-tools.test.mjs # every WebMCP tool through a document.modelContext polyfill,
# the way an agent-capable browser would call them
node tests/live-sync.test.mjs # two family members on one house: an agent acts in one browser,
# the other sees it live and undoes it
node tools/shot.mjs shots # screenshots + console-error smoke test (add `mobile` for 390x844)The Playwright suites use the installed Chrome channel. Point any of them at a
deployed instance with ATTIC_URL=https://your-worker.workers.dev.
Deploy with npm run deploy (Cloudflare account, free tier is enough).
Open the live URL in ChatGPT's in-app browser, or Chrome 149+ with chrome://flags/#enable-webmcp-testing, and try:
- "Open the demo house and tell me what needs doing this week."
- "What size filter does the furnace take?"
- "I just had the gutters cleaned by ClearFlow for $180. Remember that."
- "Who is covering Mom this week? I can do the pharmacy run. Claim it for me."
- "Undo that."
MIT. See LICENSE.