Skip to content

refactor(library): migrate vendor actions to canonical HTTP clients - #2212

Open
Pouyanpi wants to merge 28 commits into
developfrom
pouyanpi/rail-library-stack-13-http-action-migrations
Open

refactor(library): migrate vendor actions to canonical HTTP clients#2212
Pouyanpi wants to merge 28 commits into
developfrom
pouyanpi/rail-library-stack-13-http-action-migrations

Conversation

@Pouyanpi

@Pouyanpi Pouyanpi commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Description

Migrate built-in library integrations to the canonical outbound HTTP client.
This combines the former vendor-action and specialized-client stack layers.

The migrated vendor actions cover AI Defense, AutoAlign, CrowdStrike AIDR,
Fiddler, Pangea, Patronus AI, PolicyAI, Prompt Security, Trend Micro, and F5.
They receive the managed client through action-parameter injection and use
http_call for request execution.

The Hugging Face classifier and Clavata integrations retain their specialized
retry and TLS requirements. A transport-neutral HTTPTLSConfig supports custom
CA bundles and paired client certificate and key paths without leaking HTTPX
types into integrations.

Integration-owned POST retry policies remain explicit. Injected clients remain
caller-owned, while fallback factories return fully composed clients that
http_call closes deterministically.

F5 preserves its bounded Retry-After behavior. Shared recorded-response tests
verify registered endpoints in both directions, and an AST-based conformance
test prevents library integrations from importing HTTPX, aiohttp, Requests, or
urllib3 directly.

Impact

  • Built-in library integrations stop creating transport-specific sessions.
  • Runtime injection, retries, errors, ownership, and telemetry follow one HTTP
    boundary.
  • TLS-sensitive integrations retain custom CA and mTLS support.
  • F5, Hugging Face, and Clavata preserve their integration-specific retries.
  • Recorded HTTP tests reject incorrect and unused endpoint registrations.
  • New library integrations cannot bypass the canonical transport boundary.
  • Unit tests make no live vendor calls.

Stack

Layer Branch Base PR
HTTP foundation pouyanpi/rail-library-stack-9-http-contract develop #2209
HTTP instrumentation pouyanpi/rail-library-stack-10-http-instrumentation Stack 9 #2219
Request lifecycle pouyanpi/rail-library-stack-11-http-observability Stack 9 #2210
Request migrations pouyanpi/rail-library-stack-12-http-request-migrations Stack 11 #2211
Action and specialized migrations pouyanpi/rail-library-stack-13-http-action-migrations Stack 12 #2212

Related Issue(s)

  • Fixes #
  • Internal tracking: NGUARD-862
  • Issue assignee: @

Verification

  • make test TEST="tests/http tests/test_ai_defense.py tests/test_f5_guardrails.py tests/test_fiddler_rails.py tests/test_pangea_ai_guard.py tests/test_patronus_evaluate_api.py tests/test_policyai_rail.py" — 197 passed, 4 skipped.
  • Pre-commit passed across the complete cascaded HTTP stack.
  • All tests were local and made no live provider calls.

AI Assistance

  • No AI tools were used.
  • AI tools were used; a human reviewed and can explain every change (tool: Codex).

Codex assisted with implementation analysis, validation, stack restructuring,
and this draft. Check the disclosure box after human review.

Checklist

  • I've read the CONTRIBUTING guidelines.
  • This PR links to a triaged issue assigned to me.
  • My PR title follows the project commit convention.
  • I've updated the documentation if applicable.
  • I've added tests if applicable.
  • I've noted any verification beyond CI and any checks I couldn't run.
  • I did not update generated changelog files manually.
  • I addressed all CodeRabbit, Greptile, and other review comments, or replied with why no change is needed.
  • @mentions of the person or team responsible for reviewing proposed changes.

Summary by CodeRabbit

  • New Features
    • Added configurable TLS support, including certificate verification, custom CA bundles, and mutual TLS.
    • Added optional HTTP client injection across external guardrail and classifier integrations.
  • Bug Fixes
    • Improved handling of network failures, invalid responses, timeouts, and rate limits with consistent outcomes and logging.
    • Standardized retry behavior for supported external service requests.
  • Tests
    • Expanded coverage for TLS configuration, HTTP failures, retries, request validation, and recorded responses.

@github-actions github-actions Bot added status: needs triage New issues that have not yet been reviewed or categorized. size: XL labels Jul 23, 2026
@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

@Pouyanpi
Pouyanpi force-pushed the pouyanpi/rail-library-stack-13-http-action-migrations branch 2 times, most recently from 1f8c466 to 9852187 Compare July 23, 2026 16:21
@Pouyanpi
Pouyanpi force-pushed the pouyanpi/rail-library-stack-13-http-action-migrations branch from 9852187 to 736a206 Compare July 23, 2026 16:28
@Pouyanpi Pouyanpi added status: triaged Triaged by a maintainer; eligible for automated review (CodeRabbit/Greptile). and removed status: needs triage New issues that have not yet been reviewed or categorized. labels Jul 23, 2026
@Pouyanpi Pouyanpi self-assigned this Jul 23, 2026
@Pouyanpi Pouyanpi added this to the v0.24.0 milestone Jul 23, 2026
@Pouyanpi
Pouyanpi marked this pull request as ready for review July 23, 2026 17:16
@greptile-apps

greptile-apps Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR migrates ten built-in library integrations (AI Defense, AutoAlign, CrowdStrike AIDR, Fiddler, Pangea, Patronus AI, PolicyAI, Prompt Security, Trend Micro, F5) from vendor-specific HTTP clients (aiohttp, httpx) to the canonical http_call / RetryingHTTPClient layer. It also introduces HTTPTLSConfig for transport-neutral CA-bundle and mTLS support, a shared RecordedHTTPResponses test utility with bidirectional URL assertion, and an AST-based conformance test that prevents future library code from bypassing the transport boundary.

  • Transport migration: All ten integrations now receive http_client via action-parameter injection and call http_call; F5, Hugging Face, and Clavata retain their integration-specific RetryPolicy instances.
  • TLS support: HTTPTLSConfig replaces the old _HTTPXSSLConfig in the HF classifier and is wired into HttpxHTTPClient; cert+key are validated together in __post_init__.
  • Test quality: RecordedHTTPResponses (now in tests/http_utils.py) asserts exact request order and URL in both directions; test_library_boundary.py enforces the transport boundary at AST level.

Confidence Score: 3/5

Safe to merge for all integrations except CrowdStrike AIDR, where the effective request URL has changed and is not caught by the existing test suite.

The migration is thorough and well-structured across all ten integrations. The CrowdStrike AIDR endpoint URL changes from the old httpx base_url resolution result to a string-concatenated URL, and the existing test uses HTTPXMock without a URL matcher so it passes regardless of which URL is called.

Files Needing Attention: nemoguardrails/library/crowdstrike_aidr/actions.py — verify the CrowdStrike AIDR endpoint URL and update tests/test_crowdstrike_aidr_guard.py to pin the expected URL.

Important Files Changed

Filename Overview
nemoguardrails/http/types.py Adds HTTPTLSConfig dataclass with verify, ca_bundle, client_certificate, and client_key fields; validates that cert/key are always provided together.
nemoguardrails/http/transport.py Wires HTTPTLSConfig into HttpxHTTPClient; correctly rejects TLS config with an injected client and converts ca_bundle/cert/key to httpx verify/cert kwargs.
nemoguardrails/library/crowdstrike_aidr/actions.py Migrates to canonical HTTP client; the endpoint URL has changed due to switching from httpx base_url resolution to string concatenation, unverified by tests.
nemoguardrails/library/clavata/request.py Replaces aiohttp session with canonical HTTP client and module-level RetryPolicy; the outer except Exception on line 221 still erases the ClavataPluginAPIRateLimitError type.
nemoguardrails/library/f5/actions.py Replaces custom aiohttp retry loop with RetryPolicy; bounded max_retry_after and clamp_retry_after preserve F5 original behavior; fail-open paths are preserved.
nemoguardrails/library/hf_classifier/backends.py Replaces httpx SSL config with HTTPTLSConfig; retry behavior is equivalent (2 attempts, transport errors only); cache bypass for injected clients is intentional.
tests/http_utils.py Introduces shared RecordedHTTPResponses test utility with bidirectional URL and order assertions; replaces per-file duplicate classes from prior commits.
tests/http/test_library_boundary.py AST-based conformance test that prevents any library file from directly importing aiohttp, httpx, requests, or urllib3.
nemoguardrails/library/autoalign/actions.py Migrates three AutoAlign endpoints to http_call; NDJSON parsing preserved via splitlines() on buffered content, semantically equivalent to old aiohttp line iteration.
nemoguardrails/library/ai_defense/actions.py Replaces httpx client with http_call (raise_for_status=True by default); fail-open and fail-closed paths preserved.
nemoguardrails/library/patronusai/actions.py Migrates to canonical HTTP client; uses unnecessary conditional request_kwargs pattern instead of passing http_client directly.
nemoguardrails/library/pangea/actions.py Clean migration; Pangea base URL has no path component so string-concatenation endpoint construction produces the same URL as the old httpx base_url resolution.

