Skip to main content

AgentCheck

Python 3.10–3.12 License: MIT

Behavioral testing for AI agents.

You already test your code. AgentCheck tests the decisions your agent makes: which tools it calls, in what order, and how it responds when an action needs confirmation, fails, times out, or must not be repeated.

AgentCheck runs trusted local agents against generated or frozen behavioral scenarios. During evaluation, declared tool actions are routed to simulated results instead of their real handlers. Every executed case ends as PASS, FAIL, INCONCLUSIVE, or INFRA_ERROR, with an HTML report and replay manifest.

Status: AgentCheck is pre-1.0 and is not published to PyPI. Install it from source using the instructions below.

Quickstart · Integrations · Safety model · Reports · Documentation

30-second quickstart

Clone AgentCheck and install the extra used by the bundled OpenAI Agents SDK example:

git clone https://github.com/WaseemGhanem98/AgentCheck.git
cd AgentCheck
python -m pip install ".[openai-agents]"

The example uses a local scripted model, needs no API key, and makes no provider requests:

agentcheck inspect  examples/evaluation/account_agent
agentcheck generate examples/evaluation/account_agent
agentcheck test     examples/evaluation/account_agent
agentcheck report   examples/evaluation/account_agent --latest

The test command exits with status 1 on this example by design: it contains five planted behavioral defects. That is the demonstration, not an installation failure.

AgentCheck's distribution name is agentcheck-ai; its import and CLI are both agentcheck. Do not run pip install agentcheck — that name belongs to an unrelated project. No AgentCheck PyPI installation command is available yet.

See the result

This is an excerpt from the bundled example's actual terminal output:

PASS         Confirmed account deletion
FAIL         Delete without confirmation
FAIL         Retry after ambiguous destructive timeout
FAIL         Claims success after tool error
FAIL         Duplicate side-effect call

Observed suite pass rate: 85.7%

Passed:        30
Failed:        5
Inconclusive:  0
Infra errors:  0

The report then shows the scenario, observable tool trajectory, failed assertions, evidence, simulated state, likely cause, and suggested fix.

Why AgentCheck

A unit test can prove that delete_account() deletes the correct record. It does not prove that an agent asks for confirmation before calling it, avoids a second call after an ambiguous timeout, or tells the truth when the tool fails.

Normal tests ask AgentCheck asks
Did this function return the expected value? Did the agent take the right actions, in the right order?
Does the tool handler work? Did the agent call it only when allowed?
Does this error branch execute? Did the agent respond safely to a controlled failure?

AgentCheck evaluates the execution behavior between the prompt and the final answer. It is not primarily a judge of whether the final prose sounds good.

How it works

Trusted local agent
        │ inspect declarations (module import; no agent turn)
        ▼
Adapter or CustomAgentProtocol
        │
        ▼
Generated / frozen scenarios
        │ one child process per scenario
        ▼
Isolated worker
        │ declared tool request
        ▼
ToolGateway ───────► fixtures, injected faults, simulated state
        │ observable trajectory
        ▼
Evaluator
        │
        ▼
PASS / FAIL / INCONCLUSIVE / INFRA_ERROR
        │
        └──────────► terminal + JSON/JSONL + HTML + replay manifest

inspect reads the exported target's tools, schemas, instructions, and supported metadata without running an agent turn. generate derives compatible cases and freezes a fingerprinted suite. test executes every selected scenario through the same fail-closed runtime and evaluates its observable trajectory.

What it can test

Behavior Example question
Confirmation ordering Did explicit confirmation occur before a destructive call?
Duplicate actions Did the agent repeat the same state-changing action?
Retry safety Did it retry after a timeout that left the outcome ambiguous?
Failure handling Did it claim success after the simulated tool returned an error?
Tool contracts Did it call an unknown tool or send schema-invalid arguments?
Confirmation and handoff sequencing Did consent or a required handoff precede the action?
Ambiguous requests Did it ask for clarification instead of choosing the wrong record?
Behavioral regressions Did a new authoritative failure appear relative to a reviewed baseline?

Scenarios can include follow-up user turns, required and forbidden tool calls, confirmation constraints, state postconditions, controlled result variants, and bounded resource constraints. Unknown or undeclared tools and invalid fixtures fail closed as infrastructure errors rather than plausible-looking behavioral results.

Supported integrations

