Observability

Local observability stack

One-command OpenTelemetry + Loki + Tempo + Prometheus + Grafana stack, pre-wired to the DefenseClaw gateway. Grafana on :3000, dashboards seeded, no manual config.

defenseclaw setup local-observability brings up a full local OpenTelemetry stack and wires the gateway to it in one shot. It's what the project itself uses for development, demos, and rule-pack tuning.

Native Windows has a narrower optional-stack contract

Core DefenseClaw does not require Docker. The certified Windows local-stack path requires native x64 Windows Pro, Enterprise, or Education; Hyper-V; machine-installed Docker Desktop using Linux containers; Compose v2; and a real absolute docker.exe. WSL2/per-user Docker engines, Windows containers, and .cmd/.bat/shell shims are not certified. See Windows capabilities.

defenseclaw setup local-observability up — five containers come up, the gateway picks up the new OTLP endpoint, and Grafana dashboards populate live.

What it brings up

The stack runs from bundles/local_observability_stack/docker-compose.yml:

ServiceImage / roleDefault port
otel-collectorOpenTelemetry Collector — fans out to Prom/Loki/Tempo4317 (gRPC), 4318 (HTTP)
prometheusMetrics store9090
lokiLog store (gateway audit + sink failures)3100
tempoTrace store (per-decision spans)3200
grafanaUI with seeded DefenseClaw dashboards3000

All five run under one Compose project (defenseclaw-observability). They share a Docker network and the bundled Grafana datasources point at each container by service name.

Bring it up

Start the stack.

defenseclaw setup local-observability up

The openclaw-observability-bridge binary (shipped in bundles/local_observability_stack/bin/) drives Compose, waits for healthchecks, and writes one kind: otlp destination under observability.destinations in ~/.defenseclaw/config.yaml.

Open Grafana. http://localhost:3000 — anonymous viewer access is enabled by default for the demo dashboards. Follow your local stack's access policy before enabling edits; do not place credentials in terminal transcripts or support output.

Verify the destination handshake. Probe the named destination without adding the probe payload to ordinary event history or dashboard counts:

defenseclaw observability destination test local-observability

The default test is a non-mutating protocol handshake. Even the explicit --write-probe bypasses normal collection, routing, SQLite event history, and dashboard counts. The command does persist a separate bounded, local-only compliance record of the attempt and outcome. Use defenseclaw setup observability list first if you renamed the destination. Notifier webhooks use defenseclaw setup webhook test <name> instead.

Generate real traffic, then inspect the relevant dashboard. Run a DefenseClaw-managed agent turn, tool call, scan, or approval flow. Panels populate only for families that traffic actually emits; there is no fixed dashboard-population order.

up also refreshes the host-mounted stack copy in ~/.defenseclaw/observability-stack/ from the bundled version before Compose starts. That includes Grafana dashboards, Prometheus rules, Loki, Tempo, and OTel Collector config. Deleting Docker containers is not enough to update those files because they live on the host; pass --no-refresh-config only when you intentionally want to keep local edits.

Useful flags

The up subcommand exposes the bridge configuration directly:

defenseclaw setup local-observability up \
  --endpoint 127.0.0.1:4317 \
  --signals traces,metrics,logs \
  --service-name defenseclaw-gateway \
  --timeout 90
FlagWhat it does
--endpointOTLP endpoint the gateway writes into config.yaml. Defaults to whatever the bridge published (127.0.0.1:4317).
--signalsComma-separated subset of traces,metrics,logs. Omitting it selects all three, which is required for complete bundled-dashboard coverage.
--service-nameResource attribute set on every emitted span. Defaults to defenseclaw.
--no-configBring containers up but do not modify config.yaml. Useful when you manage gateway config out-of-band.
--refresh-config / --no-refresh-configRefresh bundled Grafana dashboards, Prometheus rules, Loki, Tempo, and OTel Collector config by default; opt out to preserve local edits.
--no-waitDon't block on healthchecks — fire-and-forget.
--timeoutSeconds to wait for healthchecks. Default 180.

The OTLP protocol is read from the bridge readiness contract (currently grpc); there is no --protocol flag on up. To use http/protobuf, configure that protocol on the named local-observability destination.

V7 compatibility flag

Older releases exposed --with-audit-sink/--no-audit-sink because logs and OTel signals used separate audit_sinks and otel blocks. Config v8 has one destination capable of logs, traces, and metrics, so new configuration does not need or write a second audit sink.

What ends up in config.yaml

The example below is the result of the sample up command using --service-name defenseclaw-gateway; without that flag, service.name is defenseclaw.

~/.defenseclaw/config.yaml (after the sample command)
config_version: 8
observability:
  resource:
    attributes:
      service.name: defenseclaw-gateway
  destinations:
    - name: local-observability
      kind: otlp
      endpoint: 127.0.0.1:4317
      protocol: grpc
      network_safety:
        allow_private_networks: true

