Prompts
Versioned prompt artifacts on ai.model — out schemas, via recovery, budgets, timeouts, and fx.ask.
A prompt is a versioned artifact minted on a model binding (smart.prompt(...)). It names
the ask, optional in / out shapes, a recovery chain, and a cost cap — then Flows call it
with fx.ask.
For developers who need typed triage JSON and a fallback model — declare once, ask everywhere.
The one rule
Mint prompts with model.prompt(name, options) — there is no top-level ai.prompt. Input is
JSON-serialized (no template / {{var}} API). When out is set, the reply must match or
the ask throws.
Smallest Example
Mint a prompt on a model
import { ai } from "okengine";
import { z } from "zod";
export const smart = ai.model("smart", {
provider: "openrouter",
model: "openrouter/free",
apiKey: process.env.OPENROUTER_API_KEY,
});
export const classifyTicket = smart.prompt("support.classify", {
version: 1,
budget: { maxCostPerCall: 0.01 },
in: z.object({ message: z.string() }),
out: z.object({
category: z.enum(["billing", "technical", "feature_request"]),
urgency: z.enum(["low", "medium", "high"]),
}),
});Ask from a Flow
import { on, flow, http } from "okengine";
import { z } from "zod";
import { classifyTicket } from "@/core/ai";
export const classify = on(
http.post({
in: z.object({ message: z.string().min(1) }),
}),
flow({
do: async ({ message }, fx) => {
return await fx.ask(classifyTicket, { message });
},
}),
);Manifest lists asks: ["support.classify"]. Pin a version at call time with
fx.ask("support.classify@1", input).
See structured output
With out set, the runtime appends a schema instruction and validates the JSON reply. Invalid
shape → AiSchemaValidationError (code: "AiSchemaInvalid") — no automatic correction
retry.
Progressive Patterns
Name + optional version — model is the parent binding:
export const summarize = smart.prompt("docs.summarize", { version: 1 });
await fx.ask(summarize, { text: "…" });Options
| Option | Type | Default | Meaning |
|---|---|---|---|
version | number | — | Pin with fx.ask("name@N") |
evals | string | — | Path for oke eval JSONL |
budget | { maxCostPerCall?, maxCostPerRun? } | — | Cost contracts |
via | string[] | [parent model] | Recovery chain of logical names |
timeout | "30s" | ms | — | Ask deadline (not a cost budget) |
in | Schema | — | Declared / Manifest / doctor — not runtime-validated on ask |
out | Schema | — | Runtime-validated (Zod / JSON Schema / field shorthand) |
How input reaches the model
There is no template string API. The runtime JSON-stringifies the ask input (redacting
secrets), and when out is set appends:
Reply with JSON only matching this schema: …Pass the fields you need as the second argument to fx.ask — do not invent template /
{{message}} options.
fx.ask options
| Option | Type | Default | Meaning |
|---|---|---|---|
via | refs | prompt chain | Override recovery for this call |
timeout | duration | prompt timeout | Per-call deadline |
tools | Flow refs | — | Tool loop via fx.call |
maxSteps | number | 6 | Cap on tool rounds |
Embeds (related)
ai.embed is a separate declaration for vector pipelines into store.index:
export const kb = ai.embed("kb", {
model: "smart",
into: "knowledge",
});
const vector = await fx.embed(smart, "install guide");
const hits = await fx.search(kb, "how to install", { topK: 5 });fx.embed records embeds (not asks). Missing into or a non-vector index fails at
runtime with ai: embed "…" has no into / vector-index errors.
Troubleshooting
The name was never registered with model.prompt, or the AI module was not imported before boot.
Cause: Flow "{flow}" asks "{resource}" without declaring it. Use the prompt handle in do
or list effects: { asks: ["support.classify"] }.
AiSchemaValidationError — the model reply failed out. Message includes missing / extra / type
issues. There is no retry-with-corrections loop.
AiBudgetExceededError — raise budget.maxCostPerCall or reduce tokens / tool rounds.
Every entry in the via chain failed (network, auth, or provider error). Check each binding’s
apiKey / baseUrl and driver health.
Learn more
- Models — bindings and providers
- Agents — multi-step
fx.run - AI — guardrails and PII egress
- OpenRouter — cloud ask recipe