Skip to content

AI

import { ai } from "platform:ai";

Routed through OpenRouter using the model configured in AI Settings, so guest code never holds a provider key.

const { text } = await ai.generate("Summarize this issue in one sentence.", {
systemPrompt: "You write terse status updates.",
temperature: 0.2,
});
OptionDefaultPurpose
modelAI SettingsOpenRouter model id, e.g. anthropic/claude-3.5-sonnet
systemPromptnonePrepended system message
temperature0.7Sampling temperature, 0–2

Lower the temperature for anything you intend to parse. The default suits prose, not extraction.

Structured output against a schema. Use platform:zod to declare the shape.

import { ai } from "platform:ai";
import { z } from "platform:zod";
const { object } = await ai.generateObject(
`Extract the severity and component from: ${issue.description}`,
z.object({
severity: z.enum(["low", "medium", "high", "critical"]),
component: z.string(),
}),
{ temperature: 0 },
);
object.severity; // typed

The schema constrains generation, so you get a conforming object rather than prose you have to parse.

Vector embeddings, for semantic search against pgvector.

const { embeddings } = await ai.embed("disk usage alert");
const [vector] = embeddings;

Accepts a string or an array; embeddings is always an array of vectors, so a single string still yields embeddings[0]. Defaults to openai/text-embedding-3-small, overridable with { model }.

Batch rather than looping:

const { embeddings } = await ai.embed(issues.map((i) => i.title));

Multi-turn conversation.

const { text } = await ai.chat([
{ role: "system", content: "You are a triage assistant." },
{ role: "user", content: "What should I do with PLAT-431?" },
]);

Roles are system, user, and assistant. Options are the same as generate minus systemPrompt — put the system message in the array instead.