microsoft/autogen · error · Exception

UserInputRequestedEvent should not be sent to the completion

Error message

UserInputRequestedEvent should not be sent to the completion client

What it means

UserInputRequestedEvent is a control-plane AgentEvent emitted to signal that a human-input callback is pending; it carries no model-facing content. Calling ToCompletionClientMessage on it always throws Exception, because converting the chat history for a completion client must never include this event type.

Source

Thrown at dotnet/src/Microsoft.AutoGen/AgentChat/Abstractions/Messages.cs:581

        return new Microsoft.Extensions.AI.ChatMessage(ChatRole.Assistant, this.Content) { AuthorName = this.Source };
    }
}

/// <summary>
/// An event signaling that the user proxy has requested user input. Published prior to invoking the
/// input callback.
/// </summary>
public class UserInputRequestedEvent : AgentEvent
{
    /// <summary>
    /// Identifier for the user input request.
    /// </summary>
    public required string RequestId { get; set; }

    /// <inheritdoc cref="AgentEvent.ToCompletionClientMessage(ChatRole)" />/>
    public override Extensions.AI.ChatMessage ToCompletionClientMessage(ChatRole role)
    {
        throw new Exception("UserInputRequestedEvent should not be sent to the completion client");
    }
}

public static class CompletionChatMessageExtensions
{
    /// <summary>
    /// Flattens a <see cref="Microsoft.Extensions.AI.ChatMessage"/> into a single <see cref="Microsoft.Extensions.AI.ChatMessage"/>
    /// containing all of the content in the original message as a single string.
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <param name="msg">
    /// The <see cref="Microsoft.Extensions.AI.ChatMessage"/> to flatten.
    /// </param>
    /// <returns>
    /// A new <see cref="Microsoft.Extensions.AI.ChatMessage"/> that is a flattened version of the input.
    /// </returns>
    public static Microsoft.Extensions.AI.ChatMessage Flatten(this Microsoft.Extensions.AI.ChatMessage msg)

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Filter out events before conversion: skip items where item is AgentEvent / UserInputRequestedEvent (events are not model-facing by design)
  2. Use the library's provided helpers for building completion-client messages rather than a blanket Select over the history
  3. When persisting sessions, keep the event separately from the model-facing message list you will replay

Example fix

// before
var prompt = session.Messages.Select(m => m.ToCompletionClientMessage(role)).ToList();
// after
var prompt = session.Messages
    .Where(m => m is not AgentEvent)
    .Select(m => m.ToCompletionClientMessage(role))
    .ToList();
Defensive patterns

Strategy: type-guard

Validate before calling

var modelMessages = history.Where(m => m is not AgentEvent).Select(m => m.ToCompletionClientMessage(role)).ToList();

Type guard

static bool IsModelFacing(AgentMessage msg) => msg is not AgentEvent; // events (incl. UserInputRequestedEvent) are never sent to the model

Try / catch

catch (Exception ex) when (ex.Message.Contains("UserInputRequestedEvent")) { // rebuild the prompt from non-event messages and retry }

Prevention

When it happens

Trigger: Serializing a chat history/session transcript that contains a UserInputRequestedEvent (e.g. after a human-in-the-loop turn) by indiscriminately mapping every AgentMessage via ToCompletionClientMessage, then sending it to an IChatClient.

Common situations: Replaying or resuming saved sessions that include input-request events; building prompt builders that iterate all messages; upgrading from a version where events were absent from histories.

Related errors


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