> Discover all available pages from the documentation index: https://mastra.ai/llms.txt

# Feedback

**Added in:** `@mastra/core@1.18.0`

Feedback APIs store and query human-in-the-loop observability signals such as ratings, thumbs, comments, and corrections. Use the [feedback guide](https://mastra.ai/docs/observability/feedback) for usage patterns.

## Usage example

The following example records a rating for a persisted trace through the observability entrypoint. `addFeedback()` is optional on the entrypoint, so check that the active observability implementation supports it before calling it.

```typescript
if (!mastra.observability.addFeedback) {
  throw new Error('Feedback is not supported by the active observability implementation')
}

await mastra.observability.addFeedback({
  traceId: 'trace-123',
  spanId: 'span-456',
  feedback: {
    feedbackSource: 'user',
    feedbackType: 'rating',
    value: 1,
    comment: 'Helpful answer.',
  },
})
```

## Create feedback

### `addFeedback(args)`

Adds feedback to a persisted trace or span through the observability entrypoint.

```typescript
await mastra.observability.addFeedback?.({
  traceId: 'trace-123',
  spanId: 'span-456',
  feedback: {
    feedbackSource: 'user',
    feedbackType: 'rating',
    value: 1,
    comment: 'Helpful answer.',
  },
})
```

**traceId** (`string`): Trace that anchors the feedback target.

**spanId** (`string`): Span that anchors the feedback target.

**correlationContext** (`CorrelationContext`): Live span or trace context to emit from without rehydrating the target from storage.

**feedback** (`FeedbackInput`): Feedback payload to add.

### `createFeedback(args)`

Creates one feedback record through the observability storage domain. Storage-level calls write directly to the store, so include `timestamp`.

```typescript
await observability.createFeedback({
  feedback: {
    feedbackId: 'feedback-1',
    timestamp: new Date(),
    traceId: 'trace-123',
    spanId: 'span-456',
    feedbackSource: 'user',
    feedbackType: 'rating',
    value: 1,
    comment: 'Helpful answer.',
  },
})
```

The HTTP and client SDK create route accepts `CreateFeedbackBody`, sets `timestamp` server-side, and generates `feedbackId` when omitted:

```typescript
await mastraClient.createFeedback({
  feedback: {
    traceId: 'trace-123',
    spanId: 'span-456',
    feedbackSource: 'user',
    feedbackType: 'rating',
    value: 1,
  },
})
```

### `batchCreateFeedback(args)`

Creates multiple feedback records through the observability storage domain. This method isn't exposed by the HTTP routes or `@mastra/client-js`.

```typescript
await observability.batchCreateFeedback({
  feedbacks: [
    {
      feedbackId: 'feedback-1',
      timestamp: new Date(),
      traceId: 'trace-123',
      feedbackSource: 'user',
      feedbackType: 'rating',
      value: 1,
    },
    {
      feedbackId: 'feedback-2',
      timestamp: new Date(),
      traceId: 'trace-123',
      feedbackSource: 'qa',
      feedbackType: 'comment',
      value: 'Needs a citation before shipping.',
    },
  ],
})
```

## List feedback

### `listFeedback(args?)`

Returns feedback records in page mode or delta mode.

```typescript
const response = await mastraClient.listFeedback({
  filters: {
    feedbackType: 'rating',
    feedbackSource: 'studio',
  },
  pagination: { page: 0, perPage: 20 },
  orderBy: { field: 'timestamp', direction: 'DESC' },
})
```

**mode** (`'page' | 'delta'`): List mode. Defaults to 'page'.

**filters** (`FeedbackFilter`): Filters for the feedback records.

**pagination** (`{ page?: number; perPage?: number }`): Page-mode pagination. page is zero-indexed.

**orderBy** (`{ field?: 'timestamp'; direction?: 'ASC' | 'DESC' }`): Page-mode sort configuration.

**after** (`string`): Delta cursor for incremental polling. Only valid in delta mode.

**limit** (`number`): Maximum number of updates to return in delta mode.

## OLAP queries

OLAP feedback queries operate on numeric `value` fields.

### `getFeedbackAggregate(args)`

Returns one aggregate feedback value.

```typescript
const response = await mastraClient.getFeedbackAggregate({
  feedbackType: 'rating',
  feedbackSource: 'user',
  aggregation: 'avg',
  comparePeriod: 'previous_day',
})
```

**feedbackType** (`string`): Feedback type to aggregate.

**feedbackSource** (`string`): Feedback source to aggregate.

**aggregation** (`'sum' | 'avg' | 'min' | 'max' | 'count' | 'count_distinct' | 'last'`): Aggregation to apply.

**filters** (`FeedbackFilter`): Additional filters.

**comparePeriod** (`'previous_period' | 'previous_day' | 'previous_week'`): Optional period-over-period comparison.

### `getFeedbackBreakdown(args)`

Returns feedback values grouped by dimensions.

```typescript
const response = await mastraClient.getFeedbackBreakdown({
  feedbackType: 'rating',
  groupBy: ['entityName'],
  aggregation: 'avg',
})
```

### `getFeedbackTimeSeries(args)`

Returns feedback values bucketed by interval.

```typescript
const response = await mastraClient.getFeedbackTimeSeries({
  feedbackType: 'rating',
  interval: '1h',
  aggregation: 'avg',
  groupBy: ['feedbackSource'],
})
```

### `getFeedbackPercentiles(args)`

Returns percentile values bucketed by interval.

```typescript
const response = await mastraClient.getFeedbackPercentiles({
  feedbackType: 'rating',
  percentiles: [0.5, 0.95],
  interval: '1d',
})
```

## Types

### `FeedbackRecord`

**feedbackId** (`string | null`): Unique ID for this feedback event. The server route generates one when omitted.

**timestamp** (`Date`): Time when the feedback was recorded.

**traceId** (`string | null`): Trace that anchors the feedback target when available.

**spanId** (`string | null`): Span that anchors the feedback target when available.

**feedbackSource** (`string | null`): Optional source metadata, such as 'user', 'qa', 'studio', or 'system'.

**source** (`string | null`): Deprecated alias for feedbackSource.

**feedbackType** (`string`): Type of feedback, such as 'rating', 'thumbs', 'comment', or 'correction'.

**value** (`number | string`): Feedback value. Numeric values support aggregate, breakdown, time series, and percentile queries.

**comment** (`string | null`): Additional comment or context for the feedback.

**feedbackUserId** (`string | null`): User who provided the feedback.

**sourceId** (`string | null`): ID of the source record this feedback is linked to, such as an experiment result ID.

**metadata** (`Record<string, unknown> | null`): User-defined metadata for the feedback record.

### Shared context fields

Feedback records can include shared observability context fields for filtering, grouping, and correlation with traces, logs, metrics, and scores.

**entityType** (`EntityType | null`): Entity type that produced the signal.

**entityId** (`string | null`): ID of the entity that produced the signal.

**entityName** (`string | null`): Name of the entity that produced the signal.

**parentEntityType** (`EntityType | null`): Entity type of the parent entity.

**parentEntityId** (`string | null`): ID of the parent entity.

**parentEntityName** (`string | null`): Name of the parent entity.

**rootEntityType** (`EntityType | null`): Entity type of the root entity.

**rootEntityId** (`string | null`): ID of the root entity.

**rootEntityName** (`string | null`): Name of the root entity.

**userId** (`string | null`): Human end user who triggered execution.

**organizationId** (`string | null`): Multi-tenant organization or account.

**resourceId** (`string | null`): Broader resource context.

**runId** (`string | null`): Execution run identifier.

**sessionId** (`string | null`): Session identifier for grouping traces.

**threadId** (`string | null`): Conversation thread identifier.

**requestId** (`string | null`): HTTP request ID for correlation.

**environment** (`string | null`): Deployment environment.

**serviceName** (`string | null`): Name of the service.

**scope** (`Record<string, unknown> | null`): Package, app version, or deployment metadata.

**entityVersionId** (`string | null`): Version ID of the entity that produced the signal.

**parentEntityVersionId** (`string | null`): Version ID of the parent entity.

**rootEntityVersionId** (`string | null`): Version ID of the root entity.

**experimentId** (`string | null`): Experiment or eval run identifier.

**executionSource** (`string | null`): Source of execution, such as local, cloud, or CI.

**tags** (`string[] | null`): Labels for filtering.

### `FeedbackInput`

Use `FeedbackInput` with `mastra.observability.addFeedback()`, `recordedTrace.addFeedback()`, and `recordedSpan.addFeedback()`.

**feedbackSource** (`string`): Optional source metadata for the feedback.

**source** (`string`): Deprecated alias for feedbackSource.

**feedbackType** (`string`): Type of feedback to record.

**value** (`number | string`): Feedback value to record.

**comment** (`string`): Additional comment or context.

**feedbackUserId** (`string`): User who provided the feedback.

**userId** (`string`): Deprecated alias for feedbackUserId.

**metadata** (`Record<string, unknown>`): Additional feedback-specific metadata.

**experimentId** (`string`): Experiment or eval run identifier.

**sourceId** (`string`): ID of the source record this feedback is linked to.

### `FeedbackFilter`

Use `FeedbackFilter` in `listFeedback()` and OLAP query `filters`.

**timestamp** (`{ start?: Date; end?: Date; startExclusive?: boolean; endExclusive?: boolean }`): Filter by timestamp range.

**traceId** (`string`): Filter by trace ID.

**spanId** (`string`): Filter by span ID.

**feedbackType** (`string | string[]`): Filter by one or more feedback types.

**feedbackSource** (`string`): Filter by feedback source.

**source** (`string`): Deprecated alias for feedbackSource.

**feedbackUserId** (`string`): Filter by the user who provided the feedback.

**entityType** (`EntityType`): Filter by entity type.

**entityName** (`string`): Filter by entity name.

**entityVersionId** (`string`): Filter by entity version ID.

**parentEntityType** (`EntityType`): Filter by parent entity type.

**parentEntityName** (`string`): Filter by parent entity name.

**parentEntityVersionId** (`string`): Filter by parent entity version ID.

**rootEntityType** (`EntityType`): Filter by root entity type.

**rootEntityName** (`string`): Filter by root entity name.

**rootEntityVersionId** (`string`): Filter by root entity version ID.

**userId** (`string`): Filter by human end-user ID.

**organizationId** (`string`): Filter by organization ID.

**resourceId** (`string`): Filter by resource ID.

**runId** (`string`): Filter by run ID.

**sessionId** (`string`): Filter by session ID.

**threadId** (`string`): Filter by thread ID.

**requestId** (`string`): Filter by request ID.

**serviceName** (`string`): Filter by service name.

**environment** (`string`): Filter by environment.

**executionSource** (`string`): Filter by execution source.

**experimentId** (`string`): Filter by experiment or eval run identifier.

**tags** (`string[]`): Filter by tags. Matching records must have all specified tags.

## HTTP routes

| Method | Path                                      | Purpose                      | Permission           |
| ------ | ----------------------------------------- | ---------------------------- | -------------------- |
| `GET`  | `/api/observability/feedback`             | List feedback records        | None derived         |
| `POST` | `/api/observability/feedback`             | Create a feedback record     | None derived         |
| `POST` | `/api/observability/feedback/aggregate`   | Return one aggregate value   | `observability:read` |
| `POST` | `/api/observability/feedback/breakdown`   | Group feedback by dimensions | `observability:read` |
| `POST` | `/api/observability/feedback/timeseries`  | Bucket feedback by interval  | `observability:read` |
| `POST` | `/api/observability/feedback/percentiles` | Return percentile series     | `observability:read` |

## Related

- [Feedback guide](https://mastra.ai/docs/observability/feedback)
- [Client SDK observability reference](https://mastra.ai/reference/client-js/observability)
- [Observability configuration](https://mastra.ai/reference/observability/tracing/configuration)