---
title: "Read recorded RL task evidence"
method: GET
path: "/v1/workloads/{id}/rl-events"
tags: ["Workloads"]
---

# Read recorded RL task evidence

`GET /v1/workloads/{id}/rl-events`

## Request

- Base URL: `/` (relative, and the document was published on a file host, not at the API’s origin)
- URL: `/v1/workloads/{id}/rl-events`
- Auth: HTTP bearer

Read typed task events for a workload in the authenticated tenant. Inherits the customer bearer authentication used by other workload operations. Events are reported by the customer runner and persisted by Nodus, not independently measured by this endpoint. The workload must carry RL metadata and its command must emit task events to produce evidence. A workload without recorded events returns an empty page. Follow has_more to drain available pages, then continue polling next_cursor while the workload is active. Read workload status separately and perform a fresh final drain after it becomes terminal. This endpoint does not install or launch a catalog environment and does not provide built-in training.

## Path parameters

- `id` string, required

## Query parameters

- `after` string
- `limit` integer

## Response `200`

Persisted RL event page

- RLEventPage: Tenant-scoped persisted RL evidence with a consistent database snapshot for each page. While a run is active, keep polling the returned cursor even when has_more is false. After observing terminal workload status, perform a fresh drain before considering replay complete. A terminal workload status does not establish a task score.
  - `schema_version` 1, required
  - `events` RLEventRow[], required: Available rows after the requested cursor, in ascending replay order. An empty array means no newer rows in this read.
    - `id` string, required: Server replay identity encoded as a decimal string to preserve integer precision. Treat it as an identifier. It is not the opaque after cursor or the application event_id.
    - `stage_id` string, required: Server-authorized workload stage that received the event.
    - `generation` integer, required: Execution generation authorized to report this observation. Retries within a generation retain their original row. Recovered generations receive distinct rows, even for identical application events.
    - `received_at` string, date-time, required: Server time when the event was first persisted.
    - `event` RLEvent, required: A persisted application-reported task event. The encoded event is limited to 16 KiB. Stable event IDs are deduplicated within a workload, stage and execution generation. Reusing an identity with changed content in the same generation is rejected. A stage, generation, phase, task, attempt and kind may have only one immutable observation. Recovered generations retain separate observations, including identical content. Task completion is not workload completion, and these events do not change checkpoints or recovery progress. No task_started event is required before a task_completed event.
      - `event_id` string, required: Stable application event identity. UTF-8 text, at most 128 bytes. Leading or trailing whitespace and control characters are rejected.
      - `phase` 'baseline' | 'training' | 'evaluation', required: Application-reported phase. A workload whose RL mode is evaluate cannot record training-phase events.
      - `task_id` string, required: Logical task identity within a stage and phase. UTF-8 text, at most 128 bytes. Leading or trailing whitespace and control characters are rejected.
      - `attempt` integer, required: Application attempt number. Increment it for a genuinely repeated attempt. Infrastructure generation is separate and does not create a new logical attempt.
      - `kind` 'task_completed', required
      - `outcome` 'passed' | 'failed' | 'error', required: Required for task_completed and absent for task_started. Passed and failed describe a scored check. Error describes execution failure. Outcome is explicit and is never inferred from reward.
      - `reward` number: Optional finite reward on a completed attempt. Absence means no reward was reported. Zero is a reported reward and must not be treated as missing. Negative and nonbinary finite rewards are allowed.
      - `duration_ms` number: Optional finite nonnegative attempt duration in milliseconds on a completed attempt. Absence means not reported. Zero is valid.
      - `message` string: Short task activity message. At most 1024 UTF-8 bytes. Newline, carriage return and tab are allowed. Other control characters are rejected. Present only when explicitly emitted by the runner.
      - `input` string: Task input evidence. At most 4096 UTF-8 bytes. Newline, carriage return and tab are allowed. Other control characters are rejected. Present only when explicitly emitted by the runner.
      - `output` string: Agent output evidence. At most 4096 UTF-8 bytes. Newline, carriage return and tab are allowed. Other control characters are rejected. Present only when explicitly emitted by the runner.
      - `verifier` string: Verifier evidence. At most 4096 UTF-8 bytes. Newline, carriage return and tab are allowed. Other control characters are rejected. Present only when explicitly emitted by the runner.
  - `next_cursor` string, required: Opaque exclusive cursor for the next request. Pass this value unchanged as after. It remains at the supplied position when no newer rows are returned. Do not derive a cursor from a row ID.
  - `has_more` boolean, required: More rows were available beyond this page in the current database snapshot. False does not mean the workload or task stream has ended.
  - `dropped_events` integer, required: Sum of the highest reported loss counter for each stage and infrastructure generation. It is not an exact count of every event that may be absent. The counter can exceed a single generation limit.
  - `truncated` boolean, required: True when any delivery reported loss or hit a storage limit. Stored evidence is bounded to 100,000 events and 64 MiB of encoded event bodies per workload. Treat results as partial when true or dropped_events is nonzero. False does not prove lossless delivery after host loss.

## Other responses

- `400`: Invalid cursor or page size. Error codes are invalid_cursor or invalid_limit.
- `404`: The workload does not exist in the authenticated tenant.
- `default`: Authentication, rate limits and transient failures apply. The JSON error and message fields describe the failure.

---

[API](https://skmtc.dev/nodus-compute/apis/nodus-infrastructure-execution-api.md) - [All operations](https://skmtc.dev/nodus-compute/apis/nodus-infrastructure-execution-api/llms.txt) - [OpenAPI document](https://skmtc.dev/nodus-compute/apis/nodus-infrastructure-execution-api/revisions/a59210899d95?raw)
