Multi-provider harness for testing whether AI agents can use product docs and tools.
Project description
Gauntlet
Gauntlet is a harness for answering a practical question:
Can real external agents learn and use your product from docs, specs, and tools alone and, if not, exactly where does adoption break?
This project does not try to simulate an idealized agent in a perfect environment. It tries to simulate the messy reality:
- different model providers
- different behavior styles
- ambiguous docs
- brittle tool contracts
- recovery after failure
- noisy execution traces
The result is a pipeline that can:
- run an agent against a product task using only the provided docs and tools
- record the execution automatically
- judge the run afterward
- produce a report showing what happened, where it drifted, and what to fix
What Gauntlet Is Actually Doing
Gauntlet is organized as three layers.
Layer 1: Product Context And Execution Primitives
Layer 1 is the substrate.
It knows how to:
- load
llms.txtandllms-full.txt - shape docs into a manifest and retrievable chunks
- run generic execution tools like:
- HTTP
- CLI
- Python code
- Python SDK invocation
This is where the product-facing context lives.
Layer 2: Agent Execution
Layer 2 is the agent loop.
It takes:
- a task
- a provider/model
- an optional persona
- docs sources
Then it:
- prompts the model
- lets it call tools
- captures step-by-step execution
- returns a final answer or failure
- writes a structured Layer 2 run record
This is the “can the agent do it?” layer.
Layer 3: Judgment
Layer 3 is the post-run judge.
It consumes Layer 2 run records and produces:
- a normalized view of the run
- extracted evidence
- retrieved docs context
- batch-level cross-persona context
- a judged result
- a single HTML + JSON report
This is the “what happened, why, and how do we improve adoption?” layer.
Why This Exists
Most product teams ask some version of:
- “Will agents be able to use our product?”
- “Are our docs good enough for AI agents?”
- “If an agent fails, is it our product, our docs, or just the model?”
Gauntlet is built to make those failures attributable.
The goal is not merely pass/fail.
The goal is to separate:
- product problems
- docs problems
- runtime/tooling problems
- harness problems
- model capability limits
Core Ideas
Personas Matter
A single clean run is not enough.
Gauntlet can run multiple built-in personas that stress different failure modes:
methodical: follows docs literallyimpatient: optimizes for speedchaotic: reorders and perturbs flowsconfused: exposes clarity gapslong-running: stresses session continuityadversarial: pushes boundaries and validationparallel: stresses concurrency and state isolationrecovery: intentionally fails, then tries to recover
These are not cosmetic personas. They change how the agent behaves and what kinds of product adoption failures become visible.
Docs Are First-Class Inputs
Gauntlet is designed around product docs, especially:
llms.txtllms-full.txt
The agent is expected to use those as its operating context, and Layer 3 uses them again to judge whether the run:
- had enough documentation
- consulted the docs
- followed the docs
- or drifted away from the intended path
Every Run Becomes An Artifact
By default, gauntlet chat creates a batch folder automatically:
artifacts/gauntlet_runs/gauntlet_###/
That folder contains:
- one Layer 2 run record per persona
- one Layer 3 JSON report
- one Layer 3 HTML report
So one command maps to one investigation bundle.
Installation
Gauntlet is a Python package.
python -m pip install -e .
Or just install dependencies and run with python -m.
Current package metadata is in pyproject.toml.
Environment
Gauntlet loads environment variables through Layer 1’s environment loading.
Depending on what you run, you may need some of:
GEMINI_API_KEYOPENAI_API_KEYOLLAMA_BASE_URL- product-specific keys required by the product or API you are testing
Examples:
- Layer 2 provider calls use the provider API keys
- product workflows may need the target product's own API credentials
Quick Start
Run a single task with a single persona:
gauntlet chat \
--provider gemini \
--model gemini-2.5-flash \
--docs https://example.com/llms.txt \
--docs-full https://example.com/llms-full.txt \
"Use the documented API to complete the onboarding task and report what worked."
Run all personas:
gauntlet chat \
--provider gemini \
--model gemini-2.5-flash \
--docs https://example.com/llms.txt \
--docs-full https://example.com/llms-full.txt \
--persona all \
"Use the documented quickstart to create a resource, inspect it, and clean it up."
After completion, Gauntlet prints the batch folder and Layer 3 report paths.
Common Commands
List Personas
gauntlet personas
Show one persona in detail:
gauntlet personas recovery
Run With Debug Logs
gauntlet chat \
--provider gemini \
--model gemini-2.5-flash \
--docs https://example.com/llms.txt \
--docs-full https://example.com/llms-full.txt \
--debug \
"Use the documented API to complete the requested workflow"
Runtime Controls For Longer Workflows
Layer 2 checkpoints after every step. If a run reaches --max-steps, Gauntlet continues from the latest checkpoint instead of starting over, up to --max-restarts times.
gauntlet chat \
--provider gemini \
--model gemini-2.5-flash \
--docs https://example.com/llms.txt \
--docs-full https://example.com/llms-full.txt \
--max-steps 8 \
--max-restarts 3 \
--max-model-calls 40 \
--max-runtime-seconds 900 \
"Complete a longer browser workflow"
Resume a saved Layer 2 record from its latest checkpoint:
gauntlet chat \
--provider gemini \
--resume-run artifacts/gauntlet_runs/gauntlet_001/layer2_run.json
Inspect a replay-friendly step outline without re-running tools:
gauntlet replay artifacts/gauntlet_runs/gauntlet_001/layer2_run.json
Override The Output Directory
By default, Gauntlet creates artifacts/gauntlet_runs/gauntlet_<n>/.
If you want a different batch folder:
gauntlet chat \
--provider gemini \
--model gemini-2.5-flash \
--docs https://example.com/llms.txt \
--docs-full https://example.com/llms-full.txt \
--run-record artifacts/my_custom_batch \
"Use the documented quickstart to complete the requested workflow"
Run Layer 3 Directly
If you already have Layer 2 run records, you can judge them directly:
python -m gauntlet.layer3.cli \
'artifacts/gauntlet_runs/gauntlet_003/layer2_run_*.json' \
--output-dir artifacts/judge_runs \
--name replay_batch
Use An Optional Layer 3 Judge Model
Layer 3 defaults to a deterministic judge path. You can optionally configure a model-backed judge:
python -m gauntlet.layer3.cli \
'artifacts/gauntlet_runs/gauntlet_003/layer2_run_*.json' \
--output-dir artifacts/judge_runs \
--name llm_judged_batch \
--judge-provider gemini \
--judge-model gemini-2.5-pro \
--judge-fallback-deterministic
The same judge flags are available through gauntlet chat, and they will be used automatically when Layer 3 runs after Layer 2.
Output Structure
Typical batch folder:
artifacts/gauntlet_runs/gauntlet_003/
layer2_run_default.json
layer2_run_methodical.json
layer2_run_impatient.json
...
gauntlet_003.json
gauntlet_003.html
Layer 2 Run Records
These contain:
- provider/model/persona metadata
- docs sources
- step-by-step tool execution
- tool results
- final response
- terminal failure info if present
Layer 3 Report
The Layer 3 report is the interesting part.
It includes:
- batch summary
- issue breakdowns
- top recommendations
- per-persona outcomes
- execution timeline
- documentation evidence
- trace evidence
- successful path
- reproduction path
- cross-agent comparison
The HTML report is intended to be human-readable. The JSON report is intended to be machine-readable.
How To Think About The Reports
A “completed” run is not automatically a good run.
Gauntlet tries to surface:
- clean success
- recovered success
- suspect success
- hard failure
What matters is whether the agent:
- used the product correctly
- used the docs correctly
- produced an answer supported by evidence
The most valuable output is often not “it failed,” but:
it succeeded only after a noisy recovery path that a real external agent might never find
That is adoption signal.
Project Layout
gauntlet/
cli.py # top-level CLI
providers.py # provider adapters
run_orchestrator.py # shared CLI/server run pipeline
layer1/ # docs + tool primitives
layer2/ # agent execution loop
layer3/ # judgment and reporting
server/ # optional FastAPI API
artifacts/
gauntlet_runs/ # automatic end-to-end run bundles
Key files:
gauntlet/cli.pygauntlet/run_orchestrator.pygauntlet/providers.pygauntlet/layer2/agent_runner.pygauntlet/layer2/personas.pygauntlet/layer3/cli.pygauntlet/layer3/reasoning_judge.py
Current Status
Gauntlet is still evolving. The pipeline is real and usable, but this is not trying to hide the experimental nature of the work.
What is already real:
- multi-provider execution
- multi-persona runs
- automatic Layer 2 recording
- automatic Layer 3 reporting
- deterministic and optional model-backed judgment paths
What still needs continued refinement:
- docs retrieval quality
- citation precision
- judge quality
- attribution quality
- richer product-specific mission libraries
The Spirit Of The Project
Most agent evals ask:
“Did the model solve the task?”
Gauntlet asks a more useful question:
“If a serious external agent tried to adopt this product from the docs alone, where would it break, how would it break, and what should we fix first?”
That is what this repo is for.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file run_gauntlet-0.2.6.tar.gz.
File metadata
- Download URL: run_gauntlet-0.2.6.tar.gz
- Upload date:
- Size: 157.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
747ffb4b5c39e4067420917d3de709acf39f04abc685ec0dd304599a98b79bc9
|
|
| MD5 |
235b2c3b474d057a0e0886dd68009297
|
|
| BLAKE2b-256 |
ee1b790e258f5590c4a72c788aa4195a3f864cdabda220c00f17893184378d30
|
Provenance
The following attestation bundles were made for run_gauntlet-0.2.6.tar.gz:
Publisher:
publish.yml on AryanJain107/gauntlet
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
run_gauntlet-0.2.6.tar.gz -
Subject digest:
747ffb4b5c39e4067420917d3de709acf39f04abc685ec0dd304599a98b79bc9 - Sigstore transparency entry: 1609184262
- Sigstore integration time:
-
Permalink:
AryanJain107/gauntlet@e1aebfd0a2d8bfc1d8a3d15111d646dc28feb804 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/AryanJain107
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e1aebfd0a2d8bfc1d8a3d15111d646dc28feb804 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file run_gauntlet-0.2.6-py3-none-any.whl.
File metadata
- Download URL: run_gauntlet-0.2.6-py3-none-any.whl
- Upload date:
- Size: 181.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01e6070e1b9173c5747b66938a20c484f5c8ad9e7e32351fffe9ba5eef8181bc
|
|
| MD5 |
2f08047b8c74f2eb36ac2219b19fb2cc
|
|
| BLAKE2b-256 |
c323a51a658e0a327621d57d7b1ee09b0525ebd5b97ab89329c448ffc3a7717b
|
Provenance
The following attestation bundles were made for run_gauntlet-0.2.6-py3-none-any.whl:
Publisher:
publish.yml on AryanJain107/gauntlet
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
run_gauntlet-0.2.6-py3-none-any.whl -
Subject digest:
01e6070e1b9173c5747b66938a20c484f5c8ad9e7e32351fffe9ba5eef8181bc - Sigstore transparency entry: 1609184342
- Sigstore integration time:
-
Permalink:
AryanJain107/gauntlet@e1aebfd0a2d8bfc1d8a3d15111d646dc28feb804 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/AryanJain107
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e1aebfd0a2d8bfc1d8a3d15111d646dc28feb804 -
Trigger Event:
workflow_dispatch
-
Statement type: