Observability
Everything an agent does is already a typed stream of AgentEvents — text deltas, tool calls, results, permission decisions, background completions. Observability means tapping that stream: feed it to your UI live, and/or persist it to a durable, hash-chained JSONL audit log with jsonlEventSink / recordEventStream. No separate tracing SDK needed.
Record the event stream
Wrap any event stream with recordEventStream to tee every event into an EventSink while passing it through unchanged:
The same loop is how you drive a UI: each AgentEvent is typed (text_delta, tool_use, permission_decision, background_completed, …), so renderers can switch on ev.type.
jsonlEventSink
jsonlEventSink(opts) returns an EventSink that appends one JSON record per line:
Records form a hash chain — each record commits to its predecessor, so a tampered or reordered log is detectable. Writes are serialized, and durable by default (append + fsync per record).
Related types: EventSink (write(sessionId, event) / close()), EventRecord, JsonlEventSinkOptions.
Permission audit events
Turn on permissionAudit: true and the gate appends a redacted permission_decision event to the session event log for every decision — including who made it (policy / user / auto). Because the audit trail lives in the same event stream, recordEventStream captures it alongside everything else; combine with permissionMode: "dry-run" to record what a candidate policy would deny without blocking anything. See Permissions.
See also
- Permissions —
permissionAudit, dry-run, and redaction. - Checkpointing — the session event log itself.
- Background tasks — the
background_completedevent. - Core strategies — where the
AgentEventtypes come from.