---
title: "Get Training Run"
method: GET
path: "/risk-assessment/training-runs/{training_run_id}"
tags: ["risk-assessment"]
---

# Get Training Run

`GET /risk-assessment/training-runs/{training_run_id}`

## Request

- Base URL: `https://api.kobaltlabs.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.kobaltlabs.com/risk-assessment/training-runs/{training_run_id}`
- Auth: none declared

The single polled endpoint for the training panel (F-9).

Trace, experiments and the proposal all come from here; step *results* stay
fetch-on-demand through `GET /steps/{id}/result`.

## Path parameters

- `training_run_id` string, uuid, required

## Response `200`

Successful Response

- TrainingRunDetail: The single polled payload for the training panel (F-9).
  - `training_run_id` string, uuid, required
  - `factor_assessment_id` string, uuid, required
  - `status` 'pending' | 'running' | 'completed' | 'failed', required
  - `outcome` 'promoted' | 'gave_up', required: How a `RiskFactorTrainingAgentRun` ended. Both are terminal tool calls, not failures: an agent that cannot justify a rewrite is expected to GIVE_UP with questions rather than promote one.
  - `proposal_status` 'active' | 'proposed' | 'hidden' | 'inactive', required: Where one `risk_factor_versions` row stands. A factor's name and slug are permanent; its description, assessment guidance, rating rubric and applicability logic are versioned, so a rewrite never destroys the text that produced historical ratings. ACTIVE is what the next assessment run uses, and a partial unique index (`uq_risk_factor_versions_one_active`) enforces at most one per factor. HIDDEN is a training agent's working draft — created mid-run and never shown to a reviewer. PROPOSED is a draft the agent promoted and the reviewer has not yet accepted or rejected. INACTIVE covers both "superseded" and "rejected"; the two are distinguishable from the training run's outcome.
  - `created` string, date-time, required
  - `started_at` string, date-time, nullable, required
  - `finished_at` string, date-time, nullable, required
  - `experiment_count` integer, required
  - `error` string, nullable, required
  - `vendor_id` string, uuid, required
  - `risk_assessment_id` string, uuid, required
  - `risk_factor` FactorRef, required
    - `risk_factor_id` string, uuid, nullable, required
    - `slug` string, required
    - `name` string, required
  - `guidance_text` string, nullable, required
  - `expected_rating` RatingOptionView, required: One level of the tenant's INHERENT_RISK_LEVEL scale. The scale is per-tenant and variable length, so the UI renders N cells from this list rather than assuming five. `position` is 1-based and derived from order, not from `order_index`, which may be sparse.
    - `option_id` string, uuid, required
    - `label` string, required
    - `position` integer, required
    - `hex_color` string, nullable, required
  - `force_rating` boolean, required
  - `reference_documents` ReferenceDocumentView[]
    - `upload_id` string, uuid, required
    - `filename` string, required
  - `reference_urls` string[]
  - `message` string, nullable, required
  - `baseline` TrainingExperimentView, required: One re-run of the factor subagent against a draft.
    - `label` string, required
    - `factor_version_id` string, uuid, required
    - `agent_run_id` string, uuid, nullable, required
    - `status` 'queued' | 'running' | 'complete' | 'error', required: Lifecycle of one factor's assessment within a run. There is no deferral state: a factor either produces a rating its rationale can defend, or it errors. Missing evidence is narrated in the rationale.
    - `rating` RatingOptionView, required: One level of the tenant's INHERENT_RISK_LEVEL scale. The scale is per-tenant and variable length, so the UI renders N cells from this list rather than assuming five. `position` is 1-based and derived from order, not from `order_index`, which may be sparse.
      - `option_id` string, uuid, required
      - `label` string, required
      - `position` integer, required
      - `hex_color` string, nullable, required
    - `rationale` string, nullable, required
    - `citation_count` integer, required
    - `distinct_document_count` integer, required
    - `error` string, nullable, required
  - `experiments` TrainingExperimentView[]
    - `label` string, required
    - `factor_version_id` string, uuid, required
    - `agent_run_id` string, uuid, nullable, required
    - `status` 'queued' | 'running' | 'complete' | 'error', required: Lifecycle of one factor's assessment within a run. There is no deferral state: a factor either produces a rating its rationale can defend, or it errors. Missing evidence is narrated in the rationale.
    - `rating` RatingOptionView, required: One level of the tenant's INHERENT_RISK_LEVEL scale. The scale is per-tenant and variable length, so the UI renders N cells from this list rather than assuming five. `position` is 1-based and derived from order, not from `order_index`, which may be sparse.
      - `option_id` string, uuid, required
      - `label` string, required
      - `position` integer, required
      - `hex_color` string, nullable, required
    - `rationale` string, nullable, required
    - `citation_count` integer, required
    - `distinct_document_count` integer, required
    - `error` string, nullable, required
  - `current_version` RiskFactorVersionView, required
    - `risk_factor_version_id` string, uuid, required
    - `version_number` integer, required
    - `status` 'active' | 'proposed' | 'hidden' | 'inactive', required: Where one `risk_factor_versions` row stands. A factor's name and slug are permanent; its description, assessment guidance, rating rubric and applicability logic are versioned, so a rewrite never destroys the text that produced historical ratings. ACTIVE is what the next assessment run uses, and a partial unique index (`uq_risk_factor_versions_one_active`) enforces at most one per factor. HIDDEN is a training agent's working draft — created mid-run and never shown to a reviewer. PROPOSED is a draft the agent promoted and the reviewer has not yet accepted or rejected. INACTIVE covers both "superseded" and "rejected"; the two are distinguishable from the training run's outcome.
    - `description` string, nullable, required
    - `assessment_guidance` string, required
    - `rating_rubric` string, nullable, required
    - `change_note` string, nullable, required
  - `proposed_version` RiskFactorVersionView, required
    - `risk_factor_version_id` string, uuid, required
    - `version_number` integer, required
    - `status` 'active' | 'proposed' | 'hidden' | 'inactive', required: Where one `risk_factor_versions` row stands. A factor's name and slug are permanent; its description, assessment guidance, rating rubric and applicability logic are versioned, so a rewrite never destroys the text that produced historical ratings. ACTIVE is what the next assessment run uses, and a partial unique index (`uq_risk_factor_versions_one_active`) enforces at most one per factor. HIDDEN is a training agent's working draft — created mid-run and never shown to a reviewer. PROPOSED is a draft the agent promoted and the reviewer has not yet accepted or rejected. INACTIVE covers both "superseded" and "rejected"; the two are distinguishable from the training run's outcome.
    - `description` string, nullable, required
    - `assessment_guidance` string, required
    - `rating_rubric` string, nullable, required
    - `change_note` string, nullable, required
  - `winning_experiment_label` string, nullable, required
  - `rating_options` RatingOptionView[]
    - `option_id` string, uuid, required
    - `label` string, required
    - `position` integer, required
    - `hex_color` string, nullable, required
  - `agent_run` AgentRunRef, required
    - `agent_run_id` string, uuid, required
    - `status` 'pending' | 'running' | 'completed' | 'failed', required
    - `started_at` string, date-time, nullable, required
    - `finished_at` string, date-time, nullable, required
    - `error` string, nullable, required
  - `steps` StepView[]
    - `step_id` string, uuid, required
    - `ordinal` integer, required
    - `kind` 'thinking' | 'tool_call' | 'verdict', required: One `agent_run_steps` row per unit of agent activity. VERDICT is a terminal `submit_*` step (the risk-factor subagent's rating, or a control-assessment's check label + answer); the research agent only emits THINKING/TOOL_CALL rows. A tool declares its own kind via `AgentTool.step_kind`, so the loop knows it before the row is written.
    - `group_id` string, uuid, required
    - `tool_use_id` string, nullable, required
    - `tool_name` string, nullable, required
    - `input` object, nullable, required
    - `content` string, nullable, required
    - `result_preview` unknown, required
    - `result_state` 'ok' | 'empty' | 'error' | 'timeout', required: Outcome of a TOOL_CALL step. NULL on the row means still in flight. EMPTY is distinct from ERROR: a tool that ran successfully and found nothing (e.g. an empty web search) is not a failure.
    - `result_summary` string, nullable, required
    - `result_bytes` integer, nullable, required
    - `model` string, nullable, required
    - `input_tokens` integer, nullable, required
    - `output_tokens` integer, nullable, required
    - `started_at` string, date-time, nullable, required
    - `duration_ms` integer, nullable, required
    - `cited_in_verdict` boolean
    - `risk_factor_id` string, uuid, nullable

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/kobaltlabs/apis/fastapi.md) - [All operations](https://skmtc.dev/kobaltlabs/apis/fastapi/llms.txt) - [OpenAPI document](https://skmtc.dev/kobaltlabs/apis/fastapi/revisions/8587332d5e43?raw)
