---
title: QuiverAI
description: Learn how to use QuiverAI models with the AI SDK.
url: "https://ai-sdk.dev/providers/ai-sdk-providers/quiverai"
docs_index: /llms.txt
---

> For an index of all documentation, see [/llms.txt](/llms.txt).

[QuiverAI](https://quiver.ai/) provides Arrow language models that can reason about and create SVG documents, plus native SVG generation, vectorization, editing, and animation endpoints. The AI SDK provider exposes Arrow 2 through `generateText` and `streamText` and exposes image operations through `generateImage`.

## Setup

The QuiverAI provider is available via the `@ai-sdk/quiverai` module. You can install it with

**Packages:** `@ai-sdk/quiverai`

## Provider Instance

You can import the default provider instance `quiverai` from `@ai-sdk/quiverai`:

```ts
import { quiverai } from '@ai-sdk/quiverai';
```

If you need a customized setup, you can import `createQuiverAI` and create a provider instance with your settings:

```ts
import { createQuiverAI } from '@ai-sdk/quiverai';

const quiverai = createQuiverAI({
  apiKey: 'your-api-key', // optional, defaults to QUIVERAI_API_KEY environment variable
  baseURL: 'custom-url', // optional, defaults to QUIVERAI_BASE_URL or https://api.quiver.ai/v1
  headers: {
    /* custom headers */
  }, // optional
});
```

You can use the following optional settings to customize the QuiverAI provider instance:

- **baseURL** *string*

  Use a different URL prefix for API calls, e.g. to use proxy servers.
  The default prefix is `https://api.quiver.ai/v1`. It also reads `QUIVERAI_BASE_URL` from the environment.

- **apiKey** *string*

  API key that is sent as a `Bearer` token in the `Authorization` header.
  It defaults to the `QUIVERAI_API_KEY` environment variable.

- **headers** *Record\<string,string>*

  Custom headers to include in the requests.

- **fetch** *(input: RequestInfo, init?: RequestInit) => Promise\<Response>*

  Custom [fetch](https://developer.mozilla.org/en-US/docs/Web/API/fetch) implementation.
  You can use it as a middleware to intercept requests,
  or to provide a custom fetch implementation for e.g. testing.

## Language Models

Create an Arrow language model by calling the provider or using
`.languageModel()`:

```ts
import { quiverai } from '@ai-sdk/quiverai';
import { generateText } from 'ai';

const { text } = await generateText({
  model: quiverai('arrow-2'),
  prompt: 'Design a simple compass icon and explain the visual choices.',
});

console.log(text);
```

The language-model factory supports `arrow-2` and `arrow-2-telos` through
QuiverAI's stateless `POST /v1/responses` endpoint.

### Reasoning Options

Configure QuiverAI reasoning through `providerOptions.quiverai`:

```ts
import { quiverai, type QuiverAILanguageModelOptions } from '@ai-sdk/quiverai';
import { generateText } from 'ai';

await generateText({
  model: quiverai('arrow-2-telos'),
  prompt: 'Create a precise technical SVG diagram.',
  providerOptions: {
    quiverai: {
      reasoningEffort: 'xhigh',
      reasoningSummary: 'auto',
    } satisfies QuiverAILanguageModelOptions,
  },
});
```

- **reasoningEffort** *'low' | 'medium' | 'high' | 'xhigh'*
- **reasoningSummary** *'auto'*

The provider does not request encrypted reasoning. During tool loops it replays
the full conversation, matching tool calls and results, and opaque reasoning
item IDs in order without resending private reasoning text or encrypted
reasoning state.

### Caller-Executed Tools

Standard AI SDK tools are sent as Responses API function tools and execute in
your application. Use a bounded loop because each step performs another model
request:

```ts
import { quiverai } from '@ai-sdk/quiverai';
import { generateText, isStepCount, tool } from 'ai';
import { z } from 'zod';

const result = await generateText({
  model: quiverai('arrow-2'),
  prompt: 'Create an SVG compass and stage it as compass.svg.',
  tools: {
    write_file: tool({
      description: 'Stage an SVG file in the calling application.',
      inputSchema: z.object({
        path: z.string(),
        content: z.string(),
      }),
      execute: async ({ path, content }) => {
        // Validate and restrict paths before writing model-generated content.
        return { path, staged: content.startsWith('<svg') };
      },
    }),
  },
  stopWhen: isStepCount(4),
});
```

QuiverAI custom tools return raw strings and are also executed by the caller:

```ts
const result = await generateText({
  model: quiverai('arrow-2'),
  prompt: 'Return a minimal SVG document.',
  tools: {
    write_svg: quiverai.tools.customTool({
      description: 'Return SVG source.',
      format: { type: 'text' },
      execute: async svg => ({ accepted: svg.startsWith('<svg') }),
    }),
  },
  stopWhen: isStepCount(3),
});
```

Hosted tools, including legacy `quiver:*` tools, are not supported.

### Responses API Limitations

- Requests are stateless. The provider does not enable response storage or
  response-ID continuation.
- QuiverAI currently documents text response format for this endpoint.
  Structured-output settings are omitted and reported in `warnings`.
- Streaming tool calls are assembled completely before application execution.
- Abort signals, custom headers, and custom `fetch` implementations are
  forwarded to the Responses request.

### Language Model Usage

`result.usage` and streaming finish events include input, cache-read,
cache-write, text-output, and reasoning token counts when returned by QuiverAI.

## Image Models

You can create QuiverAI image models using the `.image()` factory method.
For more on image generation with the AI SDK see [generateImage()](/docs/reference/ai-sdk-core/generate-image).

### Basic Usage

```ts
import { quiverai } from '@ai-sdk/quiverai';
import { generateImage } from 'ai';
import fs from 'fs';

const { image } = await generateImage({
  model: quiverai.image('arrow-2'),
  prompt: 'A logo for the next AI Design startup',
});

const filename = `image-${Date.now()}.svg`;
fs.writeFileSync(filename, image.uint8Array);
console.log(`Saved SVG to ${filename}`);
```

QuiverAI returns SVG documents. The generated SVG bytes are available through `result.image.uint8Array` (or `result.images` when generating multiple).

### Model Capabilities

QuiverAI supports the following Arrow models:

| Model           | Description                                                                                                                       |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `arrow-2`       | Arrow 2 balances SVG generation quality and speed. Supports SVG editing when enabled for the API key. Uses token-based billing.   |
| `arrow-2-telos` | Higher-fidelity Arrow 2 variant for complex designs. Supports SVG editing when enabled for the API key. Uses token-based billing. |
| `arrow-1`       | Base text-to-SVG model. Accepts up to 4 reference images.                                                                         |
| `arrow-1.1`     | Improved text-to-SVG model. Accepts up to 4 reference images.                                                                     |
| `arrow-1.1-max` | Higher quality variant with extended context. Accepts up to 16 reference images.                                                  |

All models in this table advertise `supportsFileInputs: true` and
`supportsMaskInputs: false`. Other model IDs leave both capabilities unknown.
File-input support includes reference images for generation; SVG editing and
animation still require the corresponding `providerOptions.quiverai.operation`,
supported input formats, and access to that operation for your API key.

### Provider Options

You can fine-tune the request using `providerOptions.quiverai`:

```ts
import { quiverai, type QuiverAIImageModelOptions } from '@ai-sdk/quiverai';
import { generateImage } from 'ai';

await generateImage({
  model: quiverai.image('arrow-2'),
  prompt: 'A geometric unicorn icon',
  providerOptions: {
    quiverai: {
      instructions: 'Use a flat monochrome style with clean geometry.',
      reasoningEffort: 'high',
      attributes: {
        viewBox: { minX: 0, minY: 0, width: 100, height: 100 },
      },
      maxOutputTokens: 4096,
    } satisfies QuiverAIImageModelOptions,
  },
});
```

Supported options:

- **operation** *'generate' | 'vectorize' | 'edit' | 'animate'*

  Choose between text-to-SVG generation (`generate`, default), image-to-SVG vectorization (`vectorize`), SVG editing (`edit`), and SVG animation (`animate`).

- **instructions** *string*

  Extra style guidance for prompt-based generation. This option is not used as the SVG edit instruction; use `prompt.text` for editing.

- **reasoningEffort** *'low' | 'medium' | 'high' | 'xhigh'*

  Reasoning effort for generation, vectorization, or editing. When omitted, QuiverAI uses its default.

- **attributes** *object*

  Requested SVG root attributes. Supports `viewBox` with numeric `minX`, `minY`, and positive `width` and `height`. This is separate from the unsupported `size` and `aspectRatio` options.

- **temperature** *number* (0-2)

  Sampling temperature.

- **topP** *number* (0-1)

  Nucleus sampling top-p value.

- **presencePenalty** *number* (-2 to 2)

  Presence penalty.

- **maxOutputTokens** *number*

  Maximum number of output tokens. Arrow 2 and Arrow 2 Telos accept 1-65536. The provider retains its legacy validation bound of 131072 for other model IDs; the API may enforce a lower model-specific limit.

- **referenceImages** `Array<{ url: string } | { base64: string }>`

  Up to four optional reference images for SVG editing. URL references must use HTTP or HTTPS. Base64 references must decode to PNG, JPEG, WebP, GIF, or SVG data. Use `prepareQuiverAIImageReference` to convert binary, data URL, or URL inputs into this JSON-safe provider option shape.

- **maxReviewSteps** *number* (0-5)

  Maximum number of edit review and redo steps after the initial edit.

- **orchestratorMaxOutputTokens** *number* (1-65536)

  Optional provider orchestrator token budget for SVG editing.

- **shallowMaxOutputTokens** *number* (1-65536)

  Optional provider shallow edit token budget for SVG editing.

- **autoCrop** *boolean*

  When vectorizing, automatically crop the input image. Only used with `operation: 'vectorize'`.

- **targetSize** *number* (128-4096)

  When vectorizing, target canvas size in pixels. Only used with `operation: 'vectorize'`.

### Reference Images

Pass reference images through `prompt.images`:

```ts
await generateImage({
  model: quiverai.image('arrow-2'),
  prompt: {
    text: 'A geometric unicorn icon',
    images: ['https://example.com/reference-1.png'],
  },
});
```

`arrow-1` and `arrow-1.1` accept up to 4 reference images. `arrow-1.1-max` accepts up to 16. For Arrow 2 and other model IDs, the provider allows the endpoint maximum of 16 references and lets the API enforce any lower model-specific limit.

### Vectorizing a Raster Image

Set `operation` to `vectorize` and pass a single image in `prompt.images`:

```ts
import { quiverai, type QuiverAIImageModelOptions } from '@ai-sdk/quiverai';
import { generateImage } from 'ai';
import fs from 'fs';

const { image } = await generateImage({
  model: quiverai.image('arrow-2'),
  prompt: {
    images: [fs.readFileSync('./logo.png')],
  },
  providerOptions: {
    quiverai: {
      operation: 'vectorize',
      autoCrop: true,
      targetSize: 1024,
    } satisfies QuiverAIImageModelOptions,
  },
});

fs.writeFileSync('logo.svg', image.uint8Array);
```

Vectorization returns one SVG per API request. To request multiple vectorizations with `n`, also set `maxImagesPerCall: 1` so `generateImage` splits them into separate calls.

### Editing an SVG

Set `operation` to `edit`, put exactly one source SVG in `prompt.images`, and provide the edit instruction in `prompt.text`:

```ts
import {
  prepareQuiverAIImageReference,
  quiverai,
  type QuiverAIImageModelOptions,
} from '@ai-sdk/quiverai';
import { generateImage } from 'ai';
import fs from 'node:fs/promises';

const { image } = await generateImage({
  model: quiverai.image('arrow-2'),
  prompt: {
    text: 'Make the logo blue and simplify the star points.',
    images: [await fs.readFile('./logo.svg')],
  },
  providerOptions: {
    quiverai: {
      operation: 'edit',
      referenceImages: [
        prepareQuiverAIImageReference(
          await fs.readFile('./blue-reference.png'),
        ),
        { url: 'https://example.com/second-reference.png' },
      ],
      maxReviewSteps: 2,
      reasoningEffort: 'medium',
      maxOutputTokens: 4096,
      orchestratorMaxOutputTokens: 4096,
      shallowMaxOutputTokens: 2048,
      temperature: 0.4,
    } satisfies QuiverAIImageModelOptions,
  },
});

await fs.writeFile('./edited-logo.svg', image.uint8Array);
```

The source SVG can be an HTTP/HTTPS URL, binary data such as a `Buffer` or `Uint8Array`, a base64 string, or an SVG data URL. Binary and base64 sources are validated as complete UTF-8 SVG documents and sent to QuiverAI as base64 SVG sources. Remote source URLs are fetched by QuiverAI and must resolve to an SVG.

Edit reference images are separate from the source SVG. Put them in `providerOptions.quiverai.referenceImages`, not `prompt.images`. Direct provider-option values use `{ url }` or `{ base64 }`; `prepareQuiverAIImageReference` converts an HTTP/HTTPS URL, `URL`, `Uint8Array`, `ArrayBuffer`, base64 string, or supported image data URL to that JSON-safe shape.

SVG editing has these validation constraints:

- The model must be `arrow-2` or `arrow-2-telos`, and the API key's live model catalog must include the `svg_edit` operation.
- `prompt.images` must contain exactly one source SVG.
- `prompt.text` is required, must not be blank, and must contain at most 4000 characters.
- Binary source SVGs must be complete UTF-8 SVG documents no larger than 200000 bytes.
- At most four reference images are accepted. Inline references can contain up to 12582912 decoded bytes.
- Editing returns exactly one SVG per API request. To request multiple edits with `n`, set `maxImagesPerCall: 1` so `generateImage` splits them into separate calls.
- Masks and generation/vectorization-only provider options are rejected for edits.
- Edit-only provider options are rejected for generation, vectorization, and animation.

The edited SVG is returned as bytes in `result.image.uint8Array`.

### Animating an SVG

Arrow 2 and Arrow 2 Telos can animate an existing SVG. Set `operation` to `animate` and pass exactly one source SVG in `prompt.images`. The text instruction is optional; omit `text` to let QuiverAI choose an animation.

```ts
import { quiverai, type QuiverAIImageModelOptions } from '@ai-sdk/quiverai';
import { generateImage } from 'ai';
import fs from 'fs';

const { image, providerMetadata } = await generateImage({
  model: quiverai.image('arrow-2'),
  prompt: {
    images: [fs.readFileSync('./logo.svg')],
    text: 'Make the logo pulse gently.',
  },
  providerOptions: {
    quiverai: {
      operation: 'animate',
      reasoningEffort: 'medium',
      maxOutputTokens: 4096,
    } satisfies QuiverAIImageModelOptions,
  },
});

fs.writeFileSync('animated-logo.svg', image.uint8Array);

const timing = providerMetadata.quiverai?.images?.[0];
console.log(timing?.loopPeriodMs, timing?.openingAnimationMs);
```

The animation source can be an HTTP or HTTPS URL, SVG bytes, raw base64, or an `image/svg+xml` base64 data URL. Local file inputs are inspected before the request and rejected when they do not contain SVG data. Remote URLs are validated for their scheme and fetched and validated by QuiverAI.

Animation returns an animated SVG as bytes in `image.uint8Array`. When QuiverAI returns timing information, the per-image metadata includes `loopPeriodMs` and `openingAnimationMs`; either timing value can be `null`.

Animation requests must use `arrow-2` or `arrow-2-telos`, contain exactly one source SVG, omit masks, and produce one result per provider request. To request multiple animations with `n`, set `maxImagesPerCall: 1` so `generateImage` splits them into separate calls. Animation supports `temperature`, `reasoningEffort`, and `maxOutputTokens`; generation-only and vectorization-only provider options are rejected.

Source SVGs, text instructions, and remote source URLs are sent to QuiverAI. Animated SVG is active document content. Sanitize it or render it in an isolated context before embedding output from an untrusted source inline in a page.

### Billing and Usage

Arrow 2 models return measured token counts in `result.usage`. Fixed-credit models may return compatibility token counts of zero; their credit charge is available in `result.providerMetadata?.quiverai?.credits` when supplied by the API.

Model availability and supported operations depend on your organization and API key permissions. Consult QuiverAI's [model catalog](https://docs.quiver.ai/developers/models) for current capabilities and billing.

---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)