Xome
FeaturesHow it worksFAQDocsTry Xome →Join waitlist

Developers

Architecture.

A client-side agent with stateless server proxies. Understanding the four layers explains almost every file in the repo.

Layout
app/
  (app)/          chat · history · connections · settings · automations · skills
  onboarding/     first-run: cloud key or on-device model
  api/
    llm/{anthropic,openai,google}/   streaming proxies (forward user key, pipe SSE)
    proxy/        allowlisted integration proxy (attaches token, stores nothing)
    oauth/        start · callback/[provider] · refresh (origin-aware credentials)
    solana/rpc/   server RPC relay (holds SOLANA_RPC_URL, same-origin only)
    mcp/ · web-fetch/                JSON-RPC + page-text proxies (SSRF-guarded)
lib/
  agent/          orchestrator · run-manager · providers · tools · system-prompt
  integrations/   google · slack · github · notion · solana · workspace · mcp · web
  store/          IndexedDB stores (conversations, skills, secrets, …) + prefs
components/       chrome (shell) · chat · connections · settings · ui

1 · The agent loop

lib/agent/orchestrator.ts is a provider-agnostic async generator: build system prompt → stream the model → execute tool calls (through the consent gate) → feed results back → repeat, capped at 6 iterations, with a doom-loop guard on repeated identical calls. It never knows whether it's talking to WebGPU or a cloud API, that's the LlmProvider interface.

run-manager.ts owns live runs at module level (outside React), so navigation doesn't kill them; the useChat hook is just a subscriber.

2 · Tools & consent

  • A Tool = name, description, JSON-schema params, an invoke(), an integrationId gate, and a consent level.
  • Consent levels: preApproved (reads), askOncePerSession, alwaysAsk (writes/money). A persisted user allowlist can promote tools, except those in NEVER_ALWAYS_ALLOW.
  • The registry only exposes tools whose integration the user enabled; small local models additionally get a lexically filtered subset.

3 · Storage

Everything user-owned sits in IndexedDB (lib/store/db.ts, versioned migrations): conversations, memory.md, secrets (API keys, OAuth tokens), MCP servers, automations + audit, skills, and the workspace folder handle. Small UI prefs live in localStorage. There is no server database.

4 · The stateless proxies

  • /api/proxy, host-allowlisted relay; the browser sends url + headers (token already attached); the server forwards once and returns. No open relay, no retention.
  • /api/llm/*, attach the user's key from a header, stream SSE back.
  • /api/oauth/*, PKCE + state cookie; tokens are posted back to the opener window and stored client-side. Credentials are chosen per request origin (the *_PROD convention).
  • /api/solana/rpc, the one route with a server secret (your RPC key); it only serves same-origin callers.
Design rule of the codebase: if a feature would require storing user data server-side, redesign it until it doesn't.