Lab Notes
Research

Artifacts

The typed files a research mission writes to disk. Each artifact is validated by a Pydantic schema. The framework's auditability depends on every artifact being typed, versioned, and reproducible.

Purpose

This page lists the artifacts that the research framework produces, where they live, what schema validates them, and what they are used for. The phases that produce them are in Mission DAG; the lifecycle is in Mission Lifecycle.

Run directory layout

Every mission writes to a single directory:

<runs_dir>/<mission_id>/
├── task.json
├── phase.json
├── candidates.json
├── reviews.json
├── prices.json
├── youtube_search.json
├── transcripts.json
├── synthesis.json           # only if P3 ran
├── report.md
└── logs/
    └── mission.log

Each JSON artifact is validated by a Pydantic schema on write. Invalid artifacts are rejected with a clear error message.

task.json

The mission task. Produced by F0.

FieldTypeDescription
mission_idstringStable mission identifier.
raw_querystringThe original user-supplied query, verbatim.
parsedParsedQueryThe parsed structure (topic, location, etc.).
created_atdatetime (UTC)When the task was created.
configobjectOptional run configuration (flags, overrides).

ParsedQuery:

FieldTypeDescription
topicstringPrimary research topic.
locationstring | nullTarget location, if any.
periodstring | nullTarget date range or period.
budget_maxfloat | nullMaximum budget, if any.
budget_currencystringISO-style currency code (default EUR).
constraintslist[string]Additional constraints.

candidates.json

The candidate list. Produced by F1.

FieldTypeDescription
mission_idstringBack-reference to the task.
created_atdatetime (UTC)When the list was finalized.
candidateslist[Candidate]The deduplicated, normalized candidates.
sourceslist[Source]All sources used to discover the candidates.

Candidate:

FieldTypeDescription
idstringStable candidate ID (UUID prefix).
namestringDisplay name.
aliaseslist[string]Alternative names found.
categorystringCandidate category (e.g., hotel, restaurant).
source_idslist[string]The Source.id values that produced this candidate.
metadataobjectFree-form metadata (depends on category).
confidencefloatConfidence score from 0.0 to 1.0.

reviews.json

Aggregated reviews. Produced by F2.

FieldTypeDescription
mission_idstringBack-reference.
created_atdatetime (UTC)When the summary was finalized.
summarieslist[ReviewSummary]One summary per candidate.
partialboolWhether any reviews were missing.

ReviewSummary:

FieldTypeDescription
candidate_idstringBack-reference to the candidate.
total_reviewsintegerNumber of reviews aggregated.
average_ratingfloat | nullAverage rating on the original scale.
sentimentobjectSentiment distribution (positive, neutral, negative).
topicslist[object]Topic aggregates (topic, count, sentiment).
sourceslist[Source]Sources used for the summary.

prices.json

Price series. Produced by F4.

FieldTypeDescription
mission_idstringBack-reference.
created_atdatetime (UTC)When the series was finalized.
currencystringISO-style currency code.
serieslist[PriceSeries]One series per candidate.
partialboolWhether any prices were missing.

PriceSeries:

FieldTypeDescription
candidate_idstringBack-reference.
snapshotslist[PriceSnapshot]Time-stamped price observations.
minfloat | nullMinimum observed price.
maxfloat | nullMaximum observed price.
medianfloat | nullMedian price.
trendstringup, down, flat, or unknown.
sourceslist[Source]Sources used for the series.

youtube_search.json

YouTube search hits. Produced by Y1.

FieldTypeDescription
mission_idstringBack-reference.
created_atdatetime (UTC)When the search ran.
resultslist[object]One record per video found.
partialboolWhether any searches failed.

Each result has: candidate_id, video_id, title, channel, url, published_at, duration_s, view_count, relevance_score.

transcripts.json

YouTube transcripts. Produced by Y2.

FieldTypeDescription
mission_idstringBack-reference.
created_atdatetime (UTC)When the extraction ran.
transcriptslist[Transcript]One transcript per video.
partialboolWhether any extractions failed.

Transcript:

FieldTypeDescription
video_idstringYouTube video ID.
urlstringVideo URL.
languagestringTranscript language.
chunkslist[TranscriptChunk]Time-stamped chunks.
full_textstringConcatenated plain text.
sourcestringyoutube_transcript_api or yt_dlp.

synthesis.json (optional)

Narrative summaries. Produced by P3 (Perplexity).

FieldTypeDescription
mission_idstringBack-reference.
created_atdatetime (UTC)When the synthesis ran.
summarieslist[object]One narrative per top candidate.
tokens_usedintegerTotal tokens consumed by Perplexity.

Each summary has: candidate_id, summary (narrative text), highlights (list of strings), caveats (list of strings).

report.md

The final aggregated report. Produced by F6. Not typed (markdown is intentionally flexible), but it has a stable structure documented in Mission DAG → F6.

phase.json

The mission state. Written by the orchestrator after every phase. Documented in Mission Lifecycle → Checkpointing.

Validation

All artifacts are validated on write. The ArtifactStore calls the schema's model_validate (Pydantic v2) and rejects invalid payloads. A failed validation:

  1. Marks the current phase as failed_terminal.
  2. Writes the validation error to the state.
  3. Halts the mission.

The Coordinator surfaces the error to the user. The user can either:

  • Fix the data and retry.
  • Skip the phase (if allow_partial is true) and continue.
  • Cancel the mission.

Reproducibility

A mission is reproducible if and only if:

  • The same task.json is used as the input.
  • All adapter responses are deterministic for the same query at the same time (true for DuckDuckGo, approximately true for Tavily and Google, false for Perplexity).

The framework does not guarantee reproducibility, but the audit trail makes it possible to detect divergence and investigate.

See also

On this page