Live and retained evidence
An investigation normally begins with current identity and moves toward evidence that can survive a reconnect or caller timeout. The diagnostics API keeps those questions separate because they belong to different components and lifetimes.
Locate the current client and its advertised surface
GET /users merges bounded observations from the registry and history inspectors. Each row reports a canonical user scope with observed connection and stream counts, followed by the completeness block described in Diagnostics API and security. A user summary adds up to 100 connection snapshots, up to 100 stream summaries, and an inspector count of pending RPCs; its completeness block identifies truncated connection or stream sources.
GET /connections filters by optional user_id, node_id, and status (connected, disconnected, or stale) and uses cursor pagination with a 1–1,000 limit. A snapshot identifies the stable client, current runtime instance, owning node, timestamps, client type, metadata, advertised action names, and derived heartbeat or recent-replacement indicators.
GET /connections/{user_id}/{client_id}/actions returns the action advertisement preserved from the hello: names and any supplied summary, description, version, argument-check flag, schema, and metadata. GET /actions aggregates a bounded sample across connections and explicitly reports whether that sample was complete.
Advertisement is capability evidence, not authorization. Central policy, client-local policy, approval, argument validation, targeting, leases, and handler behavior can still refuse an action.
Find callers that are still waiting
GET /rpc/pending filters by user, client, owning node, minimum age, and optional runtime-instance cross-check. Records carry the RPC and command identities, expected runtime instance, target node, creation and timeout timestamps, age, and any observed instance mismatch. Count and count-by-node routes support alerting without downloading the list.
A pending RPC proves that its correlator has not resolved that waiter. It does not prove that no socket write occurred, that the client did not execute, or that no result arrived after the caller stopped waiting. Use the command identity to inspect retained evidence before retrying an action whose side effects are not naturally idempotent.
Read retained messages without weakening the boundary
GET /history/streams lists one user's stream summaries by optional prefix and cursor. Message and timestamp summaries may be unknown when a backend cannot compute them cheaply.
GET /history/messages requires a full stream key and accepts exclusive time bounds, comma-separated message kinds, an include_payload flag, cursor, and limit. Its normalized summaries retain message, stream, client, instance, command, trace, and parent-span identities. Payloads are redacted by default. Terminal errors expose only a bounded diagnostic code and message; raw details, stack traces, and arbitrary exception objects remain outside that summary.
GET /history/command/{user_id}/{command_id} gathers related messages for a known command and also defaults to redacted payloads. Some implementations must scan retained streams to answer, so this is not promised as a constant-time indexed query.
Raw history is a second opt-in
GET /history/raw-messages exists only when the router was created with enable_raw_messages=True; otherwise it returns 403 after ordinary admin authentication. The response is one bounded stored-representation sample, optionally reduced to payload values. It can expose adapter-specific fields and sensitive content that the normalized DTO deliberately omits.
Disabling raw history does not make every other route payload-free. An administrator can still ask the normalized history routes to include payloads. Administrative identity, environment placement, retention, output handling, and spill-store access all remain part of the deployment design.
When a Redis history inspector receives the matching managed spill store, higher-level reads can hydrate externalized values. Managed spill objects share an immutable expiry with their references, expired files are hidden, cleanup can occur during later managed writes, and an explicit cleanup hook is available. An idle directory is not guaranteed to remove every expired file without that hook, and an explicitly unmanaged custom store remains operator-owned.
Treat deduplication as ingestion evidence
GET /dedup/stats describes what the configured deduplicator observed for a requested window. Some backends provide exact counters; others expose best-effort live-key estimates and may report zero for unavailable duplicate counters. GET /dedup/backend identifies the implementation, TTL, and safe namespace information.
Deduplication describes server ingestion, not client execution. Combine it with delivery and topology evidence, retained messages, traces, and the product's external reconciliation record before declaring the journey understood.