Poisson Tasks is out. Find where your agent breaks before your users do. Read the launch
Poisson Prove is out. It tells you whether a change to your agent really changed how often it fails. Read the launch
Poisson Labs

Tools · open source · 0.4.2

Tasks

A pass rate tells you little when you can’t move the difficulty on purpose, and when another model decides what counted as a pass.

Tasks generates tool-use tasks at a difficulty you set, from a seed. Each task has one right end state, checked by code that comes out of the same generator, so nothing is graded by another model and the same seed gives the same task on any machine.

Poisson Tasks 0.1.0, 34 seconds, no sound.
The video’s text
  1. 0:00$ pip install poisson-tasks · poisson labs · tasks 0.1.0 · Evals measure what you test. · Tasks varies the conditions. · Your schemas. No live backend calls.
  2. 0:06The eval passed. · The tool call failed. · The task didn't.
  3. 0:10Poisson Tasks · Controlled failure tests. · Introduce a failure. Measure what the agent does next.
  4. 0:13tools: OpenAI, MCP, OpenAPI · responses: simulated from schemas · backend: never called · difficulty: one variable at a time · grading: deterministic code
  5. 0:18Pass@1 by injected fault count · gpt-5-nano · petstore · faults:f0 0.900 [0.700, 1.000] · faults:f1 0.800 [0.500, 1.000] · faults:f2 0.800 [0.500, 1.000] · faults:f4 0.300 [0.000, 0.600] · 10 tasks per level · 1 attempt · 95% intervals · task-level bootstrap
  6. 0:25Vary one condition at a time. · Tool failures · History length · Competing goals · Chain depth
  7. 0:28Find the failure. Before the release.
  8. 0:31poisson labs · tasks 0.1.0 · pip install poisson-tasks · poissonlabs.ai/tasks

Start

Needs Python 3.11 to 3.13, on macOS or Linux. Check with python3 --version first: on an older Python, pip won’t install this release, and may install an empty placeholder in its place without a word.

python3 --version
pip install poisson-tasks
poisson-tasks

The last line, with nothing after it, opens a guided session in your terminal. In a new folder it walks you through setup, one task to look at, the run and your first card. Nothing calls a model until you say yes to the run’s cost.

Who it is for

Agent teams

Tasks built on your own tools: an OpenAI tools file, an MCP server or tool list, or an OpenAPI document. Every call is answered by a simulator shaped by your schemas, so your backend is never called, and the card shows where your setup starts to break.

Here is one real run, on the Petstore API with gpt-5-nano and 10 tasks at each level. With no failed calls the pass rate was 0.90. With four, it was 0.30.

People training models

Checkable tool-use tasks at the difficulty you choose, scored exactly, and a card for each model you run. The same tasks export to verifiers, to run under your own loop.

poisson-tasks export --to verifiers

The guided session

Type poisson-tasks and it walks you through a first run.

With nothing after it, the command opens a guided session in your terminal. In a new folder it takes a first run in five steps: set up, one task to look at, the run, the card, and what next. In a folder that is already set up it shows where you are and offers the next steps. Nothing calls a model until you say yes to the run’s cost.

Every action in the session is one of the command’s own verbs, and each ends with the command line that does the same thing, so what you did in the session can run from a script. There is no AI in the session itself.

Opening

In a new folder the session opens with its five steps and says what it will not do: nothing calls a model until you say yes to the run’s cost.

The guided session's first screen in a new folder: its five steps (set up, one task, the run, the card, what next), marked free except the run, and the line “Nothing calls a model until you say yes to the run's cost.”
As text
There is no tasks.toml in /Users/Shared/tasks-first-run, so this starts with setup.

  1  Set up     what to test, and against which model              free
  2  One task   look at one task before anything runs              free
  3  The run    its plan and cost first; it asks before it spends
  4  The card   what each level was worth to the model             free
  5  What next  your options from here

Nothing calls a model until you say yes to the run's cost. Ctrl-C stops the step you are in and
leaves the folder as it was; you can leave at any prompt with quit.

Enter to start, or quit
›

Setup

It asks which model to test, which environment variable holds the key (the key itself is never stored or printed), the price, what to measure, how many tasks and attempts, and where to cap spending. The last question prints the plan’s cost before anything runs: 30 episodes, about $0.02.

