Building Safe Financial Agents
Financial AI agents handle money, data, and compliance. Here's how to implement guardrails that protect transactions and meet SOX requirements.
Financial agents handle real money. A single unauthorized transaction can cost millions. Building safe financial agents requires defense in depth—multiple layers of protection that work together.
The Financial Agent Stack
A typical financial agent architecture includes several components that need protection:
financial_agent_architecture.tstypescript
// Financial Agent Architecture // ┌─────────────────────────────────────────┐ // │ User Interface │ // │ Natural language requests for trades │ // └────────────────┬────────────────────────┘ // │ // ┌────────────────▼────────────────────────┐ // │ LLM / Reasoning Layer │ // │ Parse intent, determine actions │ // └────────────────┬────────────────────────┘ // │ // ┌────────────────▼────────────────────────┐ // │ Authorization Layer (Veto) │ // │ Validate, constrain, approve │ // └────────────────┬────────────────────────┘ // │ // ┌────────────────▼────────────────────────┐ // │ Trading Execution Layer │ // │ Broker APIs, smart contracts │ // └─────────────────────────────────────────┘ // Each layer adds protection // If LLM is compromised → Veto blocks unauthorized trades // If Veto misconfigured → Broker limits provide backup
Layer 1: Intent Validation
Before any financial operation, validate that the user's intent is clear and authorized:
intent_validation.pypython
from veto import Veto, Policy, Decision
from dataclasses import dataclass
from typing import Optional
import re
@dataclass
class TradeIntent:
action: str
asset: str
amount: float
recipient: Optional[str] = None
class IntentValidator:
def __init__(self, veto: Veto):
self.veto = veto
async def validate(self, user_input: str, context: dict) -> TradeIntent:
intent = self._parse_intent(user_input)
if not intent.action:
raise ValueError("Trade action not specified")
if intent.amount <= 0:
raise ValueError("Invalid trade amount")
if self._is_ambiguous(user_input):
raise ValueError("Ambiguous trade request")
decision = await self.veto.validate({
"tool": f"trade_{intent.action}",
"arguments": intent.__dict__,
"context": context
})
if decision.action == Decision.DENY:
raise ValueError(f"Trade denied: {decision.reason}")
return intentLayer 2: Policy Constraints
financial_policies.pypython
from veto import Veto, Policy
from datetime import time
veto = Veto(api_key="veto_live_xxx")
# Trading Hours Policy
veto.register_policy(
name="trading_hours",
policy=Policy(
tool="*",
rules=[
Policy.allow_if(
time_between=(time(9, 30), time(16, 0)),
timezone="America/New_York"
),
Policy.require_approval_if(
time_outside=(time(9, 30), time(16, 0))
)
]
)
)
# Position Limits
veto.register_policy(
name="position_limits",
policy=Policy(
tool="trade_buy",
rules=[
Policy.max_position_size(percent_of_portfolio=25),
Policy.max_single_trade(amount=100000),
]
)
)
# Transfer Restrictions
veto.register_policy(
name="transfer_restrictions",
policy=Policy(
tool="transfer_funds",
rules=[
Policy.max_amount(10000),
Policy.rate_limit(5, per="day"),
Policy.require_approval_if(amount_gt=5000),
]
)
)Production Checklist
- All trading tools wrapped with Veto middleware
- Dual authorization configured for large trades
- Transaction hashes verified before execution
- Audit logging enabled for all operations
- Real-time anomaly detection active
Ready to secure your agents?