Skip to content

RunState guardrail payload serialization fails for non-JSON values #3288

@Aphroq

Description

@Aphroq

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions