This is the abridged developer documentation for Guuey # Build an agent. Guuey runs it. > Bring a system prompt, a model, and the MCP servers your agent needs. Guuey hosts it on isolated, always-on infrastructure, streams every conversation in real time, and puts it in front of users — no agent loop, no polling, no servers to babysit. Start here [Getting started](/getting-started/)Zero to a deployed, live agent in minutes — no code required. [Studio](/studio/)The no-code builder: describe your agent, pick a model, deploy in one click. [CLI](/cli/)The code path: scaffold locally, bring your own framework code, guuey deploy. Run [Hosting & runtime](/hosting/)Isolated sandboxes, scale-to-zero pods, SSE streaming, persisted conversations. [State & memory](/state-and-memory/)Managed history, a per-user KV store, durable home directories, consent-gated profiles. Distribute [Portal](/portal/)The agent App Store and universal chat client where users find and talk to your agent. [Embed & share](/embed/)Two script tags put the chat widget on your own site; share links give anyone a hosted chat page. [Build your own surface](/sdk/)The @guuey/agent-client SDK: streaming, status, and continuity for a fully custom chat UI. [Generative UI (ggui)](/protocol/)Agents that keep the default MCP server reply with interactive screens, not just text. *** **Where things live:** [guuey.com](https://guuey.com) is the platform — Studio, Portal, hosting, these docs. [docs.ggui.ai](https://docs.ggui.ai) documents the open **ggui** generative-UI protocol and its SDKs; this site documents the platform. Reading these docs as an LLM? Every page is also raw markdown at the same slug — start at [`/llms.txt`](/llms.txt), or see the [machine-readable surface](/agents/). # 404 — page not found > Nothing lives at this URL. Try the home page, the getting-started guide, or the search box in the sidebar. # For LLM agents > Machine-readable resources for LLMs and coding-assistant devtools reading Guuey docs programmatically — aggregated dumps, per-page .md companions, stable anchors. This page is for **non-human readers** — LLM agents, coding-assistant devtools (Claude Code, Cursor, Cline, Continue), evaluators, and scrapers. Humans, the rest of the site is for you. ## What’s available [Section titled “What’s available”](#whats-available) | Resource | URL | When to fetch | | --------------------- | ------------------------------------ | ----------------------------------------------------------------------------------------------- | | Entry point | [`/llms.txt`](/llms.txt) | First contact. [llms.txt format](https://llmstxt.org/) — links the abridged and complete dumps. | | Whole-site dump | [`/llms-full.txt`](/llms-full.txt) | One-shot context loading. Drop into your window for cross-topic tasks. | | Compact dump | [`/llms-small.txt`](/llms-small.txt) | Smaller one-shot context when `/llms-full.txt` is too big. | | Per-page raw markdown | `/.md` | Reading one specific page. No HTML, no chrome. | | Stable anchors | `/#` | Deep-linking to a section. Every H2/H3 has a Starlight-derived id. | ## Per-page `.md` companions [Section titled “Per-page .md companions”](#per-page-md-companions) Every page is also served as raw markdown at the same slug with a `.md` extension: * [`/getting-started.md`](/getting-started.md) — zero to deployed agent * [`/hosting.md`](/hosting.md) — the runtime model * [`/cli.md`](/cli.md) — command reference * [`/state-and-memory.md`](/state-and-memory.md) — persistence surfaces The `.md` response is the source markdown with a small `---\ntitle: ...\n---` envelope and **no other transformation**. (A few pages are authored as MDX — their `.md` companion keeps the component imports as-is; treat those lines as noise.) Fetch from any origin: ```bash curl https://docs.guuey.com/hosting.md ``` CORS is open (`Access-Control-Allow-Origin: *`); `Cache-Control` permits 5-minute CDN caching. Every HTML page also carries a `` pointing at its companion, so alternate-representation-aware fetchers can auto-discover it. ## When to use which [Section titled “When to use which”](#when-to-use-which) ```plaintext You want → Fetch ─────────────────────────────────────────── ────────────────────── Find the machine-readable surface /llms.txt Drop everything into context (one-shot) /llms-full.txt Read one specific page /.md Deep-link to a section in conversation //# ``` ## Related machine-readable surfaces [Section titled “Related machine-readable surfaces”](#related-machine-readable-surfaces) The open ggui protocol (generative UI used by Guuey agents) documents itself the same way at [`docs.ggui.ai/llms.txt`](https://docs.ggui.ai/llms.txt) — fetch that too when your task involves the protocol wire surface or SDKs rather than the hosting platform. # CLI > Install the Guuey CLI, log in, define your agent in guuey.json, and deploy it to Guuey hosting. The `guuey` CLI is the code path onto the platform: it scaffolds an agent project, runs it locally, and deploys it to Guuey hosting. ## Install [Section titled “Install”](#install) The CLI ships on npm as [`@guuey/cli`](https://www.npmjs.com/package/@guuey/cli): ```bash npm install -g @guuey/cli guuey --version ``` ## Log in [Section titled “Log in”](#log-in) ```bash guuey login ``` This opens your browser, authenticates you with your Guuey account, and delivers an API key back to the CLI via a localhost callback. For headless or CI use, pass a pre-minted API key instead: ```bash guuey login --token guuey_user_... ``` Check who you are with `guuey whoami`; clear credentials with `guuey logout`. ## The agent definition: guuey.json [Section titled “The agent definition: guuey.json”](#the-agent-definition-guueyjson) Every project is described by a single `guuey.json` at the project root. The `agent` section is the deployable definition — framework, model, system prompt, and MCP servers. A minimal valid file: ```json { "schema": "1", "agent": { "framework": "claude-agent-sdk", "model": "claude-sonnet-5", "systemPrompt": { "file": "prompts/system.md" } } } ``` Everything else defaults. Notably, `agent.mcpServers` defaults to the `ggui` server at `https://mcp.ggui.ai`, which gives your agent generative UI out of the box — see the [ggui docs](https://docs.ggui.ai) for what that enables. Servers you declare merge on top of the default; the platform is otherwise MCP-server-agnostic. Create the file in an existing directory with: ```bash guuey config init ``` The CLI stamps the app’s `appId` into the file after your first deploy — you don’t write it by hand. (`workspaceId` is only needed when you deploy hosted MCP servers, supplied via `guuey.json`, `--workspace`, or `$GUUEY_WORKSPACE`.) Secrets never go in `guuey.json`; use `guuey env set KEY=VALUE`. ## Create a project [Section titled “Create a project”](#create-a-project) Start from a working scaffold: ```bash guuey create my-agent --framework claude-agent-sdk ``` Supported frameworks for `create` are `claude-agent-sdk` and `openai-agents-sdk`. You can also scaffold without installing the CLI first: ```bash npx @guuey/create-agentic-app my-agent ``` ## Deploy [Section titled “Deploy”](#deploy) ```bash guuey deploy ``` `deploy` auto-detects which of two modes your project uses: * **Declarative mode** — `guuey.json` only, no build step. Your agent is the definition: prompt, model, MCP servers. * **Code mode** — builds and deploys your `guuey.worker.js` worker bundle (or uses a root `Dockerfile` if present), deploying your MCP servers, generative UI registration, and the agent itself in one command. Force a mode with `--declarative` or `--code`. Pick a runtime pod size with `--size` (`xs` | `sm` | `md` | `lg` | `xl`, default `xs`) and tag the version with `--label`. After deploying: ```bash guuey test "hello" # send a test message, print the response guuey logs --follow # live-tail runtime logs guuey deployments list # list deployment builds guuey undeploy # tear down the deployment (keeps the app) ``` ## Local dev [Section titled “Local dev”](#local-dev) Run your built worker locally behind the same SSE endpoint the hosted pod serves: ```bash guuey dev --serve --port 6790 ``` This gives you pod-parity iteration: `POST /agent/invoke` against localhost before you deploy. (Plain `guuey dev` — a device bridge with a QR code — is coming soon; the CLI says so itself.) ## Beyond the basics [Section titled “Beyond the basics”](#beyond-the-basics) The CLI also manages apps (`guuey apps create|list|get|update|delete`), hosted MCP servers (`guuey mcp deploy|list|status|logs|delete|secrets`), environment variables (`guuey env set|list|unset`), and worker conformance (`guuey worker verify`). Run `guuey --help` for the full surface, and `guuey open dashboard` to jump to the console. # Embed & share > Put your agent on your own website with the two-script widget embed, or share it as a hosted chat page — anonymous or signed-in, always on your allowed domains. ## Embed on your site [Section titled “Embed on your site”](#embed-on-your-site) Any deployed agent can live on your own website as a chat widget. The widget runs in an iframe on guuey’s origin, so it never touches your page’s cookies, storage, or scripts — the only thing you add to your site is two ` ``` Paste it anywhere in your HTML — before `` is typical. No SDK, no build step, no framework required. Keep the snippet exactly as generated. The first block registers a small queue so calls made before the loader finishes downloading are replayed when it arrives — that’s what makes the `async` load safe. Reformatting the one-line shim (some code formatters try) changes the bytes the loader depends on. The loader is a permanent contract: paste it once and it keeps working. New capabilities ship behind the frame, on guuey’s release cadence, without you touching your page. ### 3. Customize the launcher [Section titled “3. Customize the launcher”](#3-customize-the-launcher) Options go in the `guuey("init", …)` call: | Option | Values | Default | What it does | | ----------- | -------------------- | --------- | ------------------------------------------------------------ | | `app` | string | required | Your app id. | | `theme` | `"light"` / `"dark"` | `"light"` | `"dark"` paints the chat panel dark, from the first frame. | | `launcher` | string | `"Chat"` | Accessible label for the launcher button and the chat frame. | | `color` | CSS color | `#111` | Launcher bubble background. | | `iconColor` | CSS color | `#fff` | Launcher icon color. | | `position` | `"left"` / `"right"` | `"right"` | Which side of the viewport the widget docks to. | You can also open and close the panel from your own UI: ```js guuey("open"); guuey("close"); ``` Unknown or invalid values are ignored with a console warning — the widget never throws into your page. ### Who the visitor is [Section titled “Who the visitor is”](#who-the-visitor-is) **Anonymous (the default).** Visitors chat without signing in. The widget keeps a per-browser identity in its own storage so a returning visitor continues their conversation; continuity is best-effort (strict privacy modes may reset it). If your agent is set to **require sign-in to chat**, anonymous embeds can’t chat — use identified embeds instead. **Identified (your own sign-in).** If your site has its own logged-in users, the widget can know who they are — giving each visitor durable history tied to their account with you. This mode is configured per app in the console’s **Embed** tab, and takes three steps: 1. **Enrol your app once** and store the secret it prints (shown once — treat it like a database password): ```bash guuey widget keys create --audience ``` 2. **Add a token endpoint to your backend** with [`@guuey/widget-auth`](https://www.npmjs.com/package/@guuey/widget-auth) — a zero-dependency package that mints a short-lived token for the currently signed-in user: ```ts import { signUserToken } from "@guuey/widget-auth"; const { token } = await signUserToken( { userId: session.userId, name: session.name, email: session.email }, { appId: process.env.GUUEY_APP_ID!, appSecret: process.env.GUUEY_APP_SECRET! } ); // Return the raw token string from your endpoint. ``` 3. **Point the widget at it.** The console’s Embed tab generates the identified snippet, which adds an `identity` block: ```js identity: { getToken: (reason) => fetch("https://www.example.com/api/guuey-token" + "?reason=" + reason).then((r) => { if (!r.ok) throw new Error("token endpoint failed: " + r.status); return r.text(); }), }, ``` `getToken` is called with a `reason`: `"initial"` on first need, `"expired"` when a token has stopped working. If your endpoint caches tokens, always mint a fresh one on `"expired"`. An app configured for identified embeds fails loudly, never silently: if the identity setup is incomplete, the widget shows a clear notice instead of mounting a chat that would drop your visitors into anonymous threads. ## Share links [Section titled “Share links”](#share-links) Every agent can be shared as a hosted chat page — no website required. Open your agent in Studio and choose **Share**. The link points at guuey’s agent client: ```plaintext https://app.guuey.com/agent/ ``` Anyone who opens it gets a full chat with your agent, on web and in the mobile app. ### Two ways to share [Section titled “Two ways to share”](#two-ways-to-share) * **Unlisted link** — the agent stays off the public Discover directory and is reachable only by its direct link. Available for any agent. * **List in Discover** — the agent is also listed publicly in the Discover directory, where anyone can find it. Public listing is available only for read-only agents — agents with no connected tools that could modify data. If your agent gains write-capable tools later, you’ll be prompted to switch it back to unlisted. **Stop sharing** invalidates the link immediately. Resuming later hands out the same URL again. ### Require sign-in to chat [Section titled “Require sign-in to chat”](#require-sign-in-to-chat) Separate from how the agent is listed, you choose whether visitors must sign in before chatting. This is the real access gate — enforced by the agent itself, and it applies to the share link even when the agent is unlisted. Changes take effect within about 15 seconds. ### Listing details [Section titled “Listing details”](#listing-details) Optionally add a description, category, and icon in the Share panel. These appear on Discover cards and the agent’s page once the listing is public and published; they change nothing for unlisted agents. # Getting started > Go from zero to a deployed, live-testable agent in minutes with Guuey Studio — no code required. Guuey hosts agents. You describe what your agent should do, pick a model and its capabilities, and Guuey runs it on isolated, always-on infrastructure — conversations stream live, and history is saved for you. The fastest way in is [Studio](/studio/), the no-code builder. ## What you’ll build [Section titled “What you’ll build”](#what-youll-build) An agent on Guuey is a declarative definition: instructions (its system prompt), a model, and its capabilities — including MCP servers it can call. There is no code to write and nothing to keep running yourself. ## Create your first agent [Section titled “Create your first agent”](#create-your-first-agent) 1. **Sign in** at [studio.guuey.com](https://studio.guuey.com). Email and password always work; Google and GitHub sign-in are offered where available. One account carries you across Guuey. 2. **Start a new agent.** On your first visit, Studio points you straight at the create form — click **Create your first agent**. 3. **Write the instructions.** This is the heart of your agent: who it is, what it does, how it behaves. Not sure where to start? Click a starter template chip — Trip planner, Meeting-prep assistant, Customer FAQ answerer, Study coach, Social media copywriter, or Meal planner — and edit from there. Or open **Draft it for me**, type one sentence, and Studio expands it into full instructions. 4. **Name it.** Templates propose a name you can shuffle or replace. 5. **Pick a model.** Three plain-language tiers: **Thinking** for the deepest reasoning, **Balanced** (recommended), or **Fast** for the snappiest, lowest-cost replies. An Advanced section exposes the underlying provider, model, and framework if you want them. 6. **Choose superpowers.** **Generative UI** is on by default — your agent replies with interactive screens, not just text. You can also add your own MCP server by URL under Advanced. 7. **Click “Create my agent.”** Studio creates the agent and deploys it in one step, then drops you into its playground. Watch the status chip in the header walk from **Starting…** to **Live**. ## Test it [Section titled “Test it”](#test-it) The playground is a phone-framed chat that talks to your actually-deployed agent — the same live endpoint your users will reach, streaming responses in real time. Chat with it, then open **Settings** to tweak the instructions, model, or superpowers and hit **Deploy changes**. When you’re happy, the **Share** panel gives you a link, access controls, and an embed snippet. ## Prefer code? [Section titled “Prefer code?”](#prefer-code) Studio is one of two ways in. Developers can scaffold a code-mode agent — bring Claude Agent SDK, OpenAI Agents SDK, or Google ADK code — run it locally, and deploy it with the CLI: ```bash npx @guuey/create-agentic-app my-agent cd my-agent pnpm install pnpm dev # run locally with hot reload guuey login guuey deploy # hosted on Guuey ``` See the [CLI guide](/cli/) for the full workflow. ## Next steps [Section titled “Next steps”](#next-steps) * Read the [Studio guide](/studio/) for a tour of every screen. * Learn how generative UI works in the [ggui docs](https://docs.ggui.ai) — the open protocol behind those interactive replies. # Hosting & runtime > How Guuey runs your agent — isolated gVisor sandboxes, long-running pods that scale to zero, SSE streaming, persisted conversations, and your choice of agent framework and MCP servers. You bring a declarative agent definition — a system prompt, a model, the MCP servers your agent uses, and an optional tool allowlist. Guuey runs it. There is no SDK to import, no polling loop to write, no event handler to register: configuration and a prompt are the whole integration. Everything lives in one file, `guuey.json`, validated the same way by `guuey dev`, `guuey deploy`, and the hosted runtime — one contract everywhere. ## Isolated, long-running sandboxes [Section titled “Isolated, long-running sandboxes”](#isolated-long-running-sandboxes) Each agent runs in its own long-running pod, sandboxed with [gVisor](https://gvisor.dev) — a much stronger isolation boundary than an ordinary shared container. Long-running means your agent isn’t rebuilt on every request; it stays warm across the turns of a conversation. When nobody is talking to it, it scales to zero, and the platform wakes it when the next conversation arrives. The same isolation applies to MCP servers you host on Guuey. That matters most for compute workloads — code execution, binary tools like ffmpeg or pandoc, headless browser automation — the kind of thing most platforms can’t sandbox per tenant. ## Streaming and history [Section titled “Streaming and history”](#streaming-and-history) Live responses stream over Server-Sent Events (SSE) directly from the pod running your agent — the client connects straight to the source, with no relay in between. Conversation history is persisted automatically by the platform. Users can close the tab, come back later, and pick up the thread. You never build or operate a chat store. ## Frameworks [Section titled “Frameworks”](#frameworks) Guuey is framework-adaptive: declare a framework in `guuey.json`, and the platform loads the matching runner, drives one turn per request, and streams the framework’s native events. | You declare | Runtime it drives | | ------------------- | -------------------------------- | | `claude-agent-sdk` | `@anthropic-ai/claude-agent-sdk` | | `openai-agents-sdk` | `@openai/agents` | | `google-adk` | `@google/adk` | For a no-code agent, that declaration plus your system prompt is everything — start from `guuey config init` or [Studio](/studio/). If you’d rather write framework-native code, deploy a code-mode project — a worker bundle or Dockerfile the [CLI](/cli/) builds and ships. Scaffold a working code-mode project from a template: ```sh npx @guuey/create-agentic-app my-agent ``` ## MCP servers: bring your own [Section titled “MCP servers: bring your own”](#mcp-servers-bring-your-own) Agents declare their MCP servers in `guuey.json` in three flavors: * **hosted** — Guuey runs the server for you. * **colocated** — the server runs alongside your agent, in the same sandbox. * **external** — any URL you point at. The platform is MCP-server-agnostic: anything that speaks MCP works. The default server is `mcp.ggui.ai` — agents that keep it get generative UI out of the box, pushing real interactive interfaces to users instead of text-only replies. Generative UI, the protocol, and its SDKs are documented at [docs.ggui.ai](https://docs.ggui.ai). ## Local development [Section titled “Local development”](#local-development) `guuey dev --serve` runs your agent locally under the same host harness used on Guuey pods, so your local loop matches production. When it works, ship it: ```sh npm install -g @guuey/cli guuey login guuey deploy ``` # Portal > Guuey's agent App Store and universal chat client — where end users discover deployed agents and talk to them, on the web today with native apps on the way. Portal is Guuey’s app for end users. It’s two things in one: an App Store for agents, and a universal chat client for talking to them. Builders create and deploy agents in [Studio](https://studio.guuey.com); Portal is where everyone else finds those agents and uses them. ## Finding agents [Section titled “Finding agents”](#finding-agents) Portal is organized into four tabs: * **Explore** — the store surface. Browse featured and trending agents, official apps, and category filters, or search by name. Tap any agent to open its profile card, where you can add it to your list or start chatting right away. * **Agents** — your agents: ones you’ve added from Explore, ones you’ve chatted with, and (if you’re a builder) the agents you own. * **Chats** — every conversation, one thread per agent session. On desktop this becomes a two-pane layout with your chat list beside the open thread. * **Settings** — account, notifications, linked accounts, and your data. You can delete an individual agent’s memory of you, or delete your account entirely. ## How agents get here [Section titled “How agents get here”](#how-agents-get-here) When a builder shares an agent **publicly** from Studio, it gets a public listing in Portal’s Explore tab. Sharing **privately** instead produces a direct link that opens the agent’s profile card without listing it in Explore. Visibility and access are separate. Each agent’s builder also decides whether you need a Guuey account to chat: some agents welcome guests, others ask you to sign in first. When sign-in is required, Portal prompts you before the conversation starts. You can create an account with email or sign in with Google or Apple. ## Chatting with an agent [Section titled “Chatting with an agent”](#chatting-with-an-agent) Every agent on Guuey runs on its own isolated, long-running infrastructure, and Portal talks to it directly: * **Streaming responses** — replies stream in token by token as the agent writes them, with rich Markdown formatting. * **Generative UI** — agents built on Guuey’s default MCP server don’t just answer in text. Tool results can render as interactive cards inline in the conversation. Generative UI is the [ggui protocol](https://docs.ggui.ai); see its docs for what agents can render. * **Persistent history** — the agent keeps your conversation server-side. Reopening a thread replays the full transcript, including cards. ## For builders [Section titled “For builders”](#for-builders) Your own deployed agents appear in the Agents tab too, so you can test them exactly the way your users will experience them — same chat, same streaming, same cards. When you’re happy with an agent, share it from Studio and it’s live in Portal. # Generative UI (ggui) > Agents hosted on Guuey get generative UI through the open ggui protocol. Protocol and SDK documentation lives at docs.ggui.ai — this page is the bridge. Agents hosted on Guuey can reply with **interactive UI** — forms, dashboards, wizards, confirmation cards — instead of walls of text. That capability comes from **ggui**, an open, MCP-native generative-UI protocol. The agent describes what it needs in natural language; ggui compiles a typed component and the chat surface (Portal, the Studio playground, or an embedded widget) mounts it. When the user interacts, the agent receives typed events back. ## How it reaches your agent [Section titled “How it reaches your agent”](#how-it-reaches-your-agent) Guuey is MCP-server-agnostic — an agent’s definition lists whatever MCP servers it should use. The **default** server is the hosted ggui endpoint at `mcp.ggui.ai`: * In **Studio**, the Generative UI superpower is on by default for new agents; uncheck it and your agent is text-only. * In a **CLI-deployed** agent, the default MCP server is part of the scaffolded definition — keep it, replace it, or add servers alongside it. Nothing about ggui is required: bring different MCP servers and your agent still deploys, streams, and persists exactly the same. ## Where the protocol docs live [Section titled “Where the protocol docs live”](#where-the-protocol-docs-live) ggui is a separate open project with its own documentation at **[docs.ggui.ai](https://docs.ggui.ai)**. Go there for: * [How ggui works](https://docs.ggui.ai/how-it-works/) — the handshake → render → interact → consume walk-through * [Quickstart](https://docs.ggui.ai/oss-quickstart/) — wire ggui into any MCP-speaking agent, locally, in minutes * [MCP protocol reference](https://docs.ggui.ai/api/mcp-protocol/) — the wire surface * [Cookbook](https://docs.ggui.ai/cookbook/feedback-form/) — worked patterns: forms, wizards, dashboards, auth-gated UI * [Self-hosting](https://docs.ggui.ai/cli/serve/) — run the whole protocol yourself with `ggui serve`, no account needed The ggui docs are LLM-friendly the same way this site is — [`docs.ggui.ai/llms.txt`](https://docs.ggui.ai/llms.txt) is the machine-readable index. # Build your own surface > Use @guuey/agent-client to build a fully custom chat surface on your deployed agent — streaming, per-turn status, thread continuity, guest or signed-in identity. Guuey agents come with surfaces out of the box — the shareable page on [app.guuey.com](https://app.guuey.com), the [embeddable widget](https://widget.guuey.com), and the preview in [Studio](https://studio.guuey.com). When you want a chat surface that is fully yours — your components, your layout, your product — build it on the client SDK. ## What the SDK is [Section titled “What the SDK is”](#what-the-sdk-is) [`@guuey/agent-client`](https://www.npmjs.com/package/@guuey/agent-client) (MIT) is a typed client for a deployed agent’s streaming contract: * **`POST /agent/invoke`** — a Server-Sent-Events stream, folded into a flat transcript for you. * **`GET /threads/:id/messages`** — the persisted-history read, so returning users continue their conversation. It ships two entry points: | Import | Contents | React? | | --------------------------- | ----------------------------------------------------------------- | ------ | | `@guuey/agent-client` | Streaming helpers, history reader, web adapters, all public types | No | | `@guuey/agent-client/react` | The `useAgentInvoke` hook | Yes | The root subpath never imports React. Platform couplings — where the thread id is stored, how ids are generated, how the network request carries identity — are injected as adapters, so the same core runs in a Next.js page and a React Native app. ```sh npm install @guuey/agent-client ``` You’ll need two values from your deploy: * **Your app id** — shown by `guuey apps list`. * **Your agent’s endpoint URL** — printed by `guuey deploy` when it finishes (`Live at https://…`). ## Allow your domain [Section titled “Allow your domain”](#allow-your-domain) Your agent accepts browser requests from `localhost` and Guuey’s own surfaces automatically. Before your surface goes to production, allow its domain: ```sh guuey apps update --domains "yourapp.com" ``` A bare domain covers `https://yourapp.com` and every subdomain. To pin an exact origin, include the scheme: `--domains "https://chat.yourapp.com"`. ## Give visitors a stable identity [Section titled “Give visitors a stable identity”](#give-visitors-a-stable-identity) A custom surface should carry its own anonymous identity: a random secret your page mints once, stores, and sends on every request. Without it, each request can look like a brand-new visitor, and the conversation loses its thread. The secret must be exactly 64 lowercase hex characters — anything else is ignored. Treat the secret like a session credential: whoever holds it *is* that anonymous user. Never log it or put it in a URL. And keep the storage key stable — changing it orphans every returning visitor’s conversations. ## Minimal chat surface (React) [Section titled “Minimal chat surface (React)”](#minimal-chat-surface-react) ```tsx "use client"; import { useMemo, useState } from "react"; import { createWebAdapters } from "@guuey/agent-client"; import { useAgentInvoke } from "@guuey/agent-client/react"; const APP_ID = "your-app-id"; const AGENT_URL = "https://your-agent-endpoint"; // printed by `guuey deploy` /** 64 lowercase hex chars, minted once and persisted. Returns null if storage is blocked. */ function getGuestSecret(): string | null { try { const key = `guuey:guest-secret:${APP_ID}`; const existing = window.localStorage.getItem(key); if (existing && /^[0-9a-f]{64}$/.test(existing)) return existing; const bytes = crypto.getRandomValues(new Uint8Array(32)); const secret = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join(""); window.localStorage.setItem(key, secret); return secret; } catch { return null; } } export function AgentChat() { const adapters = useMemo(() => createWebAdapters({ getGuestSecret }), []); const { messages, send, status, activeTool, error } = useAgentInvoke({ endpointUrl: AGENT_URL, appId: APP_ID, adapters, }); const [draft, setDraft] = useState(""); return (
{messages.map((m, i) => (

{m.text}

))} {status === "connecting" &&

Waking your agent…

} {status === "using-tool" &&

Using {activeTool}…

} {error &&

{error}

}
{ e.preventDefault(); void send(draft); setDraft(""); }} > setDraft(e.target.value)} placeholder="Ask anything" />
); } ``` `messages` grows as text streams in — the last assistant entry updates in place, so rendering the array is all a live transcript takes. ## The turn lifecycle [Section titled “The turn lifecycle”](#the-turn-lifecycle) `status` tells you exactly where the current turn is, so your UI can say something honest at every phase: | `status` | Meaning | | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------ | | `ready` | No turn in flight — the composer is open. | | `connecting` | Request sent, no response yet. Agents scale to zero, so this can span a cold start — swap to “waking your agent” copy after a few seconds. | | `thinking` | The agent is awake and working, but no text is flowing yet. | | `using-tool` | A tool is running; `activeTool` carries its name. | | `responding` | Assistant text is streaming in. | Failures never occupy `status` — they land in `error` and the status returns to `ready`, so the composer re-enables. Structured errors from the platform (for example, a plan limit being reached) arrive with their human-readable message in `error`, ready to display. The hook also returns `abort()` (stop the in-flight turn, keeping partial text), `reset()` (clear the conversation and start a fresh thread), and `threadId`. ## Conversation continuity [Section titled “Conversation continuity”](#conversation-continuity) The hook persists the thread id per app (in `localStorage` on web) and replays it on the next message, so the agent keeps its context across page reloads — a returning visitor picks up where they left off. Repainting *earlier turns* in your UI is a separate read. Native and server-side clients can fetch the persisted transcript with the exported `fetchThreadHistory` helper against `https://api.us-east-1.guuey.com/v1`, authenticating with the same guest secret (as an `x-guuey-guest` header) or bearer token used for chat. In-browser custom surfaces on your own domain can’t make that cross-origin read yet — the conversation continues, but the transcript starts visually fresh on reload. ## Signed-in users (bring your own auth) [Section titled “Signed-in users (bring your own auth)”](#signed-in-users-bring-your-own-auth) If your product already authenticates users with an OIDC-compatible identity provider, your agent can know who they are. Configure the app with your issuer: ```sh guuey apps update --auth-mode byo \ --issuer-url https://auth.yourapp.com --audience your-api-audience ``` Then hand the SDK your user’s token instead of a guest secret: ```ts const adapters = createWebAdapters({ getAccessToken: async () => await yourAuth.getToken(), }); ``` The platform verifies the token against your issuer’s published keys — it never sees your signing secrets — and the user’s conversations, memory, and files follow their identity. Supply **one** identity mode per surface: `getAccessToken` for signed-in users, or `getGuestSecret` for anonymous ones. Passing both is a hazard — a momentarily unavailable token silently downgrades the user to an anonymous identity, and those turns land in a different thread. ## Beyond React on the web [Section titled “Beyond React on the web”](#beyond-react-on-the-web) * **React Native** — `useAgentInvoke` works unchanged; supply your own adapters (an AsyncStorage-backed thread store and a streaming `fetch` transport) in place of `createWebAdapters`. Both entry points ship TypeScript source with a `react-native` export condition, so Metro transpiles them with your app’s Babel config — no extra bundler setup. * **No React at all** — the root subpath’s helpers (`parseSseEvents`, `fetchThreadHistory`, `fetchStreamTransport`, and the exported types) are plain TypeScript. Anything that can hold an SSE connection can drive an agent turn with them. # State & memory > The persistence every Guuey agent gets — managed conversation history, a key-value store scoped per user, a durable per-user home directory, and a consent-gated cross-app profile. 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. ## Conversation history [Section titled “Conversation history”](#conversation-history) 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. ## Small state: `@guuey/state` [Section titled “Small state: @guuey/state”](#small-state-guueystate) 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. ```ts 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](https://www.npmjs.com/package/@guuey/state) 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. ## A home directory per user [Section titled “A home directory per user”](#a-home-directory-per-user) 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. ## Cross-app profile [Section titled “Cross-app profile”](#cross-app-profile) 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. ## Your users own their data [Section titled “Your users own their data”](#your-users-own-their-data) 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. # Studio > Guuey's no-code agent builder — describe your agent, pick its model and superpowers, deploy in one click, and test it live. Studio, at [studio.guuey.com](https://studio.guuey.com), is Guuey’s no-code agent builder. You configure an agent declaratively — instructions, model, and capabilities — and Studio deploys it to Guuey’s hosted runtime and gives you a live playground to test it in. No SDKs, no servers, no code. ## Home [Section titled “Home”](#home) Sign in with email and password, or with Google or GitHub where offered. Once you have agents, home is your **My agents** grid: each card opens that agent’s playground, with a shortcut to sharing and a **New agent** button for the next one. ## The create form [Section titled “The create form”](#the-create-form) Clicking **New agent** opens a single form that takes you from idea to deployed agent in one submit: * **Starter templates** — one click fills the instructions with a curated, complete example (Trip planner, Meeting-prep assistant, Customer FAQ answerer, Study coach, Social media copywriter, Meal planner). Every word stays editable, and a chip never silently replaces text you typed. * **Instructions** — the agent’s system prompt. The **Draft it for me** control expands a one-sentence description into full instructions you can refine. * **Name** — templates suggest one, with a **Shuffle** to cycle alternatives. * **Model** — three tier cards: **Thinking** (deepest reasoning for complex work, slower and costlier), **Balanced** (great quality at everyday speed — recommended), and **Fast** (snappiest replies at the lowest cost). An **Advanced** section exposes the real axes: provider (Anthropic, OpenAI, or Google), model, and framework (Claude Agent SDK, OpenAI Agents SDK, or Google ADK). Each framework runs its provider’s models, so the two layers can never disagree. * **Superpowers** — capabilities your agent gets beyond text. **Generative UI** is checked by default: your agent replies with interactive screens, not just text (see the [ggui docs](https://docs.ggui.ai) for how that works). Under **Advanced** you can bring your own MCP server by URL, including custom request headers. Servers that need an account sign-in aren’t supported in Studio yet — deploy those with the [CLI](/cli/). Submit with **Create my agent** and Studio creates the agent, triggers its first deploy, and opens the playground. ## The playground [Section titled “The playground”](#the-playground) Each agent’s playground is a phone-framed chat simulator wired to the real deployed agent — messages stream in live over the same endpoint your users reach, and conversation history is kept server-side. The header shows an honest deployment chip (**Starting…**, **Live**, **Deploy failed**, **Not deployed**) that updates on its own while a deploy is in motion, plus a link to open the agent in the Platform console. ### Settings [Section titled “Settings”](#settings) The **Settings** drawer edits the same fields as the create form — instructions, name, model, superpowers — seeded from what’s actually live. Edits stay local until you press **Deploy changes**; **Discard** reverts to the live version, and unsaved edits are restored if you accidentally close the drawer. Agents built with code get a pointer back to the CLI instead of an editor. ### Share [Section titled “Share”](#share) The **Share** drawer controls who can reach your agent: share it publicly or privately, decide whether chatting requires sign-in, set listing details like description, category, and icon, and grab an embed snippet to put the agent on your own website. ## Integrations [Section titled “Integrations”](#integrations) The **Integrations** page is a browsable directory of MCP servers a Guuey agent can use, searchable and filterable by category, with availability shown honestly per entry.