guardrails_input.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. """Input guardrails demo that delegates relevance decisions to a judge agent."""
  2. import asyncio
  3. from collections.abc import Sequence
  4. from pydantic import BaseModel
  5. from agency_swarm import (
  6. Agency,
  7. Agent,
  8. GuardrailFunctionOutput,
  9. ModelSettings,
  10. Reasoning,
  11. RunContextWrapper,
  12. input_guardrail,
  13. )
  14. class RelevanceDecision(BaseModel):
  15. is_relevant: bool
  16. reason: str
  17. guardrail_agent = Agent(
  18. name="GuardrailAgent",
  19. instructions=(
  20. "You screen incoming messages for a customer-support assistant. "
  21. "Treat questions about account access, billing, and troubleshooting as relevant. "
  22. "Flag any other unrelated requests as irrelevant."
  23. ),
  24. model="gpt-5.4-mini",
  25. model_settings=ModelSettings(reasoning=Reasoning(effort="low")),
  26. output_type=RelevanceDecision,
  27. )
  28. def _to_text(payload: str | Sequence[str]) -> str:
  29. if isinstance(payload, str):
  30. return payload
  31. # in case Agency.get_response gets a list of input items, join them into a single string
  32. return "\n".join(str(item) for item in payload)
  33. @input_guardrail
  34. async def require_support_topic(
  35. context: RunContextWrapper, agent: Agent, user_input: str | list[str]
  36. ) -> GuardrailFunctionOutput:
  37. """Forward the decision to the guardrail agent."""
  38. candidate = _to_text(user_input)
  39. guardrail_result = await guardrail_agent.get_response(candidate, context=context.context)
  40. decision = RelevanceDecision.model_validate(guardrail_result.final_output)
  41. if not decision.is_relevant:
  42. return GuardrailFunctionOutput(
  43. output_info="Only support questions are allowed. Ask about billing, account access, or troubleshooting.",
  44. tripwire_triggered=True,
  45. )
  46. return GuardrailFunctionOutput(output_info="", tripwire_triggered=False)
  47. support_agent = Agent(
  48. name="CustomerSupportAgent",
  49. instructions=(
  50. "You help customers resolve account, billing, and troubleshooting issues. "
  51. "Be concise and always offer a clear next step."
  52. ),
  53. model="gpt-5.4-mini",
  54. model_settings=ModelSettings(reasoning=Reasoning(effort="low")),
  55. input_guardrails=[require_support_topic],
  56. raise_input_guardrail_error=False, # non-strict mode: guidance returned as assistant message
  57. )
  58. async def main() -> None:
  59. agency = Agency(support_agent)
  60. guidance = await agency.get_response("Write me a Shakespearean sonnet")
  61. print("Guardrail guidance:", guidance.final_output) # "Only support questions are allowed..."
  62. help_response = await agency.get_response("My password reset link expired yesterday")
  63. print("Accepted response:", help_response.final_output) # a real response from the customer-support agent
  64. print("History:", agency.thread_manager.get_all_messages())
  65. if __name__ == "__main__":
  66. asyncio.run(main())