# Creating your artifacts (https://www.agentenvframework.com/docs/artifacts/creating)

> Put files as file artifacts and environment artifacts, bundle them into a universe, and put new versions

This page stores Acme's data as artifacts: the Q3 numbers as file artifacts, and the inbox and
contacts book as environment artifacts for the `email` and `contacts` envs.

## File artifacts

A file artifact is one file, of any type, stored and versioned. From the command line you put a
folder at once: each file becomes a file artifact, and a file artifact universe bundles them under
their names. The Q3 numbers, and a note on what they leave out, are one folder:

```bash title="Terminal"
agent-env artifact file-artifact-universe put-bundled --id q3-workpapers \
  --file-dir q3
```

```text title="Output (trimmed)"
Uploading 2 file(s)...
  notes.md
  q3-numbers.csv
Created FileArtifactUniverse: id=q3-workpapers version=1 file_count=2 bundle_s3_url=…
```

A file artifact names no environment, so it goes wherever a step sends it, such as into an agent's
container. Any number of agents can load the same `q3-workpapers`, and each step pins the version
it loads. [Using Artifacts with Agents](https://www.agentenvframework.com/docs/artifacts/with-agents.md) loads it.

1. The Q3 numbers and a note on what they leave out: two files in one folder.
2. `put-bundled` stores each file as a file artifact and bundles them as `q3-workpapers`.
3. A `load_artifact` step copies the files into `assistant`, at `/tmp/file_artifacts`.
4. The same `q3-workpapers` goes into `analyst`, at a path of its own, and into `judge`.
5. Put the folder again: version 2. `assistant` loads it; `analyst` and `judge` stay on 1.

Parts of the scene:

- **The folder**: `q3/` holds `q3-numbers.csv` and `notes.md`. A file artifact can be any file: a spreadsheet, a PDF, an image, a script.
- **q3-workpapers**: What `agent-env artifact file-artifact-universe put-bundled --id q3-workpapers --file-dir q3` stores: one file artifact per file, bundled under the file names. Putting the folder again stores version 2, and version 1 never changes.
- **File artifacts**: Each file in the folder is a file artifact of its own, and the bundle pins a version of each. A new put makes a new version of every file in it.
- **assistant**: An agent that answers Dana’s email. A `load_artifact` step with `agent_name` set to `assistant` copies the files into its container, at `/tmp/file_artifacts`.
- **analyst**: Another agent, which writes the Q3 report. Its step sets `destination_path` to `/workspace/q3`, so the same files land there instead.
- **judge**: An agent that grades a run. It gets the same files, to check the numbers in what the other agents wrote.
- **The version each agent got**: Each step pins the version it loads with `artifact_version`. After version 2 exists, a step that pins version 1 still copies the old files.

## Environment artifacts

An environment artifact is a file artifact together with the name of the environment it targets.
Acme's inbox is a file in the format `EmailEnv` reads through `data/add`:

```json title="acme/emails.json"
{
  "inbox": [
    {"from": "dana@example.com", "subject": "Q3 numbers",
     "body": "Can you send the Q3 numbers to Sam Lee in finance by Friday?"},
    {"from": "priya@example.com", "subject": "Offsite",
     "body": "The offsite moves to Thursday. Can you let Marcus know?"}
  ]
}
```

This command puts it for environments named `email`:

```bash title="Terminal"
agent-env artifact environment put --id acme-email --environment-name email \
  --description "Acme inbox" acme/emails.json
```

```text title="Output"
Creating FileArtifact...
Created FileArtifact: id=acme-email-file version=1 filename=emails.json
Creating EnvironmentArtifact...
Created EnvironmentArtifact: id=acme-email version=1 environment_name=email
  pinned FileArtifact: acme-email-file:1
```

The command puts the file as the file artifact `acme-email-file`, then the environment artifact
`acme-email`, which pins it. `--environment-name` is the name on an environment's
[card](https://www.agentenvframework.com/docs/environments/environment-card.md), not an env id, so every env with a server named
`email` can load `acme-email`.

The contacts book, `acme/contacts.json`, goes the same way, for environments named `contacts`:

```bash title="Terminal"
agent-env artifact environment put --id acme-contacts --environment-name contacts \
  --description "Acme contacts book" acme/contacts.json
```

## Universes

1. Acme’s inbox and contacts book, each a file in the format its server reads.
2. Each file becomes an environment artifact, named for the environment it targets.
3. `acme` bundles the two environment artifacts, each pinned to its version.
4. Loading `acme` into `office` gives each of its servers the artifact with its name.
5. In the single-server `email` env, the server takes `acme-email` and `acme-contacts` is skipped.
6. In `browser-office`, websites for computer-use agents take the same two artifacts.

Parts of the scene:

- **Acme’s files**: `emails.json` and `contacts.json`, each in the format its server reads through `data/add`.
- **Environment artifacts**: `agent-env artifact environment put` stores each file as a file artifact and names the environment it targets: `acme-email` for `email`, `acme-contacts` for `contacts`.
- **The universe**: `agent-env artifact environment-universe put --id acme` bundles the two, each pinned to the version that was latest at the put.
- **office**: The `multi` env from Composing environments, with an `email` server and a `contacts` server. One load of `acme` seeds both.
- **email**: The single-server env from Deploying your environment. A `load_artifact` step loads `acme` into it: the server takes `acme-email`, and the load skips `acme-contacts`.
- **browser-office**: A `multi` env of two websites, named `email` and `contacts`, that computer-use agents work in a browser. Each website loads the artifact with its name, as a server does.
- **A loaded server**: A load hands each server or website the artifact with its name, through its data plane: `data/reset`, then `data/add` with the file.
- **Skipped**: `email` has no `contacts` server, so `acme-contacts` has nowhere to go there. The same universe still fits.
- **The browser**: What a computer-use agent works the websites through. An env with websites deploys it next to them.

A universe bundles environment artifacts into one artifact, such as all of one company's data:

```bash title="Terminal"
agent-env artifact environment-universe put --id acme \
  --environment-artifact acme-email --environment-artifact acme-contacts
```

```text title="Output (end)"
Created EnvironmentUniverseArtifact: id=acme version=1 environment_artifacts=['acme-email:1', 'acme-contacts:1'] metadata=None
```

The universe pins the version of each artifact that was latest at the put. Loading `acme` gives
each server the artifact with its name, so one universe seeds envs of different shapes: both
servers in `office`, the one server in `email`, and websites that computer-use agents work in a
browser.

## New versions

Putting an id again adds a version and leaves the earlier ones unchanged. With Sam's reply added to
`acme/emails.json`, the same `environment put` stores version 2 of `acme-email`. `acme` still pins
version 1 until you put it again:

```text title="Output (end)"
Created EnvironmentUniverseArtifact: id=acme version=2 environment_artifacts=['acme-email:2', 'acme-contacts:1'] metadata=None
```

No env changes: `email`, `contacts` and `office` are still at version 1. To see what a universe
holds, `agent-env artifact environment-universe get --id acme --output-dir acme-out` downloads its
files, one folder per environment name.
[Using Artifacts with Environments](https://www.agentenvframework.com/docs/artifacts/with-environments.md) loads them.