Commit feb69a4
Red Team Agent Scenario Integration (#44551)
* pyrit foundry integration spec
* init implementation still need to figure out xpia / context and fix tests
* fix tests and imports
* updates
* updates
* Fix red team tests for new PyRIT API compatibility
- Update imports from initialize_pyrit to CentralMemory
- Change PromptRequestResponse to Message, PromptRequestPiece to MessagePiece
- Update request_pieces to message_pieces throughout
- Change orchestrator_identifier to attack_identifier
- Fix PyritException instantiation to use keyword argument
- Add skip decorators for tests relying on removed orchestrator module
- Add skip decorators for tests when scorer class is abstract
* Add e2e tests for RedTeam Foundry integration
- test_foundry_basic_execution: Basic Foundry execution path
- test_foundry_indirect_jailbreak: XPIA attacks with context
- test_foundry_multiple_risk_categories: Multiple risk categories
- test_foundry_with_application_scenario: Application scenario context
- test_foundry_strategy_combination: Multiple attack strategies
* Fix PyRIT API compatibility for Foundry integration
- Update RAIServiceScorer to inherit from TrueFalseScorer and match new score_async signature
- Update _CallbackChatTarget.send_prompt_async to use Message parameter and return List[Message]
- Fix AttackScoringConfig to use objective_scorer and use_score_as_feedback parameters
- Change scenario.run_attack_async() to scenario.run_async()
- Fix _scenario_result.attack_results access pattern
- Add None handling for context_type in dataset builder
- Remove context prompts for standard attacks (converters only support text)
- Update memory API from get_chat_messages_with_conversation_id to get_conversation
- Handle both dict and object message formats in strategy_utils
- Pass adversarial_chat_target to FoundryExecutionManager
- Update unit tests for new API signatures
* Handle baseline-only execution limitation in PyRIT Foundry
- Add include_baseline parameter to ScenarioOrchestrator.execute()
- Log warning when baseline-only is requested (PyRIT requires Foundry strategy)
- Update tests to use Baseline + Base64 (workaround for PyRIT limitation)
- Fix _red_team.py to pass flattened_attack_strategies for proper Baseline detection
- Update get_attack_results() and get_memory() to not raise when no scenario executed
* Use PyRIT branch with baseline-only support and simplify orchestrator
- Point pyrit dependency to slister1001/PyRIT@feature/baseline-only-execution
(TODO: Revert to @main once PR #1321 is merged)
- Simplify scenario orchestrator by removing baseline-only workaround
- Update e2e tests to use baseline-only execution (AttackStrategy.Baseline)
* Remove spec file from PR (documentation only)
* Revert to Azure/PyRIT@main until PR #1321 is merged
The fork URL was causing CI failures. Reverting to main branch with
baseline+Base64 workaround until baseline-only support is merged.
Added TODO comments to track where changes are needed once PR #1321 lands.
* Split dev requirements to avoid pillow version conflict
Create separate dev_requirements_redteam.txt for redteam tests to avoid
dependency conflict between promptflow-devkit (pillow<=11.3.0) and
pyrit (pillow>=12.1.0).
- dev_requirements.txt: removes [redteam] extra, used for regular CI
- dev_requirements_redteam.txt: includes [redteam] but excludes promptflow-devkit
* Add script for running red team tests locally
Add run_redteam_tests.py script that installs from dev_requirements_redteam.txt
and runs the red team e2e tests. This allows developers to run redteam tests
locally without the pillow version conflicts from promptflow-devkit.
Usage: python scripts/run_redteam_tests.py [pytest_args...]
* Add dedicated CI job for red team tests
Add a separate matrix entry (redteam_Ubuntu2404_310) that runs red team tests
with dev_requirements_redteam.txt to avoid pillow version conflicts.
The redteam job:
- Uses Python 3.10 (required by pyrit)
- Skips all standard tox environments
- Installs from dev_requirements_redteam.txt (without promptflow-devkit)
- Runs red team e2e tests with the [redteam] extra
* Add unit tests for DatasetConfigurationBuilder binary_path support
Add tests for context file creation, extension mapping, data type
determination, and cleanup functionality.
* Fix CI issues: add cspell words and handle sphinx autodoc gracefully
* Add @pyrit_target_retry support to CallbackChatTarget
Enable PyRIT's retry decorator for callback-based chat targets to handle
rate limit errors and empty responses with exponential backoff.
Changes:
- Add retry_enabled parameter (default True) to _CallbackChatTarget
- Apply @pyrit_target_retry decorator when retry is enabled
- Translate OpenAI RateLimitError to PyRIT RateLimitException
- Detect rate limits in error messages as fallback
- Raise EmptyResponseException for empty/whitespace responses
- Add comprehensive unit tests for retry behavior
- Add 'redef' to cspell ignore list for type: ignore comments
* Fix tests to use updated PyRIT API parameter names
* Apply black formatting to red team module
* fix: Accept both message and prompt_request keywords in _CallbackChatTarget
Update send_prompt_async to accept both 'message' (PyRIT standard) and
'prompt_request' (SDK convention) keywords for compatibility. This prevents
TypeError when orchestrators call with different keyword conventions.
Changes:
- Update send_prompt_async signature to accept both keywords as Optional
- Add validation to ensure exactly one keyword is provided
- Add tests for prompt_request keyword and error cases
* fix: Store context_items in metadata for standard attacks
DatasetConfigurationBuilder.add_objective_with_context was silently
dropping context_items for non-indirect (standard) attacks. The comment
claimed context was stored in metadata but this wasn't happening.
Changes:
- Store context_items in objective metadata for standard attacks
- Update comment to accurately describe the behavior
- Add tests verifying context storage in metadata
This enables scoring/result reconstruction to access context data for
standard Foundry runs.
* fix: Enable baseline-only execution in ScenarioOrchestrator
PyRIT 0.10.x now supports empty strategy list with include_baseline=True.
Remove the workaround that silently skipped baseline-only execution.
Changes:
- Remove workaround that skipped execution for empty strategies
- Now allow empty strategies when include_baseline=True (baseline-only)
- Fail fast with ValueError when both strategies empty AND include_baseline=False
- Add debug logging for no-results case
This enables proper baseline-only runs instead of silently completing with no data.
* fix: Standardize FoundryStrategy imports and remove unused variable
- Use shorter import path pyrit.scenario.foundry instead of
pyrit.scenario.scenarios.foundry across all files
- Remove unused has_indirect variable in _red_team.py
* chore: Update pyrit dependency to released v0.11.0
Switch from git main branch to the stable PyPI release for
production readiness.
* fix: Remove duplicate package install in CI
dev_requirements_redteam.txt already installs azure-ai-evaluation[redteam],
so the separate pip install is redundant.
* fix: Replace class-level mutable state with per-instance TemporaryDirectory
* Fix ASR artificially lowered by scoring errors
- RAIServiceScorer._score_piece_async() now re-raises exceptions instead of
returning score_value='false', so PyRIT treats scoring errors as UNDETERMINED
rather than FAILURE
- Added _build_identifier() to RAIServiceScorer (required by PyRIT ABC)
- Updated calculate_asr() and calculate_asr_by_strategy() to exclude
UNDETERMINED from denominator (matches PyRIT's _compute_stats approach)
- Updated get_summary_stats() ASR to use decided (success+failure) as denominator
- Added 6 regression tests in TestASRScoringErrorRegression
- Applied black formatting
* Fix review issues: null guards, response validation, cleanup safety, test assertions
- Fix NoneType crash when eval_result.results is None in _rai_service_eval_chat_target.py
- Guard orchestrator instantiation with _ORCHESTRATOR_AVAILABLE checks
- Validate callback response structure before key access in _callback_chat_target.py
- Add __del__ and debug logging to DatasetConfigurationBuilder cleanup
- Add try/except with helpful message for FoundryStrategy import
- Add changelog note for pyrit/promptflow-devkit pillow version conflict
- Fix tautological >= 0 assertions in test_foundry.py
- Add assertion to cleanup test in test_dataset_builder_binary_path.py
- Strengthen e2e test assertions in test_red_team_foundry.py
* Fix scoring: switch RAIServiceScorer to sync_evals endpoint with passed field
* Add regression tests for council review findings (H4, M1-M6)
* Address review comments: add logging, deduplicate code, extract redteam CI matrix
- Add log line for orchestrator-based execution path (legacy PyRIT)
- Add log suggesting upgrade to PyRIT 0.11+ for Foundry execution
- Extract shared _read_seed_content() to deduplicate file-reading logic
between _rai_scorer.py and _foundry_result_processor.py
- Extract redteam matrix entry into separate platform-matrix-redteam.json
with its own MatrixConfig in ci.yml so it always gets a PR build job
* Revert redteam CI to await eng sys InjectedPackages support
Remove separate redteam MatrixConfig, AfterTestSteps, and
platform-matrix-redteam.json. These don't work in the shared
PR pipeline and the eng sys team is building InjectedPackages
support for conflicting dependency scenarios.
Added TODO comments in platform-matrix.json and dev_requirements.txt
for what to change when the feature is delivered.
* Fix build: remove _comment_todo from platform-matrix.json and apply black formatting
* Apply black formatting and align setup.py httpx bound with upstream main
* Fix red team e2e test failures and apply SDK black formatting (24.4.0)
Bug fixes:
- Map PromptSendingAttack to indirect_jailbreak in Foundry result/execution processors
- Remap hate_fairness to hate_unfairness for Sync API in RAI scorer
- Accept binary_path and image_path data types in callback chat target validation
- Fix context KeyError in evaluation processor for messages without context field
- Fix test callback to handle messages as list (not dict)
Formatting:
- Applied black 24.4.0 via tox to all red_team source and test files
* Update red team test recording assets to tag _5922d0e1e4
* Remove eval_sim_test_image_understanding.jsonl and spec_pyrit_foundry.md
* Enable red team tests in CI via InjectedPackages matrix entry
* Fix pillow conflict: remove [redteam] from dev_requirements.txt
The redteam extra conflicts with promptflow-devkit due to pillow
version incompatibility (pyrit requires >=12.1, promptflow <11).
The redteam extra is installed via InjectedPackages in platform-matrix.json
for the dedicated CI job instead.
* fix: keep whl check enabled for redteam CI job
* Fix redteam CI: inject pyrit directly to avoid conflicting URLs
* Fix PROXY_URL usage: call as function after upstream change
PROXY_URL in devtools_testutils.config was changed from a module-level
constant to a function in commit 9233cd8. This fix calls it properly
as PROXY_URL() to get the string value instead of passing the function object.
* Fix pillow version conflict between pyrit and promptflow-devkit in redteam CI
* fix build issues
* Fix test failures: skip promptflow-dependent tests when promptflow is excluded, update assertion for changed error message
* Remove unused dev_requirements_redteam.txt and run_redteam_tests.py
* Guard Configuration.set_config against opentelemetry import errors in proxy_client.py
* fix tests and promptflow-less env
* Fix CI: promptflow Configuration compat + test recording sanitizer
- Validate imported promptflow Configuration accepts override_config
kwarg before using it; fall back to local impl on TypeError (fixes
sk job where semantic-kernel brings incompatible promptflow version)
- Add body key sanitizer for query field in sync_evals requests to
handle dynamic adversarial prompt content in test recordings (fixes
5 red team foundry e2e test recording mismatches)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix SK build (promptflow 1.18.1 compat) and redteam recording mismatch
- _check.py: Also verify promptflow.client.PFClient is importable so
MISSING_LEGACY_SDK is True when promptflow-devkit 1.18.1 drops the
promptflow namespace package. Tests that depend on PFClient now
correctly skip.
- conftest.py: Use (?s).+ regex in the query body sanitizer so
multi-line adversarial prompt values are fully replaced. The default
.+ regex doesn't match newlines, causing recording/playback body
mismatches for hate_unfairness queries.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix strategy-name mismatch in Foundry red team path
_group_results_by_strategy() used PyRIT's attack_identifier.__type__ (always
'PromptSendingAttack' for single-turn) and mapped it to 'indirect_jailbreak',
causing all strategies to get wrong attribution in evaluation and scorecard.
Fix: Use the requested AttackStrategy list with get_strategy_name() to produce
keys that match ATTACK_STRATEGY_COMPLEXITY_MAP (e.g. 'base64', 'rot13').
Also remove incorrect pyrit_technique_map from _foundry_result_processor.py
that labeled all JSONL rows as 'indirect_jailbreak'.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix CI: multi-turn assertion, IndirectJailbreak strategy key
- Relax multi-turn conversation assertion from >2 to >=2 (Foundry path
may terminate early if target immediately refuses)
- Include special strategies (e.g., IndirectJailbreak) in result grouping
so attack_technique is correctly set instead of falling back to 'Foundry'
- Search both foundry and special strategies when matching eval strategy
- Add unit test for IndirectJailbreak strategy grouping
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Defensive fix for attack_identifier type mismatch (Bug 1)
- Add _get_attack_type_name() helper that handles both dict (current
pyrit 0.11.0) and future Identifier-object forms of attack_identifier
- Update _foundry_result_processor.py and _scenario_orchestrator.py to
use the helper instead of calling .get() directly on attack_identifier
- Add 5 unit tests for dict, object, None, empty dict, and missing key
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent fdf43b0 commit feb69a4
57 files changed
Lines changed: 8241 additions & 282 deletions
File tree
- eng/scripts
- sdk/evaluation
- azure-ai-evaluation
- azure/ai/evaluation
- _evaluate/_batch_run
- _legacy/_adapters
- red_team
- _agent
- _foundry
- _utils
- tests
- e2etests
- unittests
- test_redteam
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
83 | 83 | | |
84 | 84 | | |
85 | 85 | | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
86 | 93 | | |
87 | 94 | | |
88 | 95 | | |
| |||
95 | 102 | | |
96 | 103 | | |
97 | 104 | | |
98 | | - | |
| 105 | + | |
99 | 106 | | |
100 | 107 | | |
101 | | - | |
| 108 | + | |
102 | 109 | | |
103 | 110 | | |
104 | | - | |
| 111 | + | |
105 | 112 | | |
106 | 113 | | |
107 | 114 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
9 | 13 | | |
10 | 14 | | |
11 | 15 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
| 5 | + | |
6 | 6 | | |
Lines changed: 4 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | | - | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
26 | 29 | | |
27 | 30 | | |
28 | 31 | | |
| |||
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
| |||
Lines changed: 5 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
13 | 17 | | |
14 | 18 | | |
15 | 19 | | |
| |||
Lines changed: 41 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
5 | 7 | | |
6 | 8 | | |
7 | 9 | | |
8 | 10 | | |
9 | 11 | | |
| 12 | + | |
| 13 | + | |
10 | 14 | | |
11 | | - | |
12 | | - | |
13 | | - | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
14 | 52 | | |
15 | 53 | | |
16 | 54 | | |
| |||
Lines changed: 13 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
42 | | - | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
43 | 45 | | |
44 | 46 | | |
45 | 47 | | |
| |||
58 | 60 | | |
59 | 61 | | |
60 | 62 | | |
61 | | - | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
62 | 66 | | |
63 | 67 | | |
64 | 68 | | |
| |||
194 | 198 | | |
195 | 199 | | |
196 | 200 | | |
197 | | - | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
198 | 208 | | |
199 | 209 | | |
200 | 210 | | |
| |||
Lines changed: 23 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
21 | 23 | | |
22 | 24 | | |
23 | 25 | | |
| |||
59 | 61 | | |
60 | 62 | | |
61 | 63 | | |
62 | | - | |
| 64 | + | |
| 65 | + | |
63 | 66 | | |
64 | 67 | | |
65 | 68 | | |
| |||
165 | 168 | | |
166 | 169 | | |
167 | 170 | | |
168 | | - | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
169 | 174 | | |
170 | 175 | | |
171 | 176 | | |
172 | | - | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
173 | 180 | | |
174 | 181 | | |
175 | 182 | | |
| |||
199 | 206 | | |
200 | 207 | | |
201 | 208 | | |
202 | | - | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
203 | 213 | | |
204 | 214 | | |
205 | 215 | | |
| |||
276 | 286 | | |
277 | 287 | | |
278 | 288 | | |
279 | | - | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
280 | 293 | | |
281 | 294 | | |
282 | 295 | | |
| |||
394 | 407 | | |
395 | 408 | | |
396 | 409 | | |
397 | | - | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
398 | 414 | | |
399 | 415 | | |
400 | 416 | | |
| |||
Lines changed: 22 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
77 | | - | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
78 | 81 | | |
79 | 82 | | |
80 | 83 | | |
| |||
92 | 95 | | |
93 | 96 | | |
94 | 97 | | |
95 | | - | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
96 | 101 | | |
97 | 102 | | |
98 | 103 | | |
| |||
131 | 136 | | |
132 | 137 | | |
133 | 138 | | |
134 | | - | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
135 | 143 | | |
136 | 144 | | |
137 | 145 | | |
| |||
158 | 166 | | |
159 | 167 | | |
160 | 168 | | |
161 | | - | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
162 | 172 | | |
163 | 173 | | |
164 | 174 | | |
| |||
171 | 181 | | |
172 | 182 | | |
173 | 183 | | |
174 | | - | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
175 | 187 | | |
176 | 188 | | |
177 | 189 | | |
| |||
224 | 236 | | |
225 | 237 | | |
226 | 238 | | |
227 | | - | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
228 | 244 | | |
0 commit comments