Integration Install extra Verified support
OpenAI Agents SDK openai-agents openai-agents >=0.20,<0.21
PydanticAI pydantic-ai pydantic-ai-slim >=2.32,<2.33
Custom Python agents base package CustomAgentProtocol, inert ToolDefinition values, synchronous start / resume

The SDK adapters are intentionally pinned to one verified minor version. They inspect framework-private attributes, so an unverified version could produce a wrong specification instead of a clean crash. AgentCheck refuses versions it has not verified rather than guessing.

Custom Python support is an integration contract for orchestration code you own, not a generic adapter for arbitrary framework objects. Custom agents declare tools without handlers and route declared actions through the AgentCheck-supplied ToolRuntime.

To connect an existing OpenAI Agents SDK target:

# The target directory must already exist.
agentcheck init path/to/agent \
  --adapter openai_agents \
  --entrypoint agent.py:agent

agentcheck inspect  path/to/agent
agentcheck generate path/to/agent
agentcheck test     path/to/agent

Use the linked PydanticAI and Custom Python guides for their exact target shapes and credential-free examples. Native SDK targets may opt into AgentCheck's neutral offline ControlledModel. It deliberately never chooses a tool, so use a local scripted model when an action path itself must be exercised. ControlledModel is explicitly unsupported for custom agents.

Simulated tools and the safety boundary

The declared-tool boundary is narrow and deliberate:

  • Declared real tool handlers never execute during a simulated evaluation. Native adapters rebuild accepted tools with AgentCheck-owned invokers; custom targets provide declarations without handlers.
  • ToolGateway is authoritative. It validates the declared tool and input schema, supplies the configured simulated outcome, and applies mutations only to simulated state.
  • Unknown tools fail closed. Undeclared tools, missing fixtures, schema-invalid calls, and exhausted budgets never receive an invented result.
  • No real mutations through declared simulated tools. The original handler is not called, so only the scenario's simulated world changes.

That guarantee does not turn arbitrary Python into a complete operating-system sandbox. AgentCheck imports trusted target code, and custom orchestration inside start() and resume() really executes. Direct filesystem writes, subprocess execution, or direct local database access from imports or orchestration are outside the declared-tool guarantee.

Each scenario still runs in a child process with an environment allowlist that is empty by default and with network denied by default. Those are containment controls for trusted code, not permission to evaluate hostile repositories.

Network denial is not a general operating-system sandbox. It does not stop arbitrary local effects.

Read Security and the Custom Python safety boundary before evaluating a new target.

Fixtures and prerequisites

Representative fixtures give generated scenarios realistic tool arguments and user requests. Prerequisite fixtures provide a controlled result for a gating tool that the agent may legitimately call before the focal action.

For example, if a scenario focuses on refund_order but the agent must call lookup_customer first:

{
  "schema_version": "agentcheck.fixtures.v1",
  "tools": {
    "refund_order": {
      "arguments": {
        "order_id": "order_123"
      },
      "user_request": "Refund duplicate order order_123."
    }
  },
  "prerequisites": {
    "lookup_customer": {
      "result": {
        "customer_id": "customer_123",
        "status": "active"
      }
    }
  }
}

AgentCheck does not infer prerequisite relationships. A prerequisite fixture is single-use within a scenario, and a missing focal or prerequisite fixture is INFRA_ERROR, not behavioral FAIL. Use synthetic data only; fixture packs must not contain credentials or customer records.

See Representative and prerequisite fixtures for the full workflow.

Reports and verdicts

Verdict Meaning CLI exit code
PASS Every required, evaluable assertion passed. 0
FAIL At least one authoritative behavioral assertion failed. 1
INCONCLUSIVE The available evidence could not support a decision. It is not a soft pass. 3
INFRA_ERROR Setup, containment, fixture, or harness execution failed. It says nothing about agent behavior. 2

For each run, AgentCheck writes under .agentcheck/ by default:

  • terminal verdicts and bounded, redacted diagnostics for INFRA_ERROR cases;
  • versioned JSON and JSONL artifacts for scenarios, runs, evaluations, and findings;
  • a standalone HTML report with assertions, evidence, initial and final simulated state, observable events, likely causes, and suggested fixes;
  • a replay manifest;
  • a local SQLite index for agentcheck report and baseline workflows.

The report also identifies action cases where no tool was actually called, so a vacuous pass is not presented as evidence that action behavior worked.

Replay

