5.8 KiB
Ghostfolio AI Agent — AgentForge Integration
What I Built
A LangGraph-powered portfolio assistant embedded directly inside Ghostfolio — a production open-source wealth management app. The agent runs as a FastAPI sidecar and adds a floating AI chat panel, nine specialized tools, and an optional real estate market feature, all as a brownfield addition that leaves the existing codebase untouched.
Architecture
Angular UI (port 4200)
└── GfAiChatComponent
├── AiChatService (event bus for Real Estate nav → chat)
└── HTTP calls
│
▼
FastAPI Agent (port 8000) ← agent/main.py
│
▼
LangGraph Graph ← agent/graph.py
│
┌─────┴──────────────────────────────────────────┐
│ 9 Tools (agent/tools/) │
├── portfolio_analysis portfolio data │
├── transaction_query filter transactions │
├── compliance_check concentration risk │
├── market_data live price context │
├── tax_estimate capital gains math │
├── write_transaction record buys/sells │
├── categorize label transactions │
├── real_estate city/listing search │ ← brownfield add
└── compare_neighborhoods side-by-side cities │ ← brownfield add
│
▼
Ghostfolio REST API (port 3333)
How to Run Locally
Prerequisites
- Node.js 18+, npm
- Python 3.11+
- Ghostfolio account with a bearer token
Step 1 — Start Ghostfolio
cd ghostfolio
# Terminal 1 — API server
npm run start:server
# Wait for: "Nest application successfully started"
# Terminal 2 — Angular client
npm run start:client
# Wait for: "Compiled successfully"
Step 2 — Configure the Agent
cd ghostfolio/agent
cp .env.example .env # if not already present
Edit .env:
GHOSTFOLIO_BASE_URL=http://localhost:3333
GHOSTFOLIO_BEARER_TOKEN=<your token from Ghostfolio Settings>
ANTHROPIC_API_KEY=<your Anthropic key>
ENABLE_REAL_ESTATE=true
Step 3 — Start the Agent
cd ghostfolio/agent
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --reload --port 8000
# Wait for: "Application startup complete."
Step 4 — Open the App
Go to http://localhost:4200 → sign in → click the Ask AI button (bottom right).
Portfolio data seeds automatically when the agent detects an empty portfolio — no manual step needed.
Real Estate Feature Flag
The real estate tools are gated behind ENABLE_REAL_ESTATE so they can be toggled without any code change.
Enable:
ENABLE_REAL_ESTATE=true
Disable (default):
ENABLE_REAL_ESTATE=false
When enabled:
- A Real Estate nav item appears in Ghostfolio's sidebar
- Real estate suggestion chips appear in the chat panel
- The
real_estateandcompare_neighborhoodstools are active - Tool calls are logged to
GET /real-estate/log
When disabled, all real estate endpoints return a clear REAL_ESTATE_FEATURE_DISABLED error — no silent failures.
Test Suite
cd ghostfolio/agent
source venv/bin/activate
# Run all tests with verbose output
python -m pytest evals/ -v
# Run just the real estate tests
python -m pytest evals/ -v -k "real_estate"
# Run with coverage summary
python -m pytest evals/ -v 2>&1 | tail -10
Coverage: 68+ test cases across:
- Portfolio analysis accuracy
- Transaction query filtering
- Compliance / concentration risk detection
- Tax estimation logic
- Write operation confirmation flow
- Real estate listing search & filtering
- Neighborhood snapshot data
- City comparison (affordability, yield, DOM)
- Feature flag enforcement
2-Minute Demo Script
- Open
localhost:4200, sign in - Click the floating Ask AI button (bottom right) — note the green status dot = agent online
- Click "📈 My portfolio performance" chip → agent calls
portfolio_analysis+market_data; see tool chips on the response - Click "⚠️ Any concentration risk?" → agent calls
compliance_check - Click "💰 Estimate my taxes" → agent calls
tax_estimate - Type "buy 5 shares of AAPL at $185" → agent asks for confirmation → click Confirm
- Click "Real Estate" in the sidebar → chat opens with Austin/Denver query pre-filled
- Click "📊 Austin vs Denver" chip → side-by-side comparison with tool chips visible
- Click Clear → suggestion chips reappear
What Makes This a Brownfield Integration
- Zero changes to Ghostfolio core — no existing files were modified outside of Angular routing/module registration. The agent is a fully separate FastAPI process.
- Feature-flagged addition —
ENABLE_REAL_ESTATE=falsereturns the app to its original state with no trace of the real estate feature. - Token passthrough — the agent receives the user's existing Ghostfolio bearer token from the Angular client and uses it for all API calls, so authentication is reused rather than reimplemented.
Observability Endpoints
| Endpoint | Purpose |
|---|---|
GET /health |
Agent + Ghostfolio reachability check |
GET /real-estate/log |
Real estate tool invocation log (last 50) |
GET /feedback/summary |
👍/👎 approval rate across all sessions |
GET /costs |
Estimated Anthropic API cost tracker |