Core fields
Time
Events use a hybrid logical clock:Signals
Every event belongs to one signal — the family of thing it records. Two kinds of family land in the same stream:- Captured signals record what your workload did: what it ran, printed, and requested. They
flow for a command wrapped by
hiloop runand for supported boundaries in a sandbox’s managed capture session. - Platform signals record what the platform did around the workload: lifecycle, scheduling, network-policy decisions. They carry resource identities and state vocabulary — never command lines, bodies, or output — so they flow for every sandbox regardless of its capture setting.
llm and net — HTTP exchanges
Each HTTP exchange the workload makes becomes a pair of events — http.request then
http.response — sharing an http.exchange_id. Model-provider exchanges are the llm signal;
every other exchange is net. The shapes are identical:
Ordinary bodies are captured up to a size cap, scrubbed of recognized credential
patterns by default, and stored out of line under
payload_ref — fetch
them with hiloop events payload. A local hiloop run --no-redact
disables only that generic scan. Exact supported OAuth token exchanges are metadata-only instead.
Content type and content encoding are the only header values recorded; no other header —
Authorization, Cookie and the rest — is captured. http.target is ordinarily the full request
target, while exact OAuth omission also removes its query values. A harness OpenTelemetry span that
carries gen_ai.* or llm.* attributes also lands under llm (named by the span); span attributes
are stored as sent and are not scrubbed.
log — process output
One event per captured chunk of process output:
The harness’s own OpenTelemetry log records land under
log too, named by their log event name
(the severity text when unnamed), with the body under message.
Capture health. Capture is best-effort by design — it can never fail your workload — so it
reports its own completeness instead: as a captured run drains, one final capture.drain event
states whether everything captured actually landed. capture.complete is the verdict — true
only when every uploadable payload blob landed and no exported event was lost. Behind it:
capture.blobs.found / capture.blobs.landed / capture.blobs.missing /
capture.blobs.missing_bytes, with capture.blobs.oversize counting bodies over the upload cap
that stayed local; and capture.events.dropped / capture.events.rejected /
capture.events.pending when events were spooled through a gateway outage (pending records late
delivery, never loss — the record queues behind its own backlog, so its arrival certifies
everything spooled before it landed too). capture.error carries the failure when a drain went
wrong. A captured run with no capture.drain event at all ended without draining — treat its
capture as incomplete.
exec — command lifecycle
The lifecycle of the commands your workload ran, from two vantage points that share one signal.
A command wrapped by hiloop run records its own process boundary:
Every event one
hiloop run invocation captures — lifecycle, output, HTTP exchanges, and its
run-end capture-health record — also carries wrapper.invocation_id, a unique id minted per
invocation, so one wrapped process’s events stay correlated even when several wraps share a run.
A buffered sandbox execution is observed by the platform from the
host side, so the record exists even if the process never starts:
Every emitted
exec.start gets exactly one exec.end, so a failed execution never reads as
still-running. These events carry workload command lines, so they respect the sandbox’s capture
setting. The command’s environment (a secret carrier), stdin, and captured output are never
attached — output lives in execution artifacts and log events.
span — harness traces
If the wrapped agent emits its own OpenTelemetry spans, each span becomes one event named after the
span, with the trace identity under otel.trace_id, otel.span_id, and otel.parent_span_id
(promoted to the trace_id/span_id/parent_span_id columns). Spans
carrying gen_ai.*/llm.* attributes classify as llm instead.
metric — resource samples
hiloop run --sample-resources can emit best-effort resource.sample events roughly every 15
seconds for a local process tree. Authoritative runtime-owned resource accounting will use the same
event shape when it ships.
See usage metering for turning samples into utilization and cost answers.
egress — network policy decisions
The schema reserves egress events for future runtime-native destination-policy decisions. The
current fixed network floor emits none of the connection-level events below; the retired shared
proxy’s SNI audit stream is not a current product surface.
When a runtime-native producer ships, these events remain platform metadata and must never carry
credential values or request bodies.
runtime — platform lifecycle
What the platform did to a sandbox and when: state transitions and operation lifecycle with queue
latency. These are control-plane metadata with no workload content,
so they flow for every sandbox regardless of its capture setting. Emission is best-effort and
always follows the committed change, so telemetry can never affect an operation’s outcome.
Which run they land on. An operation’s events ride the run of the sandbox it targets, and an
execution’s ride the run of its owning sandbox. A resource with no run emits nothing.
Deliberate exclusions. Periodic reconciliation emits no
operation.* events — that would flood
every active run with platform noise; what surfaces is the drift a reconcile actually commits
(sandbox.state_changed with reason=reconcile, or sandbox.preempted). Background cleanup maps
to no run and emits nothing.
annotation — knowledge you write
Annotations are ordinary events: the name is the annotation schema
name, and your payload lives in the attributes (promoted fields become typed columns in the
schema-named ann_* view). They’re the write path for eval scores, verdicts, and any other
structured knowledge you attach to runs.
Correlation keys
Attributes that join events to each other and to resources:Promoted columns
The query engine promotes common network and tracing fields into typed columns — for examplehttp_status_code, http_host, trace_id, and span_id.
Use promoted columns when you filter or aggregate on them. Everything else an event carries lives
in attributes_json (reach in with hiloop_json_get), and model-shaped fields (model, token
counts, messages) derive from the captured payload bodies through a
data view like otel_genai_calls.
See the concept page for the full allowlist.