Inspiration
A Twilio-style widget on a real shop site — Wink grooming already has a clerk in the corner. The clerk should remember the place, not the prompt. Same JavaScript on a clinic, a village line, a building-supply counter, or a compost stall. Only the room address changes.
This is a product page, not a contest entry.
What it does
@nature-labs/living-memory-js is the door. You do not pick Room vs World. You do not speak MCP.
import { enterSpace } from "@nature-labs/living-memory-js"
const room = await enterSpace(process.env.LIVING_MEMORY_URL)
await room.remember("The blue door on the left opens onto the rooftop.")
const found = await room.search("how do I get to the rooftop")
A Strands agent on top of that door can ask the same question. A local 4B model (Ollama qwen3.5:4b-mlx) called search, got the rooftop fact back from the hosted room, and answered: go through the blue door on the left. The model did not invent the path. The place remembered it.
How I built it
Three layers, kept apart:
- Door —
@nature-labs/living-memory-json npm.enterSpace/remember/search. Zero runtime dependencies. Failures areSpaceErrorwith four codes:ENTER_FAILED,MEMORY_TOO_LARGE,ROOM_FULL,REQUEST_FAILED. Raw MCP stays onerror.cause. - Mind / mouth (pre-existing) —
@nature-labs/living-memory-engineand@nature-labs/lme-mcp. Hosted rooms atlme.viibe.to. Disclosed as infrastructure, not as this week's invention. - Skin —
createAgent({ model, space })thenagent.ask(...). Strands tools wrap the door. AWS / Bedrock was not used; the account was suspended, so the proof ran local.
The README is one path. A small model can follow three words without reading MCP docs.
Challenges I ran into
- Guessing
room.kindfrom tool names would have labeled a live free room as a world, because production rooms now listworld_listandhandoff. v1 leaveskindnull rather than lie. - HTTP 429 is not
ROOM_FULL. A full free room is a 16-item cap; reads still work. Mapping every 429 to “full” would teach the wrong failure. - Browser CORS on
lme.viibe.tois an allowlist (living-memory.app,chat.viibe.to,localhost:5173), not a missing header. A widget on an arbitrary shop domain is a later origin add, notAccess-Control-Allow-Origin: *. - A navy “LM” disc that says “cable not connected” is correct engineering and unsellable. The clerk people buy already exists on Wink. That design pass is next, not this writeup.
Accomplishments that I'm proud of
- Published
@nature-labs/living-memory-js@0.1.0. - Proved the chain on a real hosted room with a local 4B: search hit, natural answer, no Bedrock.
- Kept the door package free of Strands, so a student can
remember/searchwith no agent at all.
What I learned
Design the API until a small model can use it. If a 3B has to reason about JSON-RPC, the door leaked. Intelligence saved on plumbing is spent on the shop.
What's next
A landing on living-memory.app that looks like a tool, not a lab. One script tag, Wink-quality avatar, data-space as the only wire. Same JS, different room. No new repo. No Vercel (that origin is not on the CORS list).
Built With
- javascript
- living-memory
- node.js
- ollama
- strands-agents
- typescript
Log in or sign up for Devpost to join the conversation.