Skip to content
ChatClipThatAPI
Automation recipe

Build an evidence-first observation review queue

Turn typed scanner observations into a durable human review queue without confusing relevance with confidence or losing timestamped evidence.

Updated August 14, 20269 min read

A useful review queue lets a person inspect the source evidence, record a decision, and trace that decision back to the scanner definition that produced it. The observation—not an AI-generated percentage—is the unit of work.

1. Ingest only completed-run observations

After GET /v1/runs/{run_id} reaches completed, request GET /v1/runs/{run_id}/observations. Deduplicate locally on observation_id. Store the full typed value and provenance fields your interface needs rather than flattening everything into a title and score.

{
  "observation_id": "obs_...",
  "scanner_id": "scn_...",
  "scanner_version": 3,
  "run_id": "run_...",
  "analysis_id": "ana_...",
  "type": "find_moments",
  "value_type": "object",
  "semantics": "timestamped_moment",
  "value": {"category": "setup_error"},
  "relevance_score": 0.91,
  "evidence": {
    "start_ms": 84210,
    "end_ms": 109440,
    "transcript_excerpt": null,
    "signals": []
  },
  "source_metadata": {"recording_id": "rec_1842"}
}

2. Model queue state separately

Do not mutate the API observation into your review decision. Create a local row keyed by observation_id with fields such as state, assignee, decision, note, and timestamps. This leaves the generated result immutable while your team’s review history evolves.

review_item = {
  "observation_id": observation.observation_id,
  "state": "unreviewed",
  "priority": rank_for_team(observation.relevance_score),
  "assignee": null,
  "decision": null
}

3. Present evidence, not implied certainty

Show the observation title, typed value, source metadata, scanner version, and exact start/end time. The first visual scanner normally returns a null transcript excerpt and empty evidence signals, so do not promise either in the review UI. Label relevance_score as relevance or ranking support—never “91% confidence.” It is not a calibrated probability.

Different scanner types need different controls. A monitor produces a boolean; a classifier a bounded label; a scorer a 0–1 number; an extractor structured data; and find_moments timestamped evidence. Validate value_type and semantics before choosing a UI. Treat explicit monitor false as a negative answer and zero observations as unanswerable.

4. Support cross-run triage carefully

GET /v1/observations accepts scanner_id, run_id, type, and a limit up to 100. Use those server filters, then maintain your own ingestion watermark or seen-ID set. Do not compare scores from unrelated scanners as though they shared a calibration scale.

GET /v1/observations?scanner_id=scn_...&type=find_moments&limit=100
Authorization: Bearer $CCT_API_KEY

5. Give reviewers a source-safe playback path

The public observation contains timestamps and evidence, not a permanent public media URL. Keep playback inside an authorized environment and resolve access from your account-owned upload record; do not persist the signed PUT target as a viewer URL.

6. Escalate only after a decision

An accepted item can create a ticket, send a privacy-safe alert, or feed an aggregate report. Scanner observations do not render and an observation ID is not a Moment ID. If finished video is required, create a separate one-off analysis and render selected Moment IDs from that flow.

Human review remains your policy boundary. ChatClipThat provides evidence-backed model output. Your application owns consent, access control, decision rules, and any high-impact action taken from a finding.