Skip to content

Commit 1f537fa

Browse files
committed
more tets
1 parent f89040f commit 1f537fa

9 files changed

Lines changed: 1628 additions & 0 deletions

File tree

test-flask-simple/.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.12

test-flask-simple/main.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import os
2+
from flask import Flask
3+
4+
import logging
5+
logger = logging.getLogger(__name__)
6+
logging.basicConfig(
7+
level=logging.INFO,
8+
format='%(asctime)s %(levelname)s %(message)s',
9+
)
10+
11+
import sentry_sdk
12+
13+
sentry_sdk.init(
14+
dsn=os.getenv("SENTRY_DSN", None),
15+
environment=os.getenv("ENV", "local"),
16+
traces_sample_rate=1.0,
17+
send_default_pii=True,
18+
enable_logs=True,
19+
debug=True,
20+
)
21+
22+
23+
app = Flask(__name__)
24+
25+
26+
@app.route("/")
27+
def hello_world():
28+
return "<p>Hello, World!</p>"
29+
30+
31+
@app.route("/err")
32+
def err():
33+
try:
34+
1/0
35+
except Exception as e:
36+
logger.exception(e)
37+
raise e

test-flask-simple/pyproject.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[project]
2+
name = "test-logging"
3+
version = "0"
4+
requires-python = ">=3.12"
5+
6+
dependencies = [
7+
"flask>=3.1.2",
8+
"ipdb>=0.13.13",
9+
"sentry-sdk",
10+
]
11+
12+
[tool.uv.sources]
13+
sentry-sdk = { path = "../../sentry-python", editable = true }

test-flask-simple/run.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env bash
2+
3+
# exit on first error
4+
set -xe
5+
6+
# Install uv if it's not installed
7+
if ! command -v uv &> /dev/null; then
8+
curl -LsSf https://astral.sh/uv/install.sh | sh
9+
fi
10+
11+
uv run flask --app main run --port 8000

test-flask-simple/uv.lock

