Proposal for a first-class, declarative way to build LLM chat/agent features on Wolverine, so agent workloads get the same durability, observability, and testability as every other message.
Sketch
Handlers as tools. An [AgentTool] attribute on a message type (or handler) generates the LLM tool schema from the message signature — the same reflection/codegen machinery that already builds HTTP endpoint metadata. When the model calls a tool, the call is dispatched as a real Wolverine message through IMessageBus: durable, retried, outbox-enrolled, observable. The agent loop is just another handler chain.
Conversation as a saga. A chat session is stateful, long-lived, and event-driven — exactly what sagas model:
opts.AddAgent<SupportAgent>(a => a
.Model("claude-sonnet-5")
.SystemPrompt(...)
.Tools(typeof(LookupOrder), typeof(IssueRefund)));
Each turn and each tool invocation is a message; the conversation's history is the saga's stream. Streaming deltas ride the existing SignalR transport.
Provider seam. Microsoft.Extensions.AI's IChatClient is the obvious abstraction so Anthropic/OpenAI/local models plug in without Wolverine taking a vendor dependency.
Why in Wolverine rather than app code
- Tool calls that mutate state get the transactional inbox/outbox for free — an agent's side effects stop racing its narration.
- Retries/error policies apply to flaky model calls like any other endpoint.
- Every agent decision is an envelope: correlation/causation chains answer "what did the agent do, what did it see, in what order" with infrastructure that already exists — observability tooling lights up with agent activity with no extra work.
- Handlers-as-tools are unit-testable without a model in the loop, same as handlers-as-handlers.
Open questions
- Loop ownership: does Wolverine run the model-call loop (a built-in agent runtime) or only provide the tool-dispatch + saga plumbing while the app owns the loop?
- Tool-call authorization: per-tool gating analogous to HTTP auth policies.
- Token/streaming ergonomics over SignalR vs. HTTP SSE.
- Whether
[AgentTool] schemas should reuse the JSON-schema generation planned/used elsewhere rather than a new generator.
Filed as part of a broader AI-capability planning round; happy to split into smaller issues if the shape survives discussion.
Proposal for a first-class, declarative way to build LLM chat/agent features on Wolverine, so agent workloads get the same durability, observability, and testability as every other message.
Sketch
Handlers as tools. An
[AgentTool]attribute on a message type (or handler) generates the LLM tool schema from the message signature — the same reflection/codegen machinery that already builds HTTP endpoint metadata. When the model calls a tool, the call is dispatched as a real Wolverine message throughIMessageBus: durable, retried, outbox-enrolled, observable. The agent loop is just another handler chain.Conversation as a saga. A chat session is stateful, long-lived, and event-driven — exactly what sagas model:
Each turn and each tool invocation is a message; the conversation's history is the saga's stream. Streaming deltas ride the existing SignalR transport.
Provider seam.
Microsoft.Extensions.AI'sIChatClientis the obvious abstraction so Anthropic/OpenAI/local models plug in without Wolverine taking a vendor dependency.Why in Wolverine rather than app code
Open questions
[AgentTool]schemas should reuse the JSON-schema generation planned/used elsewhere rather than a new generator.Filed as part of a broader AI-capability planning round; happy to split into smaller issues if the shape survives discussion.