Skip to main content
Core reports what hosted Runtimes and sandbox nodes consume through read-only administrator routes under /core/v1: current Runtime observations, the stored Runtime history of one Session, and the host observations and history of a sandbox node. Reads never create, wake, renew or change compute and never add samples to history. Runtime observability defines how Core collects and keeps these values; Console API usage lists the Web pages that read them. Every route requires the Core key as the bearer credential; a missing or invalid key returns 401 invalid_admin_key. A Project ID in a path selects the target Project and does not authenticate. Responses carry Cache-Control: no-store, use the Core error envelope and never contain provider responses, native identifiers, paths or credentials.

Current Runtime observations

List observations of every Project

The list has one row for every Session of every Project that is not deleted, including none, self_hosted and released managed Sessions. Each row carries the owning project_id and an observation: the RuntimeObservation plus disk. Pages use the Session list’s creation-time and ID keyset. The observation ID is the Session ID, so page boundaries do not move when the Runtime behind a Session changes. A page is not an atomic snapshot: each row has its own resolved_at and, when sampled, observed_at. Unknown query keys are ignored.

Retrieve one Session’s observation

This returns one RuntimeObservation, without disk. It accepts no query parameters. An environment:none Session returns 200 with status unsupported.

RuntimeObservation

lifecycle_state comes from Core’s allocation records, never from the sample:

RuntimeInstance

cpu

All fields are finite nonnegative numbers or null. Zero is an observed zero; null is unavailable.

memory

usage_bytes and limit_bytes are safe JSON integers or null. Zero usage is observed zero; limit_bytes is at least 1, and an unknown or unlimited limit is null.

disk

Only list rows carry disk: null, or {usage_bytes, limit_bytes} with the rules of memory. E2B fills it when the sandbox reports both its disk usage and a nonzero capacity. Docker and microsandbox return null. A non-null disk appears only on an observed row.

Status and reason

An ownership mismatch, malformed durable identity or invalid provider evidence fails the request instead of becoming an unavailable row. The generated core.openapi.yaml records each field’s type, nullability and enum but cannot express which combinations of status, mode and fields are valid; this table and the field rules above are normative.

Errors

Client

packages/agents-client exposes AdminClient.listRuntimeObservations({after, limit, order}) and AdminClient.retrieveRuntimeObservation(projectId, sessionId, options). RuntimeObservation in src/types.ts is a union discriminated by status and mode; AdminRuntimeObservation adds disk. The client checks every field, enum, nullability rule, timestamp and number and rejects unknown fields. A malformed observation rejects with a 502 invalid_runtime_observation error and a malformed page with invalid_admin_response; one bad row rejects the whole page.

Session Runtime history

Each parameter may appear once. Core chooses the bucket width: the range divided by max_points, rounded up to whole seconds, and at least 30 seconds or the sampling interval, whichever is longer. Buckets start at start; the last one ends at end. Core resolves the Project, then the Session and its Environment, before it reads storage; allocation and provider identities are results, never query inputs. History exists only for openai_hosted Sessions.
source is always durable. resolution_seconds is the bucket width and generated_at the read time. Only buckets that hold at least one sample appear in coverage.buckets, series[].points and token_usage; a gap stays a gap, never a zero.

Coverage

coverage counts every stored sample of the Session in the range, including unavailable ones that belong to no allocation. retained_start is the later of start and seven days before generated_at. expected_sample_count is the number of sampling intervals between retained_start and end, rounded up. Each bucket has start, end, first_observed_at, last_observed_at, observation_count, observed_count and unavailable_count.

Series

There is one series per managed allocation, keyed by allocation_id, so a provider that pauses, restores or replaces compute under the same allocation keeps one series. environment_id and provider_type identify its source. started_at is the earliest retained start of the allocation’s compute, as JSON-safe {seconds, nanoseconds} with nanoseconds 0 to 999,999,999; it is not a per-bucket start, and compute uptime comes only from current observations. Each point has the bucket bounds, the coverage counts of the allocation’s samples, and nullable cpu and memory objects with a contributor_count of at least 1:
  • cpu.utilization_ratio comes from consecutive cumulative CPU counters of one compute incarnation: the CPU seconds consumed divided by the elapsed time multiplied by the capacity, over the intervals that end in the bucket. The baseline resets when the incarnation changes or a counter decreases. E2B reports no cumulative CPU time; its bucket value is the mean of the ratios sampled in it. cpu.capacity_cores is the last capacity in the bucket.
  • memory.usage_bytes and memory.limit_bytes are the last values observed in the bucket.
Disk is not kept in history.

Token usage

token_usage belongs to the Session, not to an allocation. Each point holds the last cumulative measured Session usage sampled in its bucket: start, end, sampled_at, input_tokens and output_tokens. Measured Session usage is a Core extension that sums every recorded root Turn snapshot, active Turns included. It differs from public Session usage, which is null while a root Turn runs or after one ends unmeasured. These counters are measured model tokens, not prices or billing records.

Errors and bounds

A response holds at most max_points buckets per array, 64 series and 10,000 coverage and series points in total. Storage error text is neither returned nor logged.

Client

AdminClient.retrieveRuntimeHistory(projectId, sessionId, {start, end, maxPoints, signal}) validates the query before sending it. It then checks the exact fields, the echoed range and Session, bucket order within the range, coverage totals, allocation identity, contributor counts, token usage order, nullability, numbers and response size. Any violation rejects the whole response with a 502 invalid_admin_response error.

Node host observations and history

range is 1h (the default), 6h or 24h. Another parameter, a repeated or invalid range, or a malformed node ID returns 400 invalid_request; a missing or removed node returns 404 not_found_error. The response is the node object of the node list plus host and history:
host is the node’s last received heartbeat observation; every unavailable value, including an unobserved observed_at, is null. An offline node keeps its last values and their original time, so judge freshness by the node’s online and host.observed_at.
  • cpu_utilization is the share of busy ticks in the host’s aggregate /proc/stat counters between two heartbeats, 0 to 1. Idle and I/O-wait ticks are not busy, and guest time is not counted twice. The first heartbeat of a connection, a counter reset and an unreadable baseline give null. It measures the whole visible host, not the node process or its sandboxes.
  • effective_cpu_cores accounts for the node process’s CPU affinity and cgroup limits; null when those cannot be established.
  • total_memory_bytes and available_memory_bytes are MemTotal and MemAvailable.
  • available_disk_bytes is the free space of the node’s state filesystem, not a sandbox quota.
The node measures what its namespaces can see, so run it on the host it reports on. history covers the range in complete UTC buckets: 60 seconds for 1h, 300 for 6h and 900 for 24h. Every bucket of the range is present, and the bucket in progress is left out. cpu_utilization_max and memory_used_bytes_max are the maxima of the recorded observations, where used memory is total minus available memory of the same observation; available_disk_bytes_min is the minimum. Each metric is null for a bucket without a recorded value, including offline periods. Core never interpolates or backfills. SandboxAdminClient.retrieveNode(nodeId, range, options) in packages/agents-client reads this route and validates the response.