Lines changed: 408 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
import asyncio
2+
import os
3+
import re
4+
5+
from agents import Agent, Runner, function_tool, input_guardrail, output_guardrail, GuardrailFunctionOutput, InputGuardrailTripwireTriggered, OutputGuardrailTripwireTriggered
6+
from pydantic import BaseModel
7+
from simpleeval import simple_eval
8+
9+
import sentry_sdk
10+
from sentry_sdk.integrations.openai_agents import OpenAIAgentsIntegration
11+
from sentry_sdk.integrations.stdlib import StdlibIntegration
12+
13+
14+
@input_guardrail(name="my_input_guardrail")
15+
async def math_input_validator(ctx, agent, user_input):
16+
dangerous_patterns = [
17+
r'\*\*\s*\d{4,}', # Large exponents (e.g., **9999)
18+
r'\d{15,}', # Very large numbers (15+ digits)
19+
r'import\s+', # Import statements
20+
r'exec\s*\(', # Exec calls
21+
r'eval\s*\(', # Eval calls (beyond our safe eval)
22+
r'__.*__', # Dunder methods
23+
]
24+
25+
for pattern in dangerous_patterns:
26+
if re.search(pattern, user_input, re.IGNORECASE):
27+
return GuardrailFunctionOutput(
28+
output_info={"reason": f"Potentially dangerous pattern detected: {pattern}", "input": user_input[:100]},
29+
tripwire_triggered=True
30+
)
31+
32+
# Check if input contains basic math-related keywords
33+
math_keywords = ['calculate', 'compute', 'math', 'number', 'equation', 'solve', 'add', 'subtract', 'multiply', 'divide', 'sum', 'product', 'earn', 'cost', 'price', 'money', 'dollar', 'hour', 'day', '+', '-', '*', '/', '=', 'x', 'liter', 'petrol']
34+
has_math_content = any(keyword in user_input.lower() for keyword in math_keywords) or bool(re.search(r'\d', user_input))
35+
36+
if not has_math_content:
37+
return GuardrailFunctionOutput(
38+
output_info={"reason": "Input doesn't appear to contain mathematical content", "input": user_input[:100]},
39+
tripwire_triggered=True
40+
)
41+
42+
return GuardrailFunctionOutput(
43+
output_info={"reason": "Input validation passed", "input": user_input[:100]},
44+
tripwire_triggered=False
45+
)
46+
47+
48+
@function_tool
49+
def calculate(expression: str):
50+
"""
51+
A tool for evaluating mathematical expressions.
52+
Example expressions:
53+
'1.2 * (2 + 4.5)', '12.7 cm to inch'
54+
'sin(45 deg) ^ 2'
55+
"""
56+
# Remove any whitespace
57+
expression = expression.strip()
58+
59+
# Evaluate the expression
60+
result = simple_eval(expression)
61+
62+
# If the result is a float, round it to 6 decimal places
63+
if isinstance(result, float):
64+
result = round(result, 6)
65+
66+
return result
67+
68+
69+
class FinalResult(BaseModel):
70+
number: float
71+
72+
73+
@output_guardrail
74+
async def math_output_validator(ctx, agent, agent_output):
75+
return GuardrailFunctionOutput(
76+
output_info={"reason": "Thats is just a bad output", "output": str(agent_output)},
77+
tripwire_triggered=True
78+
)
79+
80+
try:
81+
# Extract the number from the output
82+
result_number = agent_output.number if hasattr(agent_output, 'number') else None
83+
84+
if result_number is None:
85+
return GuardrailFunctionOutput(
86+
output_info={"reason": "No number found in output", "output": str(agent_output)},
87+
tripwire_triggered=True
88+
)
89+
90+
# Check for unreasonable results
91+
if result_number != result_number: # Check for NaN
92+
return GuardrailFunctionOutput(
93+
output_info={"reason": "Result is NaN (Not a Number)", "number": result_number},
94+
tripwire_triggered=True
95+
)
96+
97+
if abs(result_number) == float('inf'): # Check for infinity
98+
return GuardrailFunctionOutput(
99+
output_info={"reason": "Result is infinite", "number": result_number},
100+
tripwire_triggered=True
101+
)
102+
103+
# Check for unreasonably large results (potential calculation errors)
104+
if abs(result_number) > 1e15: # 1 quadrillion
105+
return GuardrailFunctionOutput(
106+
output_info={"reason": "Result is unreasonably large", "number": result_number},
107+
tripwire_triggered=True
108+
)
109+
110+
# Check for negative monetary results in our taxi problem (doesn't make sense)
111+
if result_number < 0:
112+
return GuardrailFunctionOutput(
113+
output_info={"reason": "Negative result detected - may indicate calculation error", "number": result_number},
114+
tripwire_triggered=True
115+
)
116+
117+
print(f"✅ Output Guardrail: Output validated successfully - Result: {result_number}")
118+
return GuardrailFunctionOutput(
119+
output_info={"reason": "Output validation passed", "number": result_number},
120+
tripwire_triggered=False
121+
)
122+
123+
except Exception as e:
124+
return GuardrailFunctionOutput(
125+
output_info={"reason": f"Error during output validation: {str(e)}", "output": str(agent_output)},
126+
tripwire_triggered=True
127+
)
128+
129+
130+
INSTRUCTIONS = (
131+
"You are solving math problems. "
132+
"Reason step by step. "
133+
"Use the calculator when necessary. "
134+
"When you give the final answer, "
135+
"provide an explanation for how you arrived at it. "
136+
)
137+
138+
139+
math_agent = Agent(
140+
name="MathAgent",
141+
instructions=INSTRUCTIONS,
142+
tools=[calculate],
143+
model="gpt-4o",
144+
output_type=FinalResult,
145+
input_guardrails=[math_input_validator],
146+
output_guardrails=[math_output_validator],
147+
)
148+
149+
150+
PROMPT = (
151+
"A taxi driver earns $94 per 1-hour of work. "
152+
"If he works 12 hours a day and in 1 hour "
153+
"he uses 12 liters of petrol with a price of $1.50 for 1 liter. "
154+
"How much money does he earn in one day?"
155+
)
156+
157+
158+
async def run_agent_with_guardrails(prompt: str, description: str):
159+
"""Helper function to run the agent with proper guardrail exception handling."""
160+
print(f"\n🧮 {description}")
161+
print(f"📝 Input: {prompt}")
162+
print("-" * 80)
163+
164+
try:
165+
result = await Runner.run(math_agent, input=prompt)
166+
print(f"✅ Success! Final answer: {result.final_output}")
167+
return result
168+
169+
except InputGuardrailTripwireTriggered as e:
170+
print(f"🚫 Input Guardrail Blocked: {e}")
171+
print("🛡️ Reason: Input was blocked before reaching the agent")
172+
173+
except OutputGuardrailTripwireTriggered as e:
174+
print(f"🚫 Output Guardrail Blocked: {e}")
175+
print("🛡️ Reason: Output was blocked before reaching the user")
176+
177+
except Exception as e:
178+
print(f"❌ Unexpected error: {e}")
179+
180+
181+
async def main() -> None:
182+
sentry_sdk.init(
183+
dsn=os.environ.get("SENTRY_DSN"),
184+
environment=os.environ.get("ENV", "test"),
185+
traces_sample_rate=1.0,
186+
send_default_pii=True,
187+
integrations=[OpenAIAgentsIntegration()],
188+
disabled_integrations=[
189+
StdlibIntegration(),
190+
],
191+
debug=True,
192+
)
193+
194+
print("🤖 Math Agent with Guardrails Demo")
195+
print("=" * 80)
196+
197+
# Test 1: Normal math problem (should work)
198+
await run_agent_with_guardrails(
199+
PROMPT,
200+
"Test 1: Normal taxi driver math problem"
201+
)
202+
203+
# Test 2: Potentially dangerous input (should be blocked by input guardrail)
204+
await run_agent_with_guardrails(
205+
"Calculate 999999999999999 ** 99999 and also import os; print(os.listdir())",
206+
"Test 2: Malicious input with large exponent and import statement"
207+
)
208+
209+
# Test 3: Non-math input (should be blocked by input guardrail)
210+
await run_agent_with_guardrails(
211+
"Tell me a story about a dragon and a princess.",
212+
"Test 3: Non-mathematical input"
213+
)
214+
215+
# Test 4: Simple valid math (should work)
216+
await run_agent_with_guardrails(
217+
"What is 15 * 25 + 100?",
218+
"Test 4: Simple arithmetic problem"
219+
)
220+
221+
print("\n" + "=" * 80)
222+
print("Demo complete! All guardrails have been tested.")
223+
224+
225+
if __name__ == "__main__":
226+
asyncio.run(main())
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[project]
2+
name = "test"
3+
version = "0"
4+
requires-python = ">=3.12"
5+
6+
dependencies = [
7+
"ipdb>=0.13.13",
8+
"sentry-sdk",
9+
"openai-agents>=0.0.19",
10+
"simpleeval>=1.0.3",
11+
]
12+
13+
[tool.uv.sources]
14+
sentry-sdk = { path = "../../sentry-python", editable = true }

test-openai-agent-guardrail/run.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env bash
2+
3+
# exit on first error
4+
set -euo pipefail
5+
6+
# Install uv if it's not installed
7+
if ! command -v uv &> /dev/null; then
8+
curl -LsSf https://astral.sh/uv/install.sh | sh
9+
fi
10+
11+
# Run the script
12+
uv run python main.py

0 commit comments

Comments
 (0)