Primitives map

Before you build something for an agent, look for it here. Every primitive Glove, Glove Foundry and Kuiper give you is on this page, grouped by the part of a harness it serves. The last column is what people write by hand when they don't know the primitive exists.

◆

Reading the tables. Each row gives the smallest call that uses the primitive and its package. The name links to the docs. The same list is in /llms.txt and in the agent skills, so your coding agent sees it too. The parts and layers are explained in First principles.

Jump to a part. Production (Kuiper) wraps the system (Foundry), which wraps the harness (Glove).

Harness: Glove

A model becomes an agent when something runs its loop, hands it tools, decides what it sees, remembers for it, gives it somewhere to work and lets people reach it. That something is the harness.

Loop

How does it act?Glove

glove-core runs the loop: prompt the model, run the tools it asks for, feed the results back, repeat until it answers. Retries, turn limits, aborts, streaming and token accounting come with it.

PrimitiveWhat you getInstead of building
Agent loopglove-coreModel → tool calls → results → model, until it answers. Matched tool call/result pairs, retries, a per-request turn limit.new Glove({ model, store, displayManager, systemPrompt, compaction_config }).build().processRequest(text)a while-loop that calls the model, parses tool calls, runs them and appends results
Model adaptersglove-coreAnthropic, OpenAI, Gemini, OpenRouter, Bedrock, Vercel AI Gateway, Kimi, GLM, MiniMax, MiMo, Ollama and LM Studio behind one interface, with streaming, reasoning and prompt caching.createAdapter({ provider: "anthropic", model, cache: true })provider SDK glue, a streaming parser and tool-call format translation per provider
Hot-swap model and promptglove-coreChange the model or prompt between requests without rebuilding the agent or losing history.glove.setModel(adapter) · glove.setSystemPrompt(text)tearing the agent down to switch models
Abort and un-abortable toolsglove-coreCancel a request mid-loop; tools that must finish (a payment, a write) run to completion first.processRequest(text, signal) · fold({ ..., unAbortable: true })custom cancellation flags threaded through every tool
Subscribersglove-coreTyped events for text deltas, tool calls and results, compaction, tokens and subagents: stream them, log them, meter them.glove.addSubscriber({ record(type, data) { … } })wrapping the loop to stream text, log tool calls or count tokens

Tools

What can it do?Glove

A tool is a name, a description, a Zod schema and a function. Everything an agent can do arrives as tools, including MCP servers, code interpreters, classifiers and media pipelines.

PrimitiveWhat you getInstead of building
Toolsglove-coreZod-validated input, results the model reads, optional renderData the model never sees.glove.fold({ name, description, inputSchema, do })hand-written JSON schemas, input validation and a dispatch switch
Permission gatesglove-coreAsk before a tool runs, per call or always; decisions are stored per tool and input. In Foundry it becomes an approval record.fold({ ..., requiresPermission: (input) => input.destructive })confirm-before-delete logic inside each tool
Tools that change at runtimeglove-coreAdd tools mid-session or swap a whole set atomically.glove.fold(tool) after build · glove.replaceTools(previousNames, nextTools)rebuilding the agent when the available tools change
Tool result summariesglove-coreLarge results replaced by a short summary in later requests.enableToolResultSummary: true · fold({ ..., generateToolSummary }) · do() returns generateSummaryArgstruncating big tool results by hand
MCP serversglove-mcpAny MCP server's tools as Glove tools, a discovery subagent that activates servers mid-conversation, OAuth helpers.mountMcp(glove, { adapter, entries })an MCP client and a schema bridge
Code as the tool surfaceglove-js · glove-python · glove-lispOne execute tool over a catalogue of functions: the model writes a program that loops, filters and branches, and only the answer returns to context.mountJs(glove, { session: JsSession.create() })fifty tool definitions and a round-trip per step
Capabilities as tablesglove-scratchpadResources become SQL tables behind one execute_sql tool, with discovery, joins and staged writes.mountDatabase(glove, { db })a list/get/search tool for every resource
Classifiersglove-classifierFast, calibrated yes/no, choice and score answers from classifier models, with an LLM fallback and confidence gates.mountClassifier(glove, { classifier: jev() })a chat model call for every routing or triage decision
Image and video workflowsglove-image · glove-videoPrompt pipelines, durable characters and scenes, references, review, lineage and cost tracking.mountImage(glove, { adapter, assets, library }) · mountVideo(…)a one-shot generate_image tool with no consistency between images

