Skip to content

[python] Add AI Guard framework tests for Anthropic - #7495

Open
avara1986 wants to merge 3 commits into
mainfrom
alberto.vara/ai-guard-anthropic-framework-tests
Open

[python] Add AI Guard framework tests for Anthropic#7495
avara1986 wants to merge 3 commits into
mainfrom
alberto.vara/ai-guard-anthropic-framework-tests

Conversation

@avara1986

@avara1986 avara1986 commented Aug 12, 2026

Copy link
Copy Markdown
Member

Motivation

Jira: APPSEC-69629 (epic: APPSEC-68823)

APPSEC-68977 established that AI Guard can be exercised through the INTEGRATION_FRAMEWORKS scenario (test-agent VCR proxy serving /vcr/aiguard, assertions made from test_agent traces), 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

  • New suite 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_guard span with ai_guard.target:prompt;
    • test_tool_call_validation — the tool_use blocks the model produced are evaluated → ai_guard span with ai_guard.target:tool, plus the assistant tool_calls entry in meta_struct.ai_guard.messages;
    • both assert the local root span carries ai_guard.event:true.
  • Shared helpers: the polling/assertion helpers were about to be duplicated, so they moved to tests/integration_frameworks/llm/ai_guard_utils.py and the OpenAI suite now imports them. No behaviour change.
  • TOOLS moved to anthropic/utils.py (matching the openai/utils.py layout) and is now shared with the LLM Observability suite.
  • DD_API_KEY / DD_APP_KEY added to the anthropic entry of _required_cassette_generation_api_keys — the AI Guard client needs them when recording.
  • Manifests: python.ymlv4.11.0; nodejs.ymlmissing_feature (APPSEC-69630); java.ymlmissing_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 dedicated AI_GUARD scenario already asserts.

Cassettes

  • The two anthropic cassettes are byte-for-byte copies of already-recorded responses: the request bodies were deliberately chosen to match test_create / test_create_with_tools, so only the test-name prefix differs.
  • The four aiguard evaluate cassettes are hand-crafted ALLOW responses (no DD_API_KEY/DD_APP_KEY were 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.0

Testing

Local INTEGRATION_FRAMEWORKS runs against python@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

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>
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

CODEOWNERS have been resolved as:

tests/integration_frameworks/llm/anthropic/test_anthropic_ai_guard.py   @DataDog/ml-observability
tests/integration_frameworks/utils/vcr-cassettes/aiguard/test_before_model_validation_aiguard_evaluate_post_6445822d.json  @DataDog/system-tests-core
tests/integration_frameworks/utils/vcr-cassettes/aiguard/test_before_model_validation_aiguard_evaluate_post_6b61e487.json  @DataDog/system-tests-core
tests/integration_frameworks/utils/vcr-cassettes/aiguard/test_tool_call_validation_aiguard_evaluate_post_b3b24536.json  @DataDog/system-tests-core
tests/integration_frameworks/utils/vcr-cassettes/aiguard/test_tool_call_validation_aiguard_evaluate_post_c3f57149.json  @DataDog/system-tests-core
tests/integration_frameworks/utils/vcr-cassettes/anthropic/test_before_model_validation_anthropic_v1_messages_post_cd13d5fc.json  @DataDog/system-tests-core
tests/integration_frameworks/utils/vcr-cassettes/anthropic/test_tool_call_validation_anthropic_v1_messages_post_4936d142.json  @DataDog/system-tests-core
tests/test_the_test/test_ai_guard_span_helpers.py                       @DataDog/system-tests-core
manifests/java.yml                                                      @DataDog/asm-java @DataDog/apm-java
manifests/nodejs.yml                                                    @DataDog/dd-trace-js
manifests/python.yml                                                    @DataDog/apm-python @DataDog/asm-python
tests/integration_frameworks/llm/anthropic/test_anthropic_llmobs.py     @DataDog/ml-observability
tests/integration_frameworks/llm/anthropic/utils.py                     @DataDog/ml-observability
tests/integration_frameworks/llm/openai/test_openai_ai_guard.py         @DataDog/ml-observability
tests/integration_frameworks/llm/utils.py                               @DataDog/ml-observability
utils/_context/_scenarios/integration_frameworks.py                     @DataDog/system-tests-core

@datadog-datadog-prod-us1-2

datadog-datadog-prod-us1-2 Bot commented Aug 12, 2026

Copy link
Copy Markdown

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: b1f7fc2 | Docs | Datadog PR Page | Give us feedback!

avara1986 and others added 2 commits August 12, 2026 15:13
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
avara1986 marked this pull request as ready for review August 13, 2026 13:21
@avara1986
avara1986 requested review from a team as code owners August 13, 2026 13:21
@avara1986
avara1986 requested review from IlyasShabi, christophe-papazian, claponcet, dougqh, dromanol, sabrenner and smola and removed request for a team August 13, 2026 13:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant