Install any skill in seconds. Free to start, no credit card required.
Get Started Free →This skill helps an LLM generate correct playbook code using @ax-llm/ax. Use when the user asks about playbook(), AxPlaybook, context playbooks, evolving context, ACE / Agentic Context Engineering, agent.playbook(), or growing/applying task knowledge offline and online with evolve() and update().
.claude/skills/ax-llm-ax-playbook/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 39% | 0% |
| case-22 | ✗→✓ | ▲ Improved | 61% | 0% |
| case-01 | ✗→✓ | ▲ Improved | -13% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 90% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 53% | 0% |
Use this skill to generate context-playbook code. A playbook grows an evolving body of task knowledge and renders it into a program's context. The evolution engine (ACE — Agentic Context Engineering) is hidden behind playbook(...), exactly as optimize(...) hides its optimizer. Prefer the playbook(...) concept; only reach for AxACE directly when the user explicitly wants the low-level engine.
playbook(program, { studentAI, teacherAI? }); it returns an AxPlaybook handle.await pb.evolve(examples, metric) — returns { bestScore, playbook }.await pb.update({ example, prediction, feedback }) — no metric needed.pb.applyTo(program) (defaults to the bound program).pb.toJSON() and restore with playbook(program, opts).load(snapshot).pb.render() (markdown) and pb.getState() ({ playbook, artifact }).agent.playbook({ target: 'actor' | 'responder' }); default target is 'actor'.studentAI to run the program and an optional stronger teacherAI to reflect/curate.ai(), ax(), and agent() for new code.playbook(...) binds to an AxGen program; evolve/update need that program's signature.evolve() returns only { bestScore, playbook }. There is no Pareto front and no optimizedProgram — that is optimize(...)'s shape, not a playbook's.update({ example, prediction, feedback }) requires the full { example, prediction }; example must match the program's input fields (plus any expected output). Do not pass bare input fields at the top level.update() works without a prior evolve()/load() — the handle hydrates lazily on first use.applyTo() injects a ## Context Playbook block into the program description; calling it repeatedly recomposes from the original base (no stacking).metric deterministic and cheap, like a GEPA metric.pb.toJSON() and load(...) it into a fresh program for production.and verified agent evolution are available in TypeScript and the generated Python, Java, C++, Go, and Rust packages. Use each package's native casing and callback types.
typescriptimport { type AxMetricFn, ai, ax, playbook } from '@ax-llm/ax'; const program = ax('review:string -> sentiment:class "positive, negative"'); const studentAI = ai({ name: 'openai', apiKey: process.env.OPENAI_APIKEY! }); const metric: AxMetricFn = ({ prediction, example }) => (prediction as any).sentiment === (example as any).sentiment ? 1 : 0; const pb = playbook(program, { studentAI, maxEpochs: 2 }); const { bestScore } = await pb.evolve(train, metric); pb.applyTo(program);
typescript// After a real run, feed the outcome back so the playbook keeps learning. await pb.update({ example: { review: 'Five stars, would buy again.' }, prediction: { sentiment: 'negative' }, feedback: 'WRONG: enthusiastic praise is positive.', }); pb.applyTo(program);
typescriptconst snapshot = pb.toJSON(); // { playbook, artifact } — plain JSON // later, in another process / a production program instance: playbook(prodProgram, { studentAI }).load(snapshot).applyTo(prodProgram);
a.playbook({ target }) returns an agent-aware AxAgentPlaybook (the stage AxPlaybook handle plus an agent-level evolve). The one playbook the agent renders into its prompt grows three ways:
playbook option (see ax-agent) harvests each run's failures automatically — no dataset.apb.update({ example, prediction, feedback }).apb.evolve(dataset, options) runs the full agent over a task set, mines failure clusters, and proposes one playbook bullet per weakness; with verify (default on) it keeps a bullet only if held-in improves AND the validation held-out set does not regress, else exact rollback. verify: false = trust-batch. Bullets-only.typescriptconst a = agent('ticket:string -> reply:string', { ai }); const apb = a.playbook({ target: 'actor' }); // agent-aware handle; 'actor' (default) or 'responder' await apb.update({ example, prediction, feedback }); // online: injected into the live stage prompt const result = await apb.evolve( { train, validation }, // AxAgentEvalDataset { metric, runsPerTask: 2 }, // verify:true by default );
The agent-level evolve(dataset, options) is distinct from the program-level pb.evolve(examples, metric) above: it takes an AxAgentEvalDataset plus options, runs the whole pipeline, and returns baseline/final held-in & held-out with per-bullet outcomes (no { bestScore }). For full-pipeline tuning of agent instructions and demos (not the playbook) use agent.optimize(...) (GEPA).
Generated packages expose that same agent-bound loop with language-shaped APIs:
| Language | Agent-bound evolve call | |---|---| | Python | agent.playbook().evolve(dataset, options) | | Java | agent.playbook(null).evolve(dataset, options) | | C++ | agent.get_playbook()->evolve(dataset, options) | | Go | agent.GetPlaybook().EvolveAgent(ctx, dataset, options) | | Rust | playbook.evolve_agent(&mut agent, client, dataset, options) |
All five generated packages thread structured failureSignals through agent evaluation predictions. The default verify gate accepts a proposed bullet only when held-in score improves and held-out score stays within epsilon; rejection restores the exact prior snapshot. Scoring is host-shaped: TypeScript uses its metric, Python/Java/Go can accept a metric callback, and all generated ports can use task score/scores values plus the agent evaluation result.
playbook(...) — accumulate reusable, evolving task knowledge; the only path that also learns online via update(...).optimize(...) / agent.optimize(...) — tune instruction text and few-shot demos offline to a best/Pareto result.update() → you passed input fields at the top level; wrap them in example: { ... }.evolve() → the model already scored well, so nothing was curated; use harder/ambiguous examples or a weaker studentAI to surface lessons.apply is not false and you used agent.playbook(...) (not a bare playbook() on an internal program).ax-gepa - optimize(...) and AxGEPA for instruction/demo tuning.ax-agent-context - choosing between contextMap, contextPolicy, agent.playbook(...), and recall.ax-agent-optimize - agent.optimize(...) GEPA tuning for agents.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-04 | fail→pass | 15,004 | 11,395 | -24% | 1 | 1 | 0% | 3,050 | 4,233 | +39% | 0 | 0 | — |
case-22 | fail→pass | 12,373 | 8,550 | -31% | 1 | 1 | 0% | 2,013 | 3,234 | +61% | 0 | 0 | — |
case-01 | fail→pass | 15,922 | 6,711 | -58% | 1 | 1 | 0% | 3,888 | 3,374 | -13% | 0 | 0 | — |
case-02 | fail→pass | 17,210 | 5,069 | -71% | 1 | 1 | 0% | 1,577 | 2,997 | +90% | 0 | 0 | — |
case-03 | fail→pass | 11,783 | 8,592 | -27% | 1 | 1 | 0% | 2,291 | 3,500 | +53% | 0 | 0 | — |
case-05 | pass→fail | 17,886 | 9,182 | -49% | 1 | 1 | 0% | 3,186 | 3,613 | +13% | 0 | 0 | — |
case-06 | fail→pass | 12,617 | 4,043 | -68% | 1 | 1 | 0% | 2,370 | 2,557 | +8% | 0 | 0 | — |
case-07 | fail→pass | 9,329 | 3,331 | -64% | 1 | 1 | 0% | 1,692 | 2,491 | +47% | 0 | 0 | — |
case-08 | fail→pass | 8,491 | 3,388 | -60% | 1 | 1 | 0% | 1,619 | 2,422 | +50% | 0 | 0 | — |
case-09 | fail→pass | 9,709 | 3,264 | -66% | 1 | 1 | 0% | 1,664 | 2,448 | +47% | 0 | 0 | — |
case-10 | pass→pass | 14,018 | 2,921 | -79% | 1 | 1 | 0% | 2,392 | 2,383 | -0% | 0 | 0 | — |
case-11 | fail→pass | 10,694 | 5,878 | -45% | 1 | 1 | 0% | 2,197 | 3,027 | +38% | 0 | 0 | — |
case-12 | fail→pass | 11,035 | 7,233 | -34% | 1 | 1 | 0% | 2,174 | 3,329 | +53% | 0 | 0 | — |
case-13 | pass→pass | 8,162 | 2,959 | -64% | 1 | 1 | 0% | 1,356 | 2,393 | +76% | 0 | 0 | — |
case-14 | fail→pass | 7,603 | 1,479 | -81% | 1 | 1 | 0% | 1,388 | 2,057 | +48% | 0 | 0 | — |
case-15 | fail→pass | 14,561 | 5,843 | -60% | 1 | 1 | 0% | 2,955 | 3,004 | +2% | 0 | 0 | — |
case-16 | fail→pass | 9,399 | 6,193 | -34% | 1 | 1 | 0% | 1,773 | 3,030 | +71% | 0 | 0 | — |
case-17 | fail→pass | 14,108 | 8,288 | -41% | 1 | 1 | 0% | 2,866 | 3,421 | +19% | 0 | 0 | — |
case-18 | fail→fail | 17,912 | 7,466 | -58% | 1 | 1 | 0% | 3,427 | 3,457 | +1% | 0 | 0 | — |
case-19 | fail→pass | 7,152 | 5,281 | -26% | 1 | 1 | 0% | 1,434 | 2,830 | +97% | 0 | 0 | — |
case-20 | fail→pass | 11,230 | 5,370 | -52% | 1 | 1 | 0% | 2,182 | 2,917 | +34% | 0 | 0 | — |
case-21 | fail→pass | 10,354 | 2,593 | -75% | 1 | 1 | 0% | 1,944 | 2,299 | +18% | 0 | 0 | — |
case-23 | fail→pass | 15,573 | 5,067 | -67% | 1 | 1 | 0% | 2,530 | 2,730 | +8% | 0 | 0 | — |
case-24 | pass→pass | 13,736 | 8,064 | -41% | 1 | 1 | 0% | 2,307 | 3,207 | +39% | 0 | 0 | — |
case-25 | fail→pass | 12,172 | 2,503 | -79% | 1 | 1 | 0% | 2,131 | 2,061 | -3% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 25 cases were attempted. The headline lift of +76 percentage points is the difference between those two pass rates over the 25 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.