Skip to content

Example: skill evolution (real API, all modules)

The one complete, end-to-end example — a real dataset, a real LLM, and every module wired together. It evolves a skill playbook (accumulated lessons) on a BIG-Bench-Hard task, and it uses:

Module Used for
agentdescent.agents claude(...) / openai_compatible(...) → a Completion (provider layer)
agentdescent.evolution LLMAgent + evolve() + AppendRules strategy (the engine + rule)
agentdescent.parallel DataParallel — the parallelism method
governance blast_radius=0.2 → the L2 skill layer

Source: examples/skill_evolution.py.

from agentdescent import claude
from agentdescent import evolve, LLMAgent, AppendRules
from agentdescent import DataParallel

result = evolve(
    tasks, reward,                                   # your dataset + scorer
    agent=LLMAgent(claude(model="claude-haiku-4-5")),
    strategy=AppendRules(),                          # deduped, fused lessons
    parallel=DataParallel(),                         # parallelism method
    blast_radius=0.2,                                # L2 (a local skill)
    rounds=6, n_workers=4,
)
print(result.rendered, result.final_reward)

Choosing a task that can actually improve

The default task is salient_translation_error_detection for a specific reason. A capable model is at ceiling on most benchmarks (nothing to learn) or at floor on the hardest (a text lesson can't help), and even a mid-range category like MMLU-Pro law is a grab-bag of unrelated subtopics, so a lesson learned on one problem doesn't transfer to the held-out.

The task that works is a single-skill one where every problem is the same kind — here, "which of 6 error types does this translation have" — and the model is mid-range (haiku 4.5 ≈ 0.75). Then one learned lesson transfers to every held-out problem and there's headroom to improve.

A real run

--provider claude --model claude-haiku-4-5:

round 0  reward=0.750  items=1  +1/-0
round 1  reward=0.750  items=2  +1/-0
round 2  reward=0.792  items=3  +1/-0    ← a lesson transferred and lifted held-out
round 3  reward=0.792  items=3  +0/-1    ← the gate rejects a lesson that didn't help

0.750 → 0.792 held-out on a real benchmark, with the aggregator visibly committing helpful lessons and rejecting a useless one. The gains are modest — a text lesson only moves a strong model where its errors are process problems, not knowledge gaps — but the machinery is exactly the same as the deterministic examples that converge fully (router merge-vs-fork, etc.); there the agent can apply every learned rule, so the curve is steep.

Run it

The dataset is fetched through the agentdescent.dataloader data layer (cached, dependency-free), so the first --dry-run downloads it and every later run is offline.

python -m examples.skill_evolution --dry-run                 # dataset + estimate, no API
python -m examples.skill_evolution --model claude-haiku-4-5   # real run (Anthropic)
python -m examples.skill_evolution --task hyperbaton --rounds 8

Any model — the provider layer is pluggable:

# GLM or any OpenAI-compatible endpoint (key + base URL read from your env):
export OPENAI_BASE_URL=https://open.bigmodel.cn/api/paas/v4
export OPENAI_API_KEY=...        # set in your own shell; never in code
python -m examples.skill_evolution --provider glm --model glm-4.6

Robust to API failures

If the model backend fails mid-run (rate limit, credit exhaustion), the engine stops gracefully and returns the partial result — progress isn't lost.

Cost

A real run makes many calls (rollouts + held-out scoring + the aggregator's cheap-eval subsets). Defaults are small; --dry-run prints an estimate. Identical (skill, task) evaluations are memoized within a run.