< Summary

Information
Class: NexusLabs.Needlr.AgentFramework.Diagnostics.IAgentStageResult
Assembly: NexusLabs.Needlr.AgentFramework
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr.AgentFramework/Diagnostics/IAgentStageResult.cs
Line coverage
33%
Covered lines: 1
Uncovered lines: 2
Coverable lines: 3
Total lines: 100
Line coverage: 33.3%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_Outcome()100%210%
get_PhaseName()100%210%
get_Termination()100%11100%

File(s)

/home/runner/work/needlr/needlr/src/NexusLabs.Needlr.AgentFramework/Diagnostics/IAgentStageResult.cs

#LineLine coverage
 1using Microsoft.Extensions.AI;
 2
 3namespace NexusLabs.Needlr.AgentFramework.Diagnostics;
 4
 5/// <summary>
 6/// Result of a single agent stage within a multi-agent pipeline or group chat workflow,
 7/// combining the response text with the captured diagnostics for that stage.
 8/// </summary>
 9/// <remarks>
 10/// <para>
 11/// Access stage results via <see cref="IPipelineRunResult.Stages"/> after calling
 12/// <c>RunWithDiagnosticsAsync</c>. Each stage corresponds to one agent turn in the
 13/// workflow.
 14/// </para>
 15/// </remarks>
 16/// <example>
 17/// <code>
 18/// var result = await workflow.RunWithDiagnosticsAsync(prompt, accessor);
 19/// foreach (var stage in result.Stages)
 20/// {
 21///     var tokens = stage.Diagnostics?.AggregateTokenUsage;
 22///     Console.WriteLine($"[{stage.AgentName}] {tokens?.TotalTokens ?? 0} tokens, " +
 23///         $"{stage.Diagnostics?.TotalDuration.TotalSeconds:F1}s");
 24///     var text = stage.FinalResponse?.Text ?? string.Empty;
 25///     Console.WriteLine($"  Response: {text[..Math.Min(100, text.Length)]}...");
 26/// }
 27/// </code>
 28/// </example>
 29public interface IAgentStageResult
 30{
 31    /// <summary>Gets the agent's executor ID (agent name, possibly with a MAF-assigned GUID suffix).</summary>
 32    string AgentName { get; }
 33
 34    /// <summary>
 35    /// Gets the final <see cref="ChatResponse"/> the agent produced during this stage
 36    /// (preserving full message content, role, usage, and metadata), or
 37    /// <see langword="null"/> if the agent responded only via tool calls with no
 38    /// terminating text response. Call <c>.Text</c> for a flat text view when evaluating.
 39    /// </summary>
 40    ChatResponse? FinalResponse { get; }
 41
 42    /// <summary>
 43    /// Gets the diagnostics captured during this agent's execution, including per-call
 44    /// token usage, tool call details, and timing. <see langword="null"/> if diagnostics
 45    /// were not enabled via <c>UsingDiagnostics()</c>.
 46    /// </summary>
 47    IAgentRunDiagnostics? Diagnostics { get; }
 48
 49    /// <summary>
 50    /// Gets the outcome of this stage's execution. Defaults to
 51    /// <see cref="StageOutcome.Succeeded"/> for backward compatibility with
 52    /// implementations that do not track outcomes.
 53    /// </summary>
 054    StageOutcome Outcome => StageOutcome.Succeeded;
 55
 56    /// <summary>
 57    /// Gets the name of the pipeline phase this stage belongs to, or
 58    /// <see langword="null"/> when running a flat (non-phased) pipeline.
 59    /// </summary>
 060    string? PhaseName => null;
 61
 62    /// <summary>
 63    /// Gets the typed termination cause for this stage. <see langword="null"/> when
 64    /// the executor or runner did not specify one (legacy implementations / executors
 65    /// with no termination metadata).
 66    /// </summary>
 67    /// <remarks>
 68    /// <para>
 69    /// Use pattern matching to inspect specific cases:
 70    /// </para>
 71    /// <code>
 72    /// if (stage.Termination is StageTermination.MaxToolCallsReached { Limit: var limit })
 73    /// {
 74    ///     _logger.LogWarning("Stage {Name} exceeded {Limit} tool calls",
 75    ///         stage.AgentName, limit);
 76    /// }
 77    /// </code>
 78    /// <para>
 79    /// For OpenTelemetry / Prometheus tag values, use
 80    /// <see cref="IStageTermination.ToTagValue"/> — it returns a stable,
 81    /// low-cardinality string suitable for use as a metric dimension.
 82    /// </para>
 83    /// <para>
 84    /// Distinct from <see cref="Outcome"/>: <see cref="Outcome"/> is the rollup
 85    /// 3-value enum the runner decided about the stage; <see cref="Termination"/>
 86    /// is the detailed reason. For example, an executor that uses
 87    /// <c>shouldTreatAsSuccess</c> to flip a <c>MaxIterationsReached</c> result to
 88    /// <see cref="StageOutcome.Succeeded"/> still reports
 89    /// <see cref="StageTermination.MaxIterationsReached"/> here.
 90    /// </para>
 91    /// <para>
 92    /// Typed as <see cref="IStageTermination"/> so consumers can supply their own
 93    /// typed extension cases by implementing the interface directly. The framework's
 94    /// closed <see cref="StageTermination"/> hierarchy (with the
 95    /// <see cref="StageTermination.Custom"/> escape hatch) covers the canonical
 96    /// cases; see <see cref="IStageTermination"/> for the contract on extending.
 97    /// </para>
 98    /// </remarks>
 199    IStageTermination? Termination => null;
 100}