refactor(library): migrate vendor actions to canonical HTTP clients - #2212
refactor(library): migrate vendor actions to canonical HTTP clients#2212Pouyanpi wants to merge 28 commits into
Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
1f8c466 to
9852187
Compare
9852187 to
736a206
Compare
Greptile SummaryThis 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
|
| 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
Reviews (7): Last reviewed commit: "test(f5): remove aioresponses compatibil..." | Re-trigger Greptile
bf8c358 to
9c0ae71
Compare
9c0ae71 to
60b4af2
Compare
| except Exception as e: | ||
| raise ClavataPluginAPIError(f"Failed to make Clavata API request. Error: {e}") from e |
There was a problem hiding this 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.
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!
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>
73a2977 to
b02780f
Compare
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_callfor request execution.The Hugging Face classifier and Clavata integrations retain their specialized
retry and TLS requirements. A transport-neutral
HTTPTLSConfigsupports customCA 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_callcloses deterministically.F5 preserves its bounded
Retry-Afterbehavior. Shared recorded-response testsverify registered endpoints in both directions, and an AST-based conformance
test prevents library integrations from importing HTTPX, aiohttp, Requests, or
urllib3 directly.
Impact
boundary.
Stack
pouyanpi/rail-library-stack-9-http-contractdeveloppouyanpi/rail-library-stack-10-http-instrumentationpouyanpi/rail-library-stack-11-http-observabilitypouyanpi/rail-library-stack-12-http-request-migrationspouyanpi/rail-library-stack-13-http-action-migrationsRelated Issue(s)
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.AI Assistance
Codex assisted with implementation analysis, validation, stack restructuring,
and this draft. Check the disclosure box after human review.
Checklist
Summary by CodeRabbit