> ## Documentation Index
> Fetch the complete documentation index at: https://docs.heylua.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# AI

> Isolated text generation with any catalog model, outside the agent's chat pipeline

`AI.generate` runs one model call with a prompt you supply and returns the text or the full result. `AI.image` generates one image from a prompt and returns its hosted URL. Both skip the [agent](/concepts/agents)'s persona, skills, and processors; to run a whole turn of an agent, use [`Agents.invoke`](/reference/sdk/agents). Available in tools, jobs, webhooks, triggers, processors, and workflow code steps.

*Verified against lua-cli 3.33.0.*

```ts theme={null}
import { AI } from 'lua-cli';
```

## Quick example

The short form returns text; the options form returns the full result.

```ts theme={null}
import { AI } from 'lua-cli';

const ticketBody = 'Login fails after the password reset email arrives.';
const summary = await AI.generate('Reply in one sentence.', [{ type: 'text', text: ticketBody }]);

const result = await AI.generate({
  model: 'google/gemini-3.8-flash',
  system: 'You are concise.',
  prompt: 'What is the weather in London today?',
});
```

## Methods

### generate(prompt, content?)

Generates text and returns it as a string.

```ts theme={null}
AI.generate(prompt: string, content?: UserContent): Promise<string>
```

<ParamField path="prompt" type="string" required>
  The user prompt when called alone. When `content` is given, the system instruction instead.
</ParamField>

<ParamField path="content" type="UserContent">
  The user message: a string, or an array of AI SDK v5 parts. Parts are `{ type: 'text', text }`, `{ type: 'image', image, mediaType? }`, and `{ type: 'file', data, mediaType, filename? }`, where `image` and `data` are a URL string, a base64 string, or a `Buffer`.
</ParamField>

**Returns** — the generated text, the same value as `text` on the options form.

**Example**

```ts theme={null}
import { AI } from 'lua-cli';

const description = await AI.generate('Describe the photo in two sentences.', [
  { type: 'text', text: 'What is in this photo?' },
  { type: 'image', image: 'https://example.com/photo.jpg', mediaType: 'image/jpeg' },
]);
```

**Errors** — the same as `generate(options)`.

### generate(options)

Generates text with explicit model settings and returns the full result.

```ts theme={null}
AI.generate(options: AiGenerateInput): Promise<AiGenerateOutput>
```

<ParamField path="model" type="string" default="alibaba/qwen3.8-flash">
  A [model code](/concepts/models) in `provider/model` form, as listed by `lua models list`. Defaults to the platform default model, not to the agent's model. A code the platform doesn't approve falls back to the default.
</ParamField>

<ParamField path="system" type="string">
  System instruction.
</ParamField>

<ParamField path="prompt" type="string">
  Plain user prompt. Pass `prompt` or `messages`, not both.
</ParamField>

<ParamField path="messages" type="ModelMessage[]">
  AI SDK v5 messages, `{ role, content }`, with the same part shapes as `content` on the short form. The server validates them; a malformed part is rejected with a 400 that names its path, such as `messages[0].content[1]`.
</ParamField>

<ParamField path="temperature" type="number">
  Sampling temperature. The accepted range is the provider's.
</ParamField>

<ParamField path="maxOutputTokens" type="number">
  Maximum number of tokens to generate.
</ParamField>

<ParamField path="structuredOutput" type="{ schema: AiGenerateJsonSchema }">
  A JSON Schema the response must match; the parsed object lands on `output`. The schema needs a top-level `type: "object"`. On Google models, setting it turns Google Search grounding off for that call.
</ParamField>

**Returns**

<ResponseField name="result" type="AiGenerateOutput">
  Optional fields are omitted when empty.

  <Expandable title="properties">
    <ResponseField name="text" type="string">
      The generated text.
    </ResponseField>

    <ResponseField name="finishReason" type="FinishReason">
      One of `stop`, `length`, `content-filter`, `tool-calls`, `error`, `other`, `unknown`.
    </ResponseField>

    <ResponseField name="usage" type="LanguageModelUsage">
      `inputTokens`, `outputTokens`, `totalTokens`, and optionally `reasoningTokens` and `cachedInputTokens`. Each is `undefined` when the provider doesn't report it.
    </ResponseField>

    <ResponseField name="output" type="unknown">
      The parsed JSON when `structuredOutput` was set and `finishReason` is `stop`. It is parsed, not validated against the schema; validate it yourself.
    </ResponseField>

    <ResponseField name="sources" type="AiGenerateSource[]">
      Google Search grounding sources, Google models only: `{ sourceType: 'url', id, url, title? }`.
    </ResponseField>

    <ResponseField name="reasoning" type="ReasoningOutput[]">
      Reasoning steps when the model exposes them; `reasoningText` is their concatenation.
    </ResponseField>

    <ResponseField name="toolCalls" type="AiGenerateToolCall[]">
      Tool calls the model made, `{ type: 'tool-call', toolCallId, toolName, input }`. `toolResults` holds the matching `{ type: 'tool-result', toolCallId, toolName, output, isError? }` entries.
    </ResponseField>

    <ResponseField name="warnings" type="CallWarning[]">
      Provider warnings, for example an unsupported setting.
    </ResponseField>
  </Expandable>
</ResponseField>

**Example**

