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

# Rendering prompts

> Render a managed prompt, shape it per provider, or convert the neutral result.

`client.prompts.render(slug, options?)` resolves a prompt for the client's `projectId` and `env` in a single request. Set `format` — on the client or per call — to get a result shaped for that provider; omit it to get the neutral result.

```ts theme={null}
const to11 = createClient({ env: "production", format: "openai" });

const prompt = await to11.prompts.render("welcome-message", {
  variables: { name: "Ada" },
});
```

The options object is `{ format?, label?, subject?, variables?, fallback?, onUnknownRole? }`: `label` picks the label to resolve for this call (defaulting to the client's `env` — env is a label value), `format` overrides the client default, `subject` (a stable id) pins a weighted release to a variant, and `fallback` is served on a network error. The return shape is fixed by the call's `format`, not by the network outcome. Authored `developer` blocks render as-is; the SDK maps them per provider (OpenAI keeps `developer`, Anthropic folds them into `system`). `onUnknownRole` (`"drop"` default, `"warn"`, or `"error"`) sets how a message with an unrecognized role is handled during provider conversion — see [Unknown roles](#unknown-roles).

## Shaped result

With a `format`, `render` returns a result you can spread straight into a provider request. `format: "openai"` returns `{ messages, config, metadata }`; `format: "anthropic"` returns `{ system, messages, config, metadata }` — the authored system and developer instructions are folded into a top-level `system` string, which Anthropic takes as a separate request field. When the prompt authors tools, the result also carries provider-shaped `tools` and `tool_choice`.

| Field                   | Holds                                                                                                                                                                            |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `system`                | **Anthropic only.** The folded system/developer instruction text, passed as Anthropic's top-level `system`. Omit it and you drop the authored instructions.                      |
| `messages`              | The rendered messages, shaped for the provider.                                                                                                                                  |
| `config`                | Model parameters from the resolved version — `model`, `temperature`, `max_tokens`, and any other stored keys — passed through verbatim.                                          |
| `tools` / `tool_choice` | Provider-shaped tool definitions and directive, present only when the prompt authors tools. Spread them into the request so a tool-using prompt isn't sent without its tools.    |
| `metadata`              | Provenance: `promptId`, `version`, `versionId`, `releaseId`, `label` (the single label the prompt resolved through), and `variantName` when a weighted release served a variant. |

Spread the result into the request, and pass the whole result to `turn.headers(prompt)` for the provenance headers:

```ts theme={null}
// OpenAI — `tools`/`tool_choice` are undefined (and omitted) unless the prompt authors tools
const res = await openai.chat.completions.create(
  {
    ...prompt.config,
    messages: prompt.messages,
    tools: prompt.tools,
    tool_choice: prompt.tool_choice,
  },
  { headers: to11.turn().headers(prompt) },
);
```

```ts theme={null}
// Anthropic — pass the folded `system` and the shaped tools alongside the messages
const res = await anthropic.messages.create(
  {
    ...prompt.config,
    system: prompt.system,
    messages: prompt.messages,
    tools: prompt.tools,
    tool_choice: prompt.tool_choice,
  },
  { headers: to11.turn().headers(prompt) },
);
```

## Neutral result and converters

Omit `format` (on both the client and the call) to get the neutral `RenderedPrompt`: `messages`, `tools`, `toolChoice`, `promptId`, `version`, `versionId`, `releaseId`, `variantName`, `contentHash`, `label`, `slug`, `blockRenderRecord`, and `modelConfig`. This is the path for providers the shaper does not cover (Vercel AI, LangChain) or for driving one prompt through more than one provider.

The `@to11ai/sdk/gateway` subpath converts a neutral result into a provider's request shape:

| Helper                                         | Purpose                                                                                                                                                           |
| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `toOpenAIMessages` / `toAnthropicMessages`     | Convert the neutral `messages` to the provider's message list. Both accept an `{ onUnknownRole }` option — see [Unknown roles](#unknown-roles).                   |
| `toAnthropicSystem`                            | Fold the `system`/`developer` turns into Anthropic's top-level `system` string (they are omitted from `toAnthropicMessages`). Pair the two for an Anthropic call. |
| `toOpenAITools` / `toAnthropicTools`           | Convert `tools` to the provider's tool schema.                                                                                                                    |
| `toOpenAIToolChoice` / `toAnthropicToolChoice` | Convert `toolChoice` to the provider's directive.                                                                                                                 |
| `gatewayAuthHeaders`                           | The `x-to11-*` headers that authenticate a gateway call.                                                                                                          |
| `gatewayPromptHeaders`                         | Prompt provenance headers for a rendered prompt.                                                                                                                  |

`gatewayAuthHeaders` and `gatewayPromptHeaders` are also re-exported from the main `@to11ai/sdk` entry. With a `format`, `render` applies the message conversion for you, so most apps never call the converters directly.

## Unknown roles

The message converters recognize `system`, `user`, `assistant`, `developer`, and `tool`. A message whose role is anything else is handled by the `onUnknownRole` policy — set it per call, on `createClient`, or on the converter directly:

| Mode               | Behavior                                                                                     |
| ------------------ | -------------------------------------------------------------------------------------------- |
| `"drop"` (default) | The message is omitted silently.                                                             |
| `"warn"`           | The message is omitted and a `console.warn` names the role and index.                        |
| `"error"`          | Conversion throws `UnknownRoleError` (carrying `code: "unknown_role"`, `role`, and `index`). |

```ts theme={null}
// Fail loudly when a hand-built message array has an unrecognized role
const messages = toOpenAIMessages(history, { onUnknownRole: "error" });
```

A prompt rendered by to11 only ever carries known roles, so on `render()` this matters mainly when you convert your own message arrays (assembled conversation history, messages from another source). `onUnknownRole: "error"` on `render()` is a way to assert that invariant explicitly.