Setup's questions four to nine: the environment variable that holds the key, the price, what to measure, tasks per level, attempts per task, and the spend cap, with the plan's cost on the last: 30 episodes, about $0.02.
As text
4. Which environment variable holds your API key?
   Tasks reads the key from it when it runs and never stores or prints it.
   Answer none for a model that needs no key.
   › [OPENAI_API_KEY]
   OPENAI_API_KEY is set.
   Check it with a free request to api.openai.com? [Y/n] n

5. Its price, in dollars per million tokens, from your provider's price page.
   It is used for the cost estimate and the spend cap. Input, cached input, output
   › [0.05, 0.005, 0.40 — read 2026-09-25; check them]

6. What do you want to measure? A first look at depth: tasks 1, 3 and 8 steps deep (recommended)

7. How many tasks per level?
   Each task is a different record and a different chain; more tasks give tighter numbers.
   › [10]

8. How many attempts at each task?
   More than one shows pass@k, the chance that one of k attempts passes. The published cards use 5.
   › [1]

9. Stop the run once it has spent
   This plan: 30 episodes, about $0.02 at the published card's usage. The cap is what holds.
   › [$1.00]

One task

The task’s reference solution, and each wrong answer it ships with, with the verdict its own checker gives it. No model is called, and no model judges.

One task, before anything runs: the reference solution, then each wrong answer the task ships with and the verdict its own checker gives it.
As text
the reference solution
  1. submit_review_purchase(record_id="able-sheet-shopping-question", entry_code="public")
     → 000001 ok           484a96b1ac1cc22e078d9482a37e79b6

the wrong answers it ships with, and their verdicts
  wrong_state               wrong_state           The model stopped with the record in a state that is
                                                  not the goal.
  turn_limit                turn_limit            The model used every model call it was allowed before
                                                  it finished.
  collateral_mutation       collateral_mutation   The model reached the goal but also changed something
                                                  the task did not ask for.
  overshoot                 overshoot             The model reached the goal and then kept changing the
                                                  record past it.
  malformed_call_clause_2   malformed_call        The model wrote a tool call the harness could not
                                                  read.
  malformed_call_clause_3   malformed_call        The model wrote a tool call the harness could not
                                                  read.
  malformed_call_clause_4   malformed_call        The model wrote a tool call the harness could not
                                                  read.

same as  poisson-tasks generate --show

Enter for step 3, the run, or quit
›

The run

Before anything is spent it checks that the key is accepted and shows its plan: 30 episodes, about $0.02, a stop at $1.00. Then it asks. Answer n and it stops, with nothing called and nothing spent.

The run's own screen: the key is accepted, then the plan (30 episodes against gpt-5-nano), the calls to expect, the cost, about $0.02, and the stop at $1.00, and the question Start? [y/N].
As text
Step 3 of 5 · The run

plan  30 episodes against gpt-5-nano-2025-08-07: about $0.02, and the run stops at $1.00
  tasks     depth at 1, 3 and 8, 10 tasks each · strict
  model     gpt-5-nano-2025-08-07 at api.openai.com · key in OPENAI_API_KEY: accepted
  calls     150 if every task is solved the shortest way · about 190 expected · at most 960 (32 per
            episode)
  cost      about $0.02 expected · the run stops at $1.00
  estimate  from the published gpt-5-nano card for this model
  harness   the first episode runs uv's installer (astral.sh inside a virtualenv) and fetches four
            packages and their dependencies from PyPI
  folder    runs/first-look-gpt-5-nano-2025-08-07 (a new run)
Start? [y/N]

In a folder with a run

In a folder that has a run, the session reads the folder and shows where you are: the settings, what each run kept and spent, the latest card’s levels and the next steps. This folder holds one real run, the Petstore API on your own tools with gpt-5-nano.

The session's home screen in a folder that has a run: the settings, the run's 40 of 40 episodes and $0.015, the latest card's four levels at 0.900, 0.800, 0.800 and 0.300, and five numbered next steps.
As text
folder       ~/petstore
settings     faults at 0, 1, 2 and 4 on your tools (petstore.json), 10 tasks each, against gpt-5-nano-2025-08-07
             cap $1.00 · key in OPENAI_API_KEY (set)
your tools   petstore: 16 tools, 3 refused · no flows declared, so depth and shape are not offered (add one: flow)
ready        python 3.11.7 · macOS · tokenizer present
runs         custom-gpt-5-nano-2025-08-07   40 of 40 · $0.015 · card built
latest card  faults:f0 0.900 · faults:f1 0.800 · faults:f2 0.800 · faults:f4 0.300  strict pass@1

next
  1  Read the card                                                   card
  2  Read the replies at faults:f4, where it broke most              replies
  3  Add a flow, so depth and shape can run on your tools            flow
  4  Measure another recipe on your tools                            setup
  5  Hand the tasks to verifiers (as the poisson-tasks-own taskset)  export

› a step's number, a word, help or quit

The card

Strict pass@1 at each level with its 95% interval, then what the card means and what it does not claim. It is one run, 10 tasks at each level with one attempt each: an example of what a card shows, not a result about gpt-5-nano.

The card for that run: strict pass@1 at faults 0, 1, 2 and 4 with 95% intervals, leaky pass@1, overshoot and the tasks and attempts behind each level, then what the card means and what it does not claim.
As text
› card
ok  card for gpt-5-nano-2025-08-07: faults at 0, 1, 2 and 4, 10 tasks each
  run                         custom-gpt-5-nano-2025-08-07 · $0.015 spent · 40 of 40

  level       strict pass@1   95% interval     0 ············· 1   leaky   overshoot   tasks × attempts
  ─────────────────────────────────────────────────────────────────────────────────────────────────────
  faults:f0           0.900   [0.700, 1.000]   ···········├──●─┤   0.900       0.000   10 × 1
  faults:f1           0.800   [0.500, 1.000]   ········├────●──┤   0.900       0.000   10 × 1
  faults:f2           0.800   [0.500, 1.000]   ········├────●──┤   0.800       0.000   10 × 1
  faults:f4           0.300   [0.000, 0.600]   ├────●────┤······   0.400       0.000   10 × 1

  what it means
    This card is gpt-5-nano-2025-08-07, hosted at api.openai.com, on your tools (petstore, 16 tools)
    with responses simulated from your schemas, over 10 tasks per level with 1 attempt at each. A rate
    is the share of this model's attempts on these tasks that reached the goal with no other change and
    ended with a reply (strict) or reached it at all (leaky). Each interval resamples tasks. A level is
    called different from its knob's first level only when the paired interval excludes zero and the gap
    is at least 0.15.
  what it does not claim
    • It says nothing about your real tools' outputs, errors or latency, or about your app: every
      response in these episodes was simulated from your schemas.
    • It is not comparable with the published cards or with built-in runs: the tasks differ, so none of
      its figures reads against theirs.
    • Within this card, levels compare with each other; across two cards, only when the tool file, the
      settings and the seeds are the same.
    • Without an intent for every tool, choosing a tool was partly a word match with its description.
    • A knob that shows no effect here may still matter in your app, and the reverse.
  beside the published cards  different tasks, so none of its figures reads against theirs

Real output of a session on a fresh install, drawn by a terminal emulator; the text of each picture is under it. The last two are the same session opened on the folder of one real run, made on 2026-10-21.

Nine dials, and what the evidence says

Four make tasks harder on at least one model. Five don’t yet, and say so.

