Financial Analytics Agent is a three-in-one application — a web chat UI, a Finance REST API, and an eve-powered AI agent — all hosted within a single Next.js project at the same origin. There is no CORS configuration, no internal base-URL environment variable, and no microservice boundary to keep in sync. One Vercel project, one Neon Postgres database, one deployment command.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/astrxnomo/financial-analytics-agent/llms.txt
Use this file to discover all available pages before exploring further.
Architecture diagram
/eve/v1/*; the agent’s tools and the REST API route handlers both reach Postgres through the same shared analytics library; nothing in the agent path goes through HTTP to get its data.
The three components
1. Web Chat UI
The chat interface lives inapp/_components/agent-chat.tsx and its sibling directory agent-chat/. It uses the useEveAgent React hook to open a streaming connection to the eve channel and drive the message list reactively.
The key extension point is the custom ToolResult renderer in app/_components/tool-result/. When the agent calls a tool, the tool result arrives as a dynamic-tool message part carrying the tool name and its JSON output. ToolResult inspects the tool name and routes to the matching chart component:
| Tool name | Renderer | Chart type |
|---|---|---|
get_summary | summary-tiles.tsx | KPI stat tiles (income / expense / net) |
get_trend | trend-chart.tsx | Line or bar chart (degrades to bars for single period) |
get_category_breakdown | category-breakdown-chart.tsx | Stacked area or donut (degrades to donut for single period) |
get_cashflow | cashflow-chart.tsx | Bar + line combo chart |
get_budget_status | budget-chart.tsx | Grouped bar with over-budget highlight |
get_anomalies | anomaly-list.tsx | Compact callout list |
Panel, ChartHeader, ChartTooltip, ChartPanel) and a consistent color palette (app/_components/charts.ts, sourced from CSS custom properties in app/globals.css) keep every visualization visually consistent across light and dark modes.
The suggested-question chips at the start of a session are powered by useFinanceHighlights (app/_components/agent-chat/use-finance-highlights.ts), which fetches GET /api/finance/highlights — the only place getHighlights() is consumed. This grounds the suggestions in real seeded date ranges without requiring a model round-trip.
2. Finance REST API
The read-only REST API lives underapp/api/finance/*. Each subdirectory is a Next.js App Router route handler — one per analytic — and every handler follows the same pattern: parse and validate query parameters using the shared parseQuery helper from agent/lib/api-route.ts (which validates a ?query string against a Zod schema and returns either typed data or a ready 400 Response), call the matching function in agent/lib/finance.ts, return JSON.
The REST API exists as a real, documented external surface — useful for dashboard integrations, CI health checks, or direct exploration — but it is architecturally secondary. The agent does not call it; both the agent and the REST API converge on the same shared library instead.
3. Eve Agent
The eve agent is defined inagent/agent.ts using defineAgent(). It uses the Mistral mistral-medium-2508 model via @ai-sdk/mistral direct (not through the AI Gateway), with a 128,000-token context window maintained manually and context compaction triggered at 70% to keep the conversation focused.
The agent mounts into Next.js through a single line in next.config.ts:
withEve() registers the eve request handler at /eve/v1/* alongside the normal Next.js routing. The HTTP channel (agent/channels/eve.ts) uses a [vercelOidc(), localDev(), none()] auth chain — open for the public demo, ready to swap for a real auth provider.
Authored tools live in agent/tools/*. Each tool is a thin defineTool + Zod wrapper that calls exactly one function from agent/lib/finance.ts and returns the result verbatim.
Shared analytics library
The agent tools and REST API share the same finance library — add a new analytic once and both surfaces get it automatically.
agent/lib/finance.ts is the single source of truth for all SQL logic in the application. It exports typed functions that execute parameterized Postgres queries and convert raw numeric results to JavaScript number at the boundary (via the internal num() helper — raw Postgres numeric strings never escape this module):
| Export | Description |
|---|---|
getSummary({ from, to }) | SUM(amount) split by type over a date range |
getTrend({ metric, groupBy, from, to }) | Monthly time-series, optionally grouped by department |
getCategoryBreakdown({ type, from, to }) | Amounts grouped by category |
getCashflow({ from, to, groupBy }) | Period cashflow with running net |
getBudgetStatus({ month }) | Budget vs. actual with variance per department |
getAnomalies({ from, to, threshold }) | Transactions exceeding mean + threshold×σ per category |
getHighlights() | Real data date ranges for grounding instructions and UI chips |
getDataOverview() | Schema metadata to orient the agent at session start |
finance.ts requires only three more files to be fully live: a new tool in agent/tools/, a new route handler in app/api/finance/, and a new chart renderer in app/_components/tool-result/.
Request flow
Here is what happens from the moment a user sends a message in the chat until a chart appears on screen:- User submits a message. The
useEveAgentReact hook sends the conversation toPOST /eve/v1/sessions/{id}/messagesas a streaming request. - Eve routes to the agent. The eve channel authenticates the request and invokes the agent runtime with the current session context, including the assembled instructions.
- Agent selects a tool. Based on the question, the Mistral model picks the appropriate tool (e.g.
get_trendfor “show me revenue for the last 6 months”) and emits a tool-call part. - Tool executes against Postgres. The tool function (e.g.
agent/tools/get_trend.ts) callsgetTrend()fromagent/lib/finance.tsdirectly against the Neon Postgres database. No HTTP hop occurs. - Tool result flows back to the agent. The structured JSON result (an array of
{ period, value }rows) is returned to the model as a tool-result part. - Agent generates a reply. The model produces a short text interpretation — direction of the trend, likely driver, a recommendation when relevant — alongside the tool result.
- Chat renderer picks the chart. The
ToolResultcomponent in the chat UI receives thedynamic-toolpart, matches the tool name to the correct renderer (trend-chart.tsx), and renders the Recharts chart inline with the text.
/eve/v1/*; the browser never makes a separate request to the Finance REST API for chart data.
Dynamic date injection
The staticagent/instructions.md file defines the analyst persona, tool-selection rules, and output-style rules, but it contains no hardcoded dates. A literal “today is 2026-07-02” baked into the compiled manifest goes stale immediately after every deploy.
Instead, agent/instructions/dates.ts defines a defineDynamic resolver that fires on every session.started event. It calls new Date() for the current date and getHighlights() for the real data range in the database, then appends a short instructions block with live values. By eve convention, the root instructions.md content is always prepended before sorted agent/instructions/* entries, so this block always appends after the static persona rules.
If you need to inject other session-dependent context — the authenticated user’s department, a live exchange rate, a feature flag — extend this resolver rather than writing literal values into instructions.md.
Deployment
The application deploys as a single Vercel project. Neon Postgres is provisioned through the Vercel Marketplace and injectsDATABASE_URL automatically as an environment variable; run vercel env pull to sync it to your .env.local for local development. The vercel.json at the project root is minimal and delegates all routing to Next.js and the eve mount.
After deploying, run pnpm db:migrate and pnpm db:seed once against the production database to apply the schema and populate the synthetic data. From that point on, normal Vercel preview and production deploys are fully automatic.