@@ -752,3 +752,162 @@ def guardrail_3(result: TaskOutput) -> tuple[bool, str]:
752752 assert call_counts ["g3" ] == 1
753753
754754 assert "G3(1)" in result .raw
755+
756+
757+ def test_output_file_contains_guardrail_modified_raw_result (tmp_path , monkeypatch ):
758+ """Test that output file contains the result after guardrail modification for raw output."""
759+ monkeypatch .chdir (tmp_path )
760+ output_file = tmp_path / "output.txt"
761+
762+ def modify_guardrail (result : TaskOutput ) -> tuple [bool , str ]:
763+ return (True , "MODIFIED BY GUARDRAIL" )
764+
765+ agent = Mock ()
766+ agent .role = "test_agent"
767+ agent .execute_task .return_value = "original result"
768+ agent .crew = None
769+ agent .last_messages = []
770+
771+ task = create_smart_task (
772+ description = "Test task" ,
773+ expected_output = "Output" ,
774+ guardrails = [modify_guardrail ],
775+ output_file = "output.txt" ,
776+ )
777+
778+ result = task .execute_sync (agent = agent )
779+
780+ assert result .raw == "MODIFIED BY GUARDRAIL"
781+ assert output_file .read_text () == "MODIFIED BY GUARDRAIL"
782+
783+
784+ def test_output_file_contains_guardrail_modified_json_result (tmp_path , monkeypatch ):
785+ """Test that output file contains the result after guardrail modification for JSON output."""
786+ import json
787+
788+ from pydantic import BaseModel
789+
790+ monkeypatch .chdir (tmp_path )
791+
792+ class TestModel (BaseModel ):
793+ message : str
794+
795+ output_file = tmp_path / "output.json"
796+
797+ def modify_guardrail (result : TaskOutput ) -> tuple [bool , str ]:
798+ return (True , '{"message": "modified by guardrail"}' )
799+
800+ agent = Mock ()
801+ agent .role = "test_agent"
802+ agent .execute_task .return_value = '{"message": "original"}'
803+ agent .crew = None
804+ agent .last_messages = []
805+
806+ task = create_smart_task (
807+ description = "Test task" ,
808+ expected_output = "Output" ,
809+ guardrails = [modify_guardrail ],
810+ output_json = TestModel ,
811+ output_file = "output.json" ,
812+ )
813+
814+ result = task .execute_sync (agent = agent )
815+
816+ assert result .json_dict == {"message" : "modified by guardrail" }
817+ file_content = json .loads (output_file .read_text ())
818+ assert file_content == {"message" : "modified by guardrail" }
819+
820+
821+ def test_output_file_contains_guardrail_modified_pydantic_result (tmp_path , monkeypatch ):
822+ """Test that output file contains the result after guardrail modification for pydantic output."""
823+ import json
824+
825+ from pydantic import BaseModel
826+
827+ monkeypatch .chdir (tmp_path )
828+
829+ class TestModel (BaseModel ):
830+ message : str
831+
832+ output_file = tmp_path / "output.json"
833+
834+ def modify_guardrail (result : TaskOutput ) -> tuple [bool , str ]:
835+ return (True , '{"message": "modified by guardrail"}' )
836+
837+ agent = Mock ()
838+ agent .role = "test_agent"
839+ agent .execute_task .return_value = '{"message": "original"}'
840+ agent .crew = None
841+ agent .last_messages = []
842+
843+ task = create_smart_task (
844+ description = "Test task" ,
845+ expected_output = "Output" ,
846+ guardrails = [modify_guardrail ],
847+ output_pydantic = TestModel ,
848+ output_file = "output.json" ,
849+ )
850+
851+ result = task .execute_sync (agent = agent )
852+
853+ assert result .pydantic is not None
854+ assert result .pydantic .message == "modified by guardrail"
855+ file_content = json .loads (output_file .read_text ())
856+ assert file_content == {"message" : "modified by guardrail" }
857+
858+
859+ def test_output_file_with_single_guardrail_modification (tmp_path , monkeypatch ):
860+ """Test that output file contains the result after single guardrail modification."""
861+ monkeypatch .chdir (tmp_path )
862+ output_file = tmp_path / "output.txt"
863+
864+ def modify_guardrail (result : TaskOutput ) -> tuple [bool , str ]:
865+ return (True , result .raw .upper ())
866+
867+ agent = Mock ()
868+ agent .role = "test_agent"
869+ agent .execute_task .return_value = "hello world"
870+ agent .crew = None
871+ agent .last_messages = []
872+
873+ task = create_smart_task (
874+ description = "Test task" ,
875+ expected_output = "Output" ,
876+ guardrail = modify_guardrail ,
877+ output_file = "output.txt" ,
878+ )
879+
880+ result = task .execute_sync (agent = agent )
881+
882+ assert result .raw == "HELLO WORLD"
883+ assert output_file .read_text () == "HELLO WORLD"
884+
885+
886+ def test_output_file_with_multiple_guardrails_chained_modifications (tmp_path , monkeypatch ):
887+ """Test that output file contains the final result after multiple guardrail modifications."""
888+ monkeypatch .chdir (tmp_path )
889+ output_file = tmp_path / "output.txt"
890+
891+ def first_guardrail (result : TaskOutput ) -> tuple [bool , str ]:
892+ return (True , f"[FIRST] { result .raw } " )
893+
894+ def second_guardrail (result : TaskOutput ) -> tuple [bool , str ]:
895+ return (True , f"{ result .raw } [SECOND]" )
896+
897+ agent = Mock ()
898+ agent .role = "test_agent"
899+ agent .execute_task .return_value = "original"
900+ agent .crew = None
901+ agent .last_messages = []
902+
903+ task = create_smart_task (
904+ description = "Test task" ,
905+ expected_output = "Output" ,
906+ guardrails = [first_guardrail , second_guardrail ],
907+ output_file = "output.txt" ,
908+ )
909+
910+ result = task .execute_sync (agent = agent )
911+
912+ assert result .raw == "[FIRST] original [SECOND]"
913+ assert output_file .read_text () == "[FIRST] original [SECOND]"
0 commit comments