Guide
Recording from your own code
When the drop-in collector cannot see what your agent does, or you want precise control over what is recorded, emit events yourself with the SDK. Same wire protocol, same signed record, same bodies-off contract.
Install
npm install @adastracomputing/aer-sdk-ts
Record a run
import { createAerClient } from '@adastracomputing/aer-sdk-ts';
// Session ids and the ingest token come from POST /v1/sessions
// (tenant API key), or from your orchestrator.
const client = createAerClient({
baseUrl: 'https://api.aer.run',
sessionId: sess.agent_session_id,
ingestToken: sess.ingest_token,
});
await client.emit('tool.started', { tool: 'web_search' });
await client.emit('tool.completed', { tool: 'web_search', ok: true });
await client.emit('llm.completed', {
model: 'claude-sonnet-4-5', input_tokens: 812, output_tokens: 102, ok: true,
});
const result = await client.complete();
// result.aer_id, result.canonical_hash, result.signing_key_idEvents buffer in memory and post in batches (500 ms flush by default; size-triggered when a batch fills). Server errors retry with exponential backoff; client errors fail fast and the batch requeues for the next flush, so a transient outage never silently drops events. complete() flushes everything and seals the signed record. abort() is the crash path: the session terminates and no record is generated.
What to emit
The full event taxonomy with required and common fields is documented at aer.run/events. The rule for every payload: metadata only. Model names, token counts, tool names, hosts and paths belong in a record; prompts, completions, tool arguments and response bodies never do. The server enforces this at ingest: unknown payload keys are stripped before storage (the response reports aggregate counts when that happens) and out-of-bounds values reject the event.
Severity hints
await client.emit('guardrail.triggered', { rule: 'egress-denied' }, { severity_hint: 'high' });severity_hint (info, low, medium, high, critical) feeds the findings pipeline and the console feeds; it never changes what is captured.
Sessions from scratch
POST /v1/sessions (tenant API key)
→ { agent_session_id, ingest_token }
# then emit events with the ingest token and complete when doneThe ingest token is scoped to one session and expires with it; your tenant API key never needs to reach the agent process. A Python SDK with the same contract is in beta; Go and Rust follow once the wire protocol stabilises past v1, and any language can speak the raw HTTP API today (see the API reference).