Skip to main content

llmentary

Python (pytest) client for llmentary: deterministic trace-based integration tests for LLM apps.

CI codecov OpenSSF Scorecard License: MIT PyPI Python versions

llmentary is the Python/pytest client for the barzoj-co/llmentary recording proxy. It gives tests deterministic, trace-based assertions for OpenAI-compatible Chat Completions and Responses calls. There is no LLM judge: assertions inspect the requests, responses, tool calls, usage, timings, retries, and errors the proxy recorded.

Published platform wheels bundle proxy v0.2.0; see docs/binaries.md for how it is resolved and how to override it.

Install

pip install llmentary

Platform wheels bundle the version-pinned proxy binary (PROXY_VERSION, currently 0.2.0). The sdist is client-only and does not include a binary. Install a wheel with pip install --only-binary=:all: llmentary, or set LLMENTARY_BIN, or put llmentary on PATH. Run python -m llmentary doctor to see what this install resolved.

Supported wheel tags: manylinux2014_x86_64, manylinux2014_aarch64, macosx_11_0_x86_64, macosx_11_0_arm64, win_amd64.

For pytest fixture support:

pip install "llmentary[pytest]"

For the quickstart using openai-python:

pip install "llmentary[pytest,openai]"

Quickstart

Point pytest at an existing proxy, or let the fixture start one:

export LLMENTARY_PROXY_URL=http://127.0.0.1:7777
export LLMENTARY_CONTROL_URL=http://127.0.0.1:7778
pytest
export LLMENTARY_BIN=/path/to/llmentary
export LLMENTARY_UPSTREAM_BASE_URL=https://api.openai.com/v1
export LLMENTARY_UPSTREAM_API_KEY="$OPENAI_API_KEY"
pytest

In-process tests that can set headers:

from openai import OpenAI


def test_tool_flow(llmentary):
    client = OpenAI(
        api_key="test-key",
        base_url=llmentary.openai_base_url,
        default_headers=llmentary.headers,
    )

    first = client.chat.completions.create(
        model="gpt-4.1-mini",
        messages=[{"role": "user", "content": "Weather in Paris?"}],
        tools=[
            {
                "type": "function",
                "function": {
                    "name": "get_weather",
                    "parameters": {
                        "type": "object",
                        "properties": {"city": {"type": "string"}},
                        "required": ["city"],
                    },
                },
            }
        ],
    )
    tool_call = first.choices[0].message.tool_calls[0]

    client.chat.completions.create(
        model="gpt-4.1-mini",
        messages=[
            {"role": "user", "content": "Weather in Paris?"},
            first.choices[0].message,
            {"role": "tool", "tool_call_id": tool_call.id, "content": '{"weather":"sunny"}'},
        ],
    )

    llmentary.expect().tool_called("get_weather").args_subset(
        "get_weather", {"city": "Paris"}
    ).tool_result_fed_back("get_weather").no_errors()

Black-box / import-time clients that cannot send headers: set the service base URL to llmentary.path_base_url() inside the test, then import the app. The session id exists only after the fixture runs, so a module-level import is too early.

import importlib


def test_import_time_client(llmentary, monkeypatch):
    monkeypatch.setenv("OPENAI_BASE_URL", llmentary.path_base_url())
    app = importlib.import_module("myapp")
    app.client.chat.completions.create(
        model="gpt-4.1-mini",
        messages=[{"role": "user", "content": "ping"}],
    )
    llmentary.expect().prompt_contains("ping").no_errors()

See the proxy black-box guide and assertions guide.

The function-scoped llmentary fixture returns a Session: it creates a unique session id, exposes headers with X-Test-Session, waits for proxy quiescence before assertions, and deletes the session during teardown.

Waiting for calls

wait asks the proxy to return the session trace once the session has been idle for quiet, or to fail when timeout elapses. The proxy only reads these query parameters:

Parameter Default Meaning
timeout 30s Maximum time to wait for the session to become quiet
quiet 500ms How long the session must stay idle before wait returns
min_calls 0 Wait until this many finished calls exist, then for quiet

Override the defaults with environment variables. Each accepts a Go duration (45s, 200ms) or a bare number of seconds (45, 0.2):

Environment Default
LLMENTARY_WAIT_TIMEOUT 30s
LLMENTARY_WAIT_QUIET 500ms

The client HTTP deadline is timeout + quiet + 5s, so the client cannot abort before the proxy answers. A timeout is an error: wait timed out after 30s on session X (k calls so far, still active: n). Raise LLMENTARY_WAIT_TIMEOUT ….

Assertions

llmentary.expect().tool_called("search").called_times("search", 1)
llmentary.query(api_type="responses", model="gpt-4.1-mini").expect().no_errors()
llmentary.query().without_tools().expect().request_param("response_format.type", "json_schema")
mark = llmentary.mark()
llmentary.expect(since=mark).final_response_mentions_any("20", "sunny")

with llmentary.soft_expect() as expect:
    expect.tool_called("search")
    expect.response_contains("done")

Supported deterministic assertions include tool calls (tool_called, not_called, called_times, args_subset, args_matcher, order, parallel_tool_calls, tool_result_fed_back), request and finish metadata (model, request_param, finish_reason), usage and timing (tokens, latency, ttft, retries, no_retries), errors (no_errors, has_error, mid_stream_error), prompt or response text (prompt_contains, prompt_regex, response_contains, response_regex, response_json_valid, response_json_schema), and spec observability (no_spec_violations, no_ignored_fields). Failures raise AssertionError with the session trace summary. Use llmentary.list_sessions() when a wait or expect fails with zero calls, so the message can name the known session ids.

See docs/api.md, docs/pytest.md, and the proxy assertions guide.

llmentary repositories

Repository What
llmentary Recording proxy binary (Go)
llmentary-go Go client for go test
llmentary-python Python client and pytest plugin
llmentary-js TypeScript/JavaScript client for Vitest and Jest

License

Licensed under MIT, see LICENSE

Metadata

Release files for llmentary 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 llmentary 0.3.0
File Size Uploaded Provenance
llmentary-0.3.0.tar.gz 124.3 kB With provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for llmentary 0.3.0
File
llmentary-0.3.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
llmentary-0.3.0-py3-none-manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
llmentary-0.3.0-py3-none-manylinux2014_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details
llmentary-0.3.0-py3-none-macosx_11_0_x86_64.whl Python 3 none macOS 11.0+ x86-64 Details
llmentary-0.3.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details

Total release size: 24.4 MB

Release files / llmentary-0.3.0.tar.gz

Download URL llmentary-0.3.0.tar.gz
Size 124.3 kB
Tags Source
SHA-256 checksum
How to use checksums
44366a4988ccda8de36b1d7d559b62ac3c429c9783f0368f507860f5662cd9fe
BLAKE2b-256 checksum
How to use checksums
4785b99f7fbbc68bd2dac8907aaca12c1fa1f8e21d68d79b79d9031b772c90b1
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 21, 2026.

Transparency log

Release files / llmentary-0.3.0-py3-none-win_amd64.whl

Download URL llmentary-0.3.0-py3-none-win_amd64.whl
Size 5.0 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
471b7565d24da4f8b2c8b843c36c106dce00f77ee5aac0a471eb1cc1bbbe529c
BLAKE2b-256 checksum
How to use checksums
6be86c78531eace686610b2a0e6edeace9193a5924a197ed25dbf4cfe12c0eb2
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 21, 2026.

Transparency log

Release files / llmentary-0.3.0-py3-none-manylinux2014_x86_64.whl

Download URL llmentary-0.3.0-py3-none-manylinux2014_x86_64.whl
Size 4.9 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
db609a252f24919731b7e9b33059dff9f8bf48ad65a78b6316a11a4065cd4cdf
BLAKE2b-256 checksum
How to use checksums
8c2f9ffb334d9e426220a4c2020950ed125da9fe632456cb51a12cc6e725b101
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 21, 2026.

Transparency log

Release files / llmentary-0.3.0-py3-none-manylinux2014_aarch64.whl

Download URL llmentary-0.3.0-py3-none-manylinux2014_aarch64.whl
Size 4.5 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
0c6bfb8f59fb2088979538f2484fa19af35b7c78b5c040b7a4235ff6ae97dc3a
BLAKE2b-256 checksum
How to use checksums
11a195e7cb39b13e84a8a32b077831634569eb17ed3ffcd0e8ce456d6b7f0d66
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 21, 2026.

Transparency log

Release files / llmentary-0.3.0-py3-none-macosx_11_0_x86_64.whl

Download URL llmentary-0.3.0-py3-none-macosx_11_0_x86_64.whl
Size 5.1 MB
Tags Python 3 macOS 11.0+ x86-64
SHA-256 checksum
How to use checksums
929bb111f439ce90da4445659328eaaf9b3e3f27e586c8e9e2f9c85b79ce408e
BLAKE2b-256 checksum
How to use checksums
40d0445ecf29993bc1920136bcd0e3a260b7400d8e8362266338f1487d215dcc
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 21, 2026.

Transparency log

Release files / llmentary-0.3.0-py3-none-macosx_11_0_arm64.whl

Download URL llmentary-0.3.0-py3-none-macosx_11_0_arm64.whl
Size 4.7 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
1c3ae52f29d6eff04ba4f7b69562bb80ba29bbec31b08d7ace2f9e83cfc8f197
BLAKE2b-256 checksum
How to use checksums
ad351c47a2fac802595fccc0ce2468ea842953b34b7bf91f951dded98ce6f556
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 21, 2026.

Transparency log

Security for llmentary 0.3.0

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.

Full provenance

All 6 files in this release have been uploaded with provenance metadata.

Select from 6 files

Attestation for llmentary-0.3.0.tar.gz

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 21, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

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