Context

What does it see?Glove

A stable system prompt, the saved history, and live state appended at the tail of every model call. Skills load guidance on demand and compaction keeps long sessions inside the window.

PrimitiveWhat you getInstead of building
Runtime context providersglove-coreLive state appended after history before every model call, including between tool steps. Never saved to history, never rewrites the system prompt.glove.addContextProvider(() => renderCurrentState())rebuilding the system prompt every turn (and losing the prompt cache)
Compactionglove-coreLong sessions summarised automatically; the store keeps the full history for your UI.compaction_config: { compaction_instructions, compaction_context_limit }a summariser and history-trimming logic
Content skillsglove-coreA listing of guides the agent can read in full, by section, when it needs them.useReadSkill(glove, skills) · loadContentSkillsFromFs(dir)pasting every playbook into the system prompt
Hooks and slash skillsglove-core/commands that change agent state or inject context before the user's message.glove.defineHook("compact", handler) · glove.defineSkill({ name, handler })parsing slash commands in your request handler
Task listglove-coreA built-in plan the agent keeps up to date and your UI can show.store with getTasks/addTasks → glove_update_tasksa todo or planning tool
Pinned contextglove-memoryStanding facts every turn should see, editable by the agent, delivered as runtime context.useContext(glove, contextAdapter)a user-preferences block in the system prompt

State

What does it remember?Glove

A store holds the conversation, tasks, permissions and inbox. glove-memory, glove-facts, forms and goals hold what the agent learns and what it is trying to get done.

PrimitiveWhat you getInstead of building
Storeglove-coreMessages, token and turn counts, and optional tasks, permissions, inbox and subagent stores behind one interface.StoreAdapter (MemoryStore built in; bring your own)a conversations table and token accounting
Inboxglove-coreWork that can't finish now is posted, resolved later by anything, and injected on the next turn. Blocking items keep the agent from acting on missing results.glove_post_to_inbox (registered when the store supports it)polling, callbacks and 'check back later' state
Memoryglove-memoryAn entity graph, an episodic timeline and a resource filesystem with provenance, behind adapters you own (SQLite included).useMemoryReader · useEpisodicReader · useResourcesReader (+ curators)a vector store and an ad hoc remember tool
Formsglove-memoryValidated answers collected over a conversation: steps, branches, skips, undo and executors that act on completion.defineForm(…) · useFormRunner(glove, adapter, { registry, subject })a slot-filling state machine
Goalsglove-memoryObjectives that survive interruptions, with versioned progress and deferrals.defineGoalProgram(…) · useGoalRunner(glove, adapter, config)tracking what the agent is supposed to finish inside the prompt
Factsglove-factsThings people mention early, recorded once and reused by forms and goals.useFacts(glove, factStore, source)asking the user for something they already said

Workspace

Where does it work?Glove

A virtual filesystem with scripts, checkpoints and format adapters, sandboxed interpreters, and mounted browsers and sandboxes. Work happens in files and code, not in the context window.

PrimitiveWhat you getInstead of building
Virtual filesystemglove-vfsOne tree shared by the working environment, memory resources and REPLs, with path-scoped access rules.mountFs([...]) · withAccess(fs, policy) · inMemoryFs() · hostDirectory(dir) · cachedRemote(store)letting tools read and write the host filesystem
Working environmentglove-working-environmentFiles, named scripts in worker threads, checkpoints, undo, run history and artifact export, with no ambient network or host access.mountWorkingEnvironment(glove, { env: await createWorkingEnvironment({ stdlib }) })a read/write/run tool set and a code runner
Format adaptersglove-env-*PDF, DOCX, XLSX, PPTX, images, audio, video, archives, HTTP and secrets as script imports, plus rendering pages so the agent can look at its output.stdlib: [documents(), spreadsheets(), slides(), images(), media(), render(), fetchFiles()]wiring pdf, docx and spreadsheet libraries into tools
Browsersglove-executionexecute_browser: the model scripts observe, act and verify in one call, and screenshots arrive as images.mountBrowser(glove, { adapter })Playwright wrapped in click/type/screenshot tools
Sandboxesglove-executionexecute_sandbox over persistent containers: files, commands, terminals and long-running services, with ownership and cleanup.mountSandbox(glove, { adapter })docker exec wrappers and container bookkeeping

Surface

How do people reach it?Glove

Tools push UI onto a display stack and can wait for the user's answer. React, Next.js, voice pipelines, realtime speech and avatars all read the same stack and the same agent.

PrimitiveWhat you getInstead of building
Display stackglove-coreTools render UI mid-conversation; pushAndWait suspends the tool until the person answers.display.pushAndForget({ renderer, input }) · await display.pushAndWait({ renderer, input })a side channel from tools to the UI and a pause/resume protocol
React bindingsglove-reactTools with colocated, typed renderers, a hook with the whole timeline, and headless rendering.defineTool({ …, render, renderResult }) · useGlove() · <Render />a chat UI state machine
Streaming routeglove-nextAn SSE endpoint for Next.js (or any fetch handler) that a GloveClient talks to.export const POST = createChatHandler({ … })an SSE protocol between your server and client
Voice pipelineglove-voiceVAD → STT → agent → TTS with barge-in, push-to-talk and React Native backends.new GloveVoice(glove, { stt, createTTS, vad }) · useGloveVoice(…) · useGlovePTT(…)stitching speech-to-text, the agent and text-to-speech together
Realtime speech and avatarsglove-voice-s2s · glove-voice-avatar · glove-voice-livekitThe same tools on OpenAI Realtime, Gemini Live or GPT-Live, with live avatars and LiveKit rooms.new RealtimeAgent({ agent }) with model: s2sDrivenModel({ provider })a second tool implementation for the realtime provider
Voice callsglove-foundry/voiceA Foundry agent as a live call: same prompt, tools and memory, transcript saved, delegation results spoken at the next pause.run: voiceCall({ room, greeting }) · webSocketRoom({ port, token })a hand-written call server around RealtimeAgent

Team

Who does it work with?Glove

A subagent is a harness used as a tool. Mesh lets agents message each other through their inboxes, and Continuum supervises them as processes.

PrimitiveWhat you getInstead of building
Subagentsglove-coreglove_invoke_subagent routes work to an isolated child with its own tools and store; events bracket the child's run.glove.defineSubAgent({ name, description, factory })a router that calls other agents by hand
Delegatesglove-foundryA fast agent hands work to sibling agents and keeps talking; results and the workers' questions come back to its conversation.defineAgent({ delegates: [{ agent: "coder", description }] })a job queue and callback plumbing between a chat agent and its workers
Meshglove-meshDirect, broadcast and acknowledged messages between agents, delivered through their inboxes.mountMesh(glove, { adapter, identity })a message bus between agents
Continuumglove-continuum-signalAgents supervised as subprocesses, cold per wake-up or warm and notified inline.agent("name").triggered() · new ContinuumRunner({ agentsDir })process supervision for long-lived agents

System: Glove Foundry

A harness becomes a system when there are many of it, it acts on its own time, the outside world can wake it, people can oversee it and other software can call it.

Identity

Whose agent is this?Glove Foundry

One definition in code, many persisted instances in data. Each instance has its own conversations, context, installed capabilities and workspace.

PrimitiveWhat you getInstead of building
Definitionsglove-foundryThe file path is the id. Every field can be a function of the instance, conversation and incoming message.agents/<route>/agent.ts → export default defineAgent({ … })a factory that rebuilds the agent per request from a switch over tenants
Instancesglove-foundryPersisted agents with their own id, context, workspace, installations and playbooks.client.agent(route).create({ context }) · defineAgentInstance(definition, { … })an agents-per-customer table and lookup
Conversationsglove-foundryAny number of durable threads per instance with exact transcripts.client.createConversation(agentId) · client.conversationTranscript(…)thread tables and routing messages to the right history
Installable capabilitiesglove-foundryCapabilities mount only on instances that install them, with typed config.defineSharedTool · defineApp · defineMcp · install(definition, config)per-customer feature flags around tool lists
Shared workglove-foundryWorkspace entries, tasks, a shared inbox and scoped values that agents coordinate through.glove_foundry_workspace · _tasks · _shared_inbox · _environmentcoordination tables between agents
Data adaptersglove-foundryInstances, conversations, activations and workspace data persisted atomically; swap in a database for several hosts.new FileFoundryDataAdapter({ file }) · FoundryDataAdapterserialising runtime state yourself

Time

When does it act?Glove Foundry

Schedules, sleep, spawn and background work are built-in agent tools backed by durable activations, so an agent can act later without a job queue of your own.

PrimitiveWhat you getInstead of building
Schedulesglove-foundryCron, interval and one-shot work, declared in code or created by the agent, rebuilt on restart.defineSchedule({ timing: { kind: "cron", expression }, message }) · glove_foundry_schedulecron jobs and a job queue that call your agent
Sleepglove-foundrySuspend the run and wake the same instance and conversation later.glove_foundry_sleep({ kind: "for", duration: "20m", message })storing 'check back later' state and a timer
Spawn and backgroundglove-foundryStart another instance's run, or continue work without blocking the reply.glove_foundry_spawn · glove_foundry_backgroundfire-and-forget promises that die with the request
Schedule managementglove-foundryThe agent lists and edits its own reminders and recurring work.glove_foundry_schedules({ action: "list" | "update" | "pause" | "resume" | "cancel" })a reminders CRUD API for the agent

Arrival

What wakes it up?Glove Foundry

Transmissions turn Slack, email, tickets or webhooks into typed events. Playbooks route them to instances, and subscriptions create the instance if none exists yet.

PrimitiveWhat you getInstead of building
Transmissionsglove-foundryTyped inbound events and outbound delivery for one channel; outbound becomes a validated tool when installed. Credentials stay in your adapter.defineTransmission({ inbound, outbound, account })a webhook handler and an API client per channel
Applications and connectionsglove-foundryChannels bundled into something an instance installs; long-lived listeners started only while something needs them.defineApp({ inbound, outbound, connections }) · defineConnection(…)polling loops and socket clients you keep alive yourself
Playbooksglove-foundryRules that match events to instances, with idempotent delivery into the right conversation.composePlaybook({ transmission, match, directives })a dispatcher that decides which agent handles which event
Subscriptionsglove-foundryAn event can create the agent that handles it: zero, one or many instances provisioned atomically.definePlaybookSubscription(…) · runtime.putPlaybookSubscription(…)onboarding code that creates an agent before its first message
Inbound triageglove-classifier/foundryClassify events before any agent starts, and match playbooks on the answers.classifyInbound({ classifier, question }) · classifierPredicate(…)waking an LLM agent to read every event

Oversight

Who keeps it in check?Glove Foundry

Permission-gated tools become expiring approval records, running work can be steered, and the inspector shows every run, model call and tool call.

PrimitiveWhat you getInstead of building
Approvalsglove-foundryGated tool calls pause the run on an expiring, fail-closed approval record with the exact input.requiresPermission → client.resolveApproval(id, "approve")an approvals table and a pause/resume flow
Steeringglove-foundryInterrupt running work cleanly and restart it in the same conversation with the new instruction.handle.steer(message) · POST /v1/runs/:id/steercancel-and-resend logic that races the old run
Inspector and WebChatglove-foundryEvery instance, conversation, run, model call, tool call and approval, plus a chat to talk to any instance.glove foundry dev → http://localhost:4141an admin dashboard and a debug chat
Event streamglove-foundryCorrelated events by definition, instance, conversation and run, live or after the fact.GET /api/events (SSE) · defineSubscriber(…)log scraping to reconstruct what an agent did

Access

How does other software call it?Glove Foundry

A typed client, a REST API, an async run API and OpenAI-compatible endpoints, all writing into the same durable conversations.