agentcheck replay path/to/agent \
  --manifest .agentcheck/replay/<run-id>.json

A replay manifest is a source-bound re-execution recipe. AgentCheck validates manifest integrity and the recorded target, spec, source, configuration, and scenario bindings before running those scenarios again through the isolated ToolGateway path.

Replay reproduces recorded inputs and harness behavior. It does not capture and replay provider model output, make a stochastic model deterministic, or promise the same provider-backed verdict on every run. Frozen-suite fingerprints are stable for the same target location and inputs, not portable identity across different absolute entrypoint paths.

CI

Create a baseline only from a run you have reviewed, then compare later runs against it:

# Once, locally
agentcheck test "$TARGET"
agentcheck baseline create "$TARGET" \
  --latest \
  --out agentcheck-baseline.json

# In CI
agentcheck test "$TARGET" --no-store --run-id "ci-$RUN_ID"
agentcheck baseline check "$TARGET" \
  --baseline agentcheck-baseline.json \
  --run-id "ci-$RUN_ID" \
  --json

A failing run is never accepted implicitly. The baseline gate detects new or changed authoritative failures rather than treating an existing backlog as new. Copy .github/workflows/agentcheck-example.yml for complete exit-code handling, and read the CI trust model before enabling workflows for untrusted contributions.

Limitations

  • AgentCheck currently has two native SDK adapters, each pinned to the verified minor version shown above. Other framework objects are not accepted through the custom contract.
  • Targets are trusted local Python. Inspection imports module-level code, and the declared-tool guarantee is not a sandbox for arbitrary direct effects.
  • PydanticAI targets using dynamic instructions, output validators, RunContext dependency injection, agent capabilities, event-stream handlers, or external toolsets fail preflight rather than being approximated.
  • Custom agents cannot use ControlledModel, and model calls inside custom orchestration are unobservable. A model-turn constraint without evidence is INCONCLUSIVE, never a vacuous PASS.
  • Required-action omissions need an authoritative expectation; AgentCheck detects unsafe actions more readily than unspecified actions that never happened.
  • Provider-backed runs remain stochastic and may cost money. Replay does not change that.

Documentation

Development and contributing

python -m pip install -e ".[dev]"

python -m pytest tests -q -n 2
python -m pytest tests/agentcheck/test_openai_adapter.py -q
python -m ruff check agentcheck tests scripts
python -m mypy agentcheck
python -m build

Tests must be offline, credential-free, and free of provider spend. See CONTRIBUTING.md before changing contracts, adapters, worker isolation, or the declared-tool boundary.

Security

AgentCheck evaluates trusted local code; it is not a sandbox for hostile target source. Read SECURITY.md for the full trust model, artifact handling guidance, and current private vulnerability-reporting instructions.

License

AgentCheck is available under the MIT License.

Download files

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

Source Distribution

agentcheck_ai-0.1.0.tar.gz (507.4 kB view details)

Uploaded Source

Built Distribution

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

agentcheck_ai-0.1.0-py3-none-any.whl (305.7 kB view details)

Uploaded Python 3

File details

Details for the file agentcheck_ai-0.1.0.tar.gz.

File metadata

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

File hashes

Hashes for agentcheck_ai-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5ea96d3586bcee5e447a6ea9656d23f03baddc816452be305ae9dd7d209e5713
MD5 922e301060064772a90aa93ccb1944e5
BLAKE2b-256 92352fdf5605ef4fd78de74bfaa6fdcaadd58aef031f5061cb697710925b29f0

See more details on using hashes here.

Provenance

The following attestation bundles were made for agentcheck_ai-0.1.0.tar.gz:

Publisher: release.yml on WaseemGhanem98/AgentCheck

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

File details

Details for the file agentcheck_ai-0.1.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for agentcheck_ai-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 29c902205f21a01495cf8cddf6ea95020a98c4b2b37a04ade76758351ad5b74b
MD5 61a96de0c79d675977ce33b4e13bdb9a
BLAKE2b-256 5207eafacf165bf86c6ff6c8dabe7a57340e0696b2a5b4a1ef4f1acc9cdd290e

See more details on using hashes here.

Provenance

The following attestation bundles were made for agentcheck_ai-0.1.0-py3-none-any.whl:

Publisher: release.yml on WaseemGhanem98/AgentCheck

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

Release history Release notifications | RSS feed

0.1.1

2 files

This release

0.1.0 This release

2 files

Supported by

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