Theo Docs
TheoKitTheoCloudTheo KnowledgeTheo PromptsTheo MemoryTheo GuardrailsTheo TracesTheoDB

Overview

Versioned prompts, resolved at runtime.

Theo Prompts manages your agent's prompts as versioned, immutable revisions and resolves them at runtime — over REST, a TypeScript SDK, or MCP. A prompt is identified by name and has N revisions; you point environment labels (prod, staging) at a revision and promote by moving the label, so the next resolution reflects the new prompt with no redeploy. All three interfaces delegate to the same core (Postgres source of truth, optional Redis cache), and {{var}} templating renders client-side so variable values never leave your process.

Pre-1.0, in active development. The packages (@usetheo/promptly-sdk, @usetheo/promptly-api, @usetheo/promptly-mcp) are not yet published to npm — they run inside the workspace for now. API-key auth is required.

Quick start

prompts.ts
import { PromptlyClient } from '@usetheo/promptly-sdk';

const client = new PromptlyClient({
  baseUrl: 'http://localhost:3000',
  apiKey: process.env.THEOPROMPTLY_API_KEY!, // required — blank throws at construction
  cacheTtlSeconds: 60,
});

await client.createPrompt('greet', 'hi {{name}}'); // registers revision v1
await client.assignLabel('greet', 'prod', 1);      // point prod → v1

const p = await client.getPrompt('greet', { label: 'prod', vars: { name: 'Theo' } });
p.content; // 'hi Theo' — rendered SDK-side; the value never reaches the server

// Later: promote to v2 with no app rebuild
await client.assignLabel('greet', 'prod', 2);

The REST API exposes the same surface (POST /prompts, GET /prompts/:name?label=prod, PUT /prompts/:name/labels/:label, POST /prompts/:name/rollback, GET /openapi.json), and the MCP server exposes get_prompt, list_revisions, and list_labels as agent tools.

Core concepts

Immutable revisions

Every write creates a new revision (version = max + 1). History is append-only and auditable — `createPrompt(name, content)` / `listRevisions(name)`.

Labels + promotion

Labels like `prod` / `staging` are pointers to revisions. Promoting = moving the pointer (`assignLabel(name, label, version)`) — no redeploy.

`{{var}}` templating, client-side

The zero-dep template primitive substitutes `{{identifier}}` in the SDK/MCP. Variable values never reach the REST server; a missing var throws `MissingPromptVariableError`.

Append-only rollback

`rollback(name, toVersion)` creates a new revision cloning older content — history is never rewritten.

One core, three interfaces

REST, SDK, and MCP delegate to the same use cases; a contract test asserts REST == SDK == MCP parity.

API keys + tenancy + tracing

`promptly_live_…` keys (only the SHA-256 hash is stored) with `read`/`write`/`admin` scopes, per-workspace isolation, and one `prompt.resolve` OTel span per resolution.

Where to go next

On this page