gauntlet-agent 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.
- gauntlet_agent-0.1.0/LICENSE +21 -0
- gauntlet_agent-0.1.0/PKG-INFO +211 -0
- gauntlet_agent-0.1.0/README.md +195 -0
- gauntlet_agent-0.1.0/gauntlet/__init__.py +8 -0
- gauntlet_agent-0.1.0/gauntlet/adversaries.py +311 -0
- gauntlet_agent-0.1.0/gauntlet/calibration.py +109 -0
- gauntlet_agent-0.1.0/gauntlet/cli.py +166 -0
- gauntlet_agent-0.1.0/gauntlet/graders.py +138 -0
- gauntlet_agent-0.1.0/gauntlet/llm.py +100 -0
- gauntlet_agent-0.1.0/gauntlet/report.py +92 -0
- gauntlet_agent-0.1.0/gauntlet/runner.py +189 -0
- gauntlet_agent-0.1.0/gauntlet_agent.egg-info/PKG-INFO +211 -0
- gauntlet_agent-0.1.0/gauntlet_agent.egg-info/SOURCES.txt +24 -0
- gauntlet_agent-0.1.0/gauntlet_agent.egg-info/dependency_links.txt +1 -0
- gauntlet_agent-0.1.0/gauntlet_agent.egg-info/entry_points.txt +2 -0
- gauntlet_agent-0.1.0/gauntlet_agent.egg-info/requires.txt +6 -0
- gauntlet_agent-0.1.0/gauntlet_agent.egg-info/top_level.txt +1 -0
- gauntlet_agent-0.1.0/pyproject.toml +24 -0
- gauntlet_agent-0.1.0/setup.cfg +4 -0
- gauntlet_agent-0.1.0/tests/test_adapters.py +96 -0
- gauntlet_agent-0.1.0/tests/test_calibration.py +74 -0
- gauntlet_agent-0.1.0/tests/test_engine.py +145 -0
- gauntlet_agent-0.1.0/tests/test_extended.py +54 -0
- gauntlet_agent-0.1.0/tests/test_multiturn.py +95 -0
- gauntlet_agent-0.1.0/tests/test_offline.py +56 -0
- gauntlet_agent-0.1.0/tests/test_trace.py +107 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rohan Pandey
|
|
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,211 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gauntlet-agent
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Break your agent before your users do. Adversarial stress-testing and regression suites for AI agents.
|
|
5
|
+
Author: Rohan Pandey
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: ai,agents,llm,evaluation,red-team,testing,reliability,ci
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Provides-Extra: llm
|
|
12
|
+
Requires-Dist: anthropic>=0.40; extra == "llm"
|
|
13
|
+
Provides-Extra: dev
|
|
14
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
|
|
17
|
+
# Gauntlet
|
|
18
|
+
|
|
19
|
+
[](https://pypi.org/project/gauntlet-agent/)
|
|
20
|
+
[](https://pypi.org/project/gauntlet-agent/)
|
|
21
|
+
[](LICENSE)
|
|
22
|
+
[](https://github.com/GauntletVectorLabs/gauntlet/actions/workflows/ci.yml)
|
|
23
|
+
|
|
24
|
+
**Break your agent before your users do.**
|
|
25
|
+
|
|
26
|
+
Gauntlet fires a suite of adversarial, edge-case "users" at your AI agent over
|
|
27
|
+
HTTP, finds where it fails (system-prompt leaks, unsafe actions, scope drift,
|
|
28
|
+
crashes, runaway output), ranks the failures by severity, and turns them into a
|
|
29
|
+
regression suite you can gate in CI. Framework-agnostic: if your agent speaks
|
|
30
|
+
HTTP, Gauntlet can test it.
|
|
31
|
+
|
|
32
|
+
It is built on one belief: a green eval only means something if you defined what
|
|
33
|
+
red looks like. Most agent "evals" pass because nobody wrote the test that would
|
|
34
|
+
have failed.
|
|
35
|
+
|
|
36
|
+
## Why this exists
|
|
37
|
+
|
|
38
|
+
Teams ship agents that work in the demo and then quietly break in production: the
|
|
39
|
+
model picks the wrong tool, leaks its prompt to a clever user, confirms an action
|
|
40
|
+
it should have refused, or loops. The expensive part of reliability is not the
|
|
41
|
+
dashboard, it is finding the failures and making sure they stay fixed. Gauntlet
|
|
42
|
+
is the part that goes looking for them.
|
|
43
|
+
|
|
44
|
+
## Quickstart (30 seconds, no API key)
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Install (once published): pip install gauntlet-agent
|
|
48
|
+
# or as an isolated CLI: pipx install gauntlet-agent
|
|
49
|
+
|
|
50
|
+
# 1. See it work against a deliberately broken sample agent, in one process:
|
|
51
|
+
python examples/demo.py
|
|
52
|
+
|
|
53
|
+
# 2. Or run it against your own agent (any HTTP endpoint that takes JSON):
|
|
54
|
+
# terminal A:
|
|
55
|
+
python examples/sample_agent.py
|
|
56
|
+
# terminal B:
|
|
57
|
+
gauntlet run --target http://localhost:8000/chat --canaries examples/canaries.json
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Network-free self-test (runs anywhere, good for CI):
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
python tests/test_offline.py # or: pytest
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Using it on your agent
|
|
67
|
+
|
|
68
|
+
Point `--target` at any endpoint that accepts `POST {"message": "..."}` and
|
|
69
|
+
returns JSON or text. Field names are configurable. Agent isn't an HTTP service
|
|
70
|
+
yet (LangChain, OpenAI Assistants, a bare function)? Wrap it in a few lines with
|
|
71
|
+
the shims in [`examples/adapters/`](examples/adapters) — no server code to write.
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
gauntlet run \
|
|
75
|
+
--target https://your-agent.example.com/v1/chat \
|
|
76
|
+
--request-field input --response-field output \
|
|
77
|
+
--header "Authorization: Bearer $TOKEN" \
|
|
78
|
+
--canaries my_canaries.json \
|
|
79
|
+
--fail-on HIGH \
|
|
80
|
+
--json gauntlet-report.json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Exit code is nonzero when anything at or above `--fail-on` is found, so you can
|
|
84
|
+
drop it straight into CI:
|
|
85
|
+
|
|
86
|
+
```yaml
|
|
87
|
+
# .github/workflows/agent.yml
|
|
88
|
+
- run: gauntlet run --target $STAGING_AGENT_URL --canaries canaries.json --fail-on HIGH
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Canaries: define what failure means
|
|
92
|
+
|
|
93
|
+
The universal graders (errors, empty replies, runaway length) need no config.
|
|
94
|
+
The high-value graders are the canaries you supply, the things your agent must
|
|
95
|
+
never do:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"never_output_substrings": ["INTERNAL-OPS-KEY", "system prompt"],
|
|
100
|
+
"unsafe_compliance_substrings": ["refund of $", "deleted the account"],
|
|
101
|
+
"max_response_chars": 6000,
|
|
102
|
+
"severity_overrides": { "missing_refusal": "MEDIUM", "data_leak": "CRITICAL" }
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`severity_overrides` lets you retune any finding kind to your own risk bar
|
|
107
|
+
(CRITICAL/HIGH/MEDIUM/LOW/INFO) — e.g. downgrade `missing_refusal` if your agent
|
|
108
|
+
is intentionally chatty, or keep leaks at CRITICAL.
|
|
109
|
+
|
|
110
|
+
## How it works
|
|
111
|
+
|
|
112
|
+
1. **Adversaries** (`gauntlet/adversaries.py`) — a deterministic library of
|
|
113
|
+
probes across prompt injection, scope discipline, false premises, data
|
|
114
|
+
exfiltration, malformed input, and loop bait. Deterministic so runs are
|
|
115
|
+
reproducible.
|
|
116
|
+
2. **Runner** (`gauntlet/runner.py`) — fires probes concurrently at your HTTP
|
|
117
|
+
endpoint, stdlib only.
|
|
118
|
+
3. **Graders** (`gauntlet/graders.py`) — universal reliability checks plus your
|
|
119
|
+
canaries, producing severity-ranked findings (CRITICAL to INFO).
|
|
120
|
+
4. **Report** (`gauntlet/report.py`) — a readable summary, the worst failures,
|
|
121
|
+
and a JSON artifact for CI.
|
|
122
|
+
|
|
123
|
+
## Optional: LLM-powered mode
|
|
124
|
+
|
|
125
|
+
The default needs no API key. With `--llm`, Gauntlet generates fresh adversarial
|
|
126
|
+
personas from a description of your agent and can grade open-ended behavior with
|
|
127
|
+
a judge instead of substring canaries.
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
pip install "gauntlet-agent[llm]"
|
|
131
|
+
export ANTHROPIC_API_KEY=...
|
|
132
|
+
gauntlet run --target $URL --llm --describe "support bot for an online store"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The judge is a thin, swappable layer. The methodology is the point: generate
|
|
136
|
+
probes from your agent's real surface, and **validate the judge against a small
|
|
137
|
+
human-labeled gold set before trusting its scores.**
|
|
138
|
+
|
|
139
|
+
### Calibrate the judge (don't trust a score you haven't validated)
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
gauntlet calibrate --gold examples/gold.jsonl --min-kappa 0.6
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Runs the judge over a human-labeled gold set and reports accuracy, precision,
|
|
146
|
+
**recall** (of real failures, how many the judge catches — the number that
|
|
147
|
+
matters for a safety tool), F1, and **Cohen's κ** (chance-corrected agreement).
|
|
148
|
+
It exits nonzero below `--min-kappa`, so a weak judge fails CI instead of quietly
|
|
149
|
+
shipping bad scores. A starter gold set lives at `examples/gold.jsonl`.
|
|
150
|
+
|
|
151
|
+
## Multi-turn probes (jailbreaks that build across turns)
|
|
152
|
+
|
|
153
|
+
Real jailbreaks are rarely one message — they build trust, plant context, or
|
|
154
|
+
manufacture a false premise over several turns, then cash it in. Add `--multiturn`
|
|
155
|
+
to include built-in conversation probes (crescendo, gradual role-reset, context
|
|
156
|
+
poisoning, manufactured commitment). Gauntlet drives each turn-by-turn and grades
|
|
157
|
+
the final reply.
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# stateful agent (keeps its own session):
|
|
161
|
+
gauntlet run --target $URL --multiturn --canaries canaries.json
|
|
162
|
+
|
|
163
|
+
# stateless agent: send the running transcript as an OpenAI-style messages array
|
|
164
|
+
gauntlet run --target $URL --multiturn --history-field messages --canaries canaries.json
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
The report prints the full conversation for any multi-turn failure, so you can
|
|
168
|
+
see exactly how it got there.
|
|
169
|
+
|
|
170
|
+
Add `--extended` for newer single-turn attack classes (indirect/RAG injection,
|
|
171
|
+
unicode-homoglyph evasion, refusal suppression, base64 encoding smuggling,
|
|
172
|
+
tool-description extraction, PII handling):
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
gauntlet run --target $URL --extended --multiturn --canaries canaries.json
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Trace-aware grading (score the tool calls, not just the text)
|
|
179
|
+
|
|
180
|
+
A safe-sounding answer can hide an unsafe action. If your agent returns the tool
|
|
181
|
+
calls it made, Gauntlet can grade those directly. Have the agent include a
|
|
182
|
+
`trace` in its JSON response:
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{ "response": "All set!", "trace": [ {"tool": "issue_refund", "args": {"amount": 999}} ] }
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Then point at it and declare which tools/args are off-limits:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
gauntlet run --target $URL --trace-field trace --canaries canaries.json
|
|
192
|
+
```
|
|
193
|
+
```json
|
|
194
|
+
{ "forbidden_tools": ["issue_refund", "delete_user", "send_bulk_email"],
|
|
195
|
+
"forbidden_tool_arg_substrings": ["all_users", "DROP TABLE"] }
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
A forbidden tool call (or a forbidden argument) is a HIGH finding even if the
|
|
199
|
+
text looked fine — catching the agent that *says* "I can't" but calls the tool
|
|
200
|
+
anyway.
|
|
201
|
+
|
|
202
|
+
## Roadmap
|
|
203
|
+
|
|
204
|
+
- [x] Judge calibration command (`gauntlet calibrate`)
|
|
205
|
+
- [x] Persona memory: multi-turn conversation probes (`--multiturn`)
|
|
206
|
+
- [x] Trace-aware grading (`--trace-field` + forbidden tools/args)
|
|
207
|
+
- [x] Hosted dashboard + scheduled runs (see the `apps/dashboard` in the monorepo)
|
|
208
|
+
|
|
209
|
+
## License
|
|
210
|
+
|
|
211
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Gauntlet
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/gauntlet-agent/)
|
|
4
|
+
[](https://pypi.org/project/gauntlet-agent/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://github.com/GauntletVectorLabs/gauntlet/actions/workflows/ci.yml)
|
|
7
|
+
|
|
8
|
+
**Break your agent before your users do.**
|
|
9
|
+
|
|
10
|
+
Gauntlet fires a suite of adversarial, edge-case "users" at your AI agent over
|
|
11
|
+
HTTP, finds where it fails (system-prompt leaks, unsafe actions, scope drift,
|
|
12
|
+
crashes, runaway output), ranks the failures by severity, and turns them into a
|
|
13
|
+
regression suite you can gate in CI. Framework-agnostic: if your agent speaks
|
|
14
|
+
HTTP, Gauntlet can test it.
|
|
15
|
+
|
|
16
|
+
It is built on one belief: a green eval only means something if you defined what
|
|
17
|
+
red looks like. Most agent "evals" pass because nobody wrote the test that would
|
|
18
|
+
have failed.
|
|
19
|
+
|
|
20
|
+
## Why this exists
|
|
21
|
+
|
|
22
|
+
Teams ship agents that work in the demo and then quietly break in production: the
|
|
23
|
+
model picks the wrong tool, leaks its prompt to a clever user, confirms an action
|
|
24
|
+
it should have refused, or loops. The expensive part of reliability is not the
|
|
25
|
+
dashboard, it is finding the failures and making sure they stay fixed. Gauntlet
|
|
26
|
+
is the part that goes looking for them.
|
|
27
|
+
|
|
28
|
+
## Quickstart (30 seconds, no API key)
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Install (once published): pip install gauntlet-agent
|
|
32
|
+
# or as an isolated CLI: pipx install gauntlet-agent
|
|
33
|
+
|
|
34
|
+
# 1. See it work against a deliberately broken sample agent, in one process:
|
|
35
|
+
python examples/demo.py
|
|
36
|
+
|
|
37
|
+
# 2. Or run it against your own agent (any HTTP endpoint that takes JSON):
|
|
38
|
+
# terminal A:
|
|
39
|
+
python examples/sample_agent.py
|
|
40
|
+
# terminal B:
|
|
41
|
+
gauntlet run --target http://localhost:8000/chat --canaries examples/canaries.json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Network-free self-test (runs anywhere, good for CI):
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
python tests/test_offline.py # or: pytest
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Using it on your agent
|
|
51
|
+
|
|
52
|
+
Point `--target` at any endpoint that accepts `POST {"message": "..."}` and
|
|
53
|
+
returns JSON or text. Field names are configurable. Agent isn't an HTTP service
|
|
54
|
+
yet (LangChain, OpenAI Assistants, a bare function)? Wrap it in a few lines with
|
|
55
|
+
the shims in [`examples/adapters/`](examples/adapters) — no server code to write.
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
gauntlet run \
|
|
59
|
+
--target https://your-agent.example.com/v1/chat \
|
|
60
|
+
--request-field input --response-field output \
|
|
61
|
+
--header "Authorization: Bearer $TOKEN" \
|
|
62
|
+
--canaries my_canaries.json \
|
|
63
|
+
--fail-on HIGH \
|
|
64
|
+
--json gauntlet-report.json
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Exit code is nonzero when anything at or above `--fail-on` is found, so you can
|
|
68
|
+
drop it straight into CI:
|
|
69
|
+
|
|
70
|
+
```yaml
|
|
71
|
+
# .github/workflows/agent.yml
|
|
72
|
+
- run: gauntlet run --target $STAGING_AGENT_URL --canaries canaries.json --fail-on HIGH
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Canaries: define what failure means
|
|
76
|
+
|
|
77
|
+
The universal graders (errors, empty replies, runaway length) need no config.
|
|
78
|
+
The high-value graders are the canaries you supply, the things your agent must
|
|
79
|
+
never do:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"never_output_substrings": ["INTERNAL-OPS-KEY", "system prompt"],
|
|
84
|
+
"unsafe_compliance_substrings": ["refund of $", "deleted the account"],
|
|
85
|
+
"max_response_chars": 6000,
|
|
86
|
+
"severity_overrides": { "missing_refusal": "MEDIUM", "data_leak": "CRITICAL" }
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`severity_overrides` lets you retune any finding kind to your own risk bar
|
|
91
|
+
(CRITICAL/HIGH/MEDIUM/LOW/INFO) — e.g. downgrade `missing_refusal` if your agent
|
|
92
|
+
is intentionally chatty, or keep leaks at CRITICAL.
|
|
93
|
+
|
|
94
|
+
## How it works
|
|
95
|
+
|
|
96
|
+
1. **Adversaries** (`gauntlet/adversaries.py`) — a deterministic library of
|
|
97
|
+
probes across prompt injection, scope discipline, false premises, data
|
|
98
|
+
exfiltration, malformed input, and loop bait. Deterministic so runs are
|
|
99
|
+
reproducible.
|
|
100
|
+
2. **Runner** (`gauntlet/runner.py`) — fires probes concurrently at your HTTP
|
|
101
|
+
endpoint, stdlib only.
|
|
102
|
+
3. **Graders** (`gauntlet/graders.py`) — universal reliability checks plus your
|
|
103
|
+
canaries, producing severity-ranked findings (CRITICAL to INFO).
|
|
104
|
+
4. **Report** (`gauntlet/report.py`) — a readable summary, the worst failures,
|
|
105
|
+
and a JSON artifact for CI.
|
|
106
|
+
|
|
107
|
+
## Optional: LLM-powered mode
|
|
108
|
+
|
|
109
|
+
The default needs no API key. With `--llm`, Gauntlet generates fresh adversarial
|
|
110
|
+
personas from a description of your agent and can grade open-ended behavior with
|
|
111
|
+
a judge instead of substring canaries.
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pip install "gauntlet-agent[llm]"
|
|
115
|
+
export ANTHROPIC_API_KEY=...
|
|
116
|
+
gauntlet run --target $URL --llm --describe "support bot for an online store"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The judge is a thin, swappable layer. The methodology is the point: generate
|
|
120
|
+
probes from your agent's real surface, and **validate the judge against a small
|
|
121
|
+
human-labeled gold set before trusting its scores.**
|
|
122
|
+
|
|
123
|
+
### Calibrate the judge (don't trust a score you haven't validated)
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
gauntlet calibrate --gold examples/gold.jsonl --min-kappa 0.6
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Runs the judge over a human-labeled gold set and reports accuracy, precision,
|
|
130
|
+
**recall** (of real failures, how many the judge catches — the number that
|
|
131
|
+
matters for a safety tool), F1, and **Cohen's κ** (chance-corrected agreement).
|
|
132
|
+
It exits nonzero below `--min-kappa`, so a weak judge fails CI instead of quietly
|
|
133
|
+
shipping bad scores. A starter gold set lives at `examples/gold.jsonl`.
|
|
134
|
+
|
|
135
|
+
## Multi-turn probes (jailbreaks that build across turns)
|
|
136
|
+
|
|
137
|
+
Real jailbreaks are rarely one message — they build trust, plant context, or
|
|
138
|
+
manufacture a false premise over several turns, then cash it in. Add `--multiturn`
|
|
139
|
+
to include built-in conversation probes (crescendo, gradual role-reset, context
|
|
140
|
+
poisoning, manufactured commitment). Gauntlet drives each turn-by-turn and grades
|
|
141
|
+
the final reply.
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# stateful agent (keeps its own session):
|
|
145
|
+
gauntlet run --target $URL --multiturn --canaries canaries.json
|
|
146
|
+
|
|
147
|
+
# stateless agent: send the running transcript as an OpenAI-style messages array
|
|
148
|
+
gauntlet run --target $URL --multiturn --history-field messages --canaries canaries.json
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The report prints the full conversation for any multi-turn failure, so you can
|
|
152
|
+
see exactly how it got there.
|
|
153
|
+
|
|
154
|
+
Add `--extended` for newer single-turn attack classes (indirect/RAG injection,
|
|
155
|
+
unicode-homoglyph evasion, refusal suppression, base64 encoding smuggling,
|
|
156
|
+
tool-description extraction, PII handling):
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
gauntlet run --target $URL --extended --multiturn --canaries canaries.json
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Trace-aware grading (score the tool calls, not just the text)
|
|
163
|
+
|
|
164
|
+
A safe-sounding answer can hide an unsafe action. If your agent returns the tool
|
|
165
|
+
calls it made, Gauntlet can grade those directly. Have the agent include a
|
|
166
|
+
`trace` in its JSON response:
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{ "response": "All set!", "trace": [ {"tool": "issue_refund", "args": {"amount": 999}} ] }
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Then point at it and declare which tools/args are off-limits:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
gauntlet run --target $URL --trace-field trace --canaries canaries.json
|
|
176
|
+
```
|
|
177
|
+
```json
|
|
178
|
+
{ "forbidden_tools": ["issue_refund", "delete_user", "send_bulk_email"],
|
|
179
|
+
"forbidden_tool_arg_substrings": ["all_users", "DROP TABLE"] }
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
A forbidden tool call (or a forbidden argument) is a HIGH finding even if the
|
|
183
|
+
text looked fine — catching the agent that *says* "I can't" but calls the tool
|
|
184
|
+
anyway.
|
|
185
|
+
|
|
186
|
+
## Roadmap
|
|
187
|
+
|
|
188
|
+
- [x] Judge calibration command (`gauntlet calibrate`)
|
|
189
|
+
- [x] Persona memory: multi-turn conversation probes (`--multiturn`)
|
|
190
|
+
- [x] Trace-aware grading (`--trace-field` + forbidden tools/args)
|
|
191
|
+
- [x] Hosted dashboard + scheduled runs (see the `apps/dashboard` in the monorepo)
|
|
192
|
+
|
|
193
|
+
## License
|
|
194
|
+
|
|
195
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""Gauntlet: break your agent before your users do."""
|
|
2
|
+
|
|
3
|
+
__version__ = "0.1.0"
|
|
4
|
+
|
|
5
|
+
from .adversaries import Probe, builtin_probes # noqa: F401
|
|
6
|
+
from .runner import run_suite, Result # noqa: F401
|
|
7
|
+
from .graders import grade_all, grade, Finding # noqa: F401
|
|
8
|
+
from .report import build_report # noqa: F401
|