Sequence Diagram

sequenceDiagram
    participant Action as Library Action
    participant http_call as http_call()
    participant Retry as RetryingHTTPClient
    participant Transport as HttpxHTTPClient
    participant Vendor as Vendor API

    Action->>http_call: POST url, headers, json
    alt injected client
        http_call->>Retry: request(...)
        Retry->>Transport: request(...)
    else factory client
        http_call->>Transport: "create_http_client(tls=...)"
        Transport->>Transport: httpx.AsyncClient(verify, cert)
    end
    Transport->>Vendor: POST
    Vendor-->>Transport: HTTP response
    Transport-->>Retry: HTTPResponse
    Retry-->>http_call: HTTPResponse (or retry on 429/transport error)
    http_call-->>Action: HTTPResponse (raise_for_status if needed)
    Action->>Action: parse JSON, apply business logic
Loading

Reviews (7): Last reviewed commit: "test(f5): remove aioresponses compatibil..." | Re-trigger Greptile

Comment thread nemoguardrails/library/autoalign/actions.py Outdated
Comment thread tests/test_f5_guardrails.py Outdated
@Pouyanpi
Pouyanpi force-pushed the pouyanpi/rail-library-stack-13-http-action-migrations branch 3 times, most recently from bf8c358 to 9c0ae71 Compare July 24, 2026 15:53
@Pouyanpi
Pouyanpi force-pushed the pouyanpi/rail-library-stack-13-http-action-migrations branch from 9c0ae71 to 60b4af2 Compare July 29, 2026 08:13
Comment on lines 221 to 222
except Exception as e:
raise ClavataPluginAPIError(f"Failed to make Clavata API request. Error: {e}") from e

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Outer except Exception erases ClavataPluginAPIRateLimitError type

ClavataPluginAPIRateLimitError is a subclass of ClavataPluginAPIError, which is a subclass of Exception. When a 429 response is received after retries are exhausted, ClavataPluginAPIRateLimitError is raised on line 199, immediately caught by the outer except Exception as e on line 221, and re-wrapped as a generic ClavataPluginAPIError. Any caller that tries to except ClavataPluginAPIRateLimitError to distinguish rate-limit failures from other API errors will never match; it will always see a plain ClavataPluginAPIError instead.

Prompt To Fix With AI
This is a comment left during a code review.
Path: nemoguardrails/library/clavata/request.py
Line: 221-222

Comment:
**Outer `except Exception` erases `ClavataPluginAPIRateLimitError` type**

`ClavataPluginAPIRateLimitError` is a subclass of `ClavataPluginAPIError`, which is a subclass of `Exception`. When a 429 response is received after retries are exhausted, `ClavataPluginAPIRateLimitError` is raised on line 199, immediately caught by the outer `except Exception as e` on line 221, and re-wrapped as a generic `ClavataPluginAPIError`. Any caller that tries to `except ClavataPluginAPIRateLimitError` to distinguish rate-limit failures from other API errors will never match; it will always see a plain `ClavataPluginAPIError` instead.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Base automatically changed from pouyanpi/rail-library-stack-12-http-request-migrations to develop July 30, 2026 07:36
Pouyanpi added 28 commits July 30, 2026 09:53
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
@Pouyanpi
Pouyanpi force-pushed the pouyanpi/rail-library-stack-13-http-action-migrations branch from 73a2977 to b02780f Compare July 30, 2026 07:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size: XL status: triaged Triaged by a maintainer; eligible for automated review (CodeRabbit/Greptile).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants