Please read this first
- Have you read the docs? Yes. This is about
RunState serialization behavior rather than a documented usage option.
- Have you searched for related issues? Yes. I searched existing issues and PRs for:
Describe the bug
RunState.to_string() can fail when persisted guardrail result payloads contain non-JSON-native values. _serialize_guardrail_results() writes guardrail outputInfo and output guardrail agentOutput directly, and _serialize_tool_guardrail_results() writes tool guardrail outputInfo directly. Other RunState user payloads already use JSON-compatible normalization, so these guardrail payloads are an outlier.
Debug information
- Agents SDK version: upstream
main at 683b6e79
- Python version: Python 3.12.1
Repro steps
Run this script from a checkout of upstream main at revision 683b6e79:
from datetime import datetime
from agents import Agent
from agents.guardrail import (
GuardrailFunctionOutput,
InputGuardrail,
InputGuardrailResult,
OutputGuardrail,
OutputGuardrailResult,
)
from agents.run_context import RunContextWrapper
from agents.run_state import RunState
from agents.tool_guardrails import (
AllowBehavior,
ToolGuardrailFunctionOutput,
ToolInputGuardrail,
ToolInputGuardrailResult,
ToolOutputGuardrail,
ToolOutputGuardrailResult,
)
agent = Agent(name="GuardrailPayloadAgent")
state = RunState(
_current_agent=agent,
_starting_agent=agent,
_original_input="input",
_context=RunContextWrapper(context={}),
_max_turns=1,
)
observed_at = datetime(2026, 5, 8, 12, 0, 0)
input_guardrail = InputGuardrail(
guardrail_function=lambda ctx, ag, inp: GuardrailFunctionOutput(
output_info={"observed_at": observed_at},
tripwire_triggered=False,
),
name="input_guardrail",
)
output_guardrail = OutputGuardrail(
guardrail_function=lambda ctx, ag, out: GuardrailFunctionOutput(
output_info={"observed_at": observed_at},
tripwire_triggered=False,
),
name="output_guardrail",
)
tool_input_guardrail = ToolInputGuardrail(
guardrail_function=lambda data: ToolGuardrailFunctionOutput(
output_info={"observed_at": observed_at},
behavior=AllowBehavior(type="allow"),
),
name="tool_input_guardrail",
)
tool_output_guardrail = ToolOutputGuardrail(
guardrail_function=lambda data: ToolGuardrailFunctionOutput(
output_info={"observed_at": observed_at},
behavior=AllowBehavior(type="allow"),
),
name="tool_output_guardrail",
)
state._input_guardrail_results = [
InputGuardrailResult(
guardrail=input_guardrail,
output=GuardrailFunctionOutput(
output_info={"observed_at": observed_at},
tripwire_triggered=False,
),
)
]
state._output_guardrail_results = [
OutputGuardrailResult(
guardrail=output_guardrail,
agent_output={"observed_at": observed_at},
agent=agent,
output=GuardrailFunctionOutput(
output_info={"observed_at": observed_at},
tripwire_triggered=False,
),
)
]
state._tool_input_guardrail_results = [
ToolInputGuardrailResult(
guardrail=tool_input_guardrail,
output=ToolGuardrailFunctionOutput(
output_info={"observed_at": observed_at},
behavior=AllowBehavior(type="allow"),
),
)
]
state._tool_output_guardrail_results = [
ToolOutputGuardrailResult(
guardrail=tool_output_guardrail,
output=ToolGuardrailFunctionOutput(
output_info={"observed_at": observed_at},
behavior=AllowBehavior(type="allow"),
),
)
]
print(state.to_string())
Actual result:
TypeError: Object of type datetime is not JSON serializable
The same failure is covered by focused regression tests:
FAILED tests/test_run_state.py::TestRunState::test_guardrail_results_to_string_normalizes_non_json_payloads
FAILED tests/test_run_state.py::TestRunState::test_tool_guardrail_results_to_string_normalizes_non_json_output_info
E TypeError: Object of type datetime is not JSON serializable
Expected behavior
RunState serialization should remain JSON-compatible. Guardrail outputInfo, output guardrail agentOutput, and tool guardrail outputInfo should be normalized the same way as other user payloads already serialized by RunState.
Please read this first
RunStateserialization behavior rather than a documented usage option.Describe the bug
RunState.to_string()can fail when persisted guardrail result payloads contain non-JSON-native values._serialize_guardrail_results()writes guardrailoutputInfoand output guardrailagentOutputdirectly, and_serialize_tool_guardrail_results()writes tool guardrailoutputInfodirectly. OtherRunStateuser payloads already use JSON-compatible normalization, so these guardrail payloads are an outlier.Debug information
mainat683b6e79Repro steps
Run this script from a checkout of upstream
mainat revision683b6e79:Actual result:
The same failure is covered by focused regression tests:
Expected behavior
RunStateserialization should remain JSON-compatible. GuardrailoutputInfo, output guardrailagentOutput, and tool guardrailoutputInfoshould be normalized the same way as other user payloads already serialized byRunState.