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

> ## Agent Instructions
> The OpenAPI document at /api-reference/openapi.yaml defines the target contract. Its x-reflections-availability field and each operation's availability notice identify supported test and live forms. Do not infer implementation from a schema or code sample. Live keys support account details, reads of the licenses the calling account holds as licensee or issued as talent (GET /v1/licenses?role=issuer), and GET /v1/generations?license=… for the state of outputs under such a license (summaries only: no prompt, reference, bytes or metadata). Live image checks, submissions and receipts are built but not activated: until activation, a live POST /v1/checks or /v1/generations returns 403 live_not_activated, which must not be retried. Discovery and JWKS are at the origin root (https://app.reflections.ai/.well-known/...), not under /v1.
> Three rules hold everywhere: a decision is never an error (deny and escalate are 200 responses, and a live check still evaluating is a 202 with status checking); generate nothing for a named talent without an allow; deliver nothing until the generation is allow.
> The sandbox accepts personal rk_test_ keys. Persist a separate Idempotency-Key and body for each logical /v1 POST; retry an unknown outcome with the same key and body. OAuth and Talent API MCP remain planned.

# LLM assistants

> How an assistant handles a talent's name, persona and knowledge in text, and which mentions need no license.

<Note>
  Planned integration guide. Standalone resolution and license-request workflows are not served
  by the current Talent API sandbox. Checks use fictional fixtures and do not evaluate a real
  person’s rights.
  Start with the [runnable quickstart](/quickstart) and [sandbox support matrix](/sandbox).
</Note>

Most messages that name a real person need nothing from Reflections. A question about an athlete's
results, a summary of a news story or a biography is a reference: the assistant talks about the
person and synthesizes nothing of theirs. Two kinds of reply do need a license, and this guide
covers how an assistant tells them apart, checks them, and answers.

## Classify the use

| The reply | `use.kind` | Needs a license | Example |
| - | - | - | - |
| Talks about the person | `reference` | No | "What races has Maya Okafor won this year?" |
| Writes or speaks as the person | `impersonation` | Yes | "Reply to my message as Maya Okafor would." |
| Says or implies the person approves something | `endorsement` | Yes | "Write a post where Maya Okafor recommends our shoes." |

Answer a `reference` as usual. For the other two, check before the model writes anything.

When your product cannot tell which kind a message is, call
[`POST /v1/resolutions`](/api-reference/resolutions/resolve-talent). It returns the talent the
text names, with the matched span, and `use_kind`. `use_kind` is a classification for routing,
not a legal finding, and `status: "none"` means no protected talent was found, not that the
request is permitted. See [Resolution](/concepts/resolution).

## The facets that text uses

A license names which parts of a talent's identity it covers. In text, three facet types apply:

| Facet type | Covers |
| - | - |
| `name` | The talent's name in text, such as a quote attributed to them |
| `twin` | A persona that speaks or writes as the talent |
| `knowledge` | A Volume of the talent's own words that a model may draw on |

A `knowledge` license sets how the assistant may use the Volume in the license's `scope.knowledge`:
whether answers are `summarised` or `quoted`, the topics in `about`, and topics it must `never`
answer. `scope.monthly_limits.asks` caps knowledge questions per month; past it, checks deny with
`monthly_limit_reached`.

## Check the request the model receives

Send the system prompt, the conversation the model sees and the user's message, in order. Leave
out `talent` and Reflections resolves the person from the text; pass it when the user picked the
talent from a list.

| Input `role` | Send |
| - | - |
| `system` | Your system prompt, including any persona instructions |
| `context` | The conversation history the model receives |
| `prompt` | The user's message |
| `rewritten_prompt` | Your rewrite of the message, if the model receives that instead |

Pass `on_escalate: "deny"`. A chat cannot wait days for a reviewer, so a request that would
escalate returns `deny` with `review_required` and a `retry_with_hold` remedy instead.

