MODULE 02 · LESSON 2.5
Route work, events, and progress
Route requests, events and progress between cooperating agents.
Lesson 10 of 86 · FabrCore 2.0
Overview
Request/response is appropriate when the caller needs a result. Events describe something that happened. A fan-out gathers independent results; a chain passes one result into the next step. These are internal FabrCore patterns, distinct from the external Agent2Agent protocol.
A call and an event have different promises
A request/response call waits for a result needed by its caller. An event announces a fact such as a request changing status. A progress update tells the UI that ongoing work has reached a stage, but it is not the final business answer. Treating all three as ordinary chat bubbles makes clients finish too early or show duplicate answers.
How composition changes the workflow
A chain is appropriate when policy review needs the output of a request lookup. Fan-out is appropriate when independent specialists can investigate separate aspects. The coordinating agent still needs to handle failed, delayed or missing results and decide what to report. Internal FabrCore messaging uses known handles and ownership; public A2A interoperability is a separate interface introduced later.
Choose request, event or progress
- Create a second agent under the same principal and send it a bounded request with SendAndReceiveMessage. Return a useful error if the delegate times out.
- Use EventMessage and configured stream subscriptions for notifications that do not require a synchronous reply.
- Set status while a turn runs and propagate trace context into child work. Add cross-principal grants before delegating across owners in SQL mode.
var request = new AgentMessage { ToHandle = "analyst", Message = "Analyze this data" };
var reply = await fabrcoreAgentHost.SendAndReceiveMessage(request);
// Cross-principal:
var crossPrincipalHandleRequest = new AgentMessage { ToHandle = "principal2:analyst", Message = "Analyze this data" };
var reply = await fabrcoreAgentHost.SendAndReceiveMessage(crossPrincipalHandleRequest);
var eventMsg = new EventMessage
{
Type = "status-changed",
Namespace = "agent-status",
Channel = "listener-agent",
Data = "Agent status updated"
};
await fabrcoreAgentHost.SendEvent(eventMsg);
var ns = "agent-status";
var channel = "listener-agent";
var config = new AgentConfiguration
{
Streams = [EventStreamSubscription.For(ns, channel)]
};
await fabrcoreAgentHost.SendEvent(new EventMessage
{
Namespace = ns,
Channel = channel,
Type = "status-changed"
});
Observe the three kinds of output
- For SR-1042, call a lookup agent and wait for its returned record before invoking dependent policy work. Record the sender, target and correlation for each call.
- Emit a “lookup finished” progress message while another step remains. The client should keep the investigation pending rather than display it as the final answer.
- Send the final summary only after combining the available results, explicitly identifying a failed specialist if one failed. An event subscriber may refresh its own view independently.
A reader should be able to tell whether work was requested, progress was reported, or a result was completed. This distinction becomes essential for delegation and out-of-turn delivery.
If the result is different
Do not claim completion after a fire-and-forget send. A timeout may leave external work uncertain; check its recorded result before repeating a mutation.
Go deeper
Explore the related documentation.