Skip to main content

halflife

Your agent works on 5-step tasks. Does it work on 50?

tests PyPI Python License

halflife measures your agent's reliability half-life: the task length at which it succeeds half the time. Then it tells you where runs broke, what to change, and re-runs exactly the cases that failed once you've changed it.

Agents fail quietly as tasks get longer: they lose a running total from step 4 by step 30, skip the last item, pay a duplicate they saw twenty steps ago. Unit tests and single-turn evals don't catch it. halflife does, in your terminal, your tests, your CI, and your coding agent.

halflife terminal output: success by length, half-life 32.7 steps, failure modes, and fixes

The numbers above come from halflife demo, a simulated agent built to show the tool. Run it on your own agent for real numbers.

Start in one minute

pip install halflife-ai
halflife demo

Then pick the way in that fits what you have.

You build with Claude Code, Cursor or Codex → let your coding agent use it

Most agents today are built with a coding agent. Give it halflife once and it checks every agent it builds for you:

claude mcp add halflife -- halflife mcp

Then ask it in plain words: "check how reliable my agent is on long tasks and fix what breaks." It runs the benchmark or audits your logs, reads where runs broke and why, proposes a change for you to approve, and replays exactly the failing cases to prove the fix worked. A Claude skill and setup for other editors are in integrations/.

You have agent logs → audit them

No setup, any framework, any model. Point it at your logs (JSON Lines of tool calls) and let halflife find the rules your agent follows:

halflife audit agent_logs.jsonl --suggest-rules

It mines patterns from your own runs (a lookup before every action, one notification per claim, every listed item handled), writes them to rules_suggested.py with how often each held, and audits against them. Rules that held in every run guard future runs. Rules that broke in a few runs point straight at the runs that went wrong. The file describes what your agent usually does, so read it, delete anything that's coincidence, and keep what's policy.

Or write the rules yourself:

from halflife.rules import at_most_once, covers, eventually, requires

RULES = [
    covers("list_claims", field="claims", actions=["finalize_claim", "flag_for_review"], key="claim_id"),
    requires("finalize_claim", before="get_claim", match=["claim_id"]),
    eventually("finalize_claim", then="notify_member", match=["claim_id"]),
    at_most_once("notify_member", key=["claim_id"]),
]
halflife audit agent_logs.jsonl --rules rules.py

You get the half-life measured in tool calls, which rules break and how often, and where. No answer key needed. Try it on the sample: halflife audit examples/traces/claims.jsonl --suggest-rules.

You have agent code → benchmark it

from halflife import benchmark

@benchmark(suite="claims-intake")
def my_agent(task):
    return agent.run(task)
halflife run my_agent.py --quick

Your agent runs against a realistic simulated system with a hidden answer key, on tasks from 5 to 40 steps, several times each. Or scaffold everything with halflife init.

You want to compare models → bench them

halflife bench --model ollama:qwen2.5:7b --model anthropic:claude-sonnet-5-5 --quick

Built-in agents for Ollama, LM Studio, vLLM, OpenAI, OpenRouter, Together, Groq, Anthropic, and any OpenAI-compatible server. No code.

Every run tells you what to do next

Success rate falls with task length; fitted curve crosses 50% at 32.7 steps

  • Half-life with a 95% interval. Only lengths you actually tested count: if you tested up to 20 steps, it says "≥ 20", never a made-up number.
  • Decay shape. Do errors compound as tasks grow, or happen early? The fix differs.
  • Where runs broke. The first failure in each run, grouped: lost track of state, skipped a step, acted without a check, looped, broke a rule.
  • What to fix first. Ranked changes, structural fixes before prompt tweaks, each with a failing run as evidence.
  • Should it act on its own? --workflow-length 26 predicts success at your real workflow length and recommends act autonomously, act with approval, suggest only, or shadow mode.
  • Change since last run. Every run compares itself with the previous one: half-life 32.7 → 28.1 steps (−14%, worse).
  • An eval pack. The exact failing tasks, saved. After a fix: halflife run my_agent.py --replay .halflife/<run>.evals.json.
  • An HTML report to share, and JSON for your pipeline.

Make it a habit

In your tests:

import halflife

def test_agent_is_reliable():
    halflife.assert_reliable(my_agent, min_half_life=15)

In CI (halflife init --ci writes the workflow):

halflife run my_agent.py --min-half-life 20

In your README: halflife badge writes agent half-life

Plug in any agent

Your function gets a task:

task.instructions the goal and the policy
task.call(name, args) run a tool; errors come back as {"error": ...} so your agent can recover
task.openai_tools() tool definitions for OpenAI-compatible APIs (Ollama, vLLM, OpenRouter…)
task.anthropic_tools() tool definitions for the Anthropic API
task.max_tool_calls the budget; going over ends the run, which catches loops

Full examples: examples/claude_agent.py, examples/openai_agent.py.

