@@ -597,3 +597,140 @@ def test_guardrail_agent_without_tools(monkeypatch: pytest.MonkeyPatch) -> None:
597597 agent_instance = agents .GuardrailAgent (config = {}, name = "NoTools" , instructions = "None" )
598598
599599 assert getattr (agent_instance , "input_guardrails" , []) == [] # noqa: S101
600+
601+
602+ def test_guardrail_agent_without_instructions (monkeypatch : pytest .MonkeyPatch ) -> None :
603+ """GuardrailAgent should work without instructions parameter."""
604+ pipeline = SimpleNamespace (pre_flight = None , input = None , output = None )
605+
606+ monkeypatch .setattr (runtime_module , "load_pipeline_bundles" , lambda config : pipeline , raising = False )
607+ monkeypatch .setattr (runtime_module , "instantiate_guardrails" , lambda * args , ** kwargs : [], raising = False )
608+
609+ # Should not raise TypeError about missing instructions
610+ agent_instance = agents .GuardrailAgent (config = {}, name = "NoInstructions" )
611+
612+ assert isinstance (agent_instance , agents_module .Agent ) # noqa: S101
613+ assert agent_instance .instructions is None # noqa: S101
614+
615+
616+ def test_guardrail_agent_with_callable_instructions (monkeypatch : pytest .MonkeyPatch ) -> None :
617+ """GuardrailAgent should accept callable instructions."""
618+ pipeline = SimpleNamespace (pre_flight = None , input = None , output = None )
619+
620+ monkeypatch .setattr (runtime_module , "load_pipeline_bundles" , lambda config : pipeline , raising = False )
621+ monkeypatch .setattr (runtime_module , "instantiate_guardrails" , lambda * args , ** kwargs : [], raising = False )
622+
623+ def dynamic_instructions (ctx : Any , agent : Any ) -> str :
624+ return f"You are { agent .name } "
625+
626+ agent_instance = agents .GuardrailAgent (
627+ config = {},
628+ name = "DynamicAgent" ,
629+ instructions = dynamic_instructions ,
630+ )
631+
632+ assert isinstance (agent_instance , agents_module .Agent ) # noqa: S101
633+ assert callable (agent_instance .instructions ) # noqa: S101
634+ assert agent_instance .instructions == dynamic_instructions # noqa: S101
635+
636+
637+ def test_guardrail_agent_merges_user_input_guardrails (monkeypatch : pytest .MonkeyPatch ) -> None :
638+ """User input guardrails should be merged with config guardrails."""
639+ agent_guard = _make_guardrail ("Config Input Guard" )
640+
641+ class FakePipeline :
642+ def __init__ (self ) -> None :
643+ self .pre_flight = None
644+ self .input = SimpleNamespace ()
645+ self .output = None
646+
647+ pipeline = FakePipeline ()
648+
649+ def fake_load_pipeline_bundles (config : Any ) -> FakePipeline :
650+ return pipeline
651+
652+ def fake_instantiate_guardrails (stage : Any , registry : Any | None = None ) -> list [Any ]:
653+ if stage is pipeline .input :
654+ return [agent_guard ]
655+ return []
656+
657+ from guardrails import runtime as runtime_module
658+
659+ monkeypatch .setattr (runtime_module , "load_pipeline_bundles" , fake_load_pipeline_bundles )
660+ monkeypatch .setattr (runtime_module , "instantiate_guardrails" , fake_instantiate_guardrails )
661+
662+ # Create a custom user guardrail
663+ custom_guardrail = lambda ctx , agent , input : None # noqa: E731
664+
665+ agent_instance = agents .GuardrailAgent (
666+ config = {},
667+ name = "MergedAgent" ,
668+ instructions = "Test" ,
669+ input_guardrails = [custom_guardrail ],
670+ )
671+
672+ # Should have both config and user guardrails merged
673+ assert isinstance (agent_instance , agents_module .Agent ) # noqa: S101
674+ assert len (agent_instance .input_guardrails ) == 2 # noqa: S101
675+ # Config guardrail from _create_agents_guardrails_from_config, then user guardrail
676+
677+
678+ def test_guardrail_agent_merges_user_output_guardrails (monkeypatch : pytest .MonkeyPatch ) -> None :
679+ """User output guardrails should be merged with config guardrails."""
680+ agent_guard = _make_guardrail ("Config Output Guard" )
681+
682+ class FakePipeline :
683+ def __init__ (self ) -> None :
684+ self .pre_flight = None
685+ self .input = None
686+ self .output = SimpleNamespace ()
687+
688+ pipeline = FakePipeline ()
689+
690+ def fake_load_pipeline_bundles (config : Any ) -> FakePipeline :
691+ return pipeline
692+
693+ def fake_instantiate_guardrails (stage : Any , registry : Any | None = None ) -> list [Any ]:
694+ if stage is pipeline .output :
695+ return [agent_guard ]
696+ return []
697+
698+ from guardrails import runtime as runtime_module
699+
700+ monkeypatch .setattr (runtime_module , "load_pipeline_bundles" , fake_load_pipeline_bundles )
701+ monkeypatch .setattr (runtime_module , "instantiate_guardrails" , fake_instantiate_guardrails )
702+
703+ # Create a custom user guardrail
704+ custom_guardrail = lambda ctx , agent , output : None # noqa: E731
705+
706+ agent_instance = agents .GuardrailAgent (
707+ config = {},
708+ name = "MergedAgent" ,
709+ instructions = "Test" ,
710+ output_guardrails = [custom_guardrail ],
711+ )
712+
713+ # Should have both config and user guardrails merged
714+ assert isinstance (agent_instance , agents_module .Agent ) # noqa: S101
715+ assert len (agent_instance .output_guardrails ) == 2 # noqa: S101
716+ # Config guardrail from _create_agents_guardrails_from_config, then user guardrail
717+
718+
719+ def test_guardrail_agent_with_empty_user_guardrails (monkeypatch : pytest .MonkeyPatch ) -> None :
720+ """GuardrailAgent should handle empty user guardrail lists gracefully."""
721+ pipeline = SimpleNamespace (pre_flight = None , input = None , output = None )
722+
723+ monkeypatch .setattr (runtime_module , "load_pipeline_bundles" , lambda config : pipeline , raising = False )
724+ monkeypatch .setattr (runtime_module , "instantiate_guardrails" , lambda * args , ** kwargs : [], raising = False )
725+
726+ agent_instance = agents .GuardrailAgent (
727+ config = {},
728+ name = "EmptyListAgent" ,
729+ instructions = "Test" ,
730+ input_guardrails = [],
731+ output_guardrails = [],
732+ )
733+
734+ assert isinstance (agent_instance , agents_module .Agent ) # noqa: S101
735+ assert agent_instance .input_guardrails == [] # noqa: S101
736+ assert agent_instance .output_guardrails == [] # noqa: S101
0 commit comments