agentfault 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentfault-0.1.0/.github/workflows/ci.yml +68 -0
- agentfault-0.1.0/.github/workflows/langchain-example.yml +40 -0
- agentfault-0.1.0/.github/workflows/langgraph-integration.yml +38 -0
- agentfault-0.1.0/.github/workflows/publish.yml +114 -0
- agentfault-0.1.0/.gitignore +8 -0
- agentfault-0.1.0/.vscode/settings.json +21 -0
- agentfault-0.1.0/CHANGELOG.md +24 -0
- agentfault-0.1.0/CONTRIBUTING.md +38 -0
- agentfault-0.1.0/LICENSE +21 -0
- agentfault-0.1.0/PKG-INFO +146 -0
- agentfault-0.1.0/README.md +100 -0
- agentfault-0.1.0/RELEASE_CHECKLIST.md +30 -0
- agentfault-0.1.0/docs/custom-adapters.md +30 -0
- agentfault-0.1.0/examples/__init__.py +0 -0
- agentfault-0.1.0/examples/basic_scenario.py +22 -0
- agentfault-0.1.0/examples/basic_world.py +48 -0
- agentfault-0.1.0/examples/langchain_benchmark.py +140 -0
- agentfault-0.1.0/examples/langgraph_integration.py +143 -0
- agentfault-0.1.0/examples/openai_benchmark.py +61 -0
- agentfault-0.1.0/examples/run_agent.py +60 -0
- agentfault-0.1.0/pyproject.toml +69 -0
- agentfault-0.1.0/src/agentfault/__init__.py +54 -0
- agentfault-0.1.0/src/agentfault/agent/__init__.py +5 -0
- agentfault-0.1.0/src/agentfault/agent/base.py +11 -0
- agentfault-0.1.0/src/agentfault/agent/deterministic.py +80 -0
- agentfault-0.1.0/src/agentfault/agent/naive.py +55 -0
- agentfault-0.1.0/src/agentfault/benchmarks/__init__.py +17 -0
- agentfault-0.1.0/src/agentfault/benchmarks/models.py +141 -0
- agentfault-0.1.0/src/agentfault/benchmarks/packs/__init__.py +3 -0
- agentfault-0.1.0/src/agentfault/benchmarks/packs/buying.py +237 -0
- agentfault-0.1.0/src/agentfault/benchmarks/runner.py +83 -0
- agentfault-0.1.0/src/agentfault/cli.py +112 -0
- agentfault-0.1.0/src/agentfault/commerce/__init__.py +23 -0
- agentfault-0.1.0/src/agentfault/commerce/environment.py +119 -0
- agentfault-0.1.0/src/agentfault/commerce/models.py +45 -0
- agentfault-0.1.0/src/agentfault/commerce/tools.py +44 -0
- agentfault-0.1.0/src/agentfault/integrations/langgraph.py +227 -0
- agentfault-0.1.0/src/agentfault/integrations/openai/__init__.py +9 -0
- agentfault-0.1.0/src/agentfault/integrations/openai/agent.py +156 -0
- agentfault-0.1.0/src/agentfault/integrations/openai/tools.py +17 -0
- agentfault-0.1.0/src/agentfault/pytest_plugin.py +68 -0
- agentfault-0.1.0/src/agentfault/testing/__init__.py +19 -0
- agentfault-0.1.0/src/agentfault/testing/assertion.py +27 -0
- agentfault-0.1.0/src/agentfault/testing/assertions/__init__.py +7 -0
- agentfault-0.1.0/src/agentfault/testing/assertions/budget.py +39 -0
- agentfault-0.1.0/src/agentfault/testing/assertions/prohibited_action.py +21 -0
- agentfault-0.1.0/src/agentfault/testing/perturbations/__init__.py +12 -0
- agentfault-0.1.0/src/agentfault/testing/perturbations/base.py +8 -0
- agentfault-0.1.0/src/agentfault/testing/perturbations/change_inventory.py +14 -0
- agentfault-0.1.0/src/agentfault/testing/perturbations/change_price.py +14 -0
- agentfault-0.1.0/src/agentfault/testing/perturbations/fail_tool.py +22 -0
- agentfault-0.1.0/src/agentfault/testing/runner.py +107 -0
- agentfault-0.1.0/src/agentfault/testing/scenario.py +19 -0
- agentfault-0.1.0/src/agentfault/testing/scenario_loader.py +42 -0
- agentfault-0.1.0/src/agentfault/testing/scenario_result.py +14 -0
- agentfault-0.1.0/src/agentfault/testing/scenario_runner.py +99 -0
- agentfault-0.1.0/src/agentfault/testing/triggers/__init__.py +8 -0
- agentfault-0.1.0/src/agentfault/testing/triggers/base.py +9 -0
- agentfault-0.1.0/src/agentfault/testing/triggers/tool.py +20 -0
- agentfault-0.1.0/src/agentfault/tools/__init__.py +13 -0
- agentfault-0.1.0/src/agentfault/tools/errors.py +9 -0
- agentfault-0.1.0/src/agentfault/tools/executor.py +19 -0
- agentfault-0.1.0/src/agentfault/tools/registry.py +24 -0
- agentfault-0.1.0/src/agentfault/tools/tool.py +69 -0
- agentfault-0.1.0/src/agentfault/trajectory/__init__.py +5 -0
- agentfault-0.1.0/src/agentfault/trajectory/models.py +16 -0
- agentfault-0.1.0/tests/__init__.py +0 -0
- agentfault-0.1.0/tests/agent/__init__.py +0 -0
- agentfault-0.1.0/tests/agent/test_agent.py +63 -0
- agentfault-0.1.0/tests/agent/test_naive.py +34 -0
- agentfault-0.1.0/tests/benchmarks/test_buying_agent.py +47 -0
- agentfault-0.1.0/tests/benchmarks/test_runner.py +113 -0
- agentfault-0.1.0/tests/commerce/__init__.py +0 -0
- agentfault-0.1.0/tests/commerce/test_commerce.py +71 -0
- agentfault-0.1.0/tests/examples/test_langchain_benchmark.py +74 -0
- agentfault-0.1.0/tests/examples/test_langgraph_integration.py +26 -0
- agentfault-0.1.0/tests/examples/test_openai_benchmark.py +31 -0
- agentfault-0.1.0/tests/integrations/__init__.py +0 -0
- agentfault-0.1.0/tests/integrations/openai/__init__.py +0 -0
- agentfault-0.1.0/tests/integrations/openai/test_agent.py +255 -0
- agentfault-0.1.0/tests/integrations/openai/test_serialization.py +49 -0
- agentfault-0.1.0/tests/integrations/openai/test_tool_schema.py +40 -0
- agentfault-0.1.0/tests/test_cli.py +65 -0
- agentfault-0.1.0/tests/test_pytest_plugin.py +14 -0
- agentfault-0.1.0/tests/testing/__init__.py +0 -0
- agentfault-0.1.0/tests/testing/assertions/__init__.py +0 -0
- agentfault-0.1.0/tests/testing/assertions/test_budget.py +42 -0
- agentfault-0.1.0/tests/testing/mutations/__init__.py +0 -0
- agentfault-0.1.0/tests/testing/mutations/test_inventory_mutation.py +12 -0
- agentfault-0.1.0/tests/testing/mutations/test_price_mutation.py +12 -0
- agentfault-0.1.0/tests/testing/test_agent_runner.py +207 -0
- agentfault-0.1.0/tests/testing/test_fail_tool.py +9 -0
- agentfault-0.1.0/tests/testing/test_scenario.py +91 -0
- agentfault-0.1.0/tests/testing/test_scenario_runner.py +472 -0
- agentfault-0.1.0/tests/testing/test_tool_failure_recovery.py +165 -0
- agentfault-0.1.0/tests/testing/triggers/__init__.py +0 -0
- agentfault-0.1.0/tests/testing/triggers/mocks/__init__.py +5 -0
- agentfault-0.1.0/tests/testing/triggers/mocks/failing_agent.py +20 -0
- agentfault-0.1.0/tests/testing/triggers/test_tool.py +17 -0
- agentfault-0.1.0/tests/tools/__init__.py +0 -0
- agentfault-0.1.0/tests/tools/test_tools.py +20 -0
- agentfault-0.1.0/uv.lock +611 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
name: Python ${{ matrix.python-version }}
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: Check out repository
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- name: Set up Python
|
|
26
|
+
uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: ${{ matrix.python-version }}
|
|
29
|
+
|
|
30
|
+
- name: Set up uv
|
|
31
|
+
uses: astral-sh/setup-uv@v6
|
|
32
|
+
with:
|
|
33
|
+
enable-cache: true
|
|
34
|
+
cache-dependency-glob: uv.lock
|
|
35
|
+
|
|
36
|
+
- name: Install project and development dependencies
|
|
37
|
+
run: uv sync --locked --extra dev
|
|
38
|
+
|
|
39
|
+
- name: Run tests
|
|
40
|
+
run: uv run --locked pytest
|
|
41
|
+
|
|
42
|
+
- name: Lint
|
|
43
|
+
run: uv run --locked ruff check .
|
|
44
|
+
|
|
45
|
+
- name: Type-check
|
|
46
|
+
run: uv run --locked mypy src/agentfault
|
|
47
|
+
|
|
48
|
+
- name: Build distributions
|
|
49
|
+
run: uv build
|
|
50
|
+
|
|
51
|
+
- name: Install wheel in a clean environment and smoke-test it
|
|
52
|
+
shell: bash
|
|
53
|
+
run: |
|
|
54
|
+
python -m venv .venv-wheel-smoke
|
|
55
|
+
source .venv-wheel-smoke/bin/activate
|
|
56
|
+
python -m pip install --upgrade pip
|
|
57
|
+
python -m pip install dist/*.whl "pytest>=8.3,<9"
|
|
58
|
+
python - <<'PY'
|
|
59
|
+
from pathlib import Path
|
|
60
|
+
import agentfault
|
|
61
|
+
|
|
62
|
+
installed_from = Path(agentfault.__file__).resolve()
|
|
63
|
+
assert "site-packages" in str(installed_from), installed_from
|
|
64
|
+
print(f"Installed package: {installed_from}")
|
|
65
|
+
PY
|
|
66
|
+
agentfault --help
|
|
67
|
+
PYTHONPATH="$GITHUB_WORKSPACE" agentfault run examples.basic_scenario:build_scenario
|
|
68
|
+
pytest -q
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: LangChain example
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
paths:
|
|
6
|
+
- "examples/langchain_benchmark.py"
|
|
7
|
+
- "tests/examples/test_langchain_benchmark.py"
|
|
8
|
+
- ".github/workflows/langchain-example.yml"
|
|
9
|
+
- "README.md"
|
|
10
|
+
- "docs/custom-adapters.md"
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
langchain-example:
|
|
18
|
+
name: LangChain example (Python 3.12)
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- name: Check out repository
|
|
22
|
+
uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Set up Python
|
|
25
|
+
uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.12"
|
|
28
|
+
|
|
29
|
+
- name: Install project and integration dependencies
|
|
30
|
+
run: |
|
|
31
|
+
python -m pip install --upgrade pip
|
|
32
|
+
python -m pip install -e . "langchain-openai>=0.3,<2" "pytest>=8.3,<9"
|
|
33
|
+
|
|
34
|
+
- name: Test adapter without model API calls
|
|
35
|
+
run: pytest -q tests/examples/test_langchain_benchmark.py
|
|
36
|
+
|
|
37
|
+
- name: Check example formatting
|
|
38
|
+
run: |
|
|
39
|
+
python -m pip install "ruff>=0.12,<0.13"
|
|
40
|
+
ruff check examples/langchain_benchmark.py tests/examples/test_langchain_benchmark.py
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: LangGraph integration
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
paths:
|
|
6
|
+
- "src/agentfault/integrations/langgraph.py"
|
|
7
|
+
- "examples/langgraph_integration.py"
|
|
8
|
+
- "tests/examples/test_langgraph_integration.py"
|
|
9
|
+
- "docs/custom-adapters.md"
|
|
10
|
+
- ".github/workflows/langgraph-integration.yml"
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
langgraph-integration:
|
|
18
|
+
name: LangGraph integration (Python 3.12)
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- name: Check out repository
|
|
22
|
+
uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Set up Python
|
|
25
|
+
uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.12"
|
|
28
|
+
|
|
29
|
+
- name: Install package and LangGraph integration dependencies
|
|
30
|
+
run: |
|
|
31
|
+
python -m pip install --upgrade pip
|
|
32
|
+
python -m pip install -e . "langgraph>=1.0,<2" "pytest>=8.3,<9"
|
|
33
|
+
|
|
34
|
+
- name: Run LangGraph integration test
|
|
35
|
+
run: pytest -q tests/examples/test_langgraph_integration.py
|
|
36
|
+
|
|
37
|
+
- name: Run example
|
|
38
|
+
run: python -m examples.langgraph_integration
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
19
|
+
steps:
|
|
20
|
+
- name: Check out repository
|
|
21
|
+
uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: Set up Python
|
|
24
|
+
uses: actions/setup-python@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: ${{ matrix.python-version }}
|
|
27
|
+
|
|
28
|
+
- name: Set up uv
|
|
29
|
+
uses: astral-sh/setup-uv@v6
|
|
30
|
+
with:
|
|
31
|
+
enable-cache: true
|
|
32
|
+
cache-dependency-glob: uv.lock
|
|
33
|
+
|
|
34
|
+
- name: Install project and development dependencies
|
|
35
|
+
run: uv sync --locked --extra dev
|
|
36
|
+
|
|
37
|
+
- name: Run tests
|
|
38
|
+
run: uv run --locked pytest
|
|
39
|
+
|
|
40
|
+
- name: Lint
|
|
41
|
+
run: uv run --locked ruff check .
|
|
42
|
+
|
|
43
|
+
- name: Type-check
|
|
44
|
+
run: uv run --locked mypy src/agentfault
|
|
45
|
+
|
|
46
|
+
build:
|
|
47
|
+
name: Build and verify distributions
|
|
48
|
+
needs: test
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
steps:
|
|
51
|
+
- name: Check out repository
|
|
52
|
+
uses: actions/checkout@v4
|
|
53
|
+
|
|
54
|
+
- name: Set up Python
|
|
55
|
+
uses: actions/setup-python@v5
|
|
56
|
+
with:
|
|
57
|
+
python-version: "3.12"
|
|
58
|
+
|
|
59
|
+
- name: Set up uv
|
|
60
|
+
uses: astral-sh/setup-uv@v6
|
|
61
|
+
with:
|
|
62
|
+
enable-cache: true
|
|
63
|
+
cache-dependency-glob: uv.lock
|
|
64
|
+
|
|
65
|
+
- name: Ensure tag matches package version
|
|
66
|
+
run: |
|
|
67
|
+
python - <<'PY'
|
|
68
|
+
import os
|
|
69
|
+
import tomllib
|
|
70
|
+
from pathlib import Path
|
|
71
|
+
|
|
72
|
+
with Path("pyproject.toml").open("rb") as f:
|
|
73
|
+
project = tomllib.load(f)["project"]
|
|
74
|
+
|
|
75
|
+
expected = f"v{project['version']}"
|
|
76
|
+
actual = os.environ["GITHUB_REF_NAME"]
|
|
77
|
+
if actual != expected:
|
|
78
|
+
raise SystemExit(
|
|
79
|
+
f"Release tag {actual!r} does not match package version {expected!r}"
|
|
80
|
+
)
|
|
81
|
+
print(f"Preparing {project['name']} {project['version']}")
|
|
82
|
+
PY
|
|
83
|
+
|
|
84
|
+
- name: Build source distribution and wheel
|
|
85
|
+
run: uv build
|
|
86
|
+
|
|
87
|
+
- name: Validate distribution metadata
|
|
88
|
+
run: uv run --with twine twine check dist/*
|
|
89
|
+
|
|
90
|
+
- name: Upload distributions
|
|
91
|
+
uses: actions/upload-artifact@v4
|
|
92
|
+
with:
|
|
93
|
+
name: python-package-distributions
|
|
94
|
+
path: dist/
|
|
95
|
+
if-no-files-found: error
|
|
96
|
+
|
|
97
|
+
publish:
|
|
98
|
+
name: Publish to PyPI
|
|
99
|
+
needs: build
|
|
100
|
+
runs-on: ubuntu-latest
|
|
101
|
+
environment:
|
|
102
|
+
name: pypi
|
|
103
|
+
url: https://pypi.org/project/agentfault/
|
|
104
|
+
permissions:
|
|
105
|
+
id-token: write
|
|
106
|
+
steps:
|
|
107
|
+
- name: Download distributions
|
|
108
|
+
uses: actions/download-artifact@v4
|
|
109
|
+
with:
|
|
110
|
+
name: python-package-distributions
|
|
111
|
+
path: dist/
|
|
112
|
+
|
|
113
|
+
- name: Publish distributions
|
|
114
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"[python]": {
|
|
3
|
+
"editor.defaultFormatter": "charliermarsh.ruff",
|
|
4
|
+
"editor.formatOnSave": true,
|
|
5
|
+
"editor.codeActionsOnSave": {
|
|
6
|
+
"source.fixAll.ruff": "always",
|
|
7
|
+
"source.organizeImports.ruff": "always"
|
|
8
|
+
},
|
|
9
|
+
"editor.tabSize": 4,
|
|
10
|
+
"editor.insertSpaces": true,
|
|
11
|
+
"editor.detectIndentation": false,
|
|
12
|
+
"editor.rulers": [88]
|
|
13
|
+
},
|
|
14
|
+
"files.trimTrailingWhitespace": true,
|
|
15
|
+
"files.insertFinalNewline": true,
|
|
16
|
+
"files.trimFinalNewlines": true,
|
|
17
|
+
"python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
|
|
18
|
+
"python.analysis.autoImportCompletions": true,
|
|
19
|
+
"python.analysis.extraPaths": ["./src"],
|
|
20
|
+
"ruff.importStrategy": "fromEnvironment"
|
|
21
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Notable changes to Agent Fault are documented here.
|
|
4
|
+
|
|
5
|
+
This project is in alpha. Until the first release is tagged, changes are collected under `Unreleased`.
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- A versioned benchmark API with per-case results, assertion evidence, tool-call summaries, and scoring withheld for incomplete runs.
|
|
11
|
+
- The `buying-agent@1.0.0` benchmark suite for safe purchases under price and inventory changes.
|
|
12
|
+
- OpenAI and LangChain examples for the Benchmark API, plus a native LangGraph custom-scenario example.
|
|
13
|
+
- An optional LangChain integration workflow that checks adapter behavior without model API calls.
|
|
14
|
+
- CI validation for Python 3.12, 3.13, and 3.14, including a clean-wheel installation smoke test.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- The README is organized around the two public use cases: reusable benchmarks and custom scenarios, with framework examples for OpenAI, LangChain, and LangGraph.
|
|
18
|
+
- The product's display name is written as **Agent Fault**; the Python import package and distribution identifier remain `agentfault`.
|
|
19
|
+
- The deterministic commerce reference agent rechecks the offer price and inventory after adding an item to the cart.
|
|
20
|
+
|
|
21
|
+
### Notes
|
|
22
|
+
- APIs are in alpha and may change before the first stable release.
|
|
23
|
+
- The built-in benchmark currently covers buying agents; other categories can use custom scenarios or add versioned suites.
|
|
24
|
+
- The first release version and date will be recorded when a release is actually published.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Contributing to AgentFault
|
|
2
|
+
|
|
3
|
+
Thanks for contributing. AgentFault is an alpha project focused on testing how tool-using agents behave when the environment changes or tools fail.
|
|
4
|
+
|
|
5
|
+
## Development setup
|
|
6
|
+
|
|
7
|
+
Requirements: Python 3.12 or newer and [uv](https://docs.astral.sh/uv/).
|
|
8
|
+
|
|
9
|
+
From the repository root:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
uv sync --extra dev
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Checks before opening a pull request
|
|
16
|
+
|
|
17
|
+
Run the test suite, lint, type-check, and package build:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
uv run pytest
|
|
21
|
+
uv run ruff check .
|
|
22
|
+
uv run mypy src/agentfault
|
|
23
|
+
uv build
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
GitHub Actions runs the same checks on Python 3.12, 3.13, and 3.14, then installs the built wheel in a clean environment and smoke-tests the CLI and pytest integration.
|
|
27
|
+
|
|
28
|
+
## Change guidelines
|
|
29
|
+
|
|
30
|
+
- Keep agent execution generic. Domain-specific behavior belongs in environments, tools, scenarios, perturbations, or assertions.
|
|
31
|
+
- Prefer small, runnable examples that demonstrate one behavioral contract.
|
|
32
|
+
- When changing scenario behavior, add a test that covers the expected outcome and relevant trajectory evidence.
|
|
33
|
+
- Do not make an intentionally failing example appear to pass. Document expected failure behavior explicitly.
|
|
34
|
+
- Avoid adding runtime dependencies unless they are needed for a clear user-facing capability.
|
|
35
|
+
|
|
36
|
+
## Pull requests
|
|
37
|
+
|
|
38
|
+
Use a focused change with a Conventional Commit-style title, explain the motivation and behavioral impact, and note the checks you ran. Do not claim checks passed unless you ran them or CI reports success.
|
agentfault-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 danishmerani95
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: agentfault
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Agent Fault: open-source stateful reliability testing for AI agents
|
|
5
|
+
Project-URL: Homepage, https://github.com/danishmerani95/AgentFault
|
|
6
|
+
Project-URL: Repository, https://github.com/danishmerani95/AgentFault
|
|
7
|
+
Project-URL: Issues, https://github.com/danishmerani95/AgentFault/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/danishmerani95/AgentFault/blob/main/CHANGELOG.md
|
|
9
|
+
Author: Agent Fault Contributors
|
|
10
|
+
License: MIT License
|
|
11
|
+
|
|
12
|
+
Copyright (c) 2026 danishmerani95
|
|
13
|
+
|
|
14
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
15
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
16
|
+
in the Software without restriction, including without limitation the rights
|
|
17
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
18
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
19
|
+
furnished to do so, subject to the following conditions:
|
|
20
|
+
|
|
21
|
+
The above copyright notice and this permission notice shall be included in all
|
|
22
|
+
copies or substantial portions of the Software.
|
|
23
|
+
|
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
25
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
26
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
27
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
28
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
29
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
30
|
+
SOFTWARE.
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
Keywords: agent-reliability,agents,ai,evaluation,failure-injection,reliability,testing
|
|
33
|
+
Classifier: Development Status :: 3 - Alpha
|
|
34
|
+
Classifier: Programming Language :: Python :: 3
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
38
|
+
Requires-Python: >=3.12
|
|
39
|
+
Requires-Dist: openai>=1.0
|
|
40
|
+
Requires-Dist: python-dotenv>=1.0
|
|
41
|
+
Provides-Extra: dev
|
|
42
|
+
Requires-Dist: mypy<2,>=1.17; extra == 'dev'
|
|
43
|
+
Requires-Dist: pytest<9,>=8.3; extra == 'dev'
|
|
44
|
+
Requires-Dist: ruff<0.13,>=0.12; extra == 'dev'
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
|
|
47
|
+
# Agent Fault
|
|
48
|
+
|
|
49
|
+
**Break the world around your agent. Verify its behavior.**
|
|
50
|
+
|
|
51
|
+
Agent Fault tests tool-using AI agents against changing conditions: a price rises, inventory disappears, an account is suspended, or a tool fails while the agent is working.
|
|
52
|
+
|
|
53
|
+
It offers two APIs over the same stateful testing engine.
|
|
54
|
+
|
|
55
|
+
## 1. Benchmark API
|
|
56
|
+
|
|
57
|
+
**Use it to compare an agent against a reusable, versioned test suite.**
|
|
58
|
+
|
|
59
|
+
The built-in `buying-agent@1.0.0` benchmark contains five deterministic scenarios covering:
|
|
60
|
+
|
|
61
|
+
- Buying an eligible offer within budget.
|
|
62
|
+
- Price increases before validation.
|
|
63
|
+
- Inventory disappearing before cart creation.
|
|
64
|
+
- Price increases after an item enters the cart.
|
|
65
|
+
- Inventory disappearing after an item enters the cart.
|
|
66
|
+
|
|
67
|
+
A benchmark returns a pass percentage, per-case results, failed assertions, and observed tool calls. If any case has an execution error, the headline score is withheld rather than treating an invalid run as a pass or failure.
|
|
68
|
+
|
|
69
|
+
The API accepts an agent factory that implements AgentFault's `Agent` contract. OpenAI has a built-in adapter; other frameworks can provide an adapter for their tool-call loop.
|
|
70
|
+
|
|
71
|
+
Run the OpenAI example (requires an OpenAI API key; all tools still use a synthetic test environment):
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
uv sync --extra dev
|
|
75
|
+
export OPENAI_API_KEY=...
|
|
76
|
+
uv run python -m examples.openai_benchmark
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The example is in [`examples/openai_benchmark.py`](examples/openai_benchmark.py). It prints a JSON report and can be adapted to use your own prompts, model, and agent.
|
|
80
|
+
|
|
81
|
+
The [LangChain benchmark example](examples/langchain_benchmark.py) uses LangChain's `ChatOpenAI` and `bind_tools` APIs with the same versioned buying benchmark. AgentFault deliberately executes one tool call at a time, so the model's next decision sees the result and any state change introduced by the scenario. It requires an OpenAI API key and keeps all tool execution in the synthetic test world:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
export OPENAI_API_KEY=...
|
|
85
|
+
uv run --with "langchain-openai>=0.3,<2" python -m examples.langchain_benchmark
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
This is a LangChain chat-model adapter, not a wrapper around an arbitrary LangChain `AgentExecutor`; the AgentFault runner owns the tool loop to make stateful interventions deterministic.
|
|
89
|
+
|
|
90
|
+
## 2. Custom Scenario API
|
|
91
|
+
|
|
92
|
+
**Use it to test a failure mode specific to your application.**
|
|
93
|
+
|
|
94
|
+
A scenario defines your agent, isolated environment and tools, an optional perturbation, and assertions about acceptable behavior. Use it for buying, support, research, operations, or any workflow where an agent's actions depend on tool results or changing state.
|
|
95
|
+
|
|
96
|
+
For an agent that implements `Agent`, compose a `Scenario` and run it with `ScenarioRunner`:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from agentfault.testing import Scenario, ScenarioRunner
|
|
100
|
+
from agentfault.testing.assertions import MaxPriceAssertion
|
|
101
|
+
from agentfault.testing.perturbations import ChangePrice
|
|
102
|
+
from agentfault.testing.triggers import AfterTool
|
|
103
|
+
from agentfault.tools import ToolRegistry
|
|
104
|
+
|
|
105
|
+
# Supply these from your application or a test fixture:
|
|
106
|
+
# agent_under_test, test_environment, and the Tool objects.
|
|
107
|
+
tool_registry = ToolRegistry(test_tools)
|
|
108
|
+
|
|
109
|
+
scenario = Scenario(
|
|
110
|
+
name="price changes during checkout",
|
|
111
|
+
agent=agent_under_test,
|
|
112
|
+
environment=test_environment,
|
|
113
|
+
perturbations=[
|
|
114
|
+
(AfterTool("get_offers_for_product"),
|
|
115
|
+
ChangePrice("offer_sony_1", new_price=179.0)),
|
|
116
|
+
],
|
|
117
|
+
assertions=[MaxPriceAssertion(max_price=150.0)],
|
|
118
|
+
)
|
|
119
|
+
result = ScenarioRunner(tool_registry).run(scenario)
|
|
120
|
+
assert result.passed, [item.message for item in result.assertions if not item.passed]
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
For a graph that owns its own decision loop, use its integration runner instead of wrapping the entire graph as a generic `Agent`.
|
|
124
|
+
|
|
125
|
+
Run the LangGraph example (requires LangGraph; no model API key is needed):
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
uv run --with "langgraph>=1.0,<2" python -m examples.langgraph_integration
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The [LangGraph example](examples/langgraph_integration.py) uses a real `StateGraph` and `ToolNode`, a scripted decision node, and a fake account/refund world. It shows a custom scenario that suspends an account after lookup and checks that no refund tool is called. The current LangGraph integration supports synchronous `invoke`, sequential calls routed through the configured `ToolNode`; async execution, parallel calls, and other tool paths are not yet supported.
|
|
132
|
+
|
|
133
|
+
## Use cases
|
|
134
|
+
|
|
135
|
+
- **Buying agents:** stop unsafe purchases when prices or inventory change.
|
|
136
|
+
- **Support agents:** verify permissions and account state before refunds or account changes.
|
|
137
|
+
- **Search and research agents:** test stale, missing, or contradictory information.
|
|
138
|
+
- **Operations and workflow agents:** inject tool failures and check recovery or safe stopping.
|
|
139
|
+
|
|
140
|
+
The built-in benchmark currently covers buying. Other roles can be tested today with custom scenarios; additional benchmark packs can use the same versioned suite API.
|
|
141
|
+
|
|
142
|
+
## Safety and scope
|
|
143
|
+
|
|
144
|
+
Use fixtures, fake services, or an isolated sandbox. AgentFault does not make production tools safe automatically. Only actions routed through the configured executor/interceptor are recorded and can be perturbed.
|
|
145
|
+
|
|
146
|
+
Project status: **alpha**. APIs may change. See [custom adapter notes](docs/custom-adapters.md), [contributing](CONTRIBUTING.md), and the [changelog](CHANGELOG.md).
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Agent Fault
|
|
2
|
+
|
|
3
|
+
**Break the world around your agent. Verify its behavior.**
|
|
4
|
+
|
|
5
|
+
Agent Fault tests tool-using AI agents against changing conditions: a price rises, inventory disappears, an account is suspended, or a tool fails while the agent is working.
|
|
6
|
+
|
|
7
|
+
It offers two APIs over the same stateful testing engine.
|
|
8
|
+
|
|
9
|
+
## 1. Benchmark API
|
|
10
|
+
|
|
11
|
+
**Use it to compare an agent against a reusable, versioned test suite.**
|
|
12
|
+
|
|
13
|
+
The built-in `buying-agent@1.0.0` benchmark contains five deterministic scenarios covering:
|
|
14
|
+
|
|
15
|
+
- Buying an eligible offer within budget.
|
|
16
|
+
- Price increases before validation.
|
|
17
|
+
- Inventory disappearing before cart creation.
|
|
18
|
+
- Price increases after an item enters the cart.
|
|
19
|
+
- Inventory disappearing after an item enters the cart.
|
|
20
|
+
|
|
21
|
+
A benchmark returns a pass percentage, per-case results, failed assertions, and observed tool calls. If any case has an execution error, the headline score is withheld rather than treating an invalid run as a pass or failure.
|
|
22
|
+
|
|
23
|
+
The API accepts an agent factory that implements AgentFault's `Agent` contract. OpenAI has a built-in adapter; other frameworks can provide an adapter for their tool-call loop.
|
|
24
|
+
|
|
25
|
+
Run the OpenAI example (requires an OpenAI API key; all tools still use a synthetic test environment):
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
uv sync --extra dev
|
|
29
|
+
export OPENAI_API_KEY=...
|
|
30
|
+
uv run python -m examples.openai_benchmark
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The example is in [`examples/openai_benchmark.py`](examples/openai_benchmark.py). It prints a JSON report and can be adapted to use your own prompts, model, and agent.
|
|
34
|
+
|
|
35
|
+
The [LangChain benchmark example](examples/langchain_benchmark.py) uses LangChain's `ChatOpenAI` and `bind_tools` APIs with the same versioned buying benchmark. AgentFault deliberately executes one tool call at a time, so the model's next decision sees the result and any state change introduced by the scenario. It requires an OpenAI API key and keeps all tool execution in the synthetic test world:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
export OPENAI_API_KEY=...
|
|
39
|
+
uv run --with "langchain-openai>=0.3,<2" python -m examples.langchain_benchmark
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
This is a LangChain chat-model adapter, not a wrapper around an arbitrary LangChain `AgentExecutor`; the AgentFault runner owns the tool loop to make stateful interventions deterministic.
|
|
43
|
+
|
|
44
|
+
## 2. Custom Scenario API
|
|
45
|
+
|
|
46
|
+
**Use it to test a failure mode specific to your application.**
|
|
47
|
+
|
|
48
|
+
A scenario defines your agent, isolated environment and tools, an optional perturbation, and assertions about acceptable behavior. Use it for buying, support, research, operations, or any workflow where an agent's actions depend on tool results or changing state.
|
|
49
|
+
|
|
50
|
+
For an agent that implements `Agent`, compose a `Scenario` and run it with `ScenarioRunner`:
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from agentfault.testing import Scenario, ScenarioRunner
|
|
54
|
+
from agentfault.testing.assertions import MaxPriceAssertion
|
|
55
|
+
from agentfault.testing.perturbations import ChangePrice
|
|
56
|
+
from agentfault.testing.triggers import AfterTool
|
|
57
|
+
from agentfault.tools import ToolRegistry
|
|
58
|
+
|
|
59
|
+
# Supply these from your application or a test fixture:
|
|
60
|
+
# agent_under_test, test_environment, and the Tool objects.
|
|
61
|
+
tool_registry = ToolRegistry(test_tools)
|
|
62
|
+
|
|
63
|
+
scenario = Scenario(
|
|
64
|
+
name="price changes during checkout",
|
|
65
|
+
agent=agent_under_test,
|
|
66
|
+
environment=test_environment,
|
|
67
|
+
perturbations=[
|
|
68
|
+
(AfterTool("get_offers_for_product"),
|
|
69
|
+
ChangePrice("offer_sony_1", new_price=179.0)),
|
|
70
|
+
],
|
|
71
|
+
assertions=[MaxPriceAssertion(max_price=150.0)],
|
|
72
|
+
)
|
|
73
|
+
result = ScenarioRunner(tool_registry).run(scenario)
|
|
74
|
+
assert result.passed, [item.message for item in result.assertions if not item.passed]
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
For a graph that owns its own decision loop, use its integration runner instead of wrapping the entire graph as a generic `Agent`.
|
|
78
|
+
|
|
79
|
+
Run the LangGraph example (requires LangGraph; no model API key is needed):
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
uv run --with "langgraph>=1.0,<2" python -m examples.langgraph_integration
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The [LangGraph example](examples/langgraph_integration.py) uses a real `StateGraph` and `ToolNode`, a scripted decision node, and a fake account/refund world. It shows a custom scenario that suspends an account after lookup and checks that no refund tool is called. The current LangGraph integration supports synchronous `invoke`, sequential calls routed through the configured `ToolNode`; async execution, parallel calls, and other tool paths are not yet supported.
|
|
86
|
+
|
|
87
|
+
## Use cases
|
|
88
|
+
|
|
89
|
+
- **Buying agents:** stop unsafe purchases when prices or inventory change.
|
|
90
|
+
- **Support agents:** verify permissions and account state before refunds or account changes.
|
|
91
|
+
- **Search and research agents:** test stale, missing, or contradictory information.
|
|
92
|
+
- **Operations and workflow agents:** inject tool failures and check recovery or safe stopping.
|
|
93
|
+
|
|
94
|
+
The built-in benchmark currently covers buying. Other roles can be tested today with custom scenarios; additional benchmark packs can use the same versioned suite API.
|
|
95
|
+
|
|
96
|
+
## Safety and scope
|
|
97
|
+
|
|
98
|
+
Use fixtures, fake services, or an isolated sandbox. AgentFault does not make production tools safe automatically. Only actions routed through the configured executor/interceptor are recorded and can be perturbed.
|
|
99
|
+
|
|
100
|
+
Project status: **alpha**. APIs may change. See [custom adapter notes](docs/custom-adapters.md), [contributing](CONTRIBUTING.md), and the [changelog](CHANGELOG.md).
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# First Release Checklist
|
|
2
|
+
|
|
3
|
+
Use this checklist before publishing the first public Agent Fault release. Do not publish automatically from this checklist; repository visibility, package identity, version, and destination are deliberate release decisions.
|
|
4
|
+
|
|
5
|
+
## Project identity and license
|
|
6
|
+
|
|
7
|
+
- [ ] Confirm the repository is intended to be public before publishing.
|
|
8
|
+
- [x] Display-name decision: use **Agent Fault**. A separate product named AgentFault exists at [agentfault.com](https://agentfault.com/); the similar name remains a potential source of confusion, so the public description should clearly state that this project is an open-source AI-agent reliability testing library.
|
|
9
|
+
- [ ] Verify the PyPI distribution name `agentfault` directly against PyPI before upload; availability has not yet been conclusively established.
|
|
10
|
+
- [x] License decision confirmed: use the MIT License. Keep the `LICENSE` file and package metadata consistent with MIT.
|
|
11
|
+
- [ ] Review ownership and copyright information in `LICENSE`.
|
|
12
|
+
- [ ] Review the README, contributor guide, changelog, and example scenario commands for accuracy.
|
|
13
|
+
|
|
14
|
+
## Package readiness
|
|
15
|
+
|
|
16
|
+
- [x] Confirm the version in `pyproject.toml` (`0.1.0`) is the intended first alpha release version.
|
|
17
|
+
- [x] Confirm `uv.lock` is in sync with the project configuration (the current main-branch CI uses `uv sync --locked` successfully).
|
|
18
|
+
- [ ] Run CI on the exact commit intended for release and require all checks to pass.
|
|
19
|
+
- [ ] Build the source distribution and wheel with `uv build`.
|
|
20
|
+
- [ ] Inspect the distributions and metadata before upload; test installing the wheel in a clean environment.
|
|
21
|
+
- [ ] Verify the CLI entry point and pytest plugin work from the installed distribution.
|
|
22
|
+
|
|
23
|
+
## Publish and announce
|
|
24
|
+
|
|
25
|
+
- [ ] Decide on and configure the trusted publishing or PyPI credentials workflow.
|
|
26
|
+
- [ ] Publish only after the above checks and owner approval.
|
|
27
|
+
- [ ] Create a version tag (for example, `v0.1.0`) that matches the released package.
|
|
28
|
+
- [ ] Create a GitHub release with notes drawn from `CHANGELOG.md`.
|
|
29
|
+
- [ ] Verify the published package can be installed into a fresh environment and the documented quick start works.
|
|
30
|
+
- [ ] Announce the release with the repository link and clear alpha-status expectations.
|