Manual

Manual · API

ai

A model answers — Apple Intelligence on the Mac by default, or a provider you configure. Synchronous like everything else.

Every command on this page carries a worked example.

use function

ai.use(provider, { key, model })

Chooses the model: "apple" (on the Mac, the default), "anthropic", "openai" or "custom".

Worked example
const state = language.canTranslate("de", system.language);
if (state === "needsDownload") {
    messages.alert("macOS will download the language once — the first translation "
                   + "takes a moment.");
}

isAvailable function

ai.isAvailable()

Whether the chosen model can answer right now — ask before promising a feature.

Worked example
// Apple on the Mac is the default; a provider is one line:
ai.use("anthropic", { key: security.loadSecret("apiKey") });

availability function

ai.availability()

The reason, as text, when it cannot.

Worked example
form.suggestButton.enabled = ai.isAvailable();

ask function

ai.ask(question, { instructions }) → text

One question, one text back.

Guard with ai.isAvailable() and fall back gracefully — a feature that needs a model should degrade, not dialog-error. For fields, prefer extract: shapes beat prose.
Worked example
if (!ai.isAvailable()) {
    form.stateLabel.value = ai.availability();   // says why, in words
}

extract function

ai.extract(text, shape) → object

Structured answers: name the fields and their kinds, get an object.

Name the shape tightly — three fields you need beat ten you might. What comes back fits the fields of a record assignment directly.
Worked example
// Turn a pasted mail into a record's fields:
const parsed = ai.extract(pastedText, {
    company: "text",
    amount: "number",
    dueDate: "date"
});
form.record.company = parsed.company;

classify function

ai.classify(text, [labels]) → one label

Which of your labels fits the text best.

Worked example
const label = ai.classify(form.record.note,
                          ["complaint", "order", "question", "praise"]);
form.record.category = label;