Because send and routes are omitted, this OTLP destination receives all reviewed buckets and all three signals, unredacted. That is both the v8 capability default and the complete local-observability-v1 dashboard profile. If a destination with the same name already exists, the bridge updates it in place rather than adding a duplicate. Other telemetry destinations and notifier webhooks are left untouched.

Bundled Grafana dashboards

The bundle ships a full board set in bundles/local_observability_stack/grafana/dashboards/ — every *.json file here is auto-loaded:

defenseclaw-overview.json
defenseclaw-activity.json
defenseclaw-connectors.json
defenseclaw-connector-detail.json
defenseclaw-security.json
defenseclaw-policy-decisions.json
defenseclaw-hitl.json
defenseclaw-findings.json
defenseclaw-traffic.json
defenseclaw-scanners.json
defenseclaw-runtime.json
defenseclaw-agent-identity.json
defenseclaw-agent-360.json
defenseclaw-ai-discovery.json
Dashboard (UID)What it shows
Overview (defenseclaw-overview)KPI strip + firing alerts + SLO gauges; the landing board.
Agent Activity (Live) (defenseclaw-activity)Cross-agent prompts, models, tools, destinations, and session correlation.
Connectors / Hook Connectors (defenseclaw-connectors)Primary multi-connector view. Cross-connector compare: per-connector traffic, blocks, redactions, errors, hooks-vs-OTel drift. Filterable by the connector template variable.
Connector Detail (defenseclaw-connector-detail)Single-connector deep dive driven by $connector: identity, ingest, hooks, verdicts, judge, findings, HITL, scoped Loki streams.
Guardrail Evaluations / Security (defenseclaw-security)Verdict funnel by stage × action, severity breakdown, per-connector breakdown; connector-filterable.
Policy decisions (defenseclaw-policy-decisions)OPA verdicts by domain × verdict, egress branch, block-list hits.
HITL (defenseclaw-hitl)Chat HILT + exec approvals: approval/denial/timeout rates, pending gauge, MTTD.
Findings (defenseclaw-findings)Top rules, rule_id × time heatmap, finding-to-verdict correlation.
Proxy & LLM Guard (defenseclaw-traffic)HTTP surface latency/status, OTel ingest rates, trace samples.
Scanners (defenseclaw-scanners)Sparse-safe scan throughput and duration, errors by type, findings, and quarantine actions.
Runtime & Reliability (defenseclaw-runtime)Process, SQLite, v8 destination/exporter, queue, and canonical gateway-error health.
Agent identity (defenseclaw-agent-identity)Three-tier agent identity correlation, churn, discovery latency, per-connector header presence.
Agent360 (defenseclaw-agent-360)Automatic Agent Directory plus one-click per-agent/tree lifecycle, initial and grouped follow-up prompts, descendants, per-agent model/tool-family summaries, updates, approvals, outcomes, inputs/outputs, reported tokens/cost, security decisions, and Tempo waterfall.
AI Agent Usage & Detection (defenseclaw-ai-discovery)Continuous AI inventory loop: active signals, per-vendor/product tables, confidence.

See the complete Grafana dashboard catalog for the owner and purpose of every board, the drill-down map, backend usage, and the exact difference between 0, No data, and Not reported.

For a multi-connector gateway, start on Connectors (Overview) to compare connectors side by side, then click a connector cell to drill into Connector Detail.

Agent Directory and Agent360

Agent360 overview showing automatic agent discovery and per-agent lifecycle analytics

Open Agent identity → Runtime Agent Directory. Every hook lifecycle transition updates the stable defenseclaw.agent.last_seen inventory metric, so a newly observed root agent or subagent appears automatically. Click its Agent ID to open the reusable Agent360 dashboard; DefenseClaw does not create or provision a separate dashboard file for each agent.

Agent360 correlates the same stable fields across all three backends:

CorrelationPurpose
gen_ai.agent.idOne logical root or delegated agent.
defenseclaw.agent.root.id / parent.idFull descendant tree and direct parent relationship.
defenseclaw.agent.lifecycle.idDurable identity across gateway restarts and resumed sessions.
defenseclaw.agent.execution.idOne concrete execution attempt.
trace_idDirect pivot from a log/operation that actually reports W3C trace identity into the Tempo waterfall. Aggregate metrics do not fabricate trace IDs.

