mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-05-05 01:02:37 +00:00
131 lines
4.2 KiB
Python
131 lines
4.2 KiB
Python
"""Tests for JSON serialization of guardrail fields on Task, Agent, and LiteAgent.
|
|
|
|
Guardrails accept either string descriptions or callables. Callables cannot be
|
|
JSON-serialized, so the checkpoint path must drop them rather than raise.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from crewai import Agent, Task
|
|
from crewai.lite_agent import LiteAgent
|
|
from crewai.utilities.guardrail import (
|
|
serialize_guardrail_for_json,
|
|
serialize_guardrails_for_json,
|
|
)
|
|
|
|
|
|
def _example_guardrail(output):
|
|
return True, output
|
|
|
|
|
|
def test_serialize_guardrail_preserves_string() -> None:
|
|
assert serialize_guardrail_for_json("validate output") == "validate output"
|
|
|
|
|
|
def test_serialize_guardrail_returns_none_for_none() -> None:
|
|
assert serialize_guardrail_for_json(None) is None
|
|
|
|
|
|
def test_serialize_guardrail_drops_callable_with_warning() -> None:
|
|
with pytest.warns(UserWarning, match="cannot be JSON-serialized"):
|
|
assert serialize_guardrail_for_json(_example_guardrail) is None
|
|
|
|
|
|
def test_serialize_guardrails_drops_callables_from_list() -> None:
|
|
with pytest.warns(UserWarning):
|
|
result = serialize_guardrails_for_json(["check size", _example_guardrail])
|
|
assert result == ["check size"]
|
|
|
|
|
|
def test_serialize_guardrails_all_callables_returns_empty_list() -> None:
|
|
with pytest.warns(UserWarning):
|
|
result = serialize_guardrails_for_json([_example_guardrail, _example_guardrail])
|
|
assert result == []
|
|
|
|
|
|
def test_serialize_guardrails_handles_single_string() -> None:
|
|
assert serialize_guardrails_for_json("only check this") == "only check this"
|
|
|
|
|
|
def test_serialize_guardrails_handles_single_callable() -> None:
|
|
with pytest.warns(UserWarning):
|
|
assert serialize_guardrails_for_json(_example_guardrail) is None
|
|
|
|
|
|
def test_task_model_dump_json_with_string_guardrail() -> None:
|
|
agent = Agent(role="r", goal="g", backstory="b")
|
|
task = Task(
|
|
description="Do the thing",
|
|
expected_output="A thing",
|
|
agent=agent,
|
|
guardrail="output must be non-empty",
|
|
)
|
|
dumped = task.model_dump(mode="json")
|
|
assert dumped["guardrail"] == "output must be non-empty"
|
|
|
|
|
|
def test_task_model_dump_json_with_callable_guardrail_does_not_raise() -> None:
|
|
agent = Agent(role="r", goal="g", backstory="b")
|
|
task = Task(
|
|
description="Do the thing",
|
|
expected_output="A thing",
|
|
agent=agent,
|
|
guardrail=_example_guardrail,
|
|
)
|
|
with pytest.warns(UserWarning, match="cannot be JSON-serialized"):
|
|
dumped = task.model_dump(mode="json")
|
|
assert dumped["guardrail"] is None
|
|
|
|
|
|
def test_task_model_dump_json_with_callable_guardrails_list() -> None:
|
|
agent = Agent(role="r", goal="g", backstory="b")
|
|
task = Task(
|
|
description="Do the thing",
|
|
expected_output="A thing",
|
|
agent=agent,
|
|
guardrails=[_example_guardrail, "also check this"],
|
|
)
|
|
with pytest.warns(UserWarning):
|
|
dumped = task.model_dump(mode="json")
|
|
assert dumped["guardrails"] == ["also check this"]
|
|
|
|
|
|
def test_task_guardrails_round_trip_through_model_validate() -> None:
|
|
"""Serialized guardrails must round-trip — None entries would fail validation."""
|
|
agent = Agent(role="r", goal="g", backstory="b")
|
|
task = Task(
|
|
description="Do the thing",
|
|
expected_output="A thing",
|
|
agent=agent,
|
|
guardrails=[_example_guardrail, "also check this"],
|
|
)
|
|
with pytest.warns(UserWarning):
|
|
dumped = task.model_dump(mode="json", exclude={"id"})
|
|
if isinstance(dumped.get("agent"), dict):
|
|
dumped["agent"].pop("id", None)
|
|
Task.model_validate(dumped)
|
|
|
|
|
|
def test_agent_model_dump_json_with_callable_guardrail() -> None:
|
|
agent = Agent(
|
|
role="r",
|
|
goal="g",
|
|
backstory="b",
|
|
guardrail=_example_guardrail,
|
|
)
|
|
with pytest.warns(UserWarning, match="cannot be JSON-serialized"):
|
|
dumped = agent.model_dump(mode="json")
|
|
assert dumped["guardrail"] is None
|
|
|
|
|
|
def test_lite_agent_model_dump_json_with_callable_guardrail() -> None:
|
|
agent = LiteAgent(
|
|
role="r",
|
|
goal="g",
|
|
backstory="b",
|
|
guardrail=_example_guardrail,
|
|
)
|
|
with pytest.warns(UserWarning, match="cannot be JSON-serialized"):
|
|
dumped = agent.model_dump(mode="json")
|
|
assert dumped["guardrail"] is None
|