Skip to content

Getting Started

Zero-config quickstart

Run verist init to scaffold a working project with no API keys needed.

This guide covers both CLI and programmatic usage. For how the pieces fit together in production, see Architecture Overview.

Install

bash
bun add verist @verist/cli zod
bash
npm install verist @verist/cli zod

CLI Quickstart

The fastest way to see Verist in action — no API keys required:

bash
npx verist init
npx verist capture --step parse-contact --input "verist/inputs/*.json"
npx verist test --step parse-contact

This scaffolds a parse-contact step that extracts name, email, and phone via regex. Edit the step logic, re-run verist test, and see the diff.

Programmatic API

Core concepts

Each step returns:

  • output – partial state update
  • events – audit records (append-only)
  • commands – declarative next steps (optional)
text
(input, context) → { output, events?, commands? }

Define and run a step

ts
import { z } from "zod";
import { defineStep, run } from "verist";

const verifyDocument = defineStep({
  name: "verify-document",
  input: z.object({ docId: z.string(), text: z.string() }),
  output: z.object({
    verdict: z.enum(["accept", "reject"]),
    confidence: z.number(),
  }),
  run: async (input, ctx) => {
    const verdict = await ctx.adapters.llm.verify(input.text);
    return {
      output: { verdict, confidence: 0.84 },
      events: [{ type: "document_verified", payload: { docId: input.docId } }],
    };
  },
});

const result = await run(
  verifyDocument,
  { docId: "doc-1", text: "Invoice #1042 for ACME Corp." },
  {
    adapters: {
      llm: {
        verify: async (text) => (text.includes("fraud") ? "reject" : "accept"),
      },
    },
  },
);

if (result.ok) {
  console.log(result.value.output);
  // { verdict: "accept", confidence: 0.84 }
}

Add explicit identity

For stable IDs and version tracking, pass explicit identity to run():

ts
import { defineWorkflow, run } from "verist";

const workflow = defineWorkflow({
  name: "verify-document",
  version: "1.0.0",
  steps: { verifyDocument },
});

const result = await run(
  workflow.getStep("verifyDocument"),
  { docId: "doc-1", text: "..." },
  {
    adapters,
    workflowId: workflow.name,
    workflowVersion: workflow.version,
    runId: "run-1",
  },
);

LLM Providers

Verist supports OpenAI and Anthropic via @verist/llm. Any OpenAI-compatible API (Ollama, Azure OpenAI, etc.) works via the baseURL option.

ts
import OpenAI from "openai";
import Anthropic from "@anthropic-ai/sdk";
import { createOpenAI, createAnthropic } from "@verist/llm";

// OpenAI (or any compatible API via baseURL)
const openai = createOpenAI({
  client: new OpenAI({ apiKey: process.env.OPENAI_API_KEY }),
});

// Anthropic
const anthropic = createAnthropic({
  client: new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }),
});

// Ollama, Azure, etc.
const ollama = createOpenAI({
  client: new OpenAI({
    baseURL: "http://localhost:11434/v1",
    apiKey: "ollama",
  }),
});

Runner wiring

Verist does not ship an orchestrator. A minimal runner typically does:

  1. Load state
  2. Execute run() with explicit identity
  3. Commit output + events atomically
  4. Interpret commands (enqueue, fan-out, review, emit)
  5. Capture artifacts if you need replay/recompute

See Reference Runner for a concrete loop.

Kernel guarantees

Verist guarantees:

  • Steps are deterministic given input + adapters
  • State lives in your database
  • Commands are data (never executed by the kernel)
  • Overlay wins over computed for human overrides
  • Errors are values (Result), not exceptions

Commands

Commands are plain objects. Use helpers for common patterns:

ts
import { invoke, fanout, review, emit } from "verist";

return {
  output: { score, verdict },
  events,
  commands: [
    invoke("verify", { id }), // call another step
    fanout("score", inputs), // parallel execution
    review("low confidence", data), // human review
    emit("doc.verified", { id }), // external event
  ],
};

Decision checklist

If you...Then skip...
Don't store state yetStorage adapters
Don't branch or fan outCommands
Don't pause runsSuspend/resume
Don't need stable IDsWorkflows

LLM context: llms.txt · llms-full.txt
Released under the Apache 2.0 License.