microsoft/autogen · error · ArgumentException

No next available agents found in the current workflow

Error message

No next available agents found in the current workflow

What it means

In the obsolete SelectNextSpeakerAsync, when a workflow is set the chat calls TransitToNextAvailableAgentsAsync(currentSpeaker, history). If the workflow yields zero candidate agents for the current speaker, it throws ArgumentException('No next available agents found in the current workflow'). This means the current speaker has no outgoing transition that is currently enabled, so the conversation cannot continue along the workflow.

Source

Thrown at dotnet/src/AutoGen.Core/GroupChat/GroupChat.cs:120

    /// Select the next speaker based on the conversation history.
    /// The next speaker will be decided by a combination effort of the admin and the workflow.
    /// Firstly, a group of candidates will be selected by the workflow. If there's only one candidate, then that candidate will be the next speaker.
    /// Otherwise, the admin will be invoked to decide the next speaker using role-play prompt.
    /// </summary>
    /// <param name="currentSpeaker">current speaker</param>
    /// <param name="conversationHistory">conversation history</param>
    /// <returns>next speaker.</returns>
    [Obsolete("Please use RolePlayOrchestrator or WorkflowOrchestrator")]
    public async Task<IAgent> SelectNextSpeakerAsync(IAgent currentSpeaker, IEnumerable<IMessage> conversationHistory)
    {
        var agentNames = this.agents.Select(x => x.Name).ToList();
        if (this.workflow != null)
        {
            var nextAvailableAgents = await this.workflow.TransitToNextAvailableAgentsAsync(currentSpeaker, conversationHistory);
            agentNames = nextAvailableAgents.Select(x => x.Name).ToList();
            if (agentNames.Count == 0)
            {
                throw new ArgumentException("No next available agents found in the current workflow");
            }

            if (agentNames.Count == 1)
            {
                return this.agents.First(x => x.Name == agentNames.First());
            }
        }

        if (this.admin == null)
        {
            throw new ArgumentException("No admin is provided.");
        }

        var systemMessage = new TextMessage(Role.System,
            content: $@"You are in a role play game. Carefully read the conversation history and carry on the conversation.
The available roles are:
{string.Join(",", agentNames)}

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Add an outgoing transition (e.g. back to the admin or to a termination-friendly node) from every node that may be asked for a next speaker.
  2. Loosen or fix the condition/predicate on the current speaker's transitions so at least one is satisfiable.
  3. Detect terminal state before calling selection: if the last speaker's node has no enabled transitions, end the chat instead of asking for a next speaker.
  4. Migrate to RolePlayOrchestrator/WorkflowOrchestrator, which this API is marked obsolete in favor of.

Example fix

// before
workflow.AddTransition(Transition.Create(start, a));
workflow.AddTransition(Transition.Create(a, end)); // 'a' dead-ends after end
var next = await chat.SelectNextSpeakerAsync(end, history); // throws

// after
workflow.AddTransition(Transition.Create(end, start)); // loop back so every node has an exit
var next = await chat.SelectNextSpeakerAsync(end, history);
Defensive patterns

Strategy: validation

Validate before calling

// before asking for a next speaker, check the workflow has at least one transition from the current node
var hasExit = workflow.Transitions.Any(t => t.From == currentSpeakerNode);
if (!hasExit) { /* end the chat or route manually */ }

Try / catch

try { return await chat.SelectNextSpeakerAsync(currentSpeaker, history); }
catch (ArgumentException ex) when (ex.Message.Contains("No next available agents"))
{
    return fallbackRoundRobin(currentSpeaker); // or terminate the conversation
}

Prevention

When it happens

Trigger: A workflow where the current speaker's transitions are all conditioned and their predicates return false for the current history; the speaker is a terminal node with no outgoing edges; calling the obsolete SelectNextSpeakerAsync API on such a node.

Common situations: Designing a graph with an end node and then asking for the next speaker anyway; conditional transitions (e.g. 'only route to reviewer if output contains X') whose conditions all fail; cycles that depend on a condition that never re-enables.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/3bfb51f3208a89ec. Report an issue: GitHub.