Depth and the decoy-tools dial are measured on the two published cards. The other seven were measured by a pre-registered probe on the same two models, 60 tasks and 2 attempts per arm, scored on strict pass@1, lowest level against highest. A dial bites when it drops strict pass@1 by at least 0.15, with a 95% interval that excludes zero; for faults, block and arguments the control arm, which adds the same length without the dial, has to drop as well. Every dial works from the command line, whatever its status.

  • Depth

    Shown to make tasks harder on gpt-5-nano · the published cards

    How many chained calls the goal is away.

    depth · levels 1, 2, 3, 5, 8

    gpt-5-nano

    Harder: strict pass@1 0.547 at d1, 0.237 at d3, 0.177 at d5, then 0.870 at d8, where no stage lies past the goal.

    Qwen3-8B

    Not harder: it reaches the goal at every depth and goes past it at low levels, so strict pass@1 climbs from 0.000 at d1 to 0.997 at d8.

  • Faults

    Shown to make tasks harder on Qwen3-8B · the probe

    How many calls on the way answer "unavailable" and must be made again.

    faults · levels 0, 1, 2, 4

    gpt-5-nano

    Does not bite: 0.975 at faults:f0, 0.575 at faults:f4. Against the control arm, which adds the same length without the dial, the drop is 0.142, under 0.15.

    Qwen3-8B

    Bites: 0.992 at faults:f0, 0.167 at faults:f4.

  • History

    Shown to make tasks harder on both models · the probe

    How many tokens of earlier tool work the conversation holds.

    history · levels 0, 300, 600, 1200, 2400

    gpt-5-nano

    Bites: 0.908 at history:t0, 0.225 at history:t2400.

    Qwen3-8B

    Bites: 1.000 at history:t0, 0.692 at history:t2400.

  • Shape

    Shown to make tasks harder on Qwen3-8B · the probe

    How many records four stage calls advance side by side.

    shape · levels 1, 2, 4

    gpt-5-nano

    Does not bite: 0.325 at shape:w1, 0.625 at shape:w4.

    Qwen3-8B

    Bites: 0.967 at shape:w1, 0.608 at shape:w4.

  • Decoy tools

    Experimental · the published cards

    How many of the sixteen tools in the block are decoys.

    distractor · levels 0, 2, 4, 8, 14

    gpt-5-nano

    Not harder: strict pass@1 stays between 0.90 and 0.96, and no two adjacent levels differ.

    Qwen3-8B

    Not harder: strict pass@1 is 0.98 or more at every level.

  • Similarity

    Available · retested in v2

    How many digits of the right tool's ledger number each lookalike tool shares.

    similarity · levels 0, 1, 2, 3

    gpt-5-nano

    Does not bite: 0.408 at similarity:s0, 0.458 at similarity:s3.

    Qwen3-8B

    Does not bite: 1.000 at similarity:s0, 1.000 at similarity:s3.

  • Block

    Available · retested in v2

    How many tools are offered.

    block · levels 8, 16, 32, 64

    gpt-5-nano

    Does not bite: 0.883 at block:k8, 0.950 at block:k64.

    Qwen3-8B

    Does not bite: 1.000 at block:k8, 1.000 at block:k64.

  • Arguments

    Available · retested in v2

    How many values each call must carry, copied from the request.

    arguments · levels 2, 4, 6, 8

    gpt-5-nano

    Does not bite: 0.808 at arguments:a2, 0.717 at arguments:a8.

    Qwen3-8B

    Does not bite: 0.983 at arguments:a2, 0.833 at arguments:a8. Against the control arm, which adds the same length without the dial, the drop is 0.100, under 0.15.

  • Spread

    Available · retested in v2

    How many tool answers the entry code is split across.

    spread · levels 1, 2, 4

    gpt-5-nano

    Top easier: 0.067 at spread:p1, 0.317 at spread:p4. The top level passed more often than the base.

    Qwen3-8B

    Cannot tell: 0.008 at spread:p1, 0.000 at spread:p4. The base task passed 0.008, too seldom for a drop to show.

Strict pass@1 at the dial’s lowest and highest level. Two small models, measured once, are not the last word: the four marked “Available · retested in v2” are measured again on current models in the next release, and every contrast with its interval is in knobs and arms.

On your own tools

Every dial but the decoy-tools dial is offered, as far as your tools can support it. Depth and shape need flows. A flow is a link you declare between two of your tools: which field of one tool’s answer goes into which argument of the next. Tasks never guesses one, so without flows, depth and shape are listed as unavailable.

poisson-tasks init --own-flow FROM.FIELD:TO.PARAM

What a first run costs, and what it leaves

A first run is 30 episodes against gpt-5-nano: about two cents.

Before it spends anything, the run shows its plan, the expected cost and the cap, and it stops at the cap. By default the cap is the larger of $1.00 and twice the estimate, rounded up to a whole dollar. Ctrl-C stops a run, and running it again picks up where it stopped.

