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.

The agent is configured in agent/agent.ts using eve’s defineAgent function. Three settings drive its runtime behaviour: the model selection, the context window size, and the compaction threshold. A two-part instructions system — a static persona file and a dynamic resolver — ensures the agent always has accurate date context without requiring manual updates after each deploy. The HTTP channel is defined separately in agent/channels/eve.ts and controls how the agent is reached from the browser.

Model selection

The agent uses mistral-medium-2508, the dated snapshot of Mistral Medium, accessed directly via @ai-sdk/mistral rather than through the AI Gateway. Several models were evaluated before settling on this one:
  • devstral-latest (original): Mistral’s agentic-coding model, not a generalist reasoner. Produced a class of arithmetic and narrative-bias bugs — asserting “expenses decreased” for periods where they clearly increased, even after being shown the correct subtraction.
  • mistral-large-latest: Hit persistent rate-limit errors at this API key’s tier even with concurrency set to 1.
  • mistral-small-latest: No rate-limit issues, but behaviorally inconsistent — the anomaly-category-filter eval failed roughly half the time across repeated runs.
  • mistral-medium-latest: Passes the full eval suite consistently, including the arithmetic-safety regression test. However, the -latest alias is metered on a separate, far tighter quota than the dated snapshot — 25,000 TPM vs. 356,250 TPM for mistral-medium-2508, a roughly 14× gap for the same underlying model.
  • mistral-medium-2508 (current): The dated snapshot that -latest currently resolves to. Same eval results, without the alias’s low quota. This is metered, paid API usage.
The full defineAgent call:
agent/agent.ts
import { defineAgent } from "eve";
import { mistral } from "@ai-sdk/mistral";

export default defineAgent({
  model: mistral("mistral-medium-2508"),
  modelContextWindowTokens: 128000,
  compaction: {
    thresholdPercent: 0.7,
  },
});

Context window

modelContextWindowTokens is set to 128000 and must be kept in sync manually. Because the agent connects to Mistral directly via @ai-sdk/mistral instead of going through the AI Gateway, eve cannot look up the context window size from catalog metadata — the value has to be declared explicitly. If Mistral changes the context window for the Medium tier, update this field to match.

Compaction

The thresholdPercent: 0.7 setting tells eve to compact the running context when it reaches 70% of the declared window (roughly 89,600 tokens). Compaction summarises older turns to free up space for new tool calls and responses, keeping the context focused on the current analytical task rather than accumulating a full transcript of the session. Without this, long sessions involving multiple chart queries can exhaust the window and produce truncation errors.

Instructions

The agent’s instruction system has two parts that are composed together at session start by eve’s convention of prepending root instructions.md before sorted entries in agent/instructions/: agent/instructions.md — static persona and rules The root instructions file defines the analyst persona (a senior financial analyst at “Northwind Labs”), the tool-selection rules (which analytic to reach for in which situation), and the output-style rules. Notably it contains no literal dates — any hardcoded “today is …” string baked into this file would go stale the day after the next deploy and stay stale indefinitely. agent/instructions/dates.ts — dynamic date resolver This file exports a defineDynamic resolver that fires on the session.started event. Each time a new session begins, it computes today’s date from new Date() and queries getHighlights() to retrieve the actual data range from the live database, then appends a short instructions block with both values:
agent/instructions/dates.ts
import { defineDynamic, defineInstructions } from "eve/instructions";
import { getHighlights } from "#lib/finance.js";

export default defineDynamic({
  events: {
    "session.started": async () => {
      const today = new Date().toISOString().slice(0, 10);
      let coverage =
        "Data coverage is unknown right now — call `get_summary` or `get_trend` with a wide range to discover it before assuming any dates.";
      try {
        const h = await getHighlights();
        coverage = `Transactions and budgets exist from ${h.dataFrom} through ${h.dataTo}. The latest closed month is ${h.latestMonth}.`;
      } catch {
        // DB unreachable at session start — the fallback line above still lets
        // the model behave sensibly instead of guessing a date range.
      }
      return defineInstructions({
        markdown: `# Current date and data coverage\n\nToday is ${today}. ${coverage}`,
      });
    },
  },
});
If the database is unreachable when a session starts, the resolver falls back to a safe message instructing the model to call a wide-range tool to discover the data bounds rather than guessing. If you need to inject additional session-dependent facts (user locale, active fiscal year, feature flags), extend this resolver rather than writing literals into instructions.md.

Channel configuration

The HTTP channel is defined in agent/channels/eve.ts using an auth array with three providers:
agent/channels/eve.ts
import { eveChannel } from "eve/channels/eve";
import { localDev, none, vercelOidc } from "eve/channels/auth";

export default eveChannel({
  auth: [
    vercelOidc(),
    localDev(),
    none(),
  ],
});
vercelOidc() allows the eve TUI and Vercel deployments to reach the agent using OIDC tokens. localDev() opens the endpoint on localhost for eve dev and the REPL, and is automatically ignored in production. none() removes the authentication requirement for all other callers — it is what enables the public demo to work without a login flow.
The none() auth provider in the channel config means the agent endpoint is publicly accessible. Replace it with a real auth provider before pointing the agent at non-synthetic financial data.

Build docs developers (and LLMs) love