[python] Add AI Guard framework tests for Anthropic - #7495
Open
avara1986 wants to merge 3 commits into
Open
Conversation
Adds TestAnthropicAiGuard under the INTEGRATION_FRAMEWORKS scenario, mirroring the OpenAI AI Guard suite: before-model (target:prompt) and tool-call (target:tool) evaluations, both asserting ai_guard.event:true on the local root span. The polling/assertion helpers are extracted to tests/integration_frameworks/llm/ai_guard_utils.py and shared with the OpenAI suite; TOOLS moves to anthropic/utils.py, matching openai/utils.py. Enabled for python at v4.11.0 (dd-trace-py#18130); missing_feature for nodejs (APPSEC-69630) and java. JIRA: APPSEC-69629 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
|
|
🎉 All green!🧪 All tests passed 🔗 Commit SHA: b1f7fc2 | Docs | Datadog PR Page | Give us feedback! |
tests/test_the_test/test_conventions.py::test_utils only allows test_*.py, utils.py, conftest.py and __init__.py under tests/, so the new ai_guard_utils.py failed TEST_THE_TEST. Fold the helpers into the existing tests/integration_frameworks/llm/utils.py instead. JIRA: APPSEC-69629 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The OpenAI and Anthropic AI Guard suites carried a verbatim library_env fixture, tool-call assertion and wait/assert pairs, and llm/utils.py had the same polling loop twice. Collapse them into shared assertions (assert_ai_guard_evaluated, assert_assistant_tool_calls_forwarded) over a single selector-driven poll helper, make the rest private, and trim the new docstrings to one or two lines. Add tests/test_the_test/test_ai_guard_span_helpers.py to pin the span shapes the selectors tolerate (parent_id absent vs 0, ai_guard.event bool vs string), which nothing covered before. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
avara1986
marked this pull request as ready for review
August 13, 2026 13:21
avara1986
requested review from
IlyasShabi,
christophe-papazian,
claponcet,
dougqh,
dromanol,
sabrenner and
smola
and removed request for
a team
August 13, 2026 13:21
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Jira: APPSEC-69629 (epic: APPSEC-68823)
APPSEC-68977 established that AI Guard can be exercised through the
INTEGRATION_FRAMEWORKSscenario (test-agent VCR proxy serving/vcr/aiguard, assertions made fromtest_agenttraces), with a PoC covering OpenAI only. This extends the same coverage to the Anthropic SDK, which dd-trace-py has supported since v4.11.0 (dd-trace-py#18130).Changes
tests/integration_frameworks/llm/anthropic/test_anthropic_ai_guard.py(TestAnthropicAiGuard), mirroring the OpenAI one:test_before_model_validation— the request is evaluated before the model call →ai_guardspan withai_guard.target:prompt;test_tool_call_validation— thetool_useblocks the model produced are evaluated →ai_guardspan withai_guard.target:tool, plus the assistanttool_callsentry inmeta_struct.ai_guard.messages;ai_guard.event:true.tests/integration_frameworks/llm/ai_guard_utils.pyand the OpenAI suite now imports them. No behaviour change.TOOLSmoved toanthropic/utils.py(matching theopenai/utils.pylayout) and is now shared with the LLM Observability suite.DD_API_KEY/DD_APP_KEYadded to the anthropic entry of_required_cassette_generation_api_keys— the AI Guard client needs them when recording.python.yml→v4.11.0;nodejs.yml→missing_feature (APPSEC-69630);java.yml→missing_feature (APPSEC-68977).Not covered, for cross-language parity: the streamed-response path (
DD_AI_GUARD_ANALYZE_STREAM_RESPONSES_ENABLED), and the evaluation outcome (ALLOW / DENY / ABORT), which the dedicatedAI_GUARDscenario already asserts.Cassettes
test_create/test_create_with_tools, so only the test-name prefix differs.evaluatecassettes are hand-craftedALLOWresponses (noDD_API_KEY/DD_APP_KEYwere available to record). The tests do not assert the verdict, so this only affects fixture fidelity. They can be re-recorded with:./utils/scripts/generate-integration-framework-cassettes.sh --weblog anthropic-py@0.75.0Testing
Local
INTEGRATION_FRAMEWORKSruns againstpython@4.14.0-rc1, all cassettes replayed by hash (nothing re-recorded):./run.sh INTEGRATION_FRAMEWORKS -L python --weblog anthropic-py@0.75.0 -k TestAnthropicAiGuard→ 2 passed./run.sh INTEGRATION_FRAMEWORKS -L python --weblog openai-py@2.0.0 -k TestOpenAiAiGuard→ 2 passed (helper extraction regression check)🤖 Generated with Claude Code