Build entire apps as conversations.

An open-source TypeScript framework for AI-powered apps. You define tools — things your app can do. An AI agent decides when to use them based on what users ask for.

Works with OpenAI, Anthropic, and more. Free and open source.

Get StartedHow It Works

The idea

What if every app was a single chat interface?

Traditional apps encode user flows in UI — pages, routes, navigation hierarchies. Glove replaces that wiring with an agent. The developer defines capabilities. The agent does the orchestration.

AgentAn AI that reads what users ask for and decides which of your app's capabilities to use.
ToolA capability — a function the agent can call. Search a database, call an API, compute a result.
RendererA React component that shows the result. Product grids, forms, confirmation dialogs.

01 Tools are the backend

Every action your app can take — search, checkout, track an order — is a tool. The agent decides when to call them based on what the user asks for.

02 Renderers are the UI

Product grids, forms, confirmation dialogs — they're all renderers on a display stack. Tools push them. The agent orchestrates which ones appear and when.

03 The conversation is navigation

No routes, no page transitions, no navigation state machines. The user says what they want. The agent figures out the path to get there.

04 Human-in-the-loop is native

Tools can pause and wait for user input. Permission requests, form submissions, confirmations — all first-class primitives, not afterthoughts.

Architecture

Five components. One runtime.

Built on adapters — interfaces that decouple the runtime from specific implementations. Swap models, stores, or UI frameworks without changing application logic.

AgentThe agentic loop. Takes a message, prompts the model, executes tool calls, feeds results back, repeats until the model responds with text.
Prompt MachineThe model wrapper. Manages system prompts, dispatches requests, notifies subscribers. The model itself is swappable via the ModelAdapter interface.
ExecutorThe tool runner. Validates inputs with Zod, retries with Effect, manages permissions through the tool permission system. Tools are registered at build time.
ObserverThe session watcher. Tracks turns, token consumption, and triggers context compaction when conversations get too long. Sessions run indefinitely.
Display ManagerThe UI state machine. Manages the display stack — what the user sees. Framework-agnostic. This is what makes Glove an application runtime, not a chatbot backend.

The display stack

See it in action.

A user asks to buy running shoes. Here's what happens inside the runtime — step by step.

1

User sends a message

“Find me running shoes under 100 bucks”

The agent interprets the intent and calls the search_products tool.

Display stack
empty
2

Tool pushes a renderer

The search tool finds results and pushes a product grid to the display stack. The tool doesn't wait — it returns immediately.

pushAndForget({ renderer: "product_grid" })
Display stack
product_gridrendered
3

User continues the conversation

“Add the Nike ones to my cart and check out”

The agent calls add_to_cart, then checkout.

Display stack
product_gridrendered
cart_summaryrendered
4

Tool pauses for input

The checkout tool needs payment details. It pushes a payment form and waits. The tool's execution is suspended until the user submits.

pushAndWait({ renderer: "payment_form" })
Display stack
product_gridrendered
cart_summaryrendered
payment_formwaiting
5

User submits, tool resumes

The form resolves with payment data. The checkout tool picks up where it left off, creates the order, and pushes a confirmation.

resolve(slot_id, paymentData)
Display stack
order_confirmationdone

Developer experience

Define capabilities. Ship applications.

A tool is a function with a name and a schema. Register tools with .fold(). The agent figures out when to call them.

Simple — a weather tool

lib/glove.tsTypeScript
const client = new GloveClient({
  endpoint: "/api/chat",
  systemPrompt: "You are a helpful weather assistant.",
  tools: [{
    name: "get_weather",
    description: "Get current weather for a city",
    inputSchema: z.object({ city: z.string() }),
    async do(input) {
      return await fetchWeather(input.city);
    },
  }],
});

// That's a working AI app.
// User says "weather in Tokyo" → agent calls get_weather → shows result.

Advanced — tools with interactive UI

app.tsTypeScript
const app = new Glove({
  store, model, displayManager,
  systemPrompt: "You are a shopping assistant...",
})
  .fold({
    name: "search_products",
    description: "Search the product catalog",
    inputSchema: z.object({ query: z.string() }),
    async do(input, display) {
      const results = await catalog.search(input.query);
      // Show a product grid — tool keeps running
      await display.pushAndForget({ renderer: "product_grid", input: results });
      return results;
    },
  })
  .fold({
    name: "checkout",
    description: "Start the checkout process",
    inputSchema: z.object({ cartId: z.string() }),
    async do(input, display) {
      const cart = await carts.get(input.cartId);
      // Show a payment form — tool PAUSES until user submits
      const payment = await display.pushAndWait({ renderer: "payment_form", input: cart });
      return await orders.create(cart, payment);
    },
  })
  .build();

Adapters

Swap anything. Change nothing.

Every layer is an interface. The runtime doesn't care what's behind it.

ModelAdapter

The AI provider. Anthropic, OpenAI, local models, or mocks for testing. Anything that takes messages and returns responses.

StoreAdapter

The persistence layer. Messages, tokens, turns. In-memory, SQLite, Postgres — wherever your state lives.

DisplayManagerAdapter

The UI state layer. Manages the display stack. Framework-agnostic — React, Vue, Svelte, terminal UI. Bind however you want.

SubscriberAdapter

The event bus. Logging, analytics, real-time streaming, debugging. Plug in whatever you need to observe.

Trade-offs

Honest about what this costs.

LatencyEvery interaction round-trips through an LLM. 50ms becomes 1–2 seconds. Acceptable for complex workflows. For high-frequency actions, renderers can trigger tools directly — bypassing the agent for deterministic operations.
DeterminismA button always does what it says. Natural language probably does what you mean. The gap is real. Critical paths need deterministic fallbacks — renderer-initiated actions that skip the model entirely.
CostEvery turn consumes tokens. Compaction helps with context limits but not cumulative cost. Fewer, more capable tools mean fewer round-trips. Design tools intentionally.

Define capabilities. Ship applications.

Glove is open source and ready to build on.

View on GitHubRead the Docs