microsoft/semantic-kernel · error · KernelException

AgentDefinition Id must be set

Error message

AgentDefinition Id must be set

What it means

Thrown by the ProcessAgentBuilder code-actions constructor (the one taking onComplete/onError callbacks) when agentDefinition.Id is null. Unlike the declarative constructor (446), this overload does not fall back to agentDefinition.Name — it strictly requires Id because the code-action agent needs a deterministic, stable identifier for its step.

Source

Thrown at dotnet/src/Experimental/Process.Core/ProcessAgentBuilder.cs:55

    {
        Verify.NotNull(agentDefinition);
        this._agentDefinition = agentDefinition;
        this.DefaultThreadName = threadName;
        this.Inputs = nodeInputs;
    }

    /// <summary>
    /// Creates a new instance of the <see cref="ProcessAgentBuilder"/> class.
    /// </summary>
    /// <param name="agentDefinition"></param>
    /// <param name="onComplete"></param>
    /// <param name="onError"></param>
    /// <param name="threadName"></param>
    /// <param name="nodeInputs"></param>
    /// <param name="processBuilder"></param>
    /// <exception cref="KernelException"></exception>
    public ProcessAgentBuilder(AgentDefinition agentDefinition, Action<object?, KernelProcessStepContext> onComplete, Action<object?, KernelProcessStepContext> onError, string threadName, Dictionary<string, Type> nodeInputs, ProcessBuilder processBuilder)
        : base(agentDefinition.Id ?? throw new KernelException("AgentDefinition Id must be set"), processBuilder)
    {
        Verify.NotNull(agentDefinition);
        this._agentDefinition = agentDefinition;
        this.OnCompleteCodeAction = onComplete;
        this.OnErrorCodeAction = onError;
        this.DefaultThreadName = threadName;
        this.Inputs = nodeInputs;
    }

    #region Public Interface

    /// <summary>
    /// The optional resolver for the agent ID. This is used to determine the ID of the agent at runtime.
    /// </summary>
    public KernelProcessStateResolver<string?>? AgentIdResolver { get; init; } = null;

    /// <summary>
    /// The name of the thread that this agent will run on.

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Set agentDefinition.Id to a non-null value before using this constructor overload.
  2. If you only have a Name, use the declarative constructor overload instead, or explicitly provide the Id.
  3. Validate the agent definition's Id field before constructing the builder.

Example fix

// before
var def = new AgentDefinition { Name = "MyAgent" }; // Id is null
var builder = new ProcessAgentBuilder(def, onComplete, onError, "thread", [], processBuilder); // throws

// after
var def = new AgentDefinition { Id = "my-agent-001", Name = "MyAgent" };
var builder = new ProcessAgentBuilder(def, onComplete, onError, "thread", [], processBuilder);
Defensive patterns

Strategy: validation

Validate before calling

public static void EnsureAgentId(AgentDefinition def)
{
    if (string.IsNullOrWhiteSpace(def.Id))
    {
        throw new KernelException("AgentDefinition.Id is required for code-action agent builders.");
    }
}

Type guard

public static bool HasAgentId(AgentDefinition def)
    => !string.IsNullOrWhiteSpace(def.Id);

Prevention

When it happens

Trigger: Constructing a ProcessAgentBuilder with code-based OnComplete/OnError handlers using an AgentDefinition whose Id property is null. The step id is derived directly from agentDefinition.Id with no fallback.

Common situations: An agent definition loaded from a file missing the 'id' field but having a 'name'. A programmatically created AgentDefinition where only Name was set. Mixing declarative and code-action constructors without realizing the code-action path has stricter Id requirements.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/8002793bc32d11e8. Report an issue: GitHub.