You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add astrid-capsule-metrics — a first-party capsule that aggregates kernel and capsule telemetry into structured rollups, exposes them over IPC, and optionally publishes Prometheus/OpenTelemetry-shaped exports. The current visibility story is tracing to stderr, kernel logs, and astrid events tail (#685) — adequate for live debugging, terrible for "how is the host actually behaving over the last hour."
Why
Operators need rollups, not streams.astrid events tail shows what just happened; nobody wants to wc -l a tail to know how many tool calls succeeded today.
Capsule authors need cost visibility. LLM calls, HTTP egress, KV writes — capsule authors should be able to ask "how much did my capsule do" without each capsule rolling its own counters.
Approval and capability fatigue tracking. Deny rates per principal/action are a security signal. We have the data on the bus; nothing aggregates it.
Kernel-is-dumb compliance. Aggregation does not belong in the kernel. It belongs in a capsule that subscribes to the bus like any other consumer.
Scope
The capsule subscribes to standard topics on the event bus and maintains in-memory + persisted counters/histograms keyed by (metric, principal, capsule, outcome).
Metric families (initial):
astrid_tool_calls_total{capsule, tool, outcome} — every tool invocation
astrid_tool_call_duration_seconds{capsule, tool} — histogram per tool
Prometheus exposition — optional. Capsule binds a localhost listener (capability-gated, off by default) on configurable port and serves /metrics in standard exposition format. Off by default because exposing a local port is a capability decision, not a freebie.
OpenTelemetry push — optional, behind a config flag. Pushes OTLP-formatted metrics to a configured collector. For shops that already run an observability stack.
Hot window in-memory (configurable, default 24h, 1m resolution).
Cold storage in capsule-local KV. Default retention configurable, default 30 days at 5m resolution downsampled.
Both bounded — the capsule must never grow unbounded. Eviction is loud (logs warning if a cardinality budget is hit).
Capabilities required:
Subscribe to a curated set of astrid.v1.* and *.v1.* topics (read-only).
kv:put/kv:get for its own namespace.
net:listen:127.0.0.1:<port>only if Prometheus exposition is enabled.
No fs_write outside its capsule sandbox.
Why uniquely Astrid
Most metrics stacks are agent-side scrapes that bypass authorization. Here, the metrics capsule is itself a capability-restricted principal — it only sees topics it's allowed to subscribe to. Sensitive payloads (credentials, secrets-bearing topics) are aggregated by metadata only, never by value. This is consistent with the bus tail design notes in #685.
Out of scope
Distributed metrics — single-host only. Multi-host aggregation belongs to a downstream collector via OTLP.
Per-event log retention — that's the audit chain's job. Metrics is counters/histograms, not events.
Alerting rules — out-of-band; consumers can poll the IPC interface or scrape Prom.
Cost pricing tables for every model — start with a pluggable provider pricing config; we are not maintaining the world's pricing.
Design questions
Cardinality bounds. What's the max series count before we shed labels? Hard-code a default; configurable. Need a clear behaviour when a capsule misbehaves and emits high-cardinality tool names.
Summary
Add
astrid-capsule-metrics— a first-party capsule that aggregates kernel and capsule telemetry into structured rollups, exposes them over IPC, and optionally publishes Prometheus/OpenTelemetry-shaped exports. The current visibility story istracingto stderr, kernel logs, andastrid events tail(#685) — adequate for live debugging, terrible for "how is the host actually behaving over the last hour."Why
astrid events tailshows what just happened; nobody wants towc -la tail to know how many tool calls succeeded today.Scope
The capsule subscribes to standard topics on the event bus and maintains in-memory + persisted counters/histograms keyed by
(metric, principal, capsule, outcome).Metric families (initial):
astrid_tool_calls_total{capsule, tool, outcome}— every tool invocationastrid_tool_call_duration_seconds{capsule, tool}— histogram per toolastrid_llm_tokens_total{capsule, provider, model, direction}—direction∈ {input,output,cache_read,cache_write}astrid_llm_cost_usd_total{capsule, provider, model}— derived from provider pricing tables (config-driven, not hardcoded)astrid_http_egress_bytes_total{capsule, host}— outbound network volumeastrid_capability_decisions_total{principal, action, outcome}—outcome∈ {allow,deny}astrid_approval_prompts_total{principal, action, outcome}—outcome∈ {approve,deny,expire}astrid_kv_ops_total{capsule, op}—op∈ {get,put,delete}astrid_event_bus_publishes_total{topic, principal}— bus throughputastrid_kernel_uptime_seconds— gaugeSurfaces:
metrics.v1.query— request/response for{metric, filters, range, resolution}→ series. The primary consumer isastrid usage report(feat(cli): astrid usage report — aggregated per-agent telemetry rollup #687) and any future TUI dashboard./metricsin standard exposition format. Off by default because exposing a local port is a capability decision, not a freebie.Storage:
Capabilities required:
astrid.v1.*and*.v1.*topics (read-only).kv:put/kv:getfor its own namespace.net:listen:127.0.0.1:<port>only if Prometheus exposition is enabled.fs_writeoutside its capsule sandbox.Why uniquely Astrid
Most metrics stacks are agent-side scrapes that bypass authorization. Here, the metrics capsule is itself a capability-restricted principal — it only sees topics it's allowed to subscribe to. Sensitive payloads (credentials, secrets-bearing topics) are aggregated by metadata only, never by value. This is consistent with the bus tail design notes in #685.
Out of scope
Design questions
toolnames.Dependencies
Acceptance
astrid usage report --capsule <name> --range 24hreturns aggregated data without scraping logs.