< Summary

Information
Class: NexusLabs.Needlr.AgentFramework.Workflows.AgentFactoryWorkflowExtensions
Assembly: NexusLabs.Needlr.AgentFramework.Workflows
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr.AgentFramework.Workflows/AgentFactoryWorkflowExtensions.cs
Line coverage
100%
Covered lines: 19
Uncovered lines: 0
Coverable lines: 19
Total lines: 64
Line coverage: 100%
Branch coverage
100%
Covered branches: 4
Total branches: 4
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
BuildHandoffWorkflow(...)100%11100%
BuildHandoffWorkflow(...)100%44100%

File(s)

/home/runner/work/needlr/needlr/src/NexusLabs.Needlr.AgentFramework.Workflows/AgentFactoryWorkflowExtensions.cs

#LineLine coverage
 1using Microsoft.Agents.AI;
 2using Microsoft.Agents.AI.Workflows;
 3
 4namespace NexusLabs.Needlr.AgentFramework.Workflows;
 5
 6/// <summary>
 7/// Extension methods on <see cref="IAgentFactory"/> for building MAF handoff workflow topologies.
 8/// </summary>
 9public static class AgentFactoryWorkflowExtensions
 10{
 11    /// <summary>
 12    /// Builds a handoff workflow where <paramref name="initialAgent"/> routes to one of the
 13    /// <paramref name="handoffTargets"/> based on LLM-driven tool-call decisions.
 14    /// </summary>
 15    /// <remarks>
 16    /// This is an ergonomic wrapper over the raw MAF handoff builder, which requires passing
 17    /// <paramref name="initialAgent"/> twice — once to <c>CreateHandoffBuilderWith</c> and again
 18    /// as the <c>from</c> argument in <c>WithHandoffs</c>.
 19    /// </remarks>
 20    public static Workflow BuildHandoffWorkflow(
 21        this IAgentFactory agentFactory,
 22        AIAgent initialAgent,
 23        params AIAgent[] handoffTargets)
 24    {
 425        ArgumentNullException.ThrowIfNull(agentFactory);
 426        ArgumentNullException.ThrowIfNull(initialAgent);
 427        ArgumentNullException.ThrowIfNull(handoffTargets);
 28
 429        return agentFactory.BuildHandoffWorkflow(
 430            initialAgent,
 1131            handoffTargets.Select(t => (t, (string?)null)).ToArray());
 32    }
 33
 34    /// <summary>
 35    /// Builds a handoff workflow where <paramref name="initialAgent"/> routes to one of the
 36    /// <paramref name="handoffTargets"/> based on LLM-driven tool-call decisions.
 37    /// Each target is paired with an optional routing reason provided to the LLM when deciding
 38    /// which agent to hand off to. Targets with a null or empty reason use the no-reason handoff.
 39    /// </summary>
 40    public static Workflow BuildHandoffWorkflow(
 41        this IAgentFactory agentFactory,
 42        AIAgent initialAgent,
 43        params (AIAgent Target, string? Reason)[] handoffTargets)
 44    {
 645        ArgumentNullException.ThrowIfNull(agentFactory);
 646        ArgumentNullException.ThrowIfNull(initialAgent);
 647        ArgumentNullException.ThrowIfNull(handoffTargets);
 48
 649        var builder = AgentWorkflowBuilder.CreateHandoffBuilderWith(initialAgent);
 50
 651        var withoutReason = handoffTargets
 1152            .Where(t => string.IsNullOrEmpty(t.Reason))
 753            .Select(t => t.Target)
 654            .ToArray();
 55
 656        if (withoutReason.Length > 0)
 457            builder.WithHandoffs(initialAgent, withoutReason);
 58
 3159        foreach (var (target, reason) in handoffTargets.Where(t => !string.IsNullOrEmpty(t.Reason)))
 460            builder.WithHandoff(initialAgent, target, reason!);
 61
 662        return builder.Build();
 63    }
 64}