How to Build a transaction monitoring Agent Using CrewAI in Python for pension funds
A transaction monitoring agent for pension funds watches contribution flows, withdrawals, transfers, and benefit payments for suspicious patterns, policy breaches, and operational anomalies. It matters because pension money is regulated, long-lived, and highly sensitive to fraud, leakage, and compliance failures.
Architecture
- •
Data ingestion layer
- •Pulls transactions from core pension admin systems, payment rails, and batch files.
- •Normalizes fields like member ID, employer ID, amount, currency, channel, timestamp, and jurisdiction.
- •
Rules and policy engine
- •Applies deterministic checks first: duplicate payments, unusual withdrawal frequency, high-value transfers, sanctions hits.
- •Encodes pension-specific rules such as early-access restrictions and contribution caps.
- •
CrewAI agent layer
- •Uses a
Crewof specializedAgents to investigate alerts. - •One agent classifies risk, another explains the case in compliance language, another prepares an audit-ready summary.
- •Uses a
- •
Evidence store
- •Persists raw inputs, model outputs, tool results, and final decisions.
- •Keeps immutable traces for audit and regulator review.
- •
Case management output
- •Sends alerts to a queue or ticketing system with severity, rationale, and next actions.
- •Supports human review before any freeze or escalation action.
Implementation
- •Install CrewAI and define the data contract
Keep the transaction schema explicit. Pension operations teams need stable fields for auditability and downstream case management.
from pydantic import BaseModel
from typing import List
class Transaction(BaseModel):
transaction_id: str
member_id: str
employer_id: str
amount: float
currency: str
transaction_type: str # contribution, withdrawal, transfer, benefit_payment
country: str
timestamp: str
channel: str
notes: str = ""
class Alert(BaseModel):
transaction_id: str
risk_score: int
severity: str
reasons: List[str]
recommended_action: str
- •Create agents with narrow responsibilities
Use separate agents for investigation and reporting. That keeps prompts focused and makes it easier to defend outputs during audit.
from crewai import Agent
risk_analyst = Agent(
role="Transaction Risk Analyst",
goal="Assess pension fund transactions for AML, fraud, and policy breaches",
backstory=(
"You review pension fund transactions against compliance rules. "
"You must be precise, conservative, and produce audit-friendly findings."
),
verbose=True,
)
compliance_writer = Agent(
role="Compliance Reporter",
goal="Convert findings into a clear case note for human reviewers",
backstory=(
"You write concise case summaries for pension fund compliance teams. "
"You never invent facts or recommend automated account freezes."
),
verbose=True,
)
- •Add tools for rules lookup and evidence retrieval
CrewAI works best when agents can call deterministic tools instead of guessing. For pension funds, that usually means policy lookup plus transaction history retrieval from a controlled source.
from crewai_tools import tool
POLICY_LIMITS = {
"withdrawal_daily_limit": 50000,
"transfer_high_value": 25000,
}
@tool("check_policy_limits")
def check_policy_limits(transaction_type: str, amount: float) -> str:
if transaction_type == "withdrawal" and amount > POLICY_LIMITS["withdrawal_daily_limit"]:
return "Withdrawal exceeds daily limit"
if transaction_type == "transfer" and amount > POLICY_LIMITS["transfer_high_value"]:
return "High-value transfer"
return "No policy breach"
@tool("format_audit_summary")
def format_audit_summary(transaction_id: str, reasons: list) -> str:
return f"Transaction {transaction_id} flagged for: {', '.join(reasons)}"
- •Wire the crew and run the workflow
This is the actual pattern you want in production: one agent investigates with tools; another turns that into a clean case note. Use Task, Crew, and Process.sequential so each step is traceable.
from crewai import Task, Crew, Process
sample_txn = Transaction(
transaction_id="TXN-10021",
member_id="M-88291",
employer_id="EMP-4412",
amount=78000,
currency="USD",
transaction_type="withdrawal",
country="ZA",
timestamp="2026-04-21T10:15:00Z",
channel="bank_transfer",
)
investigation_task = Task(
description=(
f"Review this pension fund transaction for compliance issues:\n"
f"{sample_txn.model_dump()}\n\n"
f"Use the available tools to check policy limits. "
f"Return a JSON-style assessment with risk score, severity,"
f" reasons, and recommended action."
),
expected_output="A structured assessment with risk score and reasons.",
agent=risk_analyst,
)
report_task = Task(
description=(
"Turn the investigation into an audit-ready case note for a human reviewer. "
"Include only facts from the assessment."
),
expected_output="A concise compliance summary.",
agent=compliance_writer,
)
crew = Crew(
agents=[risk_analyst, compliance_writer],
tasks=[investigation_task, report_task],
process=Process.sequential,
)
result = crew.kickoff()
print(result)
If you want stricter control over output shape in production, wrap the final result in your own parser and reject anything that does not map cleanly to your Alert model.
Production Considerations
- •
Keep decisioning human-in-the-loop
- •For pension funds, an agent should flag and explain; it should not auto-block benefits or transfers without reviewer approval.
- •Route only high-confidence cases to escalation queues.
- •
Log everything needed for audit
- •Store prompt inputs, tool outputs, timestamps, model version, and final recommendations.
- •Regulators will care about why a case was flagged more than how fancy the workflow was.
- •
Respect data residency
- •Pension member data often cannot leave specific jurisdictions.
- •Host models and vector stores in-region if your fund operates under local residency rules.
- •
Add guardrails around sensitive actions
- •Block free-text instructions from triggering irreversible operations.
- •Restrict tools so agents can read evidence but cannot move money or change member records.
Common Pitfalls
- •
Letting the LLM do raw detection
- •Don’t ask CrewAI agents to find fraud from scratch on messy data.
- •Pre-filter with rules first; use the agent for triage and explanation.
- •
Mixing compliance logic into prompts
- •Hard-code thresholds like withdrawal limits in code or config.
- •Prompts drift; policy code does not.
- •
Skipping output validation
- •Never trust free-form text as a final alert payload.
- •Validate against a Pydantic schema like
Alertbefore sending anything to case management.
- •
Ignoring jurisdiction-specific rules
- •Pension funds often operate across countries with different tax treatment, withdrawal rules, and reporting obligations.
- •Build per-country policy profiles instead of one global threshold set.
Keep learning
- •The complete AI Agents Roadmap — my full 8-step breakdown
- •Free: The AI Agent Starter Kit — PDF checklist + starter code
- •Work with me — I build AI for banks and insurance companies
By Cyprian Aarons, AI Consultant at Topiax.
Want the complete 8-step roadmap?
Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.
Get the Starter Kit