IterativeLoopOptions
NexusLabs.Needlr.AgentFramework¶
NexusLabs.Needlr.AgentFramework.Iterative¶
IterativeLoopOptions Class¶
Configuration for a single run of an IIterativeAgentLoop.
Inheritance System.Object 🡒 IterativeLoopOptions
Example¶
var options = new IterativeLoopOptions
{
LoopName = "article-writer",
Instructions = "You are a travel article writer...",
Tools = [searchTool, writeTool, outlineTool],
PromptFactory = ctx =>
{
var article = ctx.Workspace.FileExists("article.md")
? ctx.Workspace.ReadFile("article.md")
: "(empty)";
return $"Continue writing. Current article:\n{article}";
},
MaxIterations = 20,
ToolResultMode = ToolResultMode.OneRoundTrip,
};
var result = await iterativeLoop.RunAsync(options, cancellationToken);
Remarks¶
At minimum, callers must provide Instructions (the system prompt), Tools (available tool functions), and PromptFactory (builds the user message each iteration from workspace state).
The loop terminates when any of these conditions is met (checked in order): 1. The System.Threading.CancellationToken is cancelled. 2. MaxIterations is reached. 3. IsComplete returns true. 4. The model produces a text response without requesting tool calls (natural completion).
Properties¶
IterativeLoopOptions.ExecutionContext Property¶
An optional IAgentExecutionContext to use for bridging workspace state to DI-resolved tools.
public NexusLabs.Needlr.AgentFramework.Context.IAgentExecutionContext? ExecutionContext { get; set; }
Property Value¶
Remarks¶
When set, the loop uses this context (and its workspace) for the IAgentExecutionContextAccessor scope. When null (the default), the loop auto-creates a context from the Workspace if an accessor is available via DI.
This is the bootstrap execution context only — it is
NOT the same as the full application execution context. It exists
solely so that DI-resolved tool classes can call
accessor.Current.GetRequiredWorkspace() during loop execution.
IterativeLoopOptions.Instructions Property¶
Gets or sets the system prompt (instructions) for the agent. Sent as the system message on every LLM call. This is constant across all iterations.
Property Value¶
IterativeLoopOptions.IsComplete Property¶
Gets or sets an optional predicate evaluated after each iteration. When it returns true, the loop terminates. The predicate receives the IterativeContext with updated workspace and tool results.
public System.Func<NexusLabs.Needlr.AgentFramework.Iterative.IterativeContext,bool>? IsComplete { get; set; }
Property Value¶
System.Func<IterativeContext,System.Boolean>
Remarks¶
Use this for domain-specific termination conditions. For example, checking whether a required workspace file exists, or whether a word count target has been reached.
IterativeLoopOptions.LoopName Property¶
Gets or sets a human-readable name for this loop run, used in diagnostics
and progress events. Defaults to "iterative-loop".
Property Value¶
IterativeLoopOptions.MaxIterations Property¶
Gets or sets the maximum number of iterations before the loop terminates.
Defaults to 25. Set to a lower value for cost-sensitive workloads.
Property Value¶
IterativeLoopOptions.MaxToolRoundsPerIteration Property¶
Gets or sets the maximum number of tool-calling rounds within a single iteration
when ToolResultMode is MultiRound.
Ignored for other modes. Defaults to 5.
Property Value¶
Remarks¶
This is a safety valve to prevent unbounded within-iteration growth. After this many rounds of tool calls within one iteration, any remaining tool call requests are executed and stored in LastToolResults for the next iteration.
IterativeLoopOptions.OnIterationEnd Property¶
Gets or sets an optional async callback invoked after each iteration completes. Receives the IterationRecord containing tool calls, tokens, and timing.
public System.Func<NexusLabs.Needlr.AgentFramework.Iterative.IterationRecord,System.Threading.Tasks.Task>? OnIterationEnd { get; set; }
Property Value¶
System.Func<IterationRecord,System.Threading.Tasks.Task>
Remarks¶
Fired after the IterationRecord is built and context is updated. Hook exceptions propagate to the caller.
IterativeLoopOptions.OnIterationStart Property¶
Gets or sets an optional async callback invoked at the start of each iteration, before the prompt factory runs. Receives the zero-based iteration number and the current IterativeContext.
public System.Func<int,NexusLabs.Needlr.AgentFramework.Iterative.IterativeContext,System.Threading.Tasks.Task>? OnIterationStart { get; set; }
Property Value¶
System.Func<System.Int32,IterativeContext,System.Threading.Tasks.Task>
Remarks¶
Use this for progress reporting (e.g., updating a SignalR client). Hook exceptions propagate directly to the caller — they are not caught by the loop's internal error handling.
IterativeLoopOptions.OnToolCall Property¶
Gets or sets an optional async callback invoked after each tool call completes. Receives the zero-based iteration number and the ToolCallResult.
public System.Func<int,NexusLabs.Needlr.AgentFramework.Iterative.ToolCallResult,System.Threading.Tasks.Task>? OnToolCall { get; set; }
Property Value¶
System.Func<System.Int32,ToolCallResult,System.Threading.Tasks.Task>
Remarks¶
Fired once per tool call, in execution order. Use for real-time progress updates such as streaming tool activity to a UI. Hook exceptions propagate to the caller.
IterativeLoopOptions.PromptFactory Property¶
Gets or sets the factory that builds the user message for each iteration. Called once at the start of every iteration with the current IterativeContext (which includes workspace state and last tool results).
public System.Func<NexusLabs.Needlr.AgentFramework.Iterative.IterativeContext,string> PromptFactory { get; set; }
Property Value¶
System.Func<IterativeContext,System.String>
Remarks¶
This is the core extensibility point. The prompt factory reads workspace files to understand current state, optionally includes data from LastToolResults, and returns a fresh user message.
The returned string becomes the sole user message — there is no conversation history. The workspace IS the memory.
IterativeLoopOptions.ToolFilter Property¶
Gets or sets an optional filter that narrows the tool list on each iteration. Receives the zero-based iteration number, the current IterativeContext, and the full Tools list. Returns the subset of tools the model should see for that iteration.
public System.Func<int,NexusLabs.Needlr.AgentFramework.Iterative.IterativeContext,System.Collections.Generic.IReadOnlyList<Microsoft.Extensions.AI.AITool>,System.Collections.Generic.IReadOnlyList<Microsoft.Extensions.AI.AITool>>? ToolFilter { get; set; }
Property Value¶
System.Func<System.Int32,IterativeContext,System.Collections.Generic.IReadOnlyList<Microsoft.Extensions.AI.AITool>,System.Collections.Generic.IReadOnlyList<Microsoft.Extensions.AI.AITool>>
Example¶
ToolFilter = (iteration, ctx, allTools) =>
{
var phase = ctx.Workspace.ReadFile("status.json");
var allowed = phase.Contains("research")
? new[] { "search" }
: new[] { "add_leg", "book_hotel", "validate_trip" };
return allTools.Where(t => allowed.Contains(t.Name)).ToList();
};
Remarks¶
Use this for phase-gating — restricting which tools are available
based on the current workspace state. For example, a trip planner might offer only
search during the research phase and only add_leg/book_hotel
during the build phase.
When null (the default), all Tools are available on every iteration.
IterativeLoopOptions.ToolResultMode Property¶
Gets or sets how tool call results are fed back to the model within a single iteration. Defaults to OneRoundTrip.
Property Value¶
See Also¶
IterativeLoopOptions.Tools Property¶
Gets or sets the tools available to the model. The loop matches tool call requests from the model against this list by function name.
Property Value¶
System.Collections.Generic.IReadOnlyList<Microsoft.Extensions.AI.AITool>
Remarks¶
Tools are typically created via Microsoft.Extensions.AI.AIFunctionFactory or obtained from the agent framework's function discovery. The same tool instances are reused across all iterations.