guardrail_example_fixed.py
1 #!/usr/bin/env python3 2 """ 3 Fixed example demonstrating proper guardrail usage with PraisonAI Agents. 4 This addresses the issues reported in issue #875. 5 """ 6 7 from praisonaiagents import Agent, Task, GuardrailResult, AgentTeam, TaskOutput 8 from typing import Tuple, Any 9 import trafilatura 10 11 # Example 1: Using GuardrailResult return type (now supported!) 12 def validate_length_guardrailresult(output: TaskOutput) -> GuardrailResult: 13 """Ensure output is between 100-500 characters using GuardrailResult""" 14 # Extract the raw text from the TaskOutput object 15 text = output.raw if hasattr(output, 'raw') else str(output) 16 length = len(text) 17 18 if 100 <= length <= 500: 19 return GuardrailResult( 20 success=True, 21 result=output, # Pass through the original output 22 error="" 23 ) 24 else: 25 return GuardrailResult( 26 success=False, 27 result=None, 28 error=f"Output must be 100-500 chars, got {length}" 29 ) 30 31 # Example 2: Using Tuple[bool, Any] return type (original method) 32 def validate_length_tuple(output: TaskOutput) -> Tuple[bool, Any]: 33 """Ensure output is between 100-500 characters using tuple""" 34 text = output.raw if hasattr(output, 'raw') else str(output) 35 length = len(text) 36 37 if 100 <= length <= 500: 38 return True, output 39 else: 40 return False, f"Output must be 100-500 chars, got {length}" 41 42 # Tool function 43 def get_url_context(url): 44 """Fetch and extract content from a URL""" 45 downloaded = trafilatura.fetch_url(url) 46 if not downloaded: 47 return "Sorry, I couldn't fetch the content from that URL." 48 49 extracted = trafilatura.extract( 50 downloaded, 51 include_comments=False, 52 include_links=True, 53 output_format='json', 54 with_metadata=True, 55 url=url 56 ) 57 58 if not extracted: 59 return "Sorry, I couldn't extract readable content from that page." 60 61 return extracted # returns JSON string 62 63 # Create agent with FIXED tools parameter (must be a list!) 64 agent = Agent( 65 name="Content Summarizer", 66 role="Content Analysis Expert", 67 goal="Summarize web content concisely", 68 instructions="You are a helpful assistant that summarizes web content", 69 llm="gemini/gemini-2.5-flash-lite-preview-06-17", 70 reflection=False, 71 output="verbose", # Use new consolidated param 72 tools=[get_url_context] # FIX: tools must be a list, not a single function 73 ) 74 75 # Create task with GuardrailResult guardrail 76 task_with_guardrailresult = Task( 77 name="summarise article with GuardrailResult", 78 description="get the context of this url: https://blog.google/technology/ai/dolphingemma/ and produce a summary below 500 characters", 79 agent=agent, 80 guardrails=validate_length_guardrailresult, # Using GuardrailResult 81 expected_output="summary of the article below 500 characters", 82 max_retries=3 # Will retry up to 3 times if guardrail fails 83 ) 84 85 # Alternative: Create task with tuple guardrail 86 task_with_tuple = Task( 87 name="summarise article with tuple", 88 description="get the context of this url: https://blog.google/technology/ai/dolphingemma/ and produce a summary below 500 characters", 89 agent=agent, 90 guardrails=validate_length_tuple, # Using Tuple[bool, Any] 91 expected_output="summary of the article below 500 characters", 92 max_retries=3 93 ) 94 95 # Example with string-based LLM guardrail 96 task_with_llm_guardrail = Task( 97 name="summarise with LLM guardrail", 98 description="get the context of this url: https://blog.google/technology/ai/dolphingemma/ and produce a summary", 99 agent=agent, 100 guardrails="Ensure the summary is professional, factual, and between 100-500 characters", 101 expected_output="professional summary of the article" 102 ) 103 104 # Run with GuardrailResult example 105 print("=== Running with GuardrailResult guardrail ===") 106 agents_gr = AgentTeam( 107 agents=[agent], 108 tasks=[task_with_guardrailresult] 109 ) 110 111 # Uncomment to run: 112 # result_gr = agents_gr.start() 113 114 # Run with Tuple example 115 print("\n=== Running with Tuple[bool, Any] guardrail ===") 116 agents_tuple = AgentTeam( 117 agents=[agent], 118 tasks=[task_with_tuple] 119 ) 120 121 # Uncomment to run: 122 # result_tuple = agents_tuple.start() 123 124 # Run with LLM guardrail example 125 print("\n=== Running with LLM-based guardrail ===") 126 agents_llm = AgentTeam( 127 agents=[agent], 128 tasks=[task_with_llm_guardrail] 129 ) 130 131 # Uncomment to run: 132 # result_llm = agents_llm.start() 133 134 print(""" 135 Key fixes applied: 136 1. GuardrailResult is now accepted as a valid return type annotation 137 2. tools parameter must be a list: tools=[get_url_context] not tools=get_url_context 138 3. Both GuardrailResult and Tuple[bool, Any] return types are supported 139 4. String-based LLM guardrails are also supported 140 141 The guardrail will automatically retry (up to max_retries times) if validation fails. 142 """)