Skip to main content

Examples & Use Cases

Real-world examples of using QWED Open Responses for agent verification.


Example 1: Financial Calculator Agent

Scenario

An AI agent helps users with financial calculations. Need to verify math before returning results.

Setup

from qwed_open_responses import ResponseVerifier
from qwed_open_responses.guards import MathGuard, SchemaGuard

verifier = ResponseVerifier()

# Schema for calculation results
calc_schema = {
"type": "object",
"required": ["operation", "operands", "result"],
"properties": {
"operation": {"enum": ["add", "subtract", "multiply", "divide", "percentage"]},
"operands": {"type": "array", "items": {"type": "number"}},
"result": {"type": "number"}
}
}

math_guard = MathGuard()
schema_guard = SchemaGuard(schema=calc_schema)

Verification

# Agent output: "25% of 200 is 50"
agent_output = {
"operation": "percentage",
"operands": [25, 200],
"result": 50
}

result = verifier.verify_structured_output(
output=agent_output,
guards=[schema_guard, math_guard]
)

# ✅ VERIFIED: 25% of 200 = 50 is correct

Catching Errors

# Agent makes mistake: "25% of 200 is 60"
bad_output = {
"operation": "percentage",
"operands": [25, 200],
"result": 60 # Wrong!
}

result = verifier.verify_structured_output(
output=bad_output,
guards=[schema_guard, math_guard]
)

# ❌ FAILED: MathGuard
# Error: 25% of 200 = 50, not 60

Example 2: Blocking Dangerous Tools

Scenario

Agent has access to shell commands. Need to prevent dangerous operations.

Setup

from qwed_open_responses.guards import ToolGuard

# Create blocklist
tool_guard = ToolGuard(
blocklist=[
"execute_shell",
"delete_file",
"drop_table",
"send_email",
"transfer_funds"
],
dangerous_patterns=[
r"rm\s+-rf",
r"DROP\s+TABLE",
r"DELETE\s+FROM.*WHERE\s+1=1"
]
)

Blocked Calls

# Agent tries to call dangerous tool
result = verifier.verify_tool_call(
tool_name="execute_shell",
arguments={"command": "rm -rf /"},
guards=[tool_guard]
)

# ❌ BLOCKED
# Reason: Tool 'execute_shell' is in blocklist
# Pattern matched: 'rm -rf'

Allowed Calls

# Safe tool call
result = verifier.verify_tool_call(
tool_name="read_file",
arguments={"path": "/data/report.txt"},
guards=[tool_guard]
)

# ✅ VERIFIED: Tool not in blocklist

Example 3: PII Detection

Scenario

Healthcare AI generating patient summaries. Must not leak PII.

Setup

from qwed_open_responses.guards import SafetyGuard

safety_guard = SafetyGuard(
block_pii=True,
pii_patterns=[
r"\b\d{3}-\d{2}-\d{4}\b", # SSN
r"\b\d{16}\b", # Credit card
r"\b[A-Z]{2}\d{6}\b", # Passport
]
)

PII Blocked

# Agent generates summary with SSN
summary = """
Patient John Doe (SSN: 123-45-6789) presented with...
"""

result = verifier.verify({
"content": summary
}, guards=[safety_guard])

# ❌ BLOCKED
# Reason: PII detected (SSN pattern: 123-45-6789)

Redacted Output

# SafetyGuard can also redact instead of block
safety_guard = SafetyGuard(
block_pii=False,
redact_pii=True
)

result = verifier.verify({"content": summary}, guards=[safety_guard])
# Output: "Patient John Doe (SSN: [REDACTED]) presented with..."

Example 4: State Machine Validation

Scenario

Order processing agent. States must follow valid transitions.

Setup

from qwed_open_responses.guards import StateGuard

# Define valid transitions
state_guard = StateGuard(
valid_transitions={
"pending": ["processing", "cancelled"],
"processing": ["shipped", "failed"],
"shipped": ["delivered", "returned"],
"delivered": ["completed"],
"failed": ["pending"], # Can retry
"cancelled": [], # Terminal state
"completed": [], # Terminal state
}
)

Valid Transition

result = verifier.verify_tool_call(
tool_name="update_order_status",
arguments={
"order_id": "ORD-123",
"from_state": "processing",
"to_state": "shipped"
},
guards=[state_guard]
)

# ✅ VERIFIED: processing → shipped is valid

Invalid Transition (Blocked)

result = verifier.verify_tool_call(
tool_name="update_order_status",
arguments={
"order_id": "ORD-123",
"from_state": "delivered",
"to_state": "pending" # Can't go back!
},
guards=[state_guard]
)

# ❌ BLOCKED
# Reason: Invalid transition: delivered → pending
# Valid transitions from 'delivered': ['completed']

Example 5: LangChain Integration

Full Agent with Verification

from langchain_openai import ChatOpenAI
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain.tools import StructuredTool
from qwed_open_responses.middleware.langchain import QWEDCallbackHandler
from qwed_open_responses.guards import ToolGuard, MathGuard, SafetyGuard

# Define tools
def calculate(expression: str) -> str:
"""Calculate a mathematical expression."""
return str(eval(expression)) # In production, use safe eval!

def send_email(to: str, subject: str, body: str) -> str:
"""Send an email."""
return f"Email sent to {to}"

tools = [
StructuredTool.from_function(calculate),
StructuredTool.from_function(send_email),
]

# Create verification callback
callback = QWEDCallbackHandler(
guards=[
ToolGuard(blocklist=["send_email"]), # Block email for now
MathGuard(),
SafetyGuard(block_pii=True),
],
block_on_failure=True,
log_verifications=True
)

# Create agent
llm = ChatOpenAI(model="gpt-4")
agent = create_tool_calling_agent(llm, tools, prompt)
executor = AgentExecutor(
agent=agent,
tools=tools,
callbacks=[callback],
verbose=True
)

# Run agent
result = executor.invoke({
"input": "Calculate 15% tip on $85.50"
})

# Output:
# ToolGuard: ✅ 'calculate' not in blocklist
# MathGuard: ✅ 0.15 × 85.50 = 12.825 verified
# Result: "The 15% tip on $85.50 is $12.83"

Example 6: Budget Control

Scenario

Prevent runaway API costs from agent loops.

Setup

from qwed_open_responses.guards import SafetyGuard

# Per-session budget
safety_guard = SafetyGuard(
max_budget=10.0, # $10 per session
cost_per_call={
"gpt-4": 0.03,
"gpt-3.5": 0.002,
"dall-e-3": 0.04,
}
)

Budget Enforcement

# After many calls...
result = verifier.verify_tool_call(
tool_name="generate_image",
arguments={"prompt": "A cat"},
guards=[safety_guard]
)

# If budget exceeded:
# ❌ BLOCKED
# Reason: Budget exceeded ($10.24 > $10.00 limit)
# Session cost breakdown:
# - 200 × gpt-3.5: $0.40
# - 50 × gpt-4: $1.50
# - 200 × dall-e-3: $8.00
# - This call: $0.04
# - Total: $10.24

Example 7: Argument Type Validation

Scenario

Ensure tool arguments match expected types.

Setup

from qwed_open_responses.guards import ArgumentGuard

# Define expected argument types
arg_guard = ArgumentGuard(
tool_schemas={
"transfer_money": {
"from_account": {"type": "string", "pattern": r"^ACC-\d{8}$"},
"to_account": {"type": "string", "pattern": r"^ACC-\d{8}$"},
"amount": {"type": "number", "minimum": 0.01, "maximum": 10000},
"currency": {"type": "string", "enum": ["USD", "EUR", "GBP"]}
}
}
)

Validation

# Invalid amount
result = verifier.verify_tool_call(
tool_name="transfer_money",
arguments={
"from_account": "ACC-12345678",
"to_account": "ACC-87654321",
"amount": "one hundred", # Should be number!
"currency": "USD"
},
guards=[arg_guard]
)

# ❌ BLOCKED
# Reason: Argument 'amount' must be number, got string

Best Practices

1. Layer Multiple Guards

# Defense in depth
verifier = ResponseVerifier(guards=[
SchemaGuard(schema), # Structure valid?
ToolGuard(blocklist), # Tool allowed?
ArgumentGuard(schemas), # Args valid?
MathGuard(), # Math correct?
SafetyGuard(block_pii=True), # Safe content?
])

2. Fail Fast, Log Everything

callback = QWEDCallbackHandler(
block_on_failure=True,
log_verifications=True,
on_block=lambda r: logger.error(f"Blocked: {r.block_reason}")
)

3. Environment-Specific Guards

if os.getenv("ENV") == "production":
guards = [ToolGuard(blocklist=PROD_BLOCKLIST), SafetyGuard(strict=True)]
else:
guards = [ToolGuard(allow_unknown=True)] # More lenient in dev

4. Test Your Guards

import pytest

def test_tool_guard_blocks_dangerous():
guard = ToolGuard(blocklist=["delete_all"])
result = guard.verify(tool_name="delete_all", arguments={})
assert not result.verified
assert "blocklist" in result.block_reason