microsoft/semantic-kernel · error · KernelException

Failed to build step from agent definition: {node.Id}

Error message

Failed to build step from agent definition: {node.Id}

What it means

Thrown by BuildDeclarativeStepAsync when ProcessBuilder.AddStepFromAgent returns a builder that is not a ProcessAgentBuilder. The declarative path assumes an agent-backed step yields a ProcessAgentBuilder so it can attach OnComplete/OnError; any other type indicates a mismatch between the agent definition and the builder factory.

Source

Thrown at dotnet/src/Experimental/Process.Core/Workflow/WorkflowBuilder.cs:139

    }

    private Task BuildDeclarativeStepAsync(Node node, ProcessBuilder processBuilder)
    {
        Verify.NotNull(node);

        // Check for built-in step types
        if (node.Id.Equals("End", StringComparison.OrdinalIgnoreCase))
        {
            var endBuilder = processBuilder.AddEndStep();
            this._stepBuilders["End"] = endBuilder;
            return Task.CompletedTask;
        }

        AgentDefinition? agentDefinition = node.Agent ?? throw new KernelException("Declarative steps must have an agent defined.");
        var stepBuilder = processBuilder.AddStepFromAgent(agentDefinition, node.Id);
        if (stepBuilder is not ProcessAgentBuilder agentBuilder)
        {
            throw new KernelException($"Failed to build step from agent definition: {node.Id}");
        }

        // ########################### Parsing on_complete and on_error conditions ###########################

        if (node.OnComplete != null)
        {
            if (node.OnComplete.Any(c => c is null || c.OnCondition is null))
            {
                throw new ArgumentException("A complete on_complete condition is required for declarative steps.");
            }

            agentBuilder.OnComplete([.. node.OnComplete.Select(c => c.OnCondition!)]);
        }

        if (node.OnError != null)
        {
            if (node.OnError.Any(c => c is null || c.OnCondition is null))
            {

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Ensure the AgentDefinition.Type corresponds to a real agent so AddStepFromAgent produces a ProcessAgentBuilder.
  2. If using a custom AddStepFromAgent override, have it return a ProcessAgentBuilder for declarative agents.
  3. Verify the Semantic Kernel version's AddStepFromAgent contract matches your agent definition format.

Example fix

// before: agent type resolves to a plain step
node.Agent = new AgentDefinition { Type = "MyPlainStep" };

// after: agent type resolves to an agent
node.Agent = new AgentDefinition { Type = "MyAgent", /* required fields */ };
Defensive patterns

Strategy: try-catch

Validate before calling

var sb = processBuilder.AddStepFromAgent(agentDef, nodeId);
if (sb is not ProcessAgentBuilder) throw new KernelException($"Agent for {nodeId} did not produce a ProcessAgentBuilder.");

Type guard

static bool IsAgentBuilder(ProcessStepBuilder? sb) => sb is ProcessAgentBuilder;

Try / catch

try { await builder.BuildProcessAsync(workflow, yaml); }
catch (KernelException ex) when (ex.Message.Contains("Failed to build step from agent"))
{ /* verify AgentDefinition.Type resolves to a real agent; check runtime version */ }

Prevention

When it happens

Trigger: Calling BuildProcessAsync where a declarative node's AgentDefinition causes ProcessBuilder.AddStepFromAgent to return a builder whose runtime type is not ProcessAgentBuilder (e.g. the agent type maps to a non-agent step, or AddStepFromAgent falls back to a generic ProcessStepBuilder).

Common situations: An AgentDefinition whose Type resolves to something that is not agent-shaped, or a custom AddStepFromAgent override that returns a generic step builder; version skew where AddStepFromAgent semantics changed.

Related errors


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