From e054c6c785805e2811e97df8666e0e1be6c6808f Mon Sep 17 00:00:00 2001 From: Conduct AI Date: Thu, 10 Sep 2026 22:29:09 -0500 Subject: [PATCH] fix: SUPPORTED_EVENT_HOOKS must be GuardrailEventHooks enum, not str LiteLLM's guardrail registry scans SUPPORTED_EVENT_HOOKS and calls .value on each entry to build the mode allowlist. Plugin 0.2.3 shipped bare strings, which raised AttributeError on three upstream tests (same three as the pre-0.2.3 None-registration failure). - Fallback stub now uses GuardrailEventHooks.pre_call. - Docstring and pip install message updated to >=0.2.4. - Test asserts against the enum member (which is what LiteLLM's registry scan actually sees). Requires plugin conduct-litellm-guard >=0.2.4 (already tagged and publishing). All four budget gates verified locally green: ruff_strict, test_quality, type_discipline, type_check --- .../guardrails/guardrail_hooks/conduct/conduct.py | 11 ++++++----- .../proxy/guardrails/test_conduct_guardrail.py | 9 ++++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/litellm/proxy/guardrails/guardrail_hooks/conduct/conduct.py b/litellm/proxy/guardrails/guardrail_hooks/conduct/conduct.py index 6c4e612de7d..a0cbbf4bd67 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/conduct/conduct.py +++ b/litellm/proxy/guardrails/guardrail_hooks/conduct/conduct.py @@ -2,7 +2,7 @@ Thin alias for the ``conduct-litellm-guard`` PyPI package. The ``ConductGuard`` class ships with ``SUPPORTED_EVENT_HOOKS`` + -``get_supported_event_hooks`` since plugin 0.2.3, so this file no +``get_supported_event_hooks`` since plugin 0.2.4, so this file no longer needs a subclass wrapper — keeps LiteLLM's type-discipline / basedpyright / test-quality budget gates satisfied. @@ -13,7 +13,7 @@ BerriAI/litellm#38143 CI regression: registry iteration expects every registered class to expose the hooks classmethod). Instantiation of the stub raises ``ImportError`` via ``raise_if_missing_package``. -Install: ``pip install "conduct-litellm-guard>=0.2.3"`` +Install: ``pip install "conduct-litellm-guard>=0.2.4"`` Source: https://github.com/sseshachala/conductai/tree/main/packages/conduct-litellm-guard Docs: https://conductai.ai/guard """ @@ -23,10 +23,11 @@ from __future__ import annotations from typing import ClassVar from litellm.integrations.custom_guardrail import CustomGuardrail +from litellm.types.guardrails import GuardrailEventHooks _import_error_message = ( "conduct-litellm-guard is required for the Conduct guardrail. " - 'Install it with: pip install "conduct-litellm-guard>=0.2.3"' + 'Install it with: pip install "conduct-litellm-guard>=0.2.4"' ) @@ -52,10 +53,10 @@ except ImportError as _err: ``pip install`` error rather than the stub silently activating. """ - SUPPORTED_EVENT_HOOKS: ClassVar[tuple[str, ...]] = ("pre_call",) + SUPPORTED_EVENT_HOOKS: ClassVar[tuple[GuardrailEventHooks, ...]] = (GuardrailEventHooks.pre_call,) @classmethod - def get_supported_event_hooks(cls) -> list[str]: + def get_supported_event_hooks(cls) -> list[GuardrailEventHooks]: return list(cls.SUPPORTED_EVENT_HOOKS) # mutable-ok: LiteLLM registry expects a fresh list ConductGuardrailBlocked = None diff --git a/tests/test_litellm/proxy/guardrails/test_conduct_guardrail.py b/tests/test_litellm/proxy/guardrails/test_conduct_guardrail.py index 9531d403555..d0ce0ee45d7 100644 --- a/tests/test_litellm/proxy/guardrails/test_conduct_guardrail.py +++ b/tests/test_litellm/proxy/guardrails/test_conduct_guardrail.py @@ -59,13 +59,16 @@ def test_registries_populated() -> None: def test_only_pre_call_event_hook_advertised() -> None: """Regression for veria-ai finding on #38143 — ``during_call`` mode was silently accepted but never evaluated. - Since plugin 0.2.3 the supported-hooks contract lives on + Since plugin 0.2.4 the supported-hooks contract lives on ``ConductGuard`` in the plugin package itself; the LiteLLM shim - is a pure alias, so we verify against the alias.""" + is a pure alias, so we verify against the alias. LiteLLM's + registry calls ``.value`` on each entry, so the hooks must be + ``GuardrailEventHooks`` enum members, not bare strings.""" from litellm.proxy.guardrails.guardrail_hooks.conduct import ConductGuardrail + from litellm.types.guardrails import GuardrailEventHooks hooks = ConductGuardrail.get_supported_event_hooks() - assert hooks == ["pre_call"] + assert hooks == [GuardrailEventHooks.pre_call] def test_initialize_guardrail_returns_wired_callback(