```ts theme={null}
import { AI } from 'lua-cli';
import { z } from 'zod';

const ticketBody = 'Login fails after the password reset email arrives.';
const SentimentSchema = z.object({
  sentiment: z.enum(['positive', 'negative', 'neutral']),
  score: z.number().min(0).max(1),
});

const result = await AI.generate({
  system: 'Classify the sentiment of the message.',
  prompt: ticketBody,
  temperature: 0,
  structuredOutput: {
    schema: {
      type: 'object',
      properties: {
        sentiment: { type: 'string', enum: ['positive', 'negative', 'neutral'] },
        score: { type: 'number', minimum: 0, maximum: 1 },
      },
      required: ['sentiment', 'score'],
    },
  },
});

const parsed = SentimentSchema.safeParse(result.output);
```

**Errors** — the call throws an `Error`:

* Invalid input: `structuredOutput.schema must be a JSON Schema with top-level type "object"`, or a malformed `messages` part. Fix the request; retrying doesn't help.
* The provider refused the request as sent (a model the provider doesn't serve, a refused prompt): the platform reports it as `PROVIDER_REJECTED` with `transient: false`. Retrying unchanged fails the same way.
* The provider is unavailable (408, 429, 5xx, or no answer): the platform retries on the next model in its fallback chain. When every model fails, a deployed agent sees `Every model in the fallback chain failed`; `lua test` sees the platform's `UPSTREAM_UNAVAILABLE` error, `… is temporarily unavailable — retry in a moment`.
* No message from the server: `AI generation failed`.

### image(prompt, options?)

Generates one image from a prompt and returns its hosted URL. Like `generate`, this runs outside the agent's chat pipeline; the image is produced server-side, stored on the CDN, and billed to the agent's organization. Available in tools, jobs, webhooks, triggers, processors, and workflow code steps.

*Verified against lua-cli 3.44.0.*

```ts theme={null}
AI.image(prompt: string, options?: Omit<AiImageInput, 'prompt'>): Promise<string>
```

<ParamField path="prompt" type="string" required>
  A plain-language description of the image to draw.
</ParamField>

<ParamField path="options" type="Omit<AiImageInput, 'prompt'>">
  The same fields as the options form below, minus `prompt`: `model`, `size`, `quality`, `outputFormat`.
</ParamField>

**Returns** — the public URL of the generated image, ready to embed (for example in a deck, a message, or a `CDN`-backed file reference). Same value as `url` on the options form.

**Example**

```ts theme={null}
import { AI } from 'lua-cli';

const cover = await AI.image('A clean, modern landscape hero image for a data-resilience pitch, no text');
const wide = await AI.image('A minimal abstract product shot', { size: '1536x1024', quality: 'high' });
```

**Errors** — the same as `image(options)`.

### image(options)

Generates one image with explicit settings and returns the full result.

```ts theme={null}
AI.image(options: AiImageInput): Promise<AiImageOutput>
```

<ParamField path="prompt" type="string" required>
  A plain-language description of the image to draw.
</ParamField>

<ParamField path="model" type="string">
  A provider-prefixed image [model code](/concepts/models), for example `openai/gpt-image-2`. Defaults to the platform image model. A code the platform doesn't approve falls back to that default.
</ParamField>

<ParamField path="size" type="string">
  Image size, for example `1024x1024`, `1536x1024`, or `1024x1536`. The accepted sizes are the provider's.
</ParamField>

<ParamField path="quality" type="'low' | 'medium' | 'high'">
  Render quality.
</ParamField>

<ParamField path="outputFormat" type="'png' | 'jpeg' | 'webp'">
  Output image format.
</ParamField>

**Returns**

<ResponseField name="result" type="AiImageOutput">
  <Expandable title="properties">
    <ResponseField name="url" type="string">
      Public URL of the generated image, hosted on the CDN.
    </ResponseField>

    <ResponseField name="model" type="string">
      The model that produced the image.
    </ResponseField>

    <ResponseField name="provider" type="string">
      The provider that produced the image.
    </ResponseField>
  </Expandable>
</ResponseField>

**Example**

```ts theme={null}
import { AI } from 'lua-cli';

const { url, model, provider } = await AI.image({
  prompt: 'A minimal abstract cover, deep indigo to orange gradient, no text',
  size: '1536x1024',
  quality: 'high',
});
```

**Errors** — the call throws an `Error`:

* Invalid input (empty prompt, an image model the platform doesn't serve, or no image produced): fix the request; retrying unchanged doesn't help.
* Image generation isn't available for the account right now (out of balance or billing unavailable): the request is refused before any image is produced.
* The provider is unavailable, or no message from the server: retry in a moment.

## Types

`AiGenerateInput`, `AiGenerateOutput`, `AiGenerateStructuredOutput`, `AiGenerateJsonSchema` (a `Record<string, unknown>`), `AiGenerateSource`, `AiGenerateToolCall`, `AiGenerateToolResult`, `AiImageInput`, and `AiImageOutput` are exported from `lua-cli`. `UserContent`, `ModelMessage`, `FinishReason`, `LanguageModelUsage`, `ReasoningOutput`, and `CallWarning` are the AI SDK v5 types of the same names; you don't need to import them to call `AI.generate` or `AI.image`.

## See also

* [`Agents`](/reference/sdk/agents) — run a full turn of an agent instead of a bare model call
* [`CDN`](/reference/sdk/cdn) — read stored files into `image` and `file` parts
* [About models](/concepts/models) — model codes, the platform default, and `lua models list`
* [Compose agents](/build/compose-agents) — when to use `AI.generate` and when to invoke an agent


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.