Skip to main content

Reflexion admin

ReflexionAdmin<TInput, TOutput> runs an actor-critic loop. The actor produces an output. The critic evaluates it. If the critic approves, the actor's output is the result. If not, the actor retries with the critic's feedback, until MaxIterations is hit.

Example — write, review, revise

using LogicGrid.Core.Admins;
using LogicGrid.Core.Agents;
using LogicGrid.Core.Llm;

var llm = LlmClientBase.Ollama("llama3.2");

IAgent actor = new Agent<string>(
name: "Actor",
description: "Writes the answer.",
systemPrompt: "Write a 100-word product description for the input. " +
"If feedback is provided, revise based on it.",
llm: llm);

IAgent critic = new Agent<string>(
name: "Critic",
description: "Reviews and approves or rejects.",
systemPrompt: "Review the description for clarity, accuracy, and persuasiveness.",
llm: llm);

var admin = new ReflexionAdmin<string, string>(
name: "ProductCopy",
llmClient: llm,
actor: actor,
critic: critic,
options: new ReflexionOptions { MaxIterations = 3 });

var ctx = new AgentContext().WithLogging();
var copy = await admin.RunAsync(
"A noise-cancelling travel pillow that supports the chin while seated.");

Console.WriteLine($"\n{copy}");
09:42:01.118 [INF] [e9f1c422] Run started — admin: ProductCopy | task: A noise-cancelling travel pillow …
09:42:04.318 [INF] [e9f1c422] [Actor] completed | output: Travel calmer with our noise-cancelling … | 3200ms | 188 tokens
09:42:06.402 [INF] [e9f1c422] [Critic] completed | output: REVISION NEEDED: mention the chin support more prominently. | 2084ms | 88 tokens
09:42:06.420 [INF] [e9f1c422] Reflexion iter 1 — revise | feedback: mention the chin support more prominently.
09:42:09.802 [INF] [e9f1c422] [Actor] completed | output: Designed for upright sleep, our travel pillow cradles the chin … | 3382ms | 192 tokens
09:42:11.901 [INF] [e9f1c422] [Critic] completed | output: APPROVED. | 2099ms | 12 tokens
09:42:11.910 [INF] [e9f1c422] Reflexion iter 2 — approved | feedback: APPROVED.
09:42:11.911 [INF] [e9f1c422] Run completed — 4 agents, 4 LLM calls | 10793ms

Notice the critic's system prompt is just "review for clarity, accuracy, and persuasiveness" — it doesn't mention APPROVED or REVISION NEEDED: anywhere. The framework appends a small protocol trailer to every critic prompt so the LLM knows which tokens to emit, freeing the user prompt to focus on the review logic.

If you ever need to change the protocol — translate it, swap the keywords, or strip it entirely (for example, when wiring a custom CriticPromptBuilder that already encodes its own approval contract) — set ReflexionOptions.CriticInstructionsTrailer to your own string (or null / empty to disable).

Constructors

public ReflexionAdmin(
string name,
LlmClientBase llmClient,
IAgent actor,
IAgent critic,
ReflexionOptions? options = null,
IAgentEventBus? eventBus = null)

public sealed class ReflexionOptions
{
public int MaxIterations { get; set; } = 3;
public decimal? MaxBudgetUsd { get; set; }
public float BudgetWarningThreshold { get; set; } = 0.8f;
public LlmOptions LlmOptions { get; set; } = new LlmOptions();
public string? CriticInstructionsTrailer { get; set; } = /* default protocol */;
public Func<string, string, int, string>? CriticPromptBuilder { get; set; }
public Func<string, string, string, string>? RetryPromptBuilder { get; set; }
}

ReflexionAdmin takes ReflexionOptions rather than AdminOptions because it adds reflexion-specific settings — MaxIterations and the two prompt-builder callbacks. The shared budget/LLM fields are mirrored on ReflexionOptions so the admin can configure them internally; you don't need to pass an AdminOptions separately.

Events

EventFired when
ReflexionIterationEventAfter every actor → critic round. Carries Iteration, Approved, CriticFeedback.
ReflexionExhaustedEventThe loop reached MaxIterations without the critic ever approving. Carries the last actor output and last critic feedback. The admin still returns the last output — subscribe to this event when you need to flag it for human review or downgrade downstream confidence.

Use it when

  • The output benefits from a second pair of eyes — drafts that need a reviewer, code that needs a linter, plans that need a sanity check.
  • You want automatic revision loops without writing the loop yourself.

Don't use it when

  • A single-shot answer is good enough.
  • The critique is rule-based and doesn't need an LLM — write a normal validator and use AgentBase<T>.ValidateOutput. See Overriding AgentBase<T>.

Common pitfalls

  • Critic never approves. If the critic's prompt is vague, every output will trigger another revision until MaxIterations exhausts. Make the approve criteria explicit and bounded.
  • Cost grows linearly per iteration. 3 iterations = up to 6 LLM calls. Set MaxBudgetUsd for hosted models.
  • Custom CriticPromptBuilder without the trailer. The default trailer (see ReflexionOptions.CriticInstructionsTrailer) is what teaches the LLM to emit APPROVED or REVISION NEEDED:. It's appended to whatever your custom builder returns, so by default the protocol is preserved. If you set CriticInstructionsTrailer to null or empty, your custom builder must include equivalent instructions or the loop will misbehave (typically: critic never approves and the loop runs to MaxIterations).