Skip to content

IStageTermination

NexusLabs.Needlr.AgentFramework

NexusLabs.Needlr.AgentFramework.Diagnostics

IStageTermination Interface

Contract for any value that describes why a pipeline stage terminated. Implemented by the framework's closed StageTermination hierarchy (12 framework cases including the Custom escape hatch) and — optionally — by consumer-defined types when a typed extension case is required.

public interface IStageTermination

Derived
StageTermination

Remarks

Framework cases — the easy path. Most consumers should use the framework's StageTermination hierarchy directly. The 11 typed framework cases cover every loop-natural, loop-bounded, external, and stage-level termination the runner produces; the Custom case carries app-specific narrative with a Reason string and an optional structured Properties dictionary. Framework cases are JSON-polymorphism-registered on this interface, so they round-trip through System.Text.Json.JsonSerializer out of the box.

Custom cases — the typed extension path. Consumers who need a typed extension case (with named-record pattern matching like is MyDomainTermination { FindingCount: var c }) can implement this interface directly:

public sealed record MyDomainTermination(int FindingCount) : IStageTermination
{
    public string ToTagValue() => "MyDomain";
}

Implementing this interface is a contract: you own the JSON serialization for your derived type. The framework's System.Text.Json.Serialization.JsonPolymorphicAttribute registry on this interface only knows about the framework cases — your type is not in it. Two practical options: 1. Register your derived type at the JSON layer via a System.Text.Json.Serialization.Metadata.JsonTypeInfoResolver modifier so it joins the polymorphism table for that System.Text.Json.JsonSerializerOptions instance. 2. Provide your own System.Text.Json.Serialization.JsonConverter<> for IStageTermination with full control over the wire format.

If you do neither, JsonSerializer.Serialize<IStageTermination>(yourInstance) throws System.NotSupportedException — same loud failure the framework cases have today for unregistered types. There is no silent data loss, but every JSON-serialising downstream consumer needs the registration. If you don't want to maintain a JSON registration, use instead — it gives you a stable wire format at the cost of dictionary-typed properties.

StageTermination itself is closed for external derivation at compile time (its constructor is internal) — the framework hierarchy is exhaustive by design. Extension happens by implementing this interface directly, not by inheriting from the abstract record.

Methods

IStageTermination.ToTagValue() Method

Returns a stable, low-cardinality string suitable for OpenTelemetry tag values (e.g. the termination_cause tag emitted by IPipelineMetrics). Framework cases return their case name (e.g. "MaxIterationsReached", "Custom") — bounded by the case enumeration. Free-form detail such as Reason is preserved on the record / in JSON rather than in this tag, so the metric stays bounded by default. Third-party implementations are responsible for their own cardinality discipline — the returned string is used directly as a metric tag value.

string ToTagValue();

Returns

System.String