Skip to content

.NET: [Bug]: Magentic participant message routing is the opposite of GroupChatHost and the Python reference #6223

@ghominejad

Description

@ghominejad

Description

What happened?

In a Magentic workflow, a participant that takes a later turn receives the
instruction the manager addressed to an earlier participant, but never
receives that earlier participant's response.

MagenticOrchestrator sends the per-round manager instruction untargeted, so
the orchestrator's fan-out edge delivers it to every participant rather than
only the selected speaker. Participant replies are never relayed to the other
participants - they reach only the manager's ChatHistory. So an idle agent
accumulates instructions meant for other agents, while never seeing what those agents actually
produced.

This is the opposite of the .NET GroupChatHost (same assembly), which tracks
the current speaker and broadcasts replies to all other participants, and the
opposite of the Python Magentic orchestrator, which targets the instruction at
the selected speaker and broadcasts responses to the others.

What did you expect to happen?

Each participant should see the running conversation - prior participants'
responses - plus its own instruction, and should NOT see instructions
addressed to other participants. This matches GroupChatHost and the Python
reference.

Before - sees the first agent's instruction (leaked via fan-out), not its reply:

System: "..."
User: "Instruction meant for Agent1" <-- ⚠️ LEAKED: Untargeted fan-out
User: "Instruction meant for Agent2"

After - sees the first agent's response, plus its own instruction:

System: "..."
Assistant/Agent1: "Agent1's response" <-- BROADCASTED: Correct context
User: "Instruction meant for Agent2" <-- 🎯 TARGETED: Direct instruction

Steps to reproduce the issue

  1. Build a Magentic workflow with one manager and two participant agents
    (e.g. HealthChecker and DatabaseChecker), each instructed to reply with a
    short fixed marker.
  2. Run it with a single task message and a TurnToken.
  3. Have the manager select HealthChecker in round 1 and DatabaseChecker in
    round 2.
  4. Inspect the message list DatabaseChecker receives on its turn (e.g. log the
    request reaching the second agent).

Actual: DatabaseChecker's input contains HealthChecker's instruction and
its own instruction, but not HealthChecker's response

Code Sample

AIAgent healthChecker = chatClient.AsAIAgent(
    name: "HealthChecker",
    description: "Checks the core application framework state.",
    instructions: """
        You only return [The core framework is healthy!] and nothing else.
        If someone asks you what is the state or asks anything, you only confirm it's healthy.
        """);

AIAgent databaseChecker = chatClient.AsAIAgent(
    name: "DatabaseChecker",
    description: "Checks the database connection state.",
    instructions: """
        You only return [The Database is healthy!] and nothing else.
        If someone asks you what is the database state, you only confirm it's healthy.
        """);

AIAgent managerAgent = chatClient.AsAIAgent(
    name: "MagenticManager",
    description: "Coordinates the health and database checkers to assess system health.",
    instructions: """
        Coordinate HealthChecker and DatabaseChecker to determine overall system health.
        Consult both participants. If either reports Unhealthy, the system is unhealthy.
        Only if both report [Healthy] is the system healthy. Do not build or fix anything.
        Synthesize a final verdict and stop.
        """);

var workflow = new MagenticWorkflowBuilder(managerAgent)
    .AddParticipants([healthChecker, databaseChecker])
    .WithName("Health Check Magentic Workflow")
    .WithDescription("Coordinates two checkers to report system health.")
    .RequirePlanSignoff(false)
    .WithMaxRounds(6)
    .WithMaxStalls(1)
    .WithMaxResets(1)
    .Build();

Error Messages / Stack Traces

Package Versions

Microsoft.Agents.AI: 1.8.0, Microsoft.Agents.AI.Workflows:1.8.0

.NET Version

.Net 10

Additional Context

No response

PR open : #6222 (implements the fix)

What The PR #6222 Fixes:

  • Targeted Instructions: Restricts the per-round manager instruction to the selected speaker only, preventing idle agents from accumulating unrelated instructions.
  • Response Broadcasting: Broadcasts each participant's response to all other participants so the running conversation context is maintained.
  • Checkpoint Integrity: Persists CurrentSpeakerExecutor across checkpoints so the exclusion
    survives restore.

Metadata

Metadata

Assignees

No one assigned

    Type

    No fields configured for Bug.

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions