Skip to main content

High-performance evaluation framework for LLM agents

Project description

Assay Python SDK

Record deterministic traces from your Python agents for regression gating.

🚀 Golden Quickstart

The fastest way to regression test your AI agent.

1. Installation

pip install assay

2. Record (record.py)

Run your agent through the SDK to capture a trace. Pass your tool functions to tool_executors so Assay can record their inputs and outputs.

import os
import openai
from assay_sdk import TraceWriter, record_chat_completions_with_tools

# 1. Setup Client & Tools
client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY", "mock"))
TOOLS = [{
    "type": "function",
    "function": {
        "name": "GetWeather",
        "parameters": {"type": "object", "properties": {"location": {"type": "string"}}}
    }
}]

# 2. Define Execution Logic (The "Real" Code)
def get_weather(args):
    return {"temp": 22, "location": args.get("location")}

# 3. Record the Loop
writer = TraceWriter("traces/quickstart.jsonl")
result = record_chat_completions_with_tools(
    writer=writer,
    client=client,
    model="gpt-4o",
    messages=[{"role": "user", "content": "Weather in Tokyo?"}],
    tools=TOOLS,
    tool_executors={"GetWeather": get_weather}, # Link schema -> function
    episode_id="weather_demo",
    test_id="weather_check"
)
print(f"Agent Final Answer: {result['content']}")

3. Configure (assay.yaml)

Tell Assay what to check.

version: 1
model: "trace"
tests:
  - id: weather_check
    input:
      prompt: "Weather in Tokyo?" # Matches the recorded prompt
    expected:
      type: regex_match
      pattern: ".*" # Pass if any content returned (baseline check)

4. Verify

Run the regression gate. This replays your trace against the recorded tool outputs to ensure determinism.

# Verify strictly (fails if any tool call arg changed even slightly)
assay ci --config assay.yaml --trace-file traces/quickstart.jsonl --replay-strict --db :memory:

🌊 Advanced: Streaming support

Capture streaming responses while maintaining tool call execution.

from assay_sdk import record_chat_completions_stream_with_tools

# ... setup client & writer ...

result = record_chat_completions_stream_with_tools(
    writer=writer,
    # ... args ...
    stream=True # SDK handles chunk aggregation automatically
    # tool_executors={...} # Required if tools are used
)

Note: The hybrid wrapper (record_chat_completions_stream_with_tools) streams the thinking tokens to the user, executes tools, and then performs a standard follow-up call.

🛡️ Advanced: Privacy & Redaction

Protect sensitive data (PII, API keys) from ever hitting the trace file.

from assay_sdk import TraceWriter, make_redactor

# Create a redactor that scrubs keys and regex patterns
redactor = make_redactor(
    key_denylist={"authorization", "password", "api_key"},
    patterns=[r"sk-[a-zA-Z0-9]{20,}"] # Mask OpenAI keys
)

# Attach to writer - happens automatically on write
writer = TraceWriter("traces/secure.jsonl", redact_fn=redactor)

⚡ Async Support

Native async support for high-throughput applications (FastAPI, etc.) is available via the assay_sdk.async_openai submodule. It provides full parity with the sync API, including loop and streaming support.

❓ Troubleshooting

E_TRACE_EPISODE_MISSING

Cause: The test_id or episode_id in your trace doesn't match what assay ci expected from its config (or implicit default). Fix: Ensure your assay.yaml test IDs match the test_id passed to record_chat_completions....

"Duplicate prompt in strict replay"

Cause: You ran record.py twice without cleaning the trace file, so it contains two identical episodes. assay ci in strict mode doesn't know which one to replay. Fix:

  1. Truncate the file before recording: trace_path = "traces/my_trace.jsonl"; open(trace_path, 'w').close().
  2. Use unique episode_ids (e.g. UUIDs) for every run.

Project details


Release history Release notifications | RSS feed

Download files

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

Source Distribution

assay_it-0.8.0.tar.gz (28.0 kB view details)

Uploaded Source

Built Distribution

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

assay_it-0.8.0-py3-none-any.whl (38.5 kB view details)

Uploaded Python 3

File details

Details for the file assay_it-0.8.0.tar.gz.

File metadata

  • Download URL: assay_it-0.8.0.tar.gz
  • Upload date:
  • Size: 28.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for assay_it-0.8.0.tar.gz
Algorithm Hash digest
SHA256 73b212dc77dcf5e3dd5215d49b75b45dcbff2169a76ac3babce0d65e0115f669
MD5 ff546c80b62c73b9ebb788dee042f970
BLAKE2b-256 c6ee629fc844bc0480499e5c44053085589a458992d35f8f247aa872fa27bad4

See more details on using hashes here.

Provenance

The following attestation bundles were made for assay_it-0.8.0.tar.gz:

Publisher: publish.yml on Rul1an/assay

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

File details

Details for the file assay_it-0.8.0-py3-none-any.whl.

File metadata

  • Download URL: assay_it-0.8.0-py3-none-any.whl
  • Upload date:
  • Size: 38.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for assay_it-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fe2ea5e77f20c007205868d27cc4900c4514884be7bda09e5cab4c8a96db574b
MD5 1f06f64e5ffba393a9cb4b2a90385eea
BLAKE2b-256 4c83443f641f6a4c38b689d548aa3a233498aa2cfd0ca131b642e58f3fe924fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for assay_it-0.8.0-py3-none-any.whl:

Publisher: publish.yml on Rul1an/assay

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