Skip to content

RockBot as A2A peer: agent card advertisement and inbound task handling #99

@rockfordlhotka

Description

@rockfordlhotka

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:

  1. Other agents can discover RockBot — it publishes an AgentCard on discovery.announce at startup (and periodically via the re-announce loop)
  2. 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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions