Flask Integration
For the classic Python stack
🌶️ Flask is Battle-Tested
Flask is the OG Python web framework. Simple, flexible, and trusted by millions of apps. This guide uses decorators to protect your routes.
Complete Implementation
This example uses a decorator to protect any route with Amorce verification:
from flask import Flask, request, jsonify
from amorce import verify_request, AmorceSecurityError
from functools import wraps
app = Flask(__name__)
def amorce_protected(f):
"""Decorator to verify incoming Amorce requests."""
@wraps(f)
def decorated_function(*args, **kwargs):
try:
# Verify the request before executing the view
verified = verify_request(
headers=request.headers,
body=request.get_data()
)
# Add verified agent info to Flask's g object
from flask import g
g.amorce_agent = verified
except AmorceSecurityError as e:
return jsonify({"error": "Unauthorized", "detail": str(e)}), 401
return f(*args, **kwargs)
return decorated_function
@app.route('/agent/weather', methods=['POST'])
@amorce_protected # ← Just add this decorator
def get_weather():
# If we get here, the request is verified
data = request.json
city = data.get("city", "Montreal")
# Access verified agent info
from flask import g
agent_id = g.amorce_agent.agent_id
print(f"✅ Verified request from: {agent_id}")
return jsonify({
"temp": 22,
"city": city,
"condition": "Sunny"
})
@app.route('/agent/forecast', methods=['POST'])
@amorce_protected # ← Reuse on any route
def get_forecast():
data = request.json
days = data.get("days", 7)
return jsonify({
"forecast": [
{"day": "Mon", "temp": 20},
{"day": "Tue", "temp": 22},
# ...
][:days]
})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)How It Works
1. Decorator Pattern
@amorce_protected wraps your route function. It runs verification before your code executes.
2. Automatic Rejection
If verification fails, the decorator returns 401 Unauthorized immediately. Your route function never runs.
3. Verified Agent Info
Access the verified agent via g.amorce_agent anywhere in your request context.
Advanced: Intent Whitelisting
Create a stricter decorator that only allows specific intents:
def amorce_protected_strict(allowed_intents):
"""Decorator with intent whitelist."""
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
try:
verified = verify_request(
headers=request.headers,
body=request.get_data(),
allowed_intents=allowed_intents # ← Whitelist
)
from flask import g
g.amorce_agent = verified
except AmorceSecurityError as e:
return jsonify({
"error": "Forbidden",
"detail": f"Intent not allowed: {e}"
}), 403
return f(*args, **kwargs)
return decorated_function
return decorator
@app.route('/agent/book-table', methods=['POST'])
@amorce_protected_strict(['book_table', 'check_availability']) # ← Strict
def book_table():
# Only these 2 intents allowed
data = request.json
return jsonify({"status": "confirmed", "table": "A5"})Testing Locally
Quick way to test your Flask app with Amorce:
# Install dependencies
pip install flask amorce-sdk
# Run your app
python app.py
# In another terminal, use curl with a signed request
# (Or use the Amorce SDK from a client agent)
# Your app will verify signatures automatically!✅ Production Ready
This code is production-ready. The decorator pattern makes it easy to protect any number of routes without duplicating verification logic.