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

# Feedback

> Record 👍/👎, scores, comments, and corrections against a generation with @bryel/feedback.

Record user feedback against a generation or session — the substrate for evals and fine-tuning datasets. Send it from your **server** (`@bryel/feedback`, secret key) or straight from the **browser** (`@bryel/browser`, publishable key). Both are zero-dependency.

## Kinds and targets

| Field         | Values                                                         |
| ------------- | -------------------------------------------------------------- |
| `kind`        | `thumb` · `score` · `comment` · `correction` · `label`         |
| `target.type` | `message` (a single turn) · `session` (the whole conversation) |
| `source`      | `end_user` · `labeler` · `model_judge` · `code`                |

A 👎 with a written note is a `thumb` (`score: 0`) plus a `comment`. Free-text feedback the user typed about the whole conversation is a `comment` on a `session` target.

## Server (secret key)

Use a secret key (`bk_…`) from your backend. It has no origin requirement.

```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { recordFeedback, thumbsUp } from "@bryel/feedback";

await recordFeedback({
  apiKey: process.env.BRYEL_KEY!,
  target: { type: "message", id: messageId },
  kind: "thumb",
  score: 0,
  comment: "wrong colors",
  userId,
  source: "end_user",
});

await thumbsUp({ apiKey, target: { type: "message", id: messageId } });
```

Session-level typed feedback uses a `comment` on a `session` target:

```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
await recordFeedback({
  apiKey: process.env.BRYEL_KEY!,
  target: { type: "session", id: sessionId },
  kind: "comment",
  comment: "Visual design: good\nTask completion: yes\nEfficiency: no",
  source: "end_user",
});
```

## Browser (publishable key)

`@bryel/browser` re-exports the same `recordFeedback`. In the browser, use a publishable key (`bkp_…`): it is write-only and origin-locked, so it is safe to ship in your client bundle — no backend proxy required. The `/v1/feedback` endpoint is CORS-enabled and accepts a `bkp_` key sent from an allowed origin, the same model as browser traces.

```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { recordFeedback } from "@bryel/browser";

await recordFeedback({
  apiKey: "bkp_…",
  target: { type: "message", id: messageId },
  kind: "thumb",
  score: 0,
  comment,
  sessionId,
  source: "end_user",
});
```

<Warning>Only publishable `bkp_` keys belong in client code. Never ship a secret `bk_` key to the browser — proxy those through your backend.</Warning>

## Joining feedback to a trace

Feedback arrives *after* the answer, so `target.id` must be an id that also exists on the trace. Two options:

* **Reuse the id your tracing already produced.** If each turn already has a stable id on its trace (the id you set as `metadata.messageId`, or a per-turn event id), pass that as `target.id`. No new id to mint — this is what the Framer integration does.
* **Mint one if you don't have it.** Otherwise create a `messageId` per turn, stamp it into telemetry metadata, and return it to the client.

<Steps>
  <Step title="Mint, stamp, and return on the server">
    ```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
    const messageId = crypto.randomUUID();
    streamText({ experimental_telemetry: { isEnabled: true, metadata: { sessionId, userId, messageId } } });
    return result.toTextStreamResponse({ headers: { "x-bryel-message-id": messageId } });
    ```
  </Step>

  <Step title="Record feedback against that id">
    ```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
    await recordFeedback({ apiKey, target: { type: "message", id: messageId }, kind: "thumb", score: 1, source: "end_user" });
    ```
  </Step>
</Steps>

To capture the `messageId` upstream in the first place, see the [Vercel instrumentation](/sdk/typescript) guide.
