# Tags and metadata

Say what each sandbox is for, and find the ones of one run, one team or one branch.

A sandbox can have tags, words such as `run-7f3a` or `team-infra`, and metadata, keys with a value each, such as `repo: honzabit/agental`. A [template](https://agental.io/docs/templates) can have them too, and every sandbox on it has the template's as well as its own.

- A tag is lowercase letters, digits and hyphens, 1 to 63 characters, not starting or ending with a hyphen. One sent in capitals is kept in lowercase. A sandbox or a template has 30 of its own at most.
- A metadata key is lowercase letters, digits, `_`, `.` and `-`, 1 to 40 characters, starting with a letter or a digit. Keys starting `agental.` are kept for agental. A value is up to 500 characters. 50 keys of its own at most.
- A sandbox shows its template's tags and its own as `tags`, and its template's metadata with its own over it as `metadata`. A key it sets itself wins over its template's. `ownTags` and `ownMetadata` are its own alone.
- A change to a template's reaches every sandbox on it at once, running or not. A sandbox put on another template has that template's from then on.
- A fork has its source's own, as they were. A sandbox made from a snapshot has only what its create and its template give it.

> **Warning:** Tags and metadata are not for secrets. They are shown in the console, sent in [webhooks](https://agental.io/docs/webhooks) and read by every key that reaches the sandbox. A token or a password goes in the template's or the sandbox's [secrets](https://agental.io/docs/templates).

## Give them as it is made

`POST /v1/sandboxes`

```shell
curl -X POST https://agental.io/v1/sandboxes \
  -H "Authorization: Bearer $AGENTAL_API_KEY" \
  -H "Idempotency-Key: run-7f3a-a" \
  -H "Content-Type: application/json" \
  -d '{"name":"parallel-a","tags":["run-7f3a","branch-auth"],"metadata":{"repo":"honzabit/agental","branch":"claude/auth-refresh"}}'
```

`POST /v1/templates` takes `tags` and `metadata` the same way, for every sandbox made from it.

## Find the sandboxes with a tag

`GET /v1/sandboxes`

```shell
curl -X GET "https://agental.io/v1/sandboxes?tag=run-7f3a&metadata[repo]=honzabit/agental" \
  -H "Authorization: Bearer $AGENTAL_API_KEY"
```

- `tag` can be sent more than once, and a sandbox is listed when it has every one: `?tag=run-7f3a&tag=claude`.
- `metadata[key]=value` lists the ones with that value for that key, for each key sent.
- A sandbox's template's tags and metadata count as its own here.

## Change them

`PUT /v1/sandboxes/{id}/tags/{tag}`

```shell
curl -X PUT https://agental.io/v1/sandboxes/{id}/tags/reviewed \
  -H "Authorization: Bearer $AGENTAL_API_KEY"
```

`PATCH /v1/sandboxes/{id}`

```shell
curl -X PATCH https://agental.io/v1/sandboxes/{id} \
  -H "Authorization: Bearer $AGENTAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"metadata":{"branch":"claude/auth-refresh-2","reviewer":null}}'
```

- `PUT …/tags/{tag}` adds one tag and `DELETE` takes it away, leaving the others as they are, so two agents tagging one sandbox at once do not undo each other.
- `PATCH` with `tags` puts them in place of its own. With `metadata` it merges them in: a key with a value is set, a key with `null` is taken away, and the keys not named are left.
- A template's are changed the same way, at `/v1/templates/{id}/tags/{tag}` and `PATCH /v1/templates/{id}`. Its template's tags are taken off a sandbox only on the template.
- A key needs `sandbox.update` to change a sandbox's, and `template.write` to change a template's.

## From the CLI

```shell
agental create --name parallel-a --tag run-7f3a,branch-auth --meta repo=honzabit/agental
agental list --tag run-7f3a
agental tags sbx_2a9a47e50daec64a add reviewed
agental meta sbx_2a9a47e50daec64a set branch=claude/auth-refresh-2
agental meta sbx_2a9a47e50daec64a unset reviewer
agental template tags claude-code add claude
```

`agental tags <sandbox-id>` and `agental meta <sandbox-id>` with nothing after them show what it has, its template's marked. In the console, a sandbox's and a template's are in their Tags view, and a tag in the Sandboxes list is a link to the sandboxes that have it. Every [lifecycle event](https://agental.io/docs/webhooks) carries the sandbox's `tags` and `metadata` as they were when it was written, and a change to a sandbox's own is the event `sandbox.labels_changed`; a change to a template's is one `template.labels_changed`, saying what was added and taken away, and its sandboxes are sent nothing.

| Answer | Why |
| --- | --- |
| `400 invalid_tag` | A tag is not one. Nothing was changed. |
| `400 invalid_metadata` | A key is not one, starts `agental.`, or its value is over 500 characters. Nothing was changed. |
| `400 too_many_tags` | It would have more than 30 tags of its own. |
| `400 too_many_metadata_keys` | It would have more than 50 keys of its own. |

---

Every page of these docs as Markdown: [llms.txt](https://agental.io/llms.txt)
