Skip to content
Early preview — you found Guuey before launch · official launch soon

State & memory

read as .md

Guuey gives agents and MCP servers a small, deliberate set of persistence primitives. Each is scoped tightly — per user, per app — and each has hard caps. The limits are the point: your server stays stateless from its own point of view, and your users keep ownership of their data.

Every conversation with a hosted agent is persisted automatically by the platform. Users reconnect and the thread is there. Don’t store chat history in any of the primitives below — that job is already done.

A key-value store scoped to (user, MCP server). It’s built for the state most MCP servers actually need: idempotency tokens, rate-limit counters, OAuth nonces, small per-user preferences.

import { createGuueyState } from "@guuey/state";
const kv = createGuueyState({
context: { userId: "u_abc", mcpId: "mcp_xyz" },
});
await kv.set("user-prefs", { theme: "dark" }, { ttl: 60 * 60 * 24 * 7 });
const prefs = await kv.get<{ theme: string }>("user-prefs");

In production you don’t pass the context by hand — it’s derived from the signed request Guuey sends your server. See the package README for the per-request wiring.

The caps are enforced everywhere, and they are the product:

  • 1 MiB per (user, server) scope; 64 KiB per value.
  • Every write needs a TTL — no permanent keys; 90 days max.
  • KV only: no queries, joins, or transactions.
  • Strict isolation: one MCP server can never read another server’s keys, even for the same user.

Without a hosted binding in your environment, the same API runs in-memory — exactly right for tests and guuey dev, non-durable by design. If you outgrow the caps, that’s the signal to move the data to a real backend and call it from your MCP server.

Every hosted agent runs with three directories bound in, used with plain node:fs — the @guuey/fs helpers just tell you where they are:

Helper What it is Lifetime
homeDir() Read-write, per (app, user) Durable — survives restarts and new sessions
appDir() Read-only files that ship with the app Same for every user
sessionDir() Read-write scratch (the working directory) This session only

The durable home is what makes “my agent remembers me” work: files written for a signed-in user today are there next week, from a fresh pod. The convention is a memories/MEMORY.md file in the home directory — the platform reads it before each turn and injects it into the model’s context for you, identically on all three frameworks. Your agent can also save memories mid-conversation; the platform tells it how.

Anonymous guests get a real, writable home too — but it’s deliberately ephemeral. Guests never accumulate durable storage; don’t build a feature that assumes otherwise.

A consent-gated user profile that can follow a user between apps — rolling out now.

  • Your app opts in by declaring profileAccess: "read" or "read-write" in guuey.json. No declaration, no access, and no prompt — ever.
  • The first time your app wants the profile in a conversation, the user sees a consent card in chat and chooses: always, only this conversation, or deny. Grants can be reviewed and revoked later from their Guuey settings.
  • Each app writes only its own section of the profile — one app structurally cannot touch another’s contribution.
  • Signed-in users only, and every unclear case fails closed: without consent the profile is simply absent and the conversation continues normally.

State is visible to the people it’s about: users can see and delete what an app has stored about them. Design your server so that a user clearing their data is a fresh start, never an error.