Artifacts and evidence
Artifacts are the files saved from a run. They are the evidence: they show what the Agent did, why it received its score, and exactly which setup produced the result.
An artifact is an output of a run. Don't confuse it with a Resource, which is an input, such as a word list the Environment provides.
Where to start
When you want to understand one attempt, read these in order:
- The trajectory, for the sequence of actions the Agent took.
- The final State, for what actually changed in the world.
- The Verifier results, for the score and the grader's feedback.
Two more files back those up. The receipt identifies the exact versions that were used. The manifest lists every captured file and its fingerprint (hash), so you can tell if anything changed afterwards.
plural trial show TRIAL_ID prints the paths of a Trial's artifacts and logs. For a recorded or hosted Job, you can open the same evidence in the web app under Jobs.
Local layout
A local plural run writes this folder at the project root:
.plural/jobs/JOB_ID/ run.json config.json lock.json events.jsonl result.json trials/TRIAL_ID/ selected.json result.json executions/0/ receipt.json result.json logs/ artifacts/ manifest.json episode.jsonl trajectory.json atif-trajectory.json result.json state.json apps.json observation.json view.json steps.jsonl states.jsonl rewards.jsonlOnly files actually produced or captured are present. Here is what the main ones hold:
run.jsonpins the version and content hash of every input, which is whatplural job rerunreuses.episode.jsonlis the episode record: every reset, step, and model call in order, with token usage and timing. With Apps, each step carries the App host's observation, rewards, and outcome rather than the Harness's; a step the host never ran is markedunverifiedand earns nothing.steps.jsonlis the App host's own record of every action it ran, andstates.jsonleach App's State after each step. They are what scoring, step rewards, andplural verifier try|applyread. A Harness can't write either: a file it returns under one of these names, or asrewards.jsonlorapps.json, is dropped.trajectory.jsonis the Agent's conversation as plain chat messages: each has aroleandcontent, plusreasoning_contentandtool_callson the model's turns. It is exactly what the model was sent, followed by its final reply, beside the episode'sstatus,time_elapsed, andfinalized. Every run gets one. When the Harness called no model, each step is written as a tool call and the observation it returned.atif-trajectory.jsonis the same episode as an ATIF document of the Agent's turns, with each call's tokens, cost, and timing.result.jsoninartifacts/is the Harness's final response.state.jsonis the final State: one App's, or a mapping from App name to State.apps.jsonhas each App's State at the start and the end, with its control level. It is what a Verifier reads asepisode.apps.observation.jsonis the last thing an action returned, andview.jsonis the final display view.rewards.jsonlis the reward ledger: one line per reward, each tied to the step, turn, or span it credits. See Training and RL.
A Harness that returns its own trajectory events also gets trajectory.jsonl, and anything else the Agent writes is captured beside them. Verifier scores and evidence are in the Trial's result.json, not in an artifact.
Evidence never changes
Execution receipts, logs, manifests, and artifact bytes are immutable. A retry adds a new executions/N/ folder; it does not overwrite the failed execution. A human review updates selected.json and the Trial and Job result.json summaries, and leaves the captured evidence unchanged.
The manifest records each artifact's path, SHA-256, media type, byte size, and optional role. Receipts bind those hashes to the exact Task, Benchmark, model endpoint, Environment, Verifiers, Agent, Harness, mode, Runtime, timing, and cost.
Episode scoring
The grader sees more than the Agent does. A Verifier function receives the completed Episode: each App's State, the last observation, the trajectory, artifacts, and usage. None of this reaches the Agent. A Verifier that runs a command receives every captured artifact in its scoring workspace. Isolate untrusted scoring code with its own VerifierRuntime.
Logs, secrets, and trust
Plural replaces the exact values of the credentials it injects, such as the secrets an Agent grants its Harness and the model API key a Verifier uses, in the stdout and stderr logs it captures. It matches exact values only, so it cannot catch a secret that code has encoded or transformed, and it does not redact custom artifacts, external systems, or anything else your code writes. State hidden from the Agent is not a secret store.
Receipts are unsigned, and a local run's receipt reports self_reported trust. Hashes detect content changes; they do not independently prove that a custom Harness recorded truthful behavior.
Import and derive
Use normalize_trajectory(...) to read a captured JSON or JSONL trajectory in a common format while keeping the original file. Imported evidence remains unverified; there is no general CLI command for importing arbitrary run directories.
Write analyses and exports as new derived files. Never edit a captured artifact and retain its old manifest or receipt.