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

# Feedback

> Rating on the answer and the downstream business outcome, kept as separate intents

Two feedback surfaces, both authenticated by the **trigger secret** for that Flow. They mean different things — don't mix them.

## `feedback(traceId, {...})`

Rating the answer itself: 👍 / 👎, an optional comment, or a `before → after` correction. This is the existing end-user feedback endpoint, exposed here for your app to forward.

* A `dislike` promotes into a **confirmed human signal** on that trace.
* A `like` retracts any pending signals attributed to that trace.

Aliased as `traces.feedback` — same call, spec-canonical name.

```ts theme={null}
await nora.feedback(r.traceId, {
  rating: "dislike",
  comment: "Coverage explained backwards",
  correction: { before: "…", after: "…" },
});
```

Options:

* `rating` (required) — `"like"` or `"dislike"`.
* `comment` — free-text note; surfaces on the trace and in cluster review.
* `correction` — `{ before, after }` pair. The `after` is what the user says the answer *should* have been. Fed into the improvement loop as candidate fix content.

## `signals.report(traceId, {...})`

An external outcome the answer-quality detectors can't see: refunded, reopened, escalated to human, resolved. These land as **candidate signals** with `origin=sdk_report` and go through the same cluster / dataset path as detected signals.

```ts theme={null}
await nora.signals.report(r.traceId, {
  outcome: "resolved",
  reason: "customer confirmed",
});
```

Options:

* `outcome` (required) — free-form string. Common vocab: `resolved`, `reopened`, `escalated`, `refunded`, `abandoned`. Pick a set and stick to it — it's how your clusters group.
* `reason` — free-text note.

## Why keep the two separate

Mixing `feedback` and `signals.report` makes detectors and clusters noisy:

* `feedback` speaks to **whether the answer was right**. It weighs into answer-quality metrics.
* `signals.report` speaks to **what actually happened downstream**. It weighs into outcome metrics and can surface failures the answer-quality detectors miss.

An answer can be technically correct (👍 `feedback`) but the user still churns (`escalated` signal). Both should land, on different tracks.

```ts theme={null}
// Answer quality — what the user thought of the reply
await nora.feedback(traceId, { rating: "dislike", correction: { before, after } });

// Business outcome — what actually happened downstream
await nora.signals.report(traceId, { outcome: "reopened", reason: "asked again next day" });
```

## Where the `traceId` comes from

* **From `flows.run`** — `r.traceId` on the return value. Preferred: you have it inline.
* **From your own logs** — if you captured `traceId` earlier and are now posting feedback on it, that also works.
* **Correlation with [`newTraceRef`](/sdk/execution#newtraceref)** — for pre-run correlation across your own logs.

## MCP / CLI equivalents

The MCP tool and CLI surface the same operation:

```bash theme={null}
# CLI
nora feedback submit <trace-id> --like            # or --dislike
nora feedback submit <trace-id> --dislike --comment "…" --correction-before "…" --correction-after "…"
```

See [`nora feedback`](/cli/feedback) for the full CLI shape.