Providers for halflife bench
Provider Key Notes
ollama none local; set OLLAMA_HOST if not localhost
lmstudio, vllm none local; --base-url if not the default port
compatible HALFLIFE_API_KEY (optional) any OpenAI-compatible server, with --base-url
openai OPENAI_API_KEY
openrouter OPENROUTER_API_KEY one key for most open and closed models
together, groq TOGETHER_API_KEY, GROQ_API_KEY
anthropic ANTHROPIC_API_KEY prompt caching on by default

Ollama: start it with a large context window, or long tasks fail for the wrong reason, because the default window silently drops older messages:

OLLAMA_CONTEXT_LENGTH=32768 ollama serve

Rules

Invariants checked on every run's tool calls. They need no answer key, so they work on any agent and on production logs.

Rule Fails when
requires(A, before=B, match=[...]) A happens without an earlier matching B
at_most_once(A, key=[...]) A happens twice for the same key
eventually(A, then=B, match=[...]) A is never followed by a matching B
covers(S, field, actions, key) an item listed by S never reaches one of the actions
never(A, when=...) A happens with forbidden arguments
no_loops(n) the same call repeats more than n times in a row
recovers_from_errors() the agent resends a call that just failed
@rule anything you can write as a function of the steps

Use them in audits, or add them to benchmarks: halflife run my_agent.py --rules rules.py.

Built-in suites

Suite Domain What gets harder with length
claims-intake Health plan claims: eligibility, network, coverage, prior auth, deductibles Members recur across claims; the deductible shown is from the start of the batch, so state must be carried
invoice-matching Accounts payable: blocked vendors, duplicates, price and quantity checks Duplicates repeat earlier invoices; receipts are consumed by earlier approvals

Every suite ships with a test proving that an agent following the written policy exactly scores 100%, so a failure is the agent's, not the answer key's. Write your own suite in about 40 lines: examples/custom_suite.py. halflife show --suite claims-intake --length 10 --answers prints exactly what an agent sees, plus the answer key.

How the number works

Success at length L is modeled as 2^(−(L/h)^k). h (half-life) and k (decay shape) are fit by maximum likelihood over every run, with a bootstrap 95% interval. The observed 50% crossing is reported alongside as a model-free check. Full definitions, file formats, and reporting rules are in SPEC.md, so any tool can produce comparable numbers.

Related work. Measuring capability by the length of task completed half the time builds on METR's time-horizon research on frontier models. halflife applies the idea to your own agent on your own workflows, explains why runs fail, and makes it a daily development check.

Commands

halflife run FILE[:function] [--quick] [--suite S] [--lengths 5,10,20,40] [--tasks N] [--runs N] [--rules FILE] [--workflow-length W] [--min-half-life H] [--replay PACK] [--save-traces FILE] [--workers N] [--out DIR]
halflife bench --model PROVIDER:MODEL [--model ...] [same options]
halflife audit TRACES.jsonl [--rules FILE] [--workflow-length W] [--min-half-life H]
halflife init [--suite S] [--ci]
halflife badge [RESULT.json]
halflife compare RESULT.json [RESULT.json ...]
halflife show [--suite S] [--length N] [--answers] [--json]
halflife mcp
halflife demo [--suite S] [--quick]
halflife suites

Roadmap

  • Generate test environments automatically from an MCP server or OpenAPI spec, so any agent gets a benchmark with no hand-written suite
  • Read OpenTelemetry GenAI traces directly in halflife audit
  • Adapters for popular agent frameworks
  • TypeScript SDK
  • More suites: support, IT ops, procurement, coding

Ideas and suites welcome: see CONTRIBUTING.md.

License

Apache 2.0

Metadata

Release files for halflife-ai 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for halflife-ai 0.3.0
File Size Uploaded
halflife_ai-0.3.0.tar.gz 71.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for halflife-ai 0.3.0
File Interpreter ABI Platform
halflife_ai-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 143.8 kB

Release files / halflife_ai-0.3.0.tar.gz

Download URL halflife_ai-0.3.0.tar.gz
Size 71.8 kB
Tags Source
SHA-256 checksum
How to use checksums
2f5999b9dadc437b3cea105e110abdc8b2df6605f7e48190d280427b4fc771b5
BLAKE2b-256 checksum
How to use checksums
77e17557cde995382db5db3ad63a11304868c556f85aabf0914108360d1cc8e8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / halflife_ai-0.3.0-py3-none-any.whl

Download URL halflife_ai-0.3.0-py3-none-any.whl
Size 71.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
375f071eb35a9aeb0c14c3aa127f5761dc18d4e26e0a3ad5751c1ad22a66ad0e
BLAKE2b-256 checksum
How to use checksums
ff847db2a50b507a3449194da3093c3c61fa7adae26a11d31520bb6768048cea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page