Conversations
The Conversations screen answers a different question from Workflow. Workflow shows the static shape — where a type can flow. Conversations shows what actually happened to one concrete message instance: the real chain of sends, receives, and handler executions that one request set off across your services, drawn as a causal graph or a timeline.
Reach it from the Explore → Conversations sidebar item (/conversations).
No tracing backend required. The feed is captured first-class from Wolverine's own
ActivitySourceinside each monitored service and pushed to CritterWatch. You do not need to bind an OpenTelemetry provider, run Jaeger, or configure anything — if a service is monitored, its conversations show up. Capture is bounded (a rolling retention window), so this is a live operational view, not a long-term trace archive.
The recent list
The left pane lists the most-recently-active conversations, newest first. Each row shows:
- Root message — the type that started the conversation (short name), with a red failed tag if any hop in it errored.
- Services — every service the conversation touched.
- Hops — how many envelope hops (sends + receives + executions) were captured.
- Started — when the first hop fired.
Click a row to open it. Use Refresh to re-pull the list.
Reading one conversation — Why vs. When
The detail pane renders the selected conversation two ways, via the Why / When toggle:
Why — the causal graph
The default view is a causal "why" graph (ServiceInsight-style) on the same Vue Flow substrate the Workflow screen uses. Each box is a message envelope; caused-by arrows connect a message to the messages it triggered. Failed hops render red, and a saga participant is badged. This is the view for "this request went wrong — what led to the failure, and what did it set off?"
When — the compacted timeline
The "when" timeline is a compacted, Temporal-style Gantt: one bar per envelope from start to finish, coloured by outcome, with the waits between bars shown as real gap markers. This is the view for "where did the time go?" — especially for flows with scheduled/delayed steps, where the gaps are the story.
Recovering a failed message inline
When a message failed and was dead-lettered, click its red box (Why view) or its row (When view). If that envelope has a captured dead-letter identity, a small action bar appears offering Replay and Discard. These reuse the exact same DlqOperation machinery as the Dead Letter Queue screen — the command travels the normal SignalR path, so recovering a poison message never leaves the conversation you're looking at.
Cross-linking with the Workflow graph
Conversations and the Workflow flow graph are wired together in both directions:
- Show on workflow map — the button in a conversation's header opens the Workflow screen with this conversation's exact path lit across the static graph (everything off the path dims), so you can see the concrete run against the whole modelled shape.
- Coming the other way, clicking an edge on the Workflow flow graph opens a drawer of the real conversations that actually traversed it; each entry opens that conversation here.
How one conversation is stitched together
A single logical flow does not always stay one distributed trace. When a message crosses the async projection boundary — an event is appended, then a projection publishes a downstream message — the runtime starts a new trace. If CritterWatch keyed conversations on the W3C trace id alone, one business flow would shatter into disconnected fragments.
Instead, conversations key on Wolverine's CorrelationId, which propagates across that boundary, so the whole flow reassembles into one conversation. Where a causal edge genuinely can't cross the boundary (only a span-parent id exists, not a causation-message id), the link is drawn as an inferred, time-ordered dashed edge rather than asserted as fact — honest about what was observed versus what was reconstructed.
