Building a Financial Planning Agent: Budget Analysis, Goal Tracking, and Recommendations
Build an AI financial planning agent that integrates bank data, analyzes spending patterns, tracks savings goals, and generates personalized financial recommendations.
Why Personal Finance Needs Intelligent Agents
Budgeting apps show you what happened. A financial planning agent tells you what to do next. By combining transaction data analysis, goal tracking, and LLM-powered reasoning, an agent can provide the kind of personalized advice that previously required a human financial advisor. In this tutorial, you will build an agent that analyzes spending patterns, monitors progress toward financial goals, and generates actionable recommendations.
System Components
- Transaction Analyzer — categorize and analyze spending data
- Goal Tracker — monitor progress toward financial targets
- Projection Engine — forecast future financial state
- Recommendation Generator — produce personalized advice
Step 1: Transaction Analysis
We start by modeling transactions and building a spending analyzer.
from pydantic import BaseModel
from datetime import date, datetime
from collections import defaultdict
class Transaction(BaseModel):
date: date
description: str
amount: float # negative = expense, positive = income
category: str | None = None
account: str
class SpendingSummary(BaseModel):
period: str
total_income: float
total_expenses: float
net_savings: float
savings_rate: float
category_breakdown: dict[str, float]
top_merchants: list[dict]
def analyze_spending(
transactions: list[Transaction], period_start: date, period_end: date
) -> SpendingSummary:
"""Analyze spending patterns for a given period."""
filtered = [
t for t in transactions
if period_start <= t.date <= period_end
]
income = sum(t.amount for t in filtered if t.amount > 0)
expenses = sum(abs(t.amount) for t in filtered if t.amount < 0)
net = income - expenses
savings_rate = (net / income * 100) if income > 0 else 0
# Category breakdown
by_category = defaultdict(float)
by_merchant = defaultdict(float)
for t in filtered:
if t.amount < 0:
cat = t.category or "Uncategorized"
by_category[cat] += abs(t.amount)
by_merchant[t.description] += abs(t.amount)
top_merchants = sorted(
[{"name": k, "total": v} for k, v in by_merchant.items()],
key=lambda x: x["total"],
reverse=True,
)[:10]
return SpendingSummary(
period=f"{period_start} to {period_end}",
total_income=income,
total_expenses=expenses,
net_savings=net,
savings_rate=round(savings_rate, 1),
category_breakdown=dict(by_category),
top_merchants=top_merchants,
)
Step 2: Transaction Categorization with LLM
Bank transactions often have cryptic descriptions. The agent uses an LLM to categorize them.
from openai import OpenAI
client = OpenAI()
class CategorizedTransaction(BaseModel):
description: str
category: str
subcategory: str
is_recurring: bool
is_essential: bool
class BatchCategorization(BaseModel):
transactions: list[CategorizedTransaction]
CATEGORIES = [
"Housing", "Transportation", "Food & Dining",
"Utilities", "Healthcare", "Insurance",
"Entertainment", "Shopping", "Personal Care",
"Education", "Savings & Investments",
"Debt Payments", "Gifts & Donations", "Other",
]
def categorize_transactions(
descriptions: list[str],
) -> list[CategorizedTransaction]:
"""Categorize transactions using an LLM."""
desc_list = "\n".join(
f"{i+1}. {d}" for i, d in enumerate(descriptions)
)
response = client.beta.chat.completions.parse(
model="gpt-4o",
messages=[
{
"role": "system",
"content": (
"Categorize each transaction into one of these "
f"categories: {', '.join(CATEGORIES)}. "
"Also identify if it is recurring and essential."
),
},
{"role": "user", "content": desc_list},
],
response_format=BatchCategorization,
)
return response.choices[0].message.parsed.transactions
Step 3: Goal Tracking
Financial goals need monitoring with progress calculations and projections.
See AI Voice Agents Handle Real Calls
Book a free demo or calculate how much you can save with AI voice automation.
from dataclasses import dataclass
@dataclass
class FinancialGoal:
name: str
target_amount: float
current_amount: float
target_date: date
monthly_contribution: float
priority: int # 1 = highest
@property
def progress_pct(self) -> float:
if self.target_amount == 0:
return 100.0
return (self.current_amount / self.target_amount) * 100
@property
def remaining(self) -> float:
return max(0, self.target_amount - self.current_amount)
@property
def months_to_goal(self) -> float | None:
if self.monthly_contribution <= 0:
return None
return self.remaining / self.monthly_contribution
@property
def on_track(self) -> bool:
if self.months_to_goal is None:
return False
today = date.today()
months_left = (
(self.target_date.year - today.year) * 12
+ self.target_date.month - today.month
)
return self.months_to_goal <= months_left
def track_goals(goals: list[FinancialGoal]) -> list[dict]:
"""Generate status report for all financial goals."""
report = []
for goal in sorted(goals, key=lambda g: g.priority):
status = {
"name": goal.name,
"progress": f"{goal.progress_pct:.1f}%",
"remaining": goal.remaining,
"monthly_contribution": goal.monthly_contribution,
"on_track": goal.on_track,
}
if goal.months_to_goal is not None:
status["months_to_goal"] = round(goal.months_to_goal, 1)
report.append(status)
return report
Step 4: Personalized Recommendations
The agent combines spending analysis and goal tracking to generate advice.
def generate_recommendations(
spending: SpendingSummary,
goals: list[dict],
monthly_income: float,
) -> str:
"""Generate personalized financial recommendations."""
context = (
f"Monthly Income: ${monthly_income:,.2f}\n"
f"Monthly Expenses: ${spending.total_expenses:,.2f}\n"
f"Savings Rate: {spending.savings_rate}%\n\n"
f"Spending Breakdown:\n"
)
for cat, amount in sorted(
spending.category_breakdown.items(),
key=lambda x: x[1],
reverse=True,
):
pct = (amount / spending.total_expenses) * 100
context += f" {cat}: ${amount:,.2f} ({pct:.1f}%)\n"
context += "\nFinancial Goals:\n"
for goal in goals:
track = "ON TRACK" if goal["on_track"] else "BEHIND"
context += (
f" {goal['name']}: {goal['progress']} "
f"[{track}]\n"
)
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "system",
"content": (
"You are a certified financial planner. Analyze the "
"spending data and goals, then provide 5 specific, "
"actionable recommendations. Be concrete with dollar "
"amounts. Prioritize high-impact changes."
),
},
{"role": "user", "content": context},
],
)
return response.choices[0].message.content
Running the Agent
# Load and analyze transactions
spending = analyze_spending(transactions, date(2026, 2, 1), date(2026, 2, 28))
# Track goals
goals = track_goals([
FinancialGoal("Emergency Fund", 15000, 8500, date(2026, 12, 31), 800, 1),
FinancialGoal("Vacation", 3000, 1200, date(2026, 8, 1), 400, 2),
])
# Get recommendations
advice = generate_recommendations(spending, goals, 6500.0)
print(advice)
FAQ
How do you connect to real bank data?
Use a service like Plaid, Yodlee, or MX to access transaction data via API. Plaid provides a Python SDK that handles bank authentication and returns standardized transaction objects. Always store tokens securely and never cache raw bank credentials.
How do you handle privacy when sending financial data to an LLM?
Anonymize transactions before sending them to the LLM — replace merchant names with categories where possible and never include account numbers or personal identifiers. For maximum privacy, use a local model for transaction categorization and only send aggregated summaries to cloud APIs.
Can the agent adapt its advice based on life events?
Yes. Add context about life events (new job, marriage, home purchase) to the recommendation prompt. The LLM can adjust advice accordingly — for example, recommending higher emergency fund targets after a job change or suggesting tax-advantaged accounts after marriage.
#FinancialPlanning #BudgetAnalysis #GoalTracking #PersonalFinance #AIAgent #AgenticAI #LearnAI #AIEngineering
CallSphere Team
Expert insights on AI voice agents and customer communication automation.
Try CallSphere AI Voice Agents
See how AI voice agents work for your industry. Live demo available -- no signup required.