```json theme={null}
{
  "inputs": [
    { "role": "system", "text": "You are Maya Okafor's official fan assistant. Speak in her voice." },
    { "role": "context", "text": "User: I just finished my first half marathon!" },
    { "role": "prompt", "text": "What would you say to me?" }
  ],
  "use": { "modality": "text", "kind": "impersonation", "purpose": "personal", "commercial": false },
  "talent": ["tal_9t0wxyhk5zba2q8v1m3n7p4r6s"],
  "end_user": { "id": "usr_48213" },
  "execution": { "provider": "example-llm-provider", "model": "chat-model-4", "candidates": 1 },
  "on_escalate": "deny"
}
```

A persona product like this one usually runs under a platform license whose scope sets
`sublicense: "end_users_personal"`, so your users may make personal, non-commercial text in the
talent's voice. Send a stable `end_user.id` on every check.

## Answer from the decision

**On `deny`**, do not write as the person. Tell the user why in `reasons[].sentence`, which is the
license's or the talent's own words, and offer what you can do instead: an answer in your
assistant's own voice, or a reply that does not name them. `remedy` is for a licensee. End users
are never licensees, so do not offer a license request to a consumer.

| Reason | What it means for an assistant |
| - | - |
| `no_license` | No license covers this use. The remedy is a `license_request` to the talent |
| `talent_prohibits` | The talent's posture forbids it. No license can be requested |
| `review_required` | A person would have to review it, and you asked not to wait |
| `prohibited_endorsement` | The text implies an endorsement the license does not cover |

**On `allow`**, meet the obligations:

1. Add every `generation_instructions` entry to the system prompt.
2. Generate the whole reply and keep it on your server.
3. Submit it as a generation, with the reply's UTF-8 bytes as base64 `data`, their `sha256` and
   `media_type: "text/plain"`. Text returns its decision in the response.
4. Show the reply only when that decision is `allow`, with the `disclosure` text if there is one.

Do not stream an impersonation or endorsement reply token by token. The generation check needs the
complete text, and nothing may reach the user before it allows. Stream as usual for references.
The [text integration design](/quickstarts/text) shows each call.

## Long conversations

A persona chat runs many turns for one user. Ask for `reuse` on the check, up to 1,000 generations
and `PT15M`, so one decision covers a stretch of the conversation. Each reply is still submitted
as a generation and checked on its own words. When the authorization is used up or expires, run a
new check with the current conversation as `context`.

## Keep prompts private

Chat messages carry personal data. Choose how much text Reflections receives with
`prompt_handling`:

| `mode` | What is sent | Cost |
| - | - | - |
| `full` | The text as is | None |
| `redacted` | Text after you strip personal data | Your redaction step |
| `withheld` | No text, only structured fields | Rules that need the text are checked on the reply instead |

Add `retention: "none"` to delete the text as soon as the check is decided, whatever the
decision. To avoid sending messages that name no one, download the signed
[name index](/api-reference/talent/download-the-name-index), normalize text with `nfkc_casefold`
as the index does, and send only messages that match. A name marked `common` is weak evidence on
its own. Indirect references, such as "the runner who won last year's mountain ultra", still need the server.
See [Privacy modes](/build/privacy-modes) and [Resolving talent](/build/resolving-talent).

## What can go wrong

| Problem | Cause | What to do |
| - | - | - |
| The assistant refuses ordinary questions | You sent `impersonation` for a reference | Classify first; answer references without a check |
| `deny` with `ambiguous_talent` | The name matches more than one talent | Ask the user which one, then pass `talent` or `exclude_talent` |
| `deny` with `monthly_limit_reached` | The knowledge license's monthly asks are used | Tell the user; the limit resets with the month |
| `409 authorization_consumed` | A reused authorization is used up | Run a new check |

## Related

<Columns cols={2}>
  <Card title="Text integration design" icon="message" href="/quickstarts/text">
    Proposed resolution and check workflows for assistant replies.
  </Card>

  <Card title="Resolution" icon="magnifying-glass" href="/concepts/resolution">
    How text is matched to talent, and why no match is not permission.
  </Card>

  <Card title="Privacy" icon="lock" href="/concepts/privacy">
    What is sent, what is kept, and for how long.
  </Card>

  <Card title="Agent builders" icon="robot" href="/guides/agent-builders">
    Passing authorizations to the tools an assistant calls.
  </Card>
</Columns>


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