PrimitiveWhat you getInstead of building
Typed clientglove-foundry/clientCreate instances, send messages, and wait on, stream, cancel or steer run handles, with route types generated from your files.createFoundryClient<FoundryRoutes>({ baseUrl }).agent(route)a hand-written HTTP client for your agent service
OpenAI-compatible APIglove-foundryAny OpenAI SDK or chat UI talks to a durable instance and conversation.POST /v1/chat/completions · POST /v1/responsesan adapter so existing chat clients can reach your agent
Run API and RESTglove-foundryAsynchronous runs with live events, and REST over every runtime record.POST /v1/runs · GET /v1/runs/:id/events · /api/*a job-status API around your agent
Request authorizationglove-foundryOne check in front of the API, the inspector and the event streams. Foundry refuses a public bind without it.defineApplication({ requestAuthorization: { authorize } })auth middleware in front of each route

Production: Kuiper

A system is in production when it has somewhere to run, somewhere to keep state, a way to reach models, browsers, sandboxes and mail, and a way to watch it.

Run

Where does it run?Kuiper

Kuiper detects a Foundry app, builds it, runs it and keeps it alive. No Dockerfile. Pushes deploy, deployments are numbered and any of them can come back.

PrimitiveWhat you getInstead of building
Zero-config deploysKuiperFoundry and Station apps detected and built with no Dockerfile: Node 22, the right start command, port and health check.kuiper deploy --source . -u UNIT --wait · kuiper link -u UNIT --repo … (push to deploy)a Dockerfile, a process manager and a deploy script
Deployments and rollbacksKuiperNumbered deployments, one live at a time; any earlier one redeploys with its manifest.kuiper deployments · kuiper rollback DEPLOYMENTimage tags and a rollback runbook
Domains and environmentsKuiperHTTPS on every unit, custom domains, and staging environments from their own branches.kuiper domains add HOST · kuiper environments create NAMEcertificates, DNS and a second copy of the stack

Keep

Where does state live?Kuiper

A persistent disk at /data for Foundry's data, transcripts and memory, plus managed Postgres, Redis and buckets, and sealed secrets bound into variables.

PrimitiveWhat you getInstead of building
Persistent diskKuiperWhere FileFoundryDataAdapter, transcripts, SQLite memory and VFS snapshots live across restarts and redeploys./data on every Foundry unitmounting and backing up a volume
Managed databases and bucketsKuiperPostgres, Redis and S3-compatible buckets inside the project, wired in by variable templates.kuiper db create postgres main · ${{main.DATABASE_URL}}provisioning a database and copying its URL into config
Secrets and variablesKuiperSealed values bound into units, never in the image, redacted from logs.kuiper secrets set NAME=- · kuiper env set 'NAME=${{secrets.NAME}}'a secrets manager integration

Reach

What does it reach?Kuiper

One model gateway in front of your own provider keys, real Chrome browsers, sandboxes from ready-made images, and email addresses for agents.

PrimitiveWhat you getInstead of building
Model gatewayKuiperEach provider's own API at one address with your keys, limits and every call recorded with tokens and cost.createAdapter({ provider, model, ...kuiper.models.glove(provider) })provider keys in every unit and your own usage tracking
Kuiper browsersKuiperReal Chrome with profiles, hibernation and recordings, billed by the second.Steel-compatible API at ${{browsers.BASE_URL}}running headless Chrome next to your agent
Kuiper sandboxesKuiperRemote computers from ready-made images with a terminal, files and ports. An app that depends on station-sandbox gets a Docker socket Kuiper polices, for Station's own containers.kuiper.sandboxes.create({ image: "kuiper/coding" }) · capabilities.sandbox in kuiper.jsona container fleet for untrusted code
Kuiper inboxKuiperAn email address per agent that receives, sends, threads and calls your unit's webhook.inboxTools(inbox, { mailbox }) from @kuiper-sh/inbox/glovean email provider, inbound parsing and webhook verification

Watch

How do you see it?Kuiper

Logs that survive restarts, the agent's runs read straight into the dashboard, every model call recorded, network logs, usage and budgets.

PrimitiveWhat you getInstead of building
Agent inspectionKuiperFoundry runs, conversations, events and approvals read into the dashboard through the node, once requestAuthorization accepts Bearer $FOUNDRY_TOKEN. The app's token never reaches a browser.the unit's Inspect card · the project's Agents pageexposing your inspector publicly to see production
Logs and network logsKuiperLogs kept across crashes and redeploys with secrets redacted, plus requests, DNS and connections per unit.kuiper logs -u UNIT -f · kuiper network summarya log shipper and a proxy to see outbound calls
Usage and budgetsKuiperSpend by resource and project, with limits that notify or block.kuiper usage · kuiper budgets create --scope project --limit 50spreadsheets reconciling provider bills
Kuiper over MCPKuiperYour coding agent reads projects, logs and usage and, if you allow it, deploys.claude mcp add --transport http kuiper https://app.kuiper.sh/mcpcopy-pasting logs into your coding agent

Something missing?

If you are about to build something that isn't here, first check whether it is a tool (most things are), an adapter behind an interface Glove already has, or a mount on an existing agent. Those are the rules every primitive follows, and a new piece usually fits one of them. If it really is new, open an issue: it may belong in Glove.