Skip to main content

pymmary

Build Status Coverage PyPI

Agent-optimized output compressor for Python tooling.

Status: alpha. The pytest adapter is the only one so far.

Why

When an AI agent runs pytest, it pays for output written for humans: progress dots, a full traceback per failure, colour codes, a summary table. A green run of a thousand tests tells the agent one thing ("everything passed") and charges thousands of tokens to say it.

Pymmary detects that a coding agent is running the tool and replaces that output with compact JSON. Outside an agent, nothing changes: no agent detected, no compression, byte-identical output for humans.

It is a decision of the project, not of the agent's environment. Add it as a dev dependency and any agent that clones the repo and runs pytest benefits, with no per-machine setup.

Features

  • Automatic agent detection via environment variables, no configuration
  • Strict no-op fallback: no agent, no change to output
  • Compact JSON keyed by pytest nodeid, so failures are pasteable straight back into the CLI
  • Zero runtime dependencies in the core; each adapter ships behind its own extra
  • Hooks into the host tool's native extension points, no global monkey-patching

Requirements

  • Python 3.10+
  • pytest 9.1+ (optional, for pymmary[pytest])

Installation

pip install pymmary

With the pytest adapter:

pip install pymmary[pytest]

Usage

Nothing to wire up. Install it as a dev dependency and run your tools as usual. When a supported agent is detected, output is compressed.

pytest
{"tool":"pytest","result":"passed","exit_code":0,"duration":0.32,"summary":{"collected":1002,"passed":1002}}

On failure, only what the agent needs to act:

{"tool":"pytest","result":"failed","exit_code":1,"duration":0.32,"summary":{"collected":1002,"passed":999,"failed":2,"error":1},"failures":[{"nodeid":"tests/test_api.py::TestAuth::test_login[user-2]","phase":"call","file":"tests/test_api.py","line":42,"type":"AssertionError","message":"assert 401 == 200"}]}

Every payload is a single line. That is the actual output, not a formatting choice. Expanded, so the fields are readable:

{
  "tool": "pytest",
  "result": "failed",
  "exit_code": 1,
  "duration": 0.32,
  "summary": { "collected": 1002, "passed": 999, "failed": 2, "error": 1 },
  "failures": [
    {
      "nodeid": "tests/test_api.py::TestAuth::test_login[user-2]",
      "phase": "call",
      "file": "tests/test_api.py",
      "line": 42,
      "type": "AssertionError",
      "message": "assert 401 == 200"
    }
  ]
}

nodeid is the whole point: paste it straight back into pytest "tests/test_api.py::TestAuth::test_login[user-2]" and the agent has its reproduction command.

A run that fails to collect is never reported as a pass. The verdict follows pytest's exit code, not our own tally:

{"tool":"pytest","result":"failed","exit_code":2,"duration":0.008,"summary":{"error":1},"failures":[{"nodeid":"test_broken.py","phase":"collect","file":"test_broken.py","line":1,"type":"ModuleNotFoundError","message":"No module named 'requests'"}]}

Configuration

Two environment variables, no config file and no CLI flags:

Variable Effect
PYMMARY_FORCE=1 Compress even when no agent is detected, useful to see what an agent sees
PYMMARY_MAX_FAILURES=N How many failures to spell out. Default 20; 0 keeps every one of them

The cap is about diminishing returns, not size: an agent facing 400 failures fixes a handful and runs again, so the rest cost context and buy nothing. summary always counts the whole run, and whatever was left out is declared in failures_omitted.

How much it actually saves

Tokens, not bytes: tokens are what an agent pays for. Counted with tiktoken (o200k_base) on real pytest output:

Scenario pytest pymmary Saving
1 test, green 136 31 4.4×
100 tests, green 146 31 4.7×
1000 tests, green 238 33 7.2×
3 tests, 1 failure 218 82 2.7×
5 failures 457 246 1.9×
400 tests, 20 failures 1,445 900 1.6×
400 failures 24,868 884 28.1×

cl100k_base agrees within 3%.

The floor is 1.6×, on a suite with many failures but no cap hit. Failure bodies are the one thing that does not compress much. The ceiling is a big green suite, where pymmary's output stays flat at ~31 tokens no matter how many tests ran.

Note that JSON tokenizes worse than prose, all those quotes and braces, so the saving in tokens is consistently lower than the saving in bytes. The 1000-test green run is 14.6× smaller in bytes but only 7.2× cheaper in tokens. These are OpenAI encodings; Anthropic does not publish a tokenizer for current Claude models, so treat this as a close proxy rather than an exact figure.

Limitations

  • pytest-xdist: pymmary stands down completely under -n, leaving normal pytest output. The controller never runs the tests itself, so a compressed summary would count none of them. Aggregating the worker streams is planned.
  • pytest 9.1 is a hard floor. The adapter unregisters pytest's terminal reporter to own the output. Before 9.1, pytest built assertion explanations through config.get_terminal_writer(), which asserts that reporter is still registered, so on older versions every assert failure degrades to a bare AssertionError pointing into pytest's internals. That is the one payload this library exists to produce, so the floor is enforced rather than worked around.

Related

Companion to pyssertive (assert phase) and pyrrange (arrange phase). Pymmary covers the report phase, for AI consumers.

Inspired by laravel/pao, the PHP original. Pymmary keeps its envelope recognizable but speaks pytest's own vocabulary rather than PHPUnit's.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pymmary-0.1.1.tar.gz (17.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pymmary-0.1.1-py3-none-any.whl (11.8 kB view details)

Uploaded Python 3

File details

Details for the file pymmary-0.1.1.tar.gz.

File metadata

  • Download URL: pymmary-0.1.1.tar.gz
  • Upload date:
  • Size: 17.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for pymmary-0.1.1.tar.gz
Algorithm Hash digest
SHA256 51ca8e7c1cc327eb6e4b38236bd31745f39593fba784f57ed40ce843cf0748d8
MD5 bcd29f4e6a2b9bdb64261c809dafa7a2
BLAKE2b-256 70228a2daa371cc03e2b7edcb18f011a54562cbe39a8ca600801824a97748a48

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymmary-0.1.1.tar.gz:

Publisher: release.yml on othercodes/pymmary

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pymmary-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: pymmary-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 11.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for pymmary-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 26b5040a70bbf13f25e3bdb4d268180900c34f22cd2eccd84b93816e1bf8b176
MD5 e818e07f58bc403616ccc24bacb96d7f
BLAKE2b-256 f96774d00fd39ab45b8c816abe80e082bba249c5db98a3e6c0acc5aab3661979

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymmary-0.1.1-py3-none-any.whl:

Publisher: release.yml on othercodes/pymmary

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page