agent = Agent( name="CustomerSupportAgent", instructions="You are a helpful customer support agent.", output_guardrails=[response_content_guardrail], validation_attempts=2,)
Setting
Behavior
validation_attempts=0
Fail-fast (no retry, immediate exception)
validation_attempts=1
Default (one retry after initial failure)
validation_attempts=2+
Multiple retries for more complex validations
Each retry sends the guardrail output_info message to the agent as a system message, giving the agent context to adjust its response.
Output guardrail failures are stored as system messages with message_origin="output_guardrail_error".
For most use cases, role, content, and message_origin are enough. Extra metadata is mainly for debugging and run tracing.
Origin
Meaning
output_guardrail_error
Output guardrail failure (system message)
Example history entry (with debug metadata)
Copy
Ask AI
{ "role": "system", "content": "You are not allowed to include your email address in your response. Ask agent to redirect user to the contact page: https://www.example.com/contact", "message_origin": "output_guardrail_error", "agent": "DatabaseAgent", "callerAgent": "CustomerSupportAgent", "agent_run_id": "agent_run_id", "parent_run_id": "call_id", "timestamp": 1758103770629217, "type": "message"}
Use guardrails to control how agents communicate with each other. When adding communication flows between agents, the recipient agent’s guardrails define the message format.
Example: Task/Response contract between agents
Copy
Ask AI
from agency_swarm import Agency, Agent, GuardrailFunctionOutput, RunContextWrapper, input_guardrail, output_guardrail@input_guardrail(name="RequireTaskPrefix")async def require_task_prefix( context: RunContextWrapper, agent: Agent, agent_input: str | list[str]) -> GuardrailFunctionOutput: text = agent_input if isinstance(agent_input, str) else " ".join(agent_input) blocked = not text.startswith("Task:") return GuardrailFunctionOutput( output_info="ERROR: Requests to this agent must begin with 'Task:'" if blocked else "", tripwire_triggered=blocked, )@output_guardrail(name="RequireResponsePrefix")async def require_response_prefix( context: RunContextWrapper, agent: Agent, response_text: str) -> GuardrailFunctionOutput: blocked = not response_text.startswith("Response:") return GuardrailFunctionOutput( output_info="ERROR: Responses must start with 'Response:'" if blocked else "", tripwire_triggered=blocked, )ceo = Agent(name="CEO", instructions="You are the CEO agent.")worker = Agent( name="Worker", instructions="You are the worker agent.", input_guardrails=[require_task_prefix], output_guardrails=[require_response_prefix], raise_input_guardrail_error=True,)agency = Agency(ceo, communication_flows=[(ceo, worker)])
In this example:
If the CEO sends a message that does not start with Task:, the worker input guardrail triggers.
The CEO receives an error and adjusts its message.
The worker output guardrail enforces Response: in returned messages.
Agent-to-agent messages are always single strings, so input guardrails for inter-agent communication receive a string (not a list).