Skip to content

AgentPrismRunOptions

Namespace AgentPrism · Assembly AgentPrism.Abstractions.dll

Run options that let the caller determine a run’s identifier, its place in the tree, and its budget.

public sealed class AgentPrismRunOptions : AgentRunOptions

object ← AgentRunOptions ← AgentPrismRunOptions

AgentRunOptions.Clone(), AgentRunOptions.ContinuationToken, AgentRunOptions.AllowBackgroundResponses, AgentRunOptions.AdditionalProperties, AgentRunOptions.ResponseFormat, object.GetType(), object.ToString(), object.Equals(object?), object.Equals(object?, object?), object.ReferenceEquals(object?, object?), object.GetHashCode()

The wrapper writing the run record normally generates its own identifier and does not report it outward. A streaming endpoint, however, must know the identifier before the first frame: only then can the client associate the streamed response with the run record. Having the caller generate the identifier solves this without an extra notification channel or ambient state, and follows the same approach as RunStartInfo.RunId.

The AgentPrismRunOptions.ParentRunId, AgentPrismRunOptions.RootRunId, AgentPrismRunOptions.Depth, and AgentPrismRunOptions.Budget fields are filled in by ChildAgentInvoker when an agent calls another agent. They do not need to be filled in by hand; if they are, the run is placed at the specified spot in the tree.

This type carries no ChatOptions. If sampling settings need to change per run, Microsoft Agent Framework’s ChatClientAgentRunOptions type is used; the two types cannot be used together. AgentPrism resolves sampling settings from the agent definition on its own endpoints, so this is not a practical constraint.

Creates a new options object.

public AgentPrismRunOptions()

The definition version this run measures. If null, the wrapper uses the (current) version from the agent’s catalog summary. For runs resolved by an A/B experiment, this field is filled in because the compiled agent’s actual version may differ from the current one.

public int? AgentVersion { get; init; }

int?

Gets the work that must be DONE AND VISIBLE before the run is closed with RunStatus.AwaitingApproval.

public Func<IEnumerable<ChatMessage>, CancellationToken, ValueTask>? BeforePendingApprovalIsPublished { get; init; }

Func<IEnumerable<ChatMessage>, CancellationToken, ValueTask>?

RunStatus.AwaitingApproval is TERMINAL and is the signal a consumer polls on. Whoever records the pending approval does so AFTER the agent call returns — but the run is closed INSIDE that call, so without this hook the status is published first and GET /api/approvals/pending answers an empty list for a run that already says it is waiting. The window was not a race: the order was fixed, so it was open on every such run.

The callback receives the messages the run produced and runs on BOTH the buffered and the streaming path, immediately before the terminal status is written. It runs only when the run actually ends by requesting approval; anything it throws fails the run, which is correct — a published RunStatus.AwaitingApproval whose approval was never recorded is unanswerable.

The budget shared across the tree. If null, the wrapper opening the root run produces a budget from its settings.

public AgentRunBudget? Budget { get; init; }

AgentRunBudget?

The object is the same instance at every run in the tree. If it were copied, each branch would get its own budget and the limit would lose its meaning.

The depth in the tree. The root run is 0.

public int Depth { get; init; }

int

The identifier of the experiment this run belongs to. null for a non-experiment run.

public Guid? ExperimentId { get; init; }

Guid?

This run’s kind. If null, the wrapper assumes RunKind.Agent.

public RunKind? Kind { get; init; }

RunKind?

The eval job processor gives RunKind.Eval for every case run; this lets IRunStore.GetStatisticsAsync exclude these synthetic calls from the summary.

The identifier of the run that started this run. null for the root run.

public Guid? ParentRunId { get; init; }

Guid?

If this run is a replay, the source run’s identifier. The value is written to the runs.replay_of_run_id column.

public Guid? ReplayOfRunId { get; init; }

Guid?

This field is meaningful only for the root run; a replay’s child calls do not carry their own lineage.

The identifier of the run at the root of the tree. null if the run itself is the root.

public Guid? RootRunId { get; init; }

Guid?

The value is denormalized: fetching a whole tree through AgentPrismRunOptions.ParentRunId would require a recursive query; a single indexed query on the root identifier is enough.

The run identifier to use. If null, the identifier is generated by the wrapper that writes the run record.

public Guid? RunId { get; init; }

Guid?

The value must be time-ordered; AgentPrismId.NewId ensures this. A random identifier produced by Guid.NewGuid fragments the storage index.

The identifier of the session at the root of the tree. Filled in for child runs; the root run reads its identifier from its own AgentSession.

public string? SessionId { get; init; }

string?

This field only feeds AgentRunScope.SessionId; it does not change a run record’s session_id column. The two concepts are separate: the column says “the run was started with this session,” while the scope says “content produced here belongs to this session.” On a child agent call, MAF passes no session, but the produced attachment still belongs to the root session.

This matters for retention: an attachment written without a session counts as orphaned, and the retention policy deletes it.

The name of the experiment variant this run is assigned to. null for a non-experiment run.

public string? Variant { get; init; }

string?

public override AgentRunOptions Clone()

AgentRunOptions

Cloning preserves all fields. Otherwise, a middleware layer copying the options would silently drop the identifier, and the wrapper would generate its own — the identifier reported to the client would then correspond to no record at all. The same trap is more insidious for the tree fields: a dropped AgentPrismRunOptions.Depth value silently disables recursion protection.