# Using Artifacts with Environments (https://www.agentenvframework.com/docs/artifacts/with-environments)

> Manage the state of your env using artifacts, capture the state of your env into artifacts

1. `acme-email` is for environments named `email`, and so is the server: they match.
2. The artifact’s file is copied into the server’s container, at `/data/emails.json`.
3. `data/reset` empties the inbox, including the email you added by hand.
4. `data/add` passes the file’s path, and `@add_data` reads three emails from it.
5. `data/get` reads the inbox back: the three emails of `acme-email` version 2.
6. `acme-contacts` is for servers named `contacts`, so the `email` instance refuses it.

Parts of the scene:

- **The environment artifact**: `acme-email` version 2, for environments named `email`. `agent-env env mcp-server load-environment-artifact` loads the latest version, and a `load_artifact` step can pin one.
- **Its file**: Version 2 of `acme-email-file`, which the environment artifact pins: the `emails.json` you put.
- **The name check**: Before it copies anything, the framework compares the artifact’s environment name with the server’s. The name is the one on the card, not the env id, so any server named `email` passes.
- **The framework**: Runs the load, from `agent-env env mcp-server load-environment-artifact` or from a `load_artifact` step in a task. It copies the file, then calls the data plane, `/agentenv`.
- **The instance**: `email-mmtflq6t`, from Deploying your environment. A load changes the instance’s data and never the env: `email` stays at version 1.
- **The gateway**: Forwards the data plane to your server while it fronts one server. In a `multi` env, each server’s data plane has a path of its own.
- **Your server**: `EmailEnv`. For a file part, its `@add_data` method opens the path in the part’s `uri` and extends the inbox and the sent folder from the file’s `inbox` and `sent` lists.
- **/data**: Where the framework puts an artifact’s file in the server’s container, under the file’s own name. The server reads it from there during `data/add`.
- **A name that differs**: Loading `acme-contacts` into the `email` instance stops with `Error: EnvironmentArtifact environment_name 'contacts' does not match env environment_name 'email'`, and the inbox keeps its data.

An env starts without data on every deploy. Loading artifacts into an env is how you manage its
state. This page loads the artifacts from [Creating your artifacts](https://www.agentenvframework.com/docs/artifacts/creating.md) into
the instances from [Environments](https://www.agentenvframework.com/docs/environments.md): `acme-email` into the `email` instance, and
the universe `acme` into `office`.

## Load an artifact into an instance

`email-mmtflq6t`, the instance from
[Deploying your environment](https://www.agentenvframework.com/docs/environments/deploying.md#deploy-it), still holds the email you
added by hand. This command loads `acme-email` into it:

```bash title="Terminal"
agent-env env mcp-server load-environment-artifact --instance-id email-mmtflq6t \
  --environment-artifact-id acme-email
```

```text title="Output"
Found env: id=email version=1 environment_name=email
Fetching environment artifact: id=acme-email...
Found environment artifact: id=acme-email version=2 environment_name=email
Loading environment artifact...
Loaded environment artifact into env
```

The load copies the artifact's file into your server's container at `/data/emails.json`, calls
`data/reset` to empty the inbox, then calls `data/add` with the file's path. `EmailEnv`'s
[`@add_data` method](https://www.agentenvframework.com/docs/environments/creating.md#the-data-plane) reads the inbox and sent folder
from that file.

`data/get` reads the state back: the three emails of version 2, without the email you added by
hand:

```bash title="Terminal"
curl -sS http://localhost:61655/agentenv -H 'content-type: application/json' \
  -d '{"jsonrpc": "2.0", "id": 2, "method": "data/get"}' | python3 -m json.tool --indent 2
```

```text title="Output (trimmed)"
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "parts": [
      {
        "kind": "data",
        "data": {
          "inbox": [
            {"from": "dana@example.com", "subject": "Q3 numbers", ...},
            {"from": "priya@example.com", "subject": "Offsite", ...},
            {"from": "sam.lee@example.com", "subject": "Re: Q3 numbers", ...}
          ],
          "sent": []
        }
      }
    ]
  }
}
```

Each load replaces the instance's data, and the env itself stays at version 1. The command loads
the latest version of the artifact; [a task](#in-a-task) can pin one.

## The name must match

The framework loads an environment artifact only into a server with the same environment name.
Loading `acme-contacts` into the `email` instance stops before it copies anything:

```text title="Output (end)"
Loading environment artifact...
Error: EnvironmentArtifact environment_name 'contacts' does not match env environment_name 'email'
```

The name is all it checks, so any server named `email` takes `acme-email`, whatever its env id or
[topology](https://www.agentenvframework.com/docs/environments/topology.md#the-server-topology). That includes a website env, such as a
webmail app that computer-use agents work in a browser, loaded with
`agent-env env website load-environment-artifact`.

## Load a universe into a composed env

A universe loads into a `multi` env in one command. This one loads `acme` into `office-jk24hzlq`,
the instance from [Composing environments](https://www.agentenvframework.com/docs/environments/composing.md#compose-the-two):

```bash title="Terminal"
agent-env env multi load-environment-universe-artifact --env-instance-id office-jk24hzlq \
  --environment-universe-artifact-id acme
```

```text title="Output (trimmed)"
Instance: office-jk24hzlq (env=office v1)
Fetching environment universe artifact: id=acme...
Found environment universe artifact: id=acme version=2
Loading environment universe artifact...
[1/2] ✓ email loaded in 0s
[2/2] ✓ contacts loaded in 0s
Successfully loaded all environment artifacts into env
```

Each artifact goes to the child server with its environment name, and the children load in
parallel. An artifact whose name no child has is skipped with a warning, so one universe fits envs
that hold only some of its servers.

## In a task

A task loads data with a `load_artifact` step. With `env_id`, it loads an environment artifact or
a universe into the instance that an earlier `deploy_env` step started:

```json title="task.json"
[
  {"id": "deploy", "type": "deploy_env", "env_id": "office", "env_version": 1},
  {
    "id": "seed",
    "type": "load_artifact",
    "env_id": "office",
    "artifact_id": "acme",
    "artifact_version": 1,
    "depends_on": [{"task_step_id": "deploy"}]
  }
]
```

Pinned to version 1, this task loads the two-email inbox on every run, even after `acme` version 2
exists. Without `artifact_version`, each run loads the latest version.

> [!WARNING]
> **A step without a version follows the latest artifact**
>
> A put between two runs changes what the next run loads, without a new task version. Pin
> `artifact_version` when runs must be comparable, as you
> [pin `env_version`](https://www.agentenvframework.com/docs/tasks/important-steps.md#deploy_env).