Current state
RockBot currently calls AddA2ACaller() only, making it a pure caller in the A2A model:
- It subscribes to
discovery.announce to discover peer agents
- It publishes
AgentTaskRequest to invoke external agents
- It receives results back on
agent.response.RockBot
It does not advertise itself on the discovery bus, and has no subscription on agent.task.RockBot. An external agent trying to send RockBot a task request would publish to agent.task.RockBot but no queue is bound to that topic — the message is dropped.
Goal
Make RockBot a full A2A peer so that:
- Other agents can discover RockBot — it publishes an
AgentCard on discovery.announce at startup (and periodically via the re-announce loop)
- Other agents can initiate tasks with RockBot — it subscribes to
agent.task.RockBot and handles incoming AgentTaskRequest messages
The hard design question: what does an inbound task mean for a conversational agent?
Unlike SampleAgent (stateless, task-in / result-out), RockBot is conversational — it has an active user session, working memory, and an ongoing dialogue. When an external agent sends an AgentTaskRequest, there are several ways to handle it:
Option A: Inject into the active user session
Treat the inbound task like a synthetic user message — add it to the current conversation and run the LLM loop. The response goes back to the calling agent via ReplyTo and is also relayed to the human user.
- Pros: RockBot can use all its tools, memory, and context to respond; the user stays in the loop
- Cons: Interleaves agent-to-agent work into the user conversation; can be disruptive if the user is mid-task
Option B: Handle in an isolated context (new session)
Create a fresh session ID for the inbound task, run the LLM loop in that context, reply to the calling agent. The human user never sees it.
- Pros: Clean separation; doesn't interrupt the user session
- Cons: RockBot loses access to its long-term memory and user context for the task
Option C: Queue and handle between user turns
Hold inbound agent tasks and process them when the user is idle (similar to how scheduled tasks work today).
- Pros: Doesn't interrupt user flow
- Cons: Adds latency; complex to implement
Option D: Separate skill-based dispatch
Define specific skills in the AgentCard that RockBot advertises. Incoming requests for known skills (e.g. memory-lookup, user-notify) are handled by dedicated lightweight handlers rather than the full LLM loop.
- Pros: Predictable, fast, no LLM cost for simple operations
- Cons: Limited to pre-defined skills; doesn't leverage RockBot's full capabilities
Implementation sketch (once design is decided)
// Program.cs — add alongside AddA2ACaller()
agent.AddA2A(opts =>
{
opts.Card = new AgentCard
{
AgentName = "RockBot",
Description = "Primary conversational agent.",
Skills = [ /* TBD based on chosen design */ ]
};
});
agent.Services.AddScoped<IAgentTaskHandler, RockBotTaskHandler>();
Questions to resolve
- Which option (A–D) fits the intended UX?
- Should the user be notified when another agent contacts RockBot?
- Should inbound agent tasks be reflected in the conversation history?
- What skills should RockBot advertise — general-purpose, or a curated list?
Current state
RockBot currently calls
AddA2ACaller()only, making it a pure caller in the A2A model:discovery.announceto discover peer agentsAgentTaskRequestto invoke external agentsagent.response.RockBotIt does not advertise itself on the discovery bus, and has no subscription on
agent.task.RockBot. An external agent trying to send RockBot a task request would publish toagent.task.RockBotbut no queue is bound to that topic — the message is dropped.Goal
Make RockBot a full A2A peer so that:
AgentCardondiscovery.announceat startup (and periodically via the re-announce loop)agent.task.RockBotand handles incomingAgentTaskRequestmessagesThe hard design question: what does an inbound task mean for a conversational agent?
Unlike
SampleAgent(stateless, task-in / result-out), RockBot is conversational — it has an active user session, working memory, and an ongoing dialogue. When an external agent sends anAgentTaskRequest, there are several ways to handle it:Option A: Inject into the active user session
Treat the inbound task like a synthetic user message — add it to the current conversation and run the LLM loop. The response goes back to the calling agent via
ReplyToand is also relayed to the human user.Option B: Handle in an isolated context (new session)
Create a fresh session ID for the inbound task, run the LLM loop in that context, reply to the calling agent. The human user never sees it.
Option C: Queue and handle between user turns
Hold inbound agent tasks and process them when the user is idle (similar to how scheduled tasks work today).
Option D: Separate skill-based dispatch
Define specific skills in the
AgentCardthat RockBot advertises. Incoming requests for known skills (e.g.memory-lookup,user-notify) are handled by dedicated lightweight handlers rather than the full LLM loop.Implementation sketch (once design is decided)
Questions to resolve