# Metrics

See what a sandbox uses of its CPU, memory, disk and network.

Every running sandbox's CPU, memory, disk and network are read once a minute, from outside the virtual machine, and kept for 15 days. Nothing is installed in the sandbox and nothing is asked of it.

## One sandbox over time

`GET /v1/sandboxes/{id}/metrics`

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

- The answer has `points`, oldest first. Each is one reading of the sandbox. It also says the `since`, `until` and `stepSeconds` it went by.
- Without `since` and `until`, it is the last hour, a point a minute.
- `since` and `until` are ISO 8601 times, at most 15 days apart. `until` is never later than now.
- `stepSeconds` is the seconds between two points: `60` at the least, which is how often a sandbox is read. Leave it out to get a step that gives about 360 points, and is never under 60.
- An answer holds 1,500 points at most. A longer stretch needs a larger step.
- There is no point for a moment the sandbox was stopped at, and none from before it was made.

## What a reading holds

```json
{
  "at": "2026-10-14T16:00:00.000Z",
  "cpuUtilization": 0.42,
  "memoryUsedBytes": 1610612736,
  "memoryTotalBytes": 4294967296,
  "diskUsedBytes": 6442450944,
  "diskTotalBytes": 42949672960,
  "networkReceivedBytesPerSecond": 1000,
  "networkSentBytesPerSecond": 200,
  "diskReadBytesPerSecond": 0,
  "diskWrittenBytesPerSecond": 4096
}
```

| Figure | What it is |
| --- | --- |
| `cpuUtilization` | The share of the sandbox's CPUs' time that was not idle, from 0 to 1. `0.42` is 42%. |
| `memoryUsedBytes` | Memory in use, as the sandbox itself counts it: what it has less what is available. |
| `memoryTotalBytes` | The memory the sandbox has. |
| `diskUsedBytes` | What is in use of its root disk: its size less what is available. |
| `diskTotalBytes` | The size of its root disk. |
| `networkReceivedBytesPerSecond` `networkSentBytesPerSecond` | Bytes a second over its link to the world. Its loopback, and the interfaces Docker makes inside it, are not counted. |
| `diskReadBytesPerSecond` `diskWrittenBytesPerSecond` | Bytes a second read from its disk and written to it. |

- Any figure may be null, when the server did not have it then.
- CPU and the four rates are averages over the step, and over 4 minutes at the least. Each is worked out from two readings, so on a sandbox that has just started they come after its memory and disk.

## Every sandbox at one moment

`GET /v1/metrics`

```shell
curl -X GET https://agental.io/v1/metrics \
  -H "Authorization: Bearer $AGENTAL_API_KEY"
```

- The answer has each of your sandboxes, with its `sandboxId`, `name`, `size` and `reading`, which holds the figures above.
- `at` names the moment, as an ISO 8601 time at most 15 days ago. Without it, the moment is now.
- A sandbox that was stopped then has a null `reading`, and so has one that was started less than a minute before.

## How many were running

`GET /v1/metrics/running`

```shell
curl -X GET https://agental.io/v1/metrics/running \
  -H "Authorization: Bearer $AGENTAL_API_KEY"
```

- The answer has `points`, each with `at` and `running`: how many of your sandboxes were running at that step.
- Without `since` and `until`, it is the last 24 hours, a point every 5 minutes. The two can be up to 366 days apart.
- `stepSeconds` is `60` at the least here too, and an answer holds 1,500 points at most.
- It is counted from the record of what ran, which is what [usage](https://agental.io/docs/usage) and billing are counted from. No server is asked for it.
- A sandbox deleted since is still counted. Its readings are no longer given.

## When a server does not answer

- Readings are kept on the server a sandbox runs on. A sandbox that was moved has readings on each server it was on, and they are put together in one answer.
- When a server does not answer, its part is missing and the answer has `"complete": false`. What the others said is still given.
- With `GET /v1/metrics`, a sandbox on that server then has a null `reading`, though it was running.
- When not one server answers, the call answers `503 metrics_unreadable`. The sandboxes are as they were: ask again in a minute.

## In the console

- The Sandboxes page draws each sandbox as a machine, with its CPU, memory and disk as three bars and what its time came to in the last 24 hours. A line counts the sandboxes running over those 24 hours, and a slider moves the drawing back along it. The list has the readings as columns.
- A sandbox's page opens on its Command view, which shows its metrics first: the machine with its sizes measured, beside a chart of its readings over 1 hour to 15 days.

## Errors

| Answer | Meaning |
| --- | --- |
| `400 invalid_request` | The window or the step cannot be answered. `message` says why: `since` is not before `until`, the two are too far apart, `at` is in the future or more than 15 days ago, or `stepSeconds` is under 60 or gives more than 1,500 points. |
| `404 not_found` | No sandbox of yours has that id. The readings of a deleted sandbox are not given. |
| `503 metrics_unreadable` | Not one server answered for its readings. Nothing is wrong with the sandboxes. Ask again in a minute. |

---

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