Use Scope = This agent for a single agent, or Agent tree to include all descendants. Prometheus supplies directory, state, throughput, latency, token, reported-cost totals, and directed phase aggregates. Loki supplies the prompt-to-outcome lifecycle DAG plus compact lifecycle/model/tool/network/security summaries with the full event available in log details. Session and durable lineage anchors may be recovered from the prior 24 hours so selected-range boundaries remain renderable; a recovered relationship edge is kept only when its child has graph-eligible activity in the selected range. Active typed parent_of and inverse delegated_by relationship records establish agent parentage; raw parent fields and trace topology do not. Repeated model work is grouped per owning agent, provider, and model. Repeated tools are grouped per owning agent as Bash, MCP, Skills, Collaboration, File edits, Web/browser, Visual, or Task control; an unrecognized tool keeps its reported name. Exact collaboration.send_message requests are excluded from generic Collaboration summaries so they appear only as message groups; other collaboration tools remain. Summary nodes show total requests and link to every exact raw canonical OTEL record, including their terminal counterparts. Stable agent nodes use agent/root/parent identity, name, type, depth, and connector; optional session fields stay in lifecycle/session/ordered/raw detail rather than splitting one agent's total. One per-root Prompt inputs node counts distinct depth-zero model.request facts, with replay-safe turn/model-request/request/operation/occurrence identity; Session start remains a separate lifecycle anchor. The ordered/raw views retain the individual initial and follow-up request records. For each sender, real collaboration updates to /root or /root/* collapse into one Messages to root node that resolves the exported root agent ID. Exact root task paths and calls remain in ordered/raw drill-downs; non-root targets remain exact groups without an invented target-agent mapping. Tempo supplies request-bounded waterfalls; it does not pretend an asynchronous lifetime is one trace. Select a row in Operation and enforcement traces to populate the waterfall. Token and cost panels only display values explicitly reported by the connector. Input tokens include the prompt/context usage reported by the provider and may be much larger than output for long-context agents. Missing values remain Not reported and are never estimated.

The local stack performs no additional redaction, masking, or field hiding. DefenseClaw applies the selected v8 profile centrally before canonical OTEL export. Grafana displays or links every field that Loki or Tempo actually receives, including content when the producer supplies it; fields removed or transformed before export are not recoverable in a dashboard.

See the Agent360 dashboard guide for a visual tour of every section, the prompt-to-agent lifecycle DAG, trace drill-down, and the difference between 0, No data, and Not reported.

They're auto-provisioned via bundles/local_observability_stack/grafana/provisioning/. The folder is named "DefenseClaw" inside Grafana so they're easy to find. Edits you make in the UI are not persisted back to disk by default — copy them out with Dashboard → JSON Model if you want to keep them.

Managed AI Defense fail-open monitoring

Managed-enterprise mode deliberately allows a request when the authoritative AI Defense inspection cannot return a verdict. DefenseClaw exposes every such decision through the generated OpenTelemetry counter defenseclaw.managed_aid.fail_open.decisions (int64, unit {decision}, delta temporality). The counter has one bounded defenseclaw.metric.reason attribute; the local-observability projection exports it as the Prometheus reason label on defenseclaw_managed_aid_fail_open_decisions_total.

reasonMeaningPaging treatment
inspector_unwiredThe gateway entered managed inspection without an AI Defense inspector.Page when sustained.
aid_unavailableAI Defense returned no verdict, including transport, timeout, or token failures.Page when sustained.
no_contentThe request contained no inspectable messages.Diagnostic only; never page.
unknownA future or invalid producer reason was normalized at the metric boundary.Diagnostic only; investigate producer drift.

The bundled DefenseClawManagedAIDFailOpenSustained rule uses a positive availability-reason allowlist, so no_content and unknown cannot accidentally become paging conditions:

sum by (reason) (
  rate(defenseclaw_managed_aid_fail_open_decisions_total{reason=~"inspector_unwired|aid_unavailable"}[5m])
) > 0

The expression must remain true for 10 minutes before the critical alert fires. It is traffic-gated by construction: an idle gateway produces no fail-open decisions and does not page. If it fires, verify that the gateway is running in the intended deployment mode, confirm the managed inspector was wired at startup, test AI Defense credentials and endpoint reachability, and check the provider status. The allow behavior is intentional during recovery; restore authoritative inspection before considering the incident resolved.

Tear it down

defenseclaw setup local-observability down

Stops all five containers and removes the Compose project. Dashboards and Grafana state live in named Docker volumes so they survive down/up cycles.

To wipe everything including the volumes:

defenseclaw setup local-observability reset --yes

reset is destructive — your historical traces, logs, and metrics go with it. Splunk HEC and JSONL destinations are unaffected. down only stops the containers; named Docker volumes survive across down/up cycles until you run reset.

Status and logs

defenseclaw setup local-observability status
defenseclaw setup local-observability logs --service grafana --follow

status shows container health and the resolved OTLP endpoint. logs --service <name> tails one of the five containers — useful when Grafana isn't picking up dashboards or the OTel collector is dropping spans. Drop --service to fan out logs from every container at once.

Use it alongside Splunk

Local observability and Splunk are independent destinations. A common pattern:

  • Engineers and SREs use the local Grafana stack for live investigation.
  • The same gateway also forwards every event to the org Splunk for retention and SOC.

Just run both setup commands. They add separate entries to the same observability.destinations list:

defenseclaw setup local-observability up
defenseclaw setup splunk --enterprise --hec-endpoint ... --hec-token ...

See Splunk integration for the dashboards we ship for the local Splunk app and for tips on building your own SPL queries against the gateway sourcetypes.

Troubleshooting