Agentic AITypeScriptverifiedVerified
Evaluator-Optimizer Agent Pattern in TypeScript
An iterative refinement loop where an 'Evaluator' provides granular feedback on an 'Optimizer’s' output until quality thresholds are met.
How to Implement the Evaluator-Optimizer Agent Pattern in TypeScript
1Step 1: Define the Feedback, Optimizer, and Evaluator interfaces
interface Feedback {
isPass: boolean;
critique: string;
score: number;
}
interface Optimizer {
generate(task: string): Promise<string>;
refine(current: string, feedback: string): Promise<string>;
}
interface Evaluator {
check(output: string): Promise<Feedback>;
}2Step 2: Implement the iterative refinement loop
const MAX_ITERATIONS = 5;
async function refinementLoop(
task: string,
optimizer: Optimizer,
evaluator: Evaluator
): Promise<string> {
let currentOutput = await optimizer.generate(task);
for (let i = 0; i < MAX_ITERATIONS; i++) {
const feedback = await evaluator.check(currentOutput);
if (feedback.isPass) return currentOutput;
currentOutput = await optimizer.refine(
currentOutput,
feedback.critique
);
}
return currentOutput;
}import { z } from "zod";
// ── Schemas ──────────────────────────────────────────────────────
const FeedbackSchema = z.object({
isPass: z.boolean(),
critique: z.string(),
score: z.number().min(0).max(100),
categories: z.record(z.number().min(0).max(100)),
});
type Feedback = z.infer<typeof FeedbackSchema>;
interface OptimizerConfig {
model: string;
temperature: number;
maxTokens: number;
}
interface EvaluatorConfig {
model: string;
rubric: string;
passThreshold: number;
}
interface RefinementOptions {
maxIterations: number;
onIteration?: (iteration: number, feedback: Feedback) => void;
signal?: AbortSignal;
}
// ── Optimizer Agent ──────────────────────────────────────────────
class OptimizerAgent {
constructor(private config: OptimizerConfig) {}
async generate(task: string): Promise<string> {
// Call LLM API with task prompt
const response = await this.callLLM(`Generate: ${task}`);
return response;
}
async refine(current: string, critique: string): Promise<string> {
const prompt = [
"Improve the following output based on feedback.",
`\nCurrent output:\n${current}`,
`\nFeedback:\n${critique}`,
"\nProvide the improved version:",
].join("\n");
return this.callLLM(prompt);
}
private async callLLM(prompt: string): Promise<string> {
// Replace with actual LLM API call
return `[LLM Response for: ${prompt.slice(0, 50)}...]`;
}
}
// ── Evaluator Agent ──────────────────────────────────────────────
class EvaluatorAgent {
constructor(private config: EvaluatorConfig) {}
async check(output: string): Promise<Feedback> {
const prompt = [
`Evaluate against rubric: ${this.config.rubric}`,
`\nOutput:\n${output}`,
"\nRespond with JSON: { isPass, critique, score, categories }",
].join("\n");
const raw = await this.callLLM(prompt);
return FeedbackSchema.parse(JSON.parse(raw));
}
private async callLLM(prompt: string): Promise<string> {
return JSON.stringify({
isPass: true,
critique: "Meets all criteria",
score: 95,
categories: { accuracy: 96, completeness: 94 },
});
}
}
// ── Refinement Loop ──────────────────────────────────────────────
async function refinementLoop(
task: string,
optimizer: OptimizerAgent,
evaluator: EvaluatorAgent,
options: RefinementOptions
): Promise<{ output: string; iterations: number; finalScore: number }> {
const { maxIterations, onIteration, signal } = options;
let currentOutput = await optimizer.generate(task);
for (let i = 0; i < maxIterations; i++) {
if (signal?.aborted) {
throw new Error("Refinement loop aborted");
}
const feedback = await evaluator.check(currentOutput);
onIteration?.(i + 1, feedback);
if (feedback.isPass) {
return {
output: currentOutput,
iterations: i + 1,
finalScore: feedback.score,
};
}
currentOutput = await optimizer.refine(
currentOutput,
feedback.critique
);
}
const finalFeedback = await evaluator.check(currentOutput);
return {
output: currentOutput,
iterations: maxIterations,
finalScore: finalFeedback.score,
};
}
export {
OptimizerAgent,
EvaluatorAgent,
refinementLoop,
type Feedback,
type RefinementOptions,
};Evaluator-Optimizer Agent Pattern Architecture
hourglass_empty
Rendering diagram...
lightbulb
Evaluator-Optimizer Agent Pattern in the Real World
“Think of a student writing an essay (Optimizer) and a teacher grading it with detailed feedback (Evaluator). The student revises based on the red-ink comments and resubmits. This cycle repeats until the essay meets the teacher’s standards—or the deadline (max iterations) is reached.”