optimize() GEPA Tune programs with the top-level GEPA helper. typescript subsystems subsystems/optimize website/content-src/templates/subsystem-optimize.md subsystems optimize() GEPA

optimize() GEPA

Use optimize() for normal GEPA tuning. It accepts a programmable root, training examples, a metric, and optimizer options.

TypeScript
import { AxAIOpenAIModel, ai, ax, optimize } from '@ax-llm/ax';

const program = ax('emailText:string -> priority:class "high, normal, low"');
const studentAI = ai({ name: 'openai', apiKey: process.env.OPENAI_APIKEY!, config: { model: AxAIOpenAIModel.GPT4OMini } });
const teacherAI = ai({ name: 'openai', apiKey: process.env.OPENAI_APIKEY!, config: { model: AxAIOpenAIModel.GPT4O } });
const metric = ({ prediction, example }: any) => prediction.priority === example.priority ? 1 : 0;

const result = await optimize(program, train, metric, { studentAI, teacherAI, maxMetricCalls: 40 });
program.applyOptimization(result.optimizedProgram!);

The optimizer runs a program against examples, scores predictions, searches for better instructions/demos/component settings, and returns an artifact that can be applied immediately or serialized.

What It Does

GEPA explores changes and keeps tradeoffs visible through Pareto-aware results. The TypeScript helper also runs bootstrap demos for small starter sets before GEPA, which gives the optimizer concrete examples to work with.

flowchart LR
  A["Program"] --> D["GEPA"]
  B["Train examples"] --> D
  C["Metric or judge"] --> D
  D --> E["Reflective mutation"]
  E --> F["Pareto evaluation"]
  F -->|explore| E
  F --> G["Optimized artifact"]
  G --> H["Save / load / apply"]

Core Call Shape

text
result = optimize(program, examples, metric, options)
program.applyOptimization(result.optimizedProgram)

Generated language packages expose the optimizer surface available in their AxIR API, usually as an AxGEPA engine.

Common Patterns

  • Start with no-key deterministic examples for the metric.
  • Keep maxMetricCalls explicit.
  • Use scalar metrics for one clear objective.
  • Use multi-objective metrics for tradeoffs such as accuracy/cost or quality/brevity.
  • Keep validation examples separate when the optimizer surface supports them.
  • Save artifacts with enough metadata to explain the examples and metric that produced them.

AxGen

TypeScript
const classifier = ax('emailText:string -> priority:class "high, normal, low"');
const metric = ({ prediction, example }) =>
  prediction.priority === example.priority ? 1 : 0;

const result = await optimize(classifier, train, metric, {
  studentAI,
  teacherAI,
  validationExamples,
  maxMetricCalls: 120,
});
classifier.applyOptimization(result.optimizedProgram!);

Flow

TypeScript
const wf = flow<{ emailText: string }>()
  .n('classifier', 'emailText:string -> priority:class "high, normal, low"')
  .n('rationale', 'emailText:string, priority:string -> rationale:string')
  .e('classifier', (s) => ({ emailText: s.emailText }))
  .e('rationale', (s) => ({ emailText: s.emailText, priority: s.classifierResult.priority }))
  .r((s) => ({ priority: s.classifierResult.priority, rationale: s.rationaleResult.rationale }));

const result = await optimize(wf, train, multiObjectiveMetric, { studentAI, teacherAI });

Agent

TypeScript
const result = await supportAgent.optimize(tasks, {
  judgeAI,
  judgeOptions: { description: 'Prefer correct tool use over polished wording.' },
  bootstrap: true,
  maxMetricCalls: 24,
});
supportAgent.applyOptimization(result.optimizedProgram!);

Artifact

TypeScript
import { axDeserializeOptimizedProgram, axSerializeOptimizedProgram } from "@ax-llm/ax";

const saved = axSerializeOptimizedProgram(result.optimizedProgram!);
const restored = axDeserializeOptimizedProgram(saved);
program.applyOptimization(restored);

Production Notes

Optimization is a build-time or evaluation-time workflow, not something to hide in every request path. Track score history, cost, token usage, selected Pareto point, and the final artifact version.

See optimize() API.

Docs