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

# Observability

> Observability and tracking exports

## Observability Exports

```typescript theme={null}
import {
  createTraceCollector,
  RunflowTraceCollector,
  RunflowTraceSpan,
  traced
} from '@runflow-ai/sdk';
```

## Conversation Messages

```typescript theme={null}
import { message } from '@runflow-ai/sdk/observability';
```

### `message(data, options?)`

Emit a `conversation_message` trace. The portal renders these as chat bubbles and uses them to populate the thread sidebar preview. See [Conversation Messages](/core-concepts/observability#conversation-messages) for the full guide and examples.

```typescript theme={null}
message({ role: 'user',      content: 'Quais acomodações?' });
message({ role: 'assistant', content: 'Oferecemos duas opções...' });
```

**Parameters (`MessageData`):**

| Name       | Type                                                    | Description                                                                                       |
| ---------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `role`     | `'user' \| 'assistant' \| 'system' \| 'tool' \| string` | Speaker. Custom strings are accepted.                                                             |
| `content`  | `string \| Record<string, any>`                         | Plain text or a structured object with a `type` field (e.g. `{ type: 'buttons', items: [...] }`). |
| `metadata` | `Record<string, any>`                                   | Optional extra fields (citations, confidence, custom flags).                                      |
| `parentId` | `string`                                                | Optional explicit parent span's `traceId`. Falls back to the active `startSpan()` context.        |

**`LogOptions`:**

| Name       | Type     | Description                                                                 |
| ---------- | -------- | --------------------------------------------------------------------------- |
| `parentId` | `string` | Same as `data.parentId`. Provided for symmetry with `log()` / `logError()`. |

Available since `@runflow-ai/sdk@1.1.10`.

## Code-first Metrics

```typescript theme={null}
import { metrics, MetricsRegistry } from '@runflow-ai/sdk/observability';
```

### `metrics` (singleton)

Process-wide `MetricsRegistry` instance. `import { metrics }` returns the same object across modules, mirroring how `track()` and `identify()` share state.

### `metrics.defineTab(input)`

Idempotent on `name` — re-registering updates the `sortOrder`.

```typescript theme={null}
metrics.defineTab({ name: 'Vendas', sortOrder: 0 });
```

### `metrics.defineCard(input)`

Validates synchronously via shared Zod schemas. Throws on invalid `cardType`, invalid `gridLayout`, or duplicate `(cardType, title)` pairs. Legacy aliases (e.g. `tableMode → mode`) are auto-normalized before validation.

```typescript theme={null}
metrics.defineCard({
  tab: 'Vendas',
  title: 'Funil de checkout',
  cardType: 'funnel',
  config: {
    funnelMode: 'multi_event',
    steps: [
      { eventName: 'cart_open',        label: 'Carrinho aberto' },
      { eventName: 'checkout_started', label: 'Início checkout' },
      { eventName: 'sale',             label: 'Pagamento' },
    ],
  },
  gridLayout: { x: 0, y: 0, w: 6, h: 5 },
});
```

### `metrics.sync(options?)`

Two-phase upsert against the runtime endpoints. Returns a tally:

```typescript theme={null}
const result = await metrics.sync();
// { agentId, tabs: { created, updated, total }, cards: { created, updated, failed, total } }
```

**`SyncOptions`:**

| Name      | Type      | Default                | Description                                     |
| --------- | --------- | ---------------------- | ----------------------------------------------- |
| `agentId` | `string`  | `RUNFLOW_AGENT_ID` env | Override the target agent.                      |
| `baseUrl` | `string`  | `RUNFLOW_API_URL` env  | Override the API host.                          |
| `apiKey`  | `string`  | `RUNFLOW_API_KEY` env  | Override the API key.                           |
| `strict`  | `boolean` | `false`                | Throw on any tab/card error instead of warning. |

Each card carries a deterministic `idempotencyKey = ${cardType}:${title}:${tab ?? ''}` so repeated `sync()` calls are safe.

See [Metrics Registry](/core-concepts/metrics) for the full guide.

## Execution Reviews

```typescript theme={null}
import { Reviews } from '@runflow-ai/sdk';
```

### `new Reviews(options?)`

Programmatic access to execution reviews. Requires an underlying `RunflowAPIClient` exposing the `reviews` namespace (SDK ≥ `1.1.13`).

```typescript theme={null}
const reviews = new Reviews();
// or with a custom client:
const reviews = new Reviews({ apiClient: customClient });
```

**Methods:**

| Method              | Signature                                                                    | Description                                                                                                                                                                                                       |
| ------------------- | ---------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `create`            | `(args: CreateExecutionReviewArgs) => Promise<CreateExecutionReviewResult>`  | Create a review. `comment` must be ≥ 10 chars. Optional owner (`assignedToUserId`), deadline (`dueAt`) and `source` since `1.5.1`.                                                                                |
| `checkHasReview`    | `(executionId: string) => Promise<CheckHasReviewResult>`                     | Idempotent check before `create()`.                                                                                                                                                                               |
| `list`              | `(filters?: ListReviewsFilters) => Promise<ListReviewsResult>`               | List with filters — including `queue` (`active` / `history`), `source` (`human` / `sdk` / `policy` / `legacy`) and `assignedToUserId` since `1.5.1`. Backend caps `limit` at 100 (defaults to 50).                |
| `get`               | `(reviewId: string) => Promise<ExecutionReview>`                             | Fetch a single review.                                                                                                                                                                                            |
| `update`            | `(reviewId, args: UpdateExecutionReviewArgs) => Promise<UpdateReviewResult>` | Partial update — also `assignedToUserId`, `dueAt` and `disposition` (`fixed` / `false_positive` / `duplicate` / `no_action`) since `1.5.1`. Setting `status: 'resolved'` auto-stamps `resolvedBy` / `resolvedAt`. |
| `delete`            | `(reviewId: string) => Promise<DeleteReviewResult>`                          | Hard delete.                                                                                                                                                                                                      |
| `stats`             | `(filters: { agentId }) => Promise<ReviewsStats>`                            | Aggregate counts + `avgResolutionHours`.                                                                                                                                                                          |
| `exportForTraining` | `(filters: ExportForTrainingFilters) => Promise<ExportForTrainingResult>`    | Export as OpenAI conversational fine-tuning examples.                                                                                                                                                             |

**Typed errors (all extend `ReviewsError`):**

| Class                      | Status | When                                              |
| -------------------------- | ------ | ------------------------------------------------- |
| `ReviewAlreadyExistsError` | 409    | Execution already has a review.                   |
| `ReviewNotFoundError`      | 404    | reviewId not found (or wrong tenant).             |
| `ReviewsError`             | any    | Other failures — exposes `status` and raw `body`. |

See [Execution Reviews](/core-concepts/observability#execution-reviews) for the feedback-loop pattern.

## Business Events Tracking

```typescript theme={null}
import { track, flushTrackEvents } from '@runflow-ai/sdk/observability';
```

### `track(eventName, properties?, options?)`

Emit a business event for the portal dashboard.

```typescript theme={null}
track('alert_received', { company: 'NW', severity: 'High' });
```

**Parameters:**

| Name         | Type                  | Description                        |
| ------------ | --------------------- | ---------------------------------- |
| `eventName`  | `string`              | Event name (e.g. `'order_placed'`) |
| `properties` | `Record<string, any>` | Key-value event data               |
| `options`    | `TrackOptions`        | Optional overrides                 |

**`TrackOptions`:**

| Name          | Type     | Description                          |
| ------------- | -------- | ------------------------------------ |
| `threadId`    | `string` | Override auto-resolved thread ID     |
| `executionId` | `string` | Override auto-resolved execution ID  |
| `timestamp`   | `string` | ISO-8601 timestamp (defaults to now) |

### `flushTrackEvents()`

Manually flush all buffered events. Returns a `Promise<void>`.

```typescript theme={null}
await flushTrackEvents();
```

## Next Steps

<CardGroup cols={2}>
  <Card title="API Client" icon="code" href="/api-reference/api-client">
    View API client exports
  </Card>

  <Card title="Standalone Modules" icon="box" href="/api-reference/standalone-modules">
    View standalone modules
  </Card>
</CardGroup>
