Elements

AI

Reaching machine intelligence — models, versioned prompts, embeddings, and bounded agents, with cost and PII egress as first-class constraints.

AI is how your app calls machine intelligence: triage a ticket, embed a knowledge base, let an agent resolve a support case. Model calls differ from every other effect — they are nondeterministic, they cost money per call, and your data leaves the building — so prompts are versioned artifacts, not strings buried in a handler.

The one rule

The production model is declared, never guessed — there is no prod default. Development uses mock for determinism, and sending PII to a third-party model fails the build unless you explicitly acknowledge it.

Quick start

Declare a model and a prompt

The model is a logical binding (smart, fast); the prompt is a versioned artifact with a typed output:

src/ai.ts
import { ai } from "okengine";
import { z } from "zod";

export const smart = ai.model("smart", { provider: "anthropic", tier: "opus" });

export const triage = smart.prompt("ticket-triage", {
  in: z.object({ subject: z.string(), body: z.string() }),
  out: z.object({ urgency: z.enum(["low", "high"]), team: z.string(), summary: z.string() }),
  version: 3,
  budget: { maxCostPerCall: 0.02 },
});

Ask it from a Flow

fx.ask routes the call through the declared model and validates the response against out:

src/flows/support/triage.ts
do: async (input, fx) => {
  const result = await fx.ask(triage, { subject: input.subject, body: input.body });
  // result is typed by the prompt's `out` schema
};

Gate regressions in CI

Point the prompt at an eval set and it becomes a CI check — a prompt change that degrades answers fails the build like a broken test:

export const triage = smart.prompt("ticket-triage", {
  // …
  evals: "./evals/triage.jsonl", // run with `oke eval`
});

The four building blocks

DeclarationProduces
ai.model(name, opts)Logical model binding — provider / tier / concrete model id
model.prompt(name, opts)Versioned prompt with typed in/out, evals, budget
ai.embed(name, opts)Embedding pipeline into a store.index (searched via fx.search)
ai.agent(name, opts)Bounded agent whose tools are your own flows

Prompt options

OptionTypeMeaning
in / outzod / Standard SchemaInput and output contracts — responses validated against out
versionnumberArtifact version — diffs and regressions tracked per version
evalsstringPath to a .jsonl eval set, regression-gated via oke eval
budgetobjectmaxCostPerCall — cost is a first-class dimension

Agents with real guardrails

An agent's tools are your flows — each carrying its own gates, effects, and typed errors, so the agent can never do anything a flow couldn't:

export const support = ai.agent("support", {
  model: smart,
  tools: [getBooking, refundBooking], // flows, with their gates attached
  maxSteps: 6,
  budget: { maxCostPerRun: 0.25 },
});

maxSteps bounds the loop; budget.maxCostPerRun bounds the spend. Both are declared, so "the agent ran away" is a violated contract, not a surprise.

PII cannot leak by accident

At build time, OKE checks which fields each fx.ask sends against your store classifications. If a PII field (.pii() in your schema) would reach a third-party model, the build fails:

build failed: flow "ticket-triage" sends pii field(s) [email] to a third-party model without allowPii

The escape hatch is explicit acknowledgment — allowPii: true (or pii: "allow") on the flow — so egress is a decision that shows up in code review. The mock driver and local models are not third-party; the check targets external providers.

Nondeterminism is priced in

Because fx.ask is nondeterministic, the runtime adjusts around it: journaling is forced on (durable flows can replay), and auto-caching is disabled for the call. In development and tests the mock driver makes model calls deterministic — your suite never hits a network, and CI never flakes on a provider.

Per-environment drivers

DriverWhat it is
mockDeterministic fake — dev + test default
anthropicAnthropic API
openai-compatibleAny OpenAI-compatible endpoint
bedrockAWS Bedrock
vertexGoogle Vertex AI
ollamaLocal models — counts as on-premise for the PII check

There is deliberately no production default: prod must name a driver, which keeps the model choice visible in oke.config.ts where review can see it.

Troubleshooting

Learn more

  • Flowfx.ask and fx.search inside do
  • Storestore.index, the home of embeddings
  • Console · AI — prompts, versions, cost per run

Next

On this page