# Collecting Artifacts from Deployed Agents and Environments (https://www.agentenvframework.com/docs/artifacts/collecting)

> Capture the state of deployed agents and envs as artifacts, for a judge to grade or for a later run to resume from

1. Artifacts you put seed a run: `acme` goes into the env instance, `q3-workpapers` into the agent.
2. The agent reads the inbox, works from the files and sends Sam the numbers. Both sides change.
3. Steps collect what changed as new artifacts, from the env instance and from the agent.
4. A judge loads the agent’s files and the env’s snapshot, and grades the run.
5. A new env instance loads the snapshot, and starts with the inbox and the sent email.
6. A new agent deploys from the agent’s snapshot, and carries on its conversation.

Parts of the scene:

- **Artifacts you put**: The universe `acme` and the file artifacts `q3-workpapers`, from Creating your artifacts. `load_artifact` steps load them before the agent starts.
- **The env instance**: An instance of `email`, seeded from `acme`. When the agent calls `send`, the email lands in `sent`, a state that no artifact holds yet.
- **The agent**: Loaded with `q3-workpapers` at `/tmp/file_artifacts`. It writes `q3-summary.md`, and its conversation is state of its own.
- **An env snapshot**: `snapshot_env` reads each server’s state through `data/get` and stores it as a new universe, `snapshot-email-3hpbbwj3`, with one environment artifact per server.
- **Collected files**: `collect_artifacts` stores the files the agent wrote as a file artifact universe named for the run, `q3-email-3hpbbwj3`.
- **An agent snapshot**: `snapshot_agent_state` asks the agent for its conversation, through its `urn:agentenv:snapshot/v1` extension, and stores it under the id you give the step, `assistant-state`. Snapshots move through signed URLs, so they need an object store that issues them, such as S3.
- **A judge**: `load_artifact` steps with `artifact_from_step_id` give the judge the collected files, and the env’s snapshot as files. `rubrics_verifier` then has it grade the run.
- **A resumed env instance**: A new instance of `email`. A `load_artifact` step loads `snapshot-email-3hpbbwj3` into it, and the server reads back the inbox and the sent email through `data/add`.
- **A resumed agent**: A `deploy_agent` step with `agent_snapshot_files_artifact_id` set to `assistant-state` loads the snapshot into a fresh agent, which carries on the conversation. The agent must advertise the snapshot extension.

[Built-in task steps](https://www.agentenvframework.com/docs/tasks/more-steps.md#capture) collect artifacts from deployed agents and envs:
`snapshot_env`, `collect_artifacts` and `snapshot_agent_state`. Other agents and envs can load what
they collect, which supports snapshot and resume workflows for both. This page adds them to the
task from [Using Artifacts with Agents](https://www.agentenvframework.com/docs/artifacts/with-agents.md), after a `prompt_agent` step has
the agent answer Dana and save what it sent:

```json title="task.json"
{"id": "ask", "type": "prompt_agent", "agent_name": "assistant", "prompt_id": "p1",
 "prompt": "Answer Dana's email with the Q3 numbers. Save what you sent as /app/artifact/q3-summary.md.",
 "depends_on": [{"task_step_id": "skills"}]}
```

## Snapshot an environment

A `snapshot_env` step reads each server's state through `data/get` and stores it as a new universe,
with one environment artifact per server:

```json title="task.json"
{"id": "snapshot", "type": "snapshot_env", "env_id": "email",
 "depends_on": [{"task_step_id": "ask"}]}
```

The universe is named for the env and the run, such as `snapshot-email-3hpbbwj3`, and the step
records its id and version under `metadata["env_snapshotted_universes"]["snapshot"]`. It holds the
inbox, and in `sent` the email the agent sent Sam.

## Resume an environment

A `load_artifact` step with `artifact_from_step_id` loads whatever the named step produced, so it
can restore the snapshot into a new instance of `email`:

```json title="task.json"
{"id": "resume-env", "type": "deploy_env", "env_id": "email", "env_version": 1,
 "depends_on": [{"task_step_id": "snapshot"}]},
{"id": "restore", "type": "load_artifact", "env_id": "email", "env_step_id": "resume-env",
 "artifact_from_step_id": "snapshot",
 "depends_on": [{"task_step_id": "resume-env"}]}
```

`env_step_id` picks the second deployment, since the task now deploys `email` twice. A later task
can load the same snapshot by its id and version, like any universe. A snapshot restores only what
your `@add_data` reads, which is why `EmailEnv` reads `sent` as well as `inbox`.

## Collect an agent's files

A `collect_artifacts` step reads the files an agent wrote and stores them as a new file artifact
universe. The `ask` prompt had the agent save what it sent as `q3-summary.md` in `/app/artifact`,
the directory the step reads by default:

```json title="task.json"
{"id": "collect", "type": "collect_artifacts", "agent_name": "assistant",
 "artifact_paths": ["q3-summary.md"],
 "depends_on": [{"task_step_id": "ask"}]}
```

## Grade with a judge

These steps give the collected files to a judge, a second agent that the `rubrics_verifier` step
asks to grade the run:

```json title="task.json"
{"id": "judge", "type": "deploy_agent", "a2a_agent_id": "my-judge", "agent_name": "judge",
 "depends_on": [{"task_step_id": "collect"}]},
{"id": "judge-files", "type": "load_artifact", "agent_name": "judge",
 "artifact_from_step_id": "collect",
 "depends_on": [{"task_step_id": "judge"}]},
{"id": "grade", "type": "rubrics_verifier", "agent_name": "judge", "prompt_id": "p1",
 "verifier_id": "q3-rubric",
 "criteria": [{"id": "c1", "criterion": "The email to Sam gives revenue, costs and margin for each region.", "weight": 1.0}],
 "depends_on": [{"task_step_id": "judge-files"}]}
```

`artifact_from_step_id` loads whatever `collect` produced, so the task does not need the new id in
advance. The verifier lists the judge's files in the prompt it grades with, and
[Important steps](https://www.agentenvframework.com/docs/tasks/important-steps.md#rubrics_verifier) covers verifiers.

## Snapshot and resume an agent

A `snapshot_agent_state` step stores an agent's conversation under the id you give it, and a
`deploy_agent` step with `agent_snapshot_files_artifact_id` starts a fresh agent from it:

```json title="task.json"
{"id": "agent-state", "type": "snapshot_agent_state", "agent_name": "assistant",
 "prompt_id": "p1", "artifact_id": "assistant-state",
 "depends_on": [{"task_step_id": "ask"}]},
{"id": "resume-agent", "type": "deploy_agent", "a2a_agent_id": "my-agent",
 "agent_name": "assistant-resumed", "agent_snapshot_files_artifact_id": "assistant-state",
 "depends_on": [{"task_step_id": "agent-state"}]}
```

`prompt_id` names the prompt whose conversation the step captures. The resumed agent carries on
from it, so a follow-up prompt can pick up where the first agent stopped.

> [!WARNING]
> **Agent snapshots need the snapshot extension**
>
> Both steps reach the agent through its `urn:agentenv:snapshot/v1`
> [extension](https://www.agentenvframework.com/docs/agents/extensions.md), so the agent must advertise it.