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

# Introduction

> Prompt management for AI products. Change a prompt without shipping a release.

Anpord keeps the prompts your product sends to a model outside your codebase. Your application asks for a prompt by id, and Anpord decides which version it gets.

<Info>
  **TL;DR**

  Create a key in the dashboard, `npm install anpord`, then `anpord.prompts.get({ id })`. Updating a prompt appends a version; pointing the `production` channel at it is how the change goes live — no deploy.
</Info>

## The mental model

Three terms carry the whole product: **prompt → version → channel**.

| Term        | What it is                                                                                    |
| ----------- | --------------------------------------------------------------------------------------------- |
| **Prompt**  | An id you choose, such as `support-reply`. Every caller addresses this, and it never changes. |
| **Version** | One revision of the content. Numbered from 1, append-only, so nothing is ever overwritten.    |
| **Channel** | A named pointer at a version. `production` is what callers get by default.                    |

Changing what your product sends is a promotion — moving a channel to a different version — rather than a code change.

## Get an API key

Create a key in the dashboard under **Settings → API keys**, then set it in your environment:

```bash theme={null}
export ANPORD_API_KEY="anp_..."
```

Keys are scoped to one organization, so a key only ever reads that organization's prompts.

## Install

<CodeGroup>
  ```bash npm theme={null}
  npm install anpord
  ```

  ```bash bun theme={null}
  bun add anpord
  ```
</CodeGroup>

## Resolve a prompt

```ts theme={null}
import { Anpord } from "anpord";

const anpord = new Anpord();

const prompt = await anpord.prompts.get({ id: "support-reply" });

console.log(prompt.content);
```

The constructor reads `ANPORD_API_KEY` when you do not pass one. To hold the key yourself, pass `{ apiKey }`.

With no selector, `get` returns the version the `production` channel points at. This is the call you want in application code: changing which version ships becomes a promotion, not a deploy.

## Create and publish

```ts theme={null}
await anpord.prompts.create({
  id: "support-reply",
  name: "Support reply",
  content: "You are a support agent for {{product}}. Be brief.",
});

await anpord.prompts.update({
  id: "support-reply",
  content: "You are a support agent for {{product}}. Be brief and warm.",
  message: "Warmer tone",
});

await anpord.prompts.promote({
  id: "support-reply",
  channel: "production",
  version: 2,
});
```

`create` makes the prompt and its first version. `update` appends a version rather than overwriting one, so version 1 stays readable. Until you promote, callers asking for production keep receiving version 1.

<Info>
  Separating `update` from `promote` is deliberate. You can write a version, review it, try it against a `staging` channel, and promote only once it is right.
</Info>

## Handle failures

Every failure is an `AnpordError` carrying the status the API returned.

```ts theme={null}
import { Anpord, AnpordError } from "anpord";

try {
  await anpord.prompts.get({ id: "does-not-exist" });
} catch (error) {
  if (error instanceof AnpordError && error.status === 404) {
    // fall back to a prompt you ship with the code
  }
  throw error;
}
```

<Note>
  An id that cannot be valid is refused before the request leaves your process, and the message names the field: `id: Prompt id must be lowercase alphanumeric, optionally with / _ or -`.
</Note>

Next, read [versions and channels](/concepts) to understand how resolution works, or go straight to [resolving prompts](/guides/resolving-prompts) for the runtime patterns.
