Skip to main content

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.

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.

Architecture diagram

Browser (Web Chat + chart renderer)
   │  /eve/v1/*  (useEveAgent → eve channel)

eve agent ── authored tools (agent/tools/*) ──┐
   │                                          ▼
   │                              agent/lib/finance.ts ──► Postgres (Neon)
   │                                          ▲
app/api/finance/* ────────────────────────────┘
The arrows tell the whole story: the browser talks to the eve agent over /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 in app/_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 nameRendererChart type
get_summarysummary-tiles.tsxKPI stat tiles (income / expense / net)
get_trendtrend-chart.tsxLine or bar chart (degrades to bars for single period)
get_category_breakdowncategory-breakdown-chart.tsxStacked area or donut (degrades to donut for single period)
get_cashflowcashflow-chart.tsxBar + line combo chart
get_budget_statusbudget-chart.tsxGrouped bar with over-budget highlight
get_anomaliesanomaly-list.tsxCompact callout list
Shared chart primitives (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 under app/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 in agent/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:
import { withEve } from "eve/next";
const nextConfig: NextConfig = {};
export default withEve(nextConfig);
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):
ExportDescription
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
Because both the agent tools and the REST route handlers import from this module directly, a new analytic added to 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:
  1. User submits a message. The useEveAgent React hook sends the conversation to POST /eve/v1/sessions/{id}/messages as a streaming request.
  2. 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.
  3. Agent selects a tool. Based on the question, the Mistral model picks the appropriate tool (e.g. get_trend for “show me revenue for the last 6 months”) and emits a tool-call part.
  4. Tool executes against Postgres. The tool function (e.g. agent/tools/get_trend.ts) calls getTrend() from agent/lib/finance.ts directly against the Neon Postgres database. No HTTP hop occurs.
  5. 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.
  6. 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.
  7. Chat renderer picks the chart. The ToolResult component in the chat UI receives the dynamic-tool part, matches the tool name to the correct renderer (trend-chart.tsx), and renders the Recharts chart inline with the text.
The entire round-trip is a single streaming response from /eve/v1/*; the browser never makes a separate request to the Finance REST API for chart data.

Dynamic date injection

The static agent/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 injects DATABASE_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.

Build docs developers (and LLMs) love