These TypeScript examples are real runnable files. Edit the source file first; this page is rebuilt from the checked-in example and its metadata header.
TypeScript AxGen Optimization
Runs a baseline OpenAI prediction and applies a real optimizer result.
- Provider:
openai - Env:
OPENAI_API_KEY,OPENAI_APIKEY - Level:
beginner - Run:
npm run example -- typescript src/examples/typescript/optimization/axgen-optimization.ts - Source: src/examples/typescript/optimization/axgen-optimization.ts
import { AxAIOpenAIModel, ai, ax, optimize } from '@ax-llm/ax';
const apiKey = process.env.OPENAI_API_KEY ?? process.env.OPENAI_APIKEY;
if (!apiKey) {
throw new Error('Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.');
}
const llm = ai({
name: 'openai',
apiKey,
config: {
model: AxAIOpenAIModel.GPT54Mini,
temperature: 0,
},
});
const program = ax(
'emailText:string -> priority:class "high, normal, low", rationale:string'
);
const baseline = await program.forward(llm, {
emailText: 'Production checkout is failing for enterprise customers.',
});
const train = [
{
emailText: 'URGENT: checkout is down',
priority: 'high',
rationale: 'Production checkout outage blocks customers.',
},
{
emailText: 'Weekly newsletter',
priority: 'low',
rationale: 'Informational update with no action needed.',
},
{
emailText: 'Reminder to submit timesheets',
priority: 'normal',
rationale: 'Routine request with a clear deadline.',
},
];
const metric = ({ prediction, example }: { prediction: any; example: any }) =>
prediction.priority === example.priority ? 1 : 0;
const result = await optimize(program, train, metric, {
studentAI: llm,
teacherAI: llm,
numTrials: 1,
maxMetricCalls: 4,
});
if (!result.optimizedProgram) {
throw new Error('Optimizer did not return an optimized program.');
}
program.applyOptimization(result.optimizedProgram);
const after = await program.forward(llm, {
emailText: 'Production checkout is failing for enterprise customers.',
});
console.log(
JSON.stringify({ baseline, after, bestScore: result.bestScore }, null, 2)
);TypeScript GEPA Optimization
Pairs a real OpenAI baseline with a local GEPA optimization pass.
- Provider:
openai - Env:
OPENAI_API_KEY,OPENAI_APIKEY - Level:
intermediate - Run:
npm run example -- typescript src/examples/typescript/optimization/gepa-optimization.ts - Source: src/examples/typescript/optimization/gepa-optimization.ts
import { AxAIOpenAIModel, ai, ax, optimize } from '@ax-llm/ax';
const apiKey = process.env.OPENAI_API_KEY ?? process.env.OPENAI_APIKEY;
if (!apiKey) {
throw new Error('Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.');
}
const llm = ai({
name: 'openai',
apiKey,
config: {
model: AxAIOpenAIModel.GPT54Mini,
temperature: 0,
},
});
const program = ax(
'emailText:string -> priority:class "high, normal, low", rationale:string'
);
const baseline = await program.forward(llm, {
emailText: 'Production checkout is failing for enterprise customers.',
});
const train = [
{
emailText: 'URGENT: checkout is down',
priority: 'high',
rationale: 'Production checkout outage blocks customers.',
},
{
emailText: 'Weekly newsletter',
priority: 'low',
rationale: 'Informational update with no action needed.',
},
{
emailText: 'Reminder to submit timesheets',
priority: 'normal',
rationale: 'Routine request with a clear deadline.',
},
];
const metric = ({ prediction, example }: { prediction: any; example: any }) =>
prediction.priority === example.priority ? 1 : 0;
const result = await optimize(program, train, metric, {
studentAI: llm,
teacherAI: llm,
numTrials: 1,
maxMetricCalls: 4,
});
if (!result.optimizedProgram) {
throw new Error('Optimizer did not return an optimized program.');
}
program.applyOptimization(result.optimizedProgram);
console.log(JSON.stringify({ baseline, bestScore: result.bestScore }, null, 2));TypeScript Playbook Context Evolution
Grows a context playbook offline with playbook().evolve, then refines it online with .update().
- Provider:
openai - Env:
OPENAI_API_KEY,OPENAI_APIKEY - Level:
intermediate - Run:
npm run example -- typescript src/examples/typescript/optimization/playbook-context-evolution.ts - Source: src/examples/typescript/optimization/playbook-context-evolution.ts
import { AxAIOpenAIModel, type AxMetricFn, ai, ax, playbook } from '@ax-llm/ax';
const apiKey = process.env.OPENAI_API_KEY ?? process.env.OPENAI_APIKEY;
if (!apiKey) {
throw new Error('Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.');
}
const studentAI = ai({
name: 'openai',
apiKey,
config: { model: AxAIOpenAIModel.GPT54Mini, temperature: 0.2 },
});
// A generator we want to improve without hand-editing its prompt.
const triage = ax('ticket:string -> urgency:class "p0, p1, p2"');
triage.setDescription('Classify the support ticket urgency.');
// Labeled examples capture the nuance we want the playbook to absorb.
const train = [
{
ticket: 'Checkout is down for all customers in the EU region.',
urgency: 'p0',
},
{ ticket: 'A single user cannot change their avatar.', urgency: 'p2' },
{
ticket: 'Login works but is intermittently slow for many users.',
urgency: 'p1',
},
{ ticket: 'Production database returns 500s on every write.', urgency: 'p0' },
{ ticket: 'Typo in the footer copyright year.', urgency: 'p2' },
];
const metric: AxMetricFn = ({ prediction, example }) =>
(prediction as { urgency?: string }).urgency ===
(example as { urgency?: string }).urgency
? 1
: 0;
// 1) Grow a playbook offline from the labeled examples (ACE runs under the hood).
const pb = playbook(triage, { studentAI, maxEpochs: 2 });
const { bestScore } = await pb.evolve(train, metric);
pb.applyTo(triage);
console.log(`offline best score: ${bestScore}`);
console.log('\nlearned playbook:\n');
console.log(pb.render());
// 2) Use the improved program.
const live = await triage.forward(studentAI, {
ticket: 'Password reset emails are delayed ~10 minutes for some users.',
});
console.log('\nlive prediction:', live);
// 3) Keep improving online from feedback — no metric required.
await pb.update({
example: { ticket: 'The status page itself is unreachable.' },
prediction: { urgency: 'p2' },
feedback: 'WRONG: if customers cannot even see status, treat it as p0.',
});
pb.applyTo(triage);
// 4) Persist the playbook and restore it into a fresh program instance.
const snapshot = pb.toJSON();
const restored = playbook(ax('ticket:string -> urgency:class "p0, p1, p2"'), {
studentAI,
}).load(snapshot);
console.log(
'\nrestored playbook bullets:',
restored.getState().playbook.stats.bulletCount
);TypeScript Agent Playbook — Learn From Failures
An agent that learns from its own failed runs — the playbook config harvests each run’s errors into avoidance rules that ride the next run.
- Provider:
openai - Env:
OPENAI_API_KEY,OPENAI_APIKEY - Level:
intermediate - Run:
npm run example -- typescript src/examples/typescript/optimization/agent-playbook-learning.ts - Source: src/examples/typescript/optimization/agent-playbook-learning.ts
import {
type AxAgentPlaybookUpdateResult,
AxAIOpenAIModel,
agent,
ai,
} from '@ax-llm/ax';
const apiKey = process.env.OPENAI_API_KEY ?? process.env.OPENAI_APIKEY;
if (!apiKey) {
throw new Error('Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.');
}
const llm = ai({
name: 'openai',
apiKey,
config: { model: AxAIOpenAIModel.GPT54Mini },
});
// A ledger tool that quietly REQUIRES the "LGR-" id prefix. Neither the tool
// description nor the task reveals it — only the rejection error teaches it.
const ledger = {
'LGR-4471': 'balance 812.55 EUR (ref TXN-CC12)',
'LGR-8290': 'balance 4210.09 EUR (ref TXN-KD73)',
} as Record<string, string>;
const lookupLedgerEntry = {
name: 'lookupLedgerEntry',
description: 'Look up a ledger entry by its id and return the balance',
parameters: {
type: 'object' as const,
properties: {
id: { type: 'string' as const, description: 'Ledger entry id' },
},
required: ['id'],
},
func: async ({ id }: { id: string }) => {
if (!/^LGR-\d{4}$/.test(id)) {
throw new Error(
`InvalidLedgerIdError: ledger entry ids use the "LGR-" prefix followed by 4 digits (got "${id}"); retry with e.g. "LGR-4471"`
);
}
return { id, entry: ledger[id] ?? 'no such entry' };
},
};
// Attach a playbook at construction. `learn` is on by default: after each run
// that produced failure signals, one bounded update curates an avoidance rule.
let learned: AxAgentPlaybookUpdateResult | undefined;
const support = agent('query:string -> answer:string', {
ai: llm,
functions: [lookupLedgerEntry],
playbook: {
onUpdate: (r) => {
learned = r;
},
},
maxTurns: 8,
});
// Run A: the agent trips the id-format trap, recovers in-run, and the
// run-end harvest curates a "don't do that" rule into the playbook.
const a = await support.forward(llm, {
query:
'Look up ledger entry 4471 and report its balance with the transaction ref.',
});
console.log('Run A answer:', a.answer);
console.log('\nHarvested playbook after run A:\n');
console.log(support.getPlaybook()?.render() ?? '(none)');
console.log('\nonUpdate status:', learned?.status);
// Run B on the SAME agent. forward() keeps no memory of run A's turns — the
// only thing that carries over is the curated playbook, now riding the actor
// prompt. So the agent uses the "LGR-" prefix on the first try (no failing
// tool call) purely because of the harvested rule.
const b = await support.forward(llm, {
query:
'Look up ledger entry 4471 and report its balance with the transaction ref.',
});
console.log('\nRun B answer:', b.answer);
// Persist the learned playbook for a future session with support.getPlaybook().getState().
TypeScript Optimization Artifact Reuse
Saves and reapplies a real optimizer artifact after an OpenAI baseline.
- Provider:
openai - Env:
OPENAI_API_KEY,OPENAI_APIKEY - Level:
advanced - Run:
npm run example -- typescript src/examples/typescript/optimization/artifact-optimization.ts - Source: src/examples/typescript/optimization/artifact-optimization.ts
import {
AxAIOpenAIModel,
ai,
ax,
axDeserializeOptimizedProgram,
axSerializeOptimizedProgram,
optimize,
} from '@ax-llm/ax';
const apiKey = process.env.OPENAI_API_KEY ?? process.env.OPENAI_APIKEY;
if (!apiKey) {
throw new Error('Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.');
}
const llm = ai({
name: 'openai',
apiKey,
config: {
model: AxAIOpenAIModel.GPT54Mini,
temperature: 0,
},
});
const program = ax(
'emailText:string -> priority:class "high, normal, low", rationale:string'
);
const baseline = await program.forward(llm, {
emailText: 'Production checkout is failing for enterprise customers.',
});
const train = [
{
emailText: 'URGENT: checkout is down',
priority: 'high',
rationale: 'Production checkout outage blocks customers.',
},
{
emailText: 'Weekly newsletter',
priority: 'low',
rationale: 'Informational update with no action needed.',
},
{
emailText: 'Reminder to submit timesheets',
priority: 'normal',
rationale: 'Routine request with a clear deadline.',
},
];
const metric = ({ prediction, example }: { prediction: any; example: any }) =>
prediction.priority === example.priority ? 1 : 0;
const result = await optimize(program, train, metric, {
studentAI: llm,
teacherAI: llm,
numTrials: 1,
maxMetricCalls: 4,
});
if (!result.optimizedProgram) {
throw new Error('Optimizer did not return an optimized program.');
}
const saved = axSerializeOptimizedProgram(result.optimizedProgram);
const restored = axDeserializeOptimizedProgram(saved);
program.applyOptimization(restored);
const after = await program.forward(llm, {
emailText: 'Production checkout is failing for enterprise customers.',
});
console.log(
JSON.stringify(
{
baseline,
after,
bestScore: result.bestScore,
artifactComponents: Object.keys(saved.componentMap ?? {}),
},
null,
2
)
);TypeScript Agent Playbook — Verified Evolve
Repair a failing agent from a task set with playbook().evolve — mine failures, propose a bullet, keep it ONLY if it provably helps without regressing a held-out set.
- Provider:
openai - Env:
OPENAI_API_KEY,OPENAI_APIKEY - Level:
advanced - Run:
npm run example -- typescript src/examples/typescript/optimization/agent-playbook-evolve.ts - Source: src/examples/typescript/optimization/agent-playbook-evolve.ts
import { AxAIOpenAIModel, type AxMetricFn, agent, ai } from '@ax-llm/ax';
const apiKey = process.env.OPENAI_API_KEY ?? process.env.OPENAI_APIKEY;
if (!apiKey) {
throw new Error('Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.');
}
const llm = ai({
name: 'openai',
apiKey,
config: { model: AxAIOpenAIModel.GPT54Mini },
});
const LEDGER: Record<string, string> = {
'LGR-4471': 'balance 812.55 EUR (ref TXN-CC12)',
'LGR-9130': 'balance 77.10 EUR (ref TXN-QP55)',
'LGR-8290': 'balance 4210.09 EUR (ref TXN-KD73)',
};
// Same "LGR-" id-format trap: the agent recovers in-run but wastes a failing
// tool call each time — something a curated playbook rule can fix.
const lookupLedgerEntry = {
name: 'lookupLedgerEntry',
description: 'Look up a ledger entry by its id and return the balance',
parameters: {
type: 'object' as const,
properties: {
id: { type: 'string' as const, description: 'Ledger entry id' },
},
required: ['id'],
},
func: async ({ id }: { id: string }) => {
if (!/^LGR-\d{4}$/.test(id)) {
throw new Error(
`InvalidLedgerIdError: ledger entry ids use the "LGR-" prefix followed by 4 digits (got "${id}"); retry with e.g. "LGR-4471"`
);
}
return { id, entry: LEDGER[id] ?? 'no such entry' };
},
};
const support = agent('query:string -> answer:string', {
ai: llm,
functions: [lookupLedgerEntry],
maxTurns: 8,
});
// A deterministic scorer: correct answer with NO wasted failing tool call = 1;
// correct answer that tripped the trap = 0.4; wrong answer = 0.
const task = (entry: string, nonce: string, id: string) => ({
id,
input: {
query: `Look up ledger entry ${entry} and report its balance with the transaction ref.`,
},
criteria: 'Reports the correct balance and transaction ref.',
metadata: { nonce },
});
const metric: AxMetricFn = ({ example, prediction }) => {
const nonce =
(example as { metadata?: { nonce?: string } }).metadata?.nonce ?? '';
const answer = String(
(prediction as { output?: { answer?: unknown } }).output?.answer ?? ''
);
if (!answer.toLowerCase().includes(nonce.toLowerCase())) return 0;
return ((prediction as { toolErrors?: unknown[] }).toolErrors?.length ??
0) === 0
? 1
: 0.4;
};
// Verified evolve: mine the failing train tasks, propose a playbook bullet,
// and keep it ONLY if train improves AND the held-out task doesn't regress.
const result = await support.playbook().evolve(
{
train: [
task('4471', 'TXN-CC12', 'train-4471'),
task('9130', 'TXN-QP55', 'train-9130'),
],
validation: [task('8290', 'TXN-KD73', 'holdout-8290')],
},
{ metric, maxProposals: 2, runsPerTask: 2, verbose: true }
);
console.log(
`\nbaseline held-in ${result.baseline.heldIn.toFixed(2)} / held-out ${result.baseline.heldOut?.toFixed(2)}`
);
console.log(
`final held-in ${result.final.heldIn.toFixed(2)} / held-out ${result.final.heldOut?.toFixed(2)} (${result.metricCallsUsed} eval calls)`
);
for (const w of result.weaknesses) {
console.log(`\nweakness: ${w.description}`);
}
for (const o of result.outcomes) {
console.log(`proposal ${o.accepted ? 'ACCEPTED' : 'rejected'} — ${o.reason}`);
}
console.log('\nlearned playbook:\n');
console.log(support.getPlaybook()?.render() ?? '(none)');