It writes to the folder you work in (tasks.toml, runs/, tasks/), and outside it only these:

  • the tokenizer file, 3.6 MB, fetched once into the installed package;
  • the harness’s setup: uv and uvx in ~/.local/bin, their receipt in ~/.config/uv, and four packages in uv’s cache;
  • verifiers’ cache, in ~/.cache/verifiers;
  • one /tmp/vf-port-<hex> file per episode, and one empty uv lock file in the temporary folder.

Your key goes to your model’s endpoint and nowhere else. The docs list each of these in full.

How the probe ran

Three things about the run, disclosed wherever its results appear.

  1. A check changed after its first result (gpt-5-nano). As registered, phase 1 stopped the probe if any of 21 base episodes made no tool call. gpt-5-nano’s first phase 1 stopped on 1 of 21, where the model asked for a record id in plain text instead of calling a tool. On 2026-10-13 the check was changed to the published cards’ own rule (stop above 10%, so 3 or more of 21), and the recorded phase 1 was read again once with nothing rerun. It passed. Qwen3-8B passed under the original rule.
  2. A crash at the start, and one arm run again (gpt-5-nano). The run hit macOS’s open-file limit while its first arm, similarity:s0, was in flight. The episodes lost in the crash voided that arm, so it was run once more, as the pre-registration allows for a cause on our side. The void attempt is kept. gpt-5-nano cost $1.60 of a $4.00 cap. The crash is fixed in this release: a run raises the limit itself, or refuses in one line saying how.
  3. More time for Qwen3-8B. The Colab run reached its two-hour allowance with 14 of 18 arms done and stopped cleanly. It was given more time and finished the last four with the same settings, using 2.56 hours in all.

The published cards

A card says what each level is worth to one named model.

60 tasks per level, 5 attempts each. Each level shows its pass rate with an interval, how often the model went past the goal, and its cost in calls and tokens. Both cards ship inside the package and rebuild byte for byte from their records.

DEPTH · dependent calls d1 0.55 d2 0.40 d3 0.24 d5 0.18 d8 0.87 DISTRACTOR · of 16 tools r0 0.92 r2 0.90 r4 0.91 r8 0.91 r14 0.96 0%25%50%75%100% PASS@1 · 60 TASKS × 5 ATTEMPTS PER LEVEL · TASK-RESAMPLED 95% ON STRICT
strict: reached the goal and stopped there leaky: reached the goal, and may have gone past it
Fig. 1gpt-5-nano-2025-08-07, 4,200 episodes. It usually reaches the goal, then goes past it: between 0.43 and 0.56 of attempts at d1 to d5 overshoot. Decoy tools do not make the task harder.
DEPTH · dependent calls d1 0.00 d2 0.40 d3 0.82 d5 0.86 d8 1.00 DISTRACTOR · of 16 tools r0 1.00 r2 0.99 r4 0.99 r8 0.98 r14 1.00 0%25%50%75%100% PASS@1 · 60 TASKS × 5 ATTEMPTS PER LEVEL · TASK-RESAMPLED 95% ON STRICT
strict: reached the goal and stopped there leaky: reached the goal, and may have gone past it
Fig. 2Qwen3-8B, 4,200 episodes. It reaches the goal at every depth and stops at the goal more often as depth grows: strict pass@1 climbs from 0.000 at d1 to 0.997 at d8.

What it cannot tell you yet

A level’s number is one model’s.

The two cards agree on none of the 12 adjacent level pairs and disagree on one, depth 2 against 3, in opposite directions. No number is claimed for a model that has not been run, and a dial that did not bite on these two models may bite on another.

The published cards were measured before the newer dials existed, so a card from your own run can’t be read beside them in this release: the comparison refuses in one line, and it comes back with v2’s cards. OpenAI shuts down the gpt-5-nano-2025-08-07 snapshot on 2026-12-11, and v2’s cards run on current models, a Claude model among them. verify doesn’t judge tasks made on your own tools yet; a run’s card judges each of those episodes by replay. Windows isn’t supported.

The release

0.4.2, released on 2026-11-12.

What it changed is in its changelog entry, and the notes of every release are in the docs changelog. The docs are copied from the repository at c8d48af.

MATH ASINFRASTRUCTURE.

Get started