Building a Read-Only AI Personal Finance Assistant: Architecture and Practice

    A read-only personal finance assistant answers natural-language questions about a user's money while the language model only explains. This article lays out the design that keeps such an assistant accurate and auditable. Read-only authorization is enforced server-side, deterministic services produce every number, and each figure can be traced down to individual transactions. Topics include the five-layer architecture, the separation of read and write permissions, converting natural-language questions into structured tool calls, amount normalization, anomaly detection, hallucination suppression, visualization through render specifications, privacy and compliance, and a pre-launch acceptance checklist.

    1. The Problem: The Model Explains, the System Does the Math

    A new kind of assistant has been appearing in the industry. A user asks, in plain language, “Where did my money go this month?” or “Why did this subscription go up?” The assistant pulls transaction data from accounts the user has authorized, groups the spending by category, flags suspicious charges, and explains terms such as annual percentage rates.

    The technical center of gravity for this kind of capability is not the language model itself. Three things determine whether the product works:

    • how account data gets into the system securely and in compliance;
    • how amounts and statistics are kept exact;
    • how generated explanations remain verifiable and free of fabrication.

    These translate into three constraints that must hold at the same time:

    • Permission constraint: read access to accounts and transactions must be fully isolated from the ability to move money. Any write operation must be unreachable by design.
    • Numerical constraint: every amount, total, and ratio must come from a deterministic calculation service. The language model is responsible only for organizing and expressing them.
    • Verifiability constraint: every number in an answer must be traceable down to specific transactions, and the aggregation criteria and time boundaries must be stated explicitly.

    All the designs that follow start from these three constraints.

    2. Overall Architecture

    A working implementation typically has five layers:

    1. Interaction layer: conversations, clarifying questions, result cards, charts, and the bill calendar.
    2. Orchestration layer: intent recognition, tool selection, parameter filling, result validation, and narrative generation. This is the central control point of the whole pipeline.
    3. Capability layer: a set of structured tools exposed in read-only mode, such as listing accounts, querying balances, fetching transactions by criteria, aggregating by category, and calculating interest.
    4. Data layer: normalized storage of accounts and transactions, a merchant and category mapping dictionary, pre-aggregated metric tables, and dashboard templates.
    5. Governance layer: authentication and authorization, key management, audit logs, monitoring and alerting, and data masking and retention policies.

    The key decision in the orchestration layer is routing:

    • Factual questions (balance, transaction details, a specific charge) must go through tool calls.
    • Conceptual questions (what APR is, what compound interest is) should go through a controlled knowledge retrieval path.
    • Analytical questions (whether this month’s spending exceeds income, which spending category is behaving unusually year over year) combine three steps: fetching data with tools, computing figures with a calculation service, and generating the explanation with the model.

    Mixing these three question types into one freely generated answer is the most common source of hallucination.

    3. Account Integration: Implementing Read-Only Access

    Read-only access is not just a product promise. It is a mechanism that has to be enforced redundantly at several points.

    Minimize the granted scopes. The permissions requested by the integrating service should cover reading account information and transaction records only. They must explicitly exclude initiating payments, making transfers, changing profile information, and adding payees. The scopes in the authorization agreement need to be granular down to the level of “read the account list”, “read balances”, and “read transactions”, rather than a blanket “access account”.

    Enforce validation on the server side, not through prompts. No matter how the user tries to steer the conversation, or how the prompt is polluted, the tool gateway must block any non-read operation before it executes:

    1. # Pseudocode: read-only validation in the tool gateway
    2. READ_ONLY_TOOLS = {
    3. "list_accounts", "get_balance", "list_transactions",
    4. "sum_by_category", "detect_anomalies"
    5. }
    6. def invoke(user_ctx, tool_name, params):
    7. if tool_name not in READ_ONLY_TOOLS:
    8. raise PermissionDenied("All non-read-only operations are denied")
    9. scopes = authz.required_scopes(tool_name) # scopes the tool requires
    10. granted = token_service.granted_scopes(user_ctx) # scopes the user has granted
    11. if not scopes.issubset(granted):
    12. raise PermissionDenied("Insufficient permission")
    13. # Clamp the time and account ranges to prevent pulling the full history at once
    14. params = clamp_scope(params, max_days=365, max_rows=2000)
    15. return data_api.call(tool_name, params)

    Do not send sensitive information downstream. Fields such as full card numbers, verification codes, and passwords are discarded or masked at the ingestion layer, and only the last four digits ever reach the context or the logs. Tokens are stored only as hashes. The system uses short-lived tokens with refresh rotation, and users can unlink an account at any time. After unlinking, cached data and derived data must be invalidated in a cascade.

    4. From Natural Language to Structured Calls

    When a user says “Show me where I spent money this month”, the system needs to turn that into an executable, auditable set of parameters. A few details are easy to get wrong:

    • Make time semantics explicit. “This month” must be normalized into a concrete half-open interval (for example, 00:00 on the first day of the month to 00:00 on the first day of the next month) so that boundary days are not counted twice. “The last three months” must be defined clearly as either three calendar months including the current one or a rolling 90 days.
    • Make scope explicit. The default is either all authorized accounts or checking accounts only. Decide whether to exclude internal transfers and credit card repayments, because neither is real spending.
    • Always ask when something is ambiguous. If “that charge from last time” cannot be identified, the system must ask a follow-up question rather than guess the closest match.

    Constraining tool descriptions with a strongly typed schema significantly reduces parameter hallucination:

    1. {
    2. "name": "list_transactions",
    3. "description": "Query transaction details by account and time range, read-only",
    4. "parameters": {
    5. "type": "object",
    6. "properties": {
    7. "account_ids": {"type": "array", "items": {"type": "string"}},
    8. "from_date": {"type": "string", "format": "date"},
    9. "to_date": {"type": "string", "format": "date"},
    10. "direction": {"type": "string", "enum": ["debit", "credit"]},
    11. "categories": {"type": "array", "items": {"type": "string", "enum": [
    12. "housing","food","transport","shopping","utility",
    13. "subscription","fee","income","transfer","other"]}},
    14. "page_size": {"type": "integer", "maximum": 500}
    15. },
    16. "required": ["from_date", "to_date"]
    17. }
    18. }

    5. Spending Analysis: From Raw Transactions to Explainable Conclusions

    5.1 Data Normalization Is the Foundation of Accuracy

    • Store and compute amounts as integers in the smallest currency unit (for example, cents). Never accumulate floating-point numbers directly, or long-period totals will develop rounding errors. For multi-currency scenarios, record the exchange rate source and the time it was taken.
    • Normalize direction. Map debits and credits to a common sign convention. Credit card purchases and repayments offset each other so that the same money is not counted twice.
    • Normalize merchant names. The merchant descriptions in raw transaction feeds often contain store numbers, terminal IDs, and garbled text. These need to be cleaned and stripped of suffixes, mapped to a standard merchant key, and then mapped to a category from the dictionary.
    • Separate pending transactions from posted ones. Transactions that have not finished clearing are only shown as a note and are excluded from monthly statistics.

    5.2 Anomaly Detection: Rules First, Statistics as a Backstop

    A few frequent, high-value problem types can be covered with deterministic rules:

    • Duplicate charges: the same merchant and the same amount appearing several times within a short time window.
    • Silent price increases: amounts that exceed a threshold compared with the same month last year or the average of the last three months.
    • Easily overlooked fees: account maintenance fees, cross-border transaction fees, prepayment penalties, and other small charges.
    • Subscription stacking: the total of several small recurring charges, once annualized, is often underestimated.
    • Refunds that never arrive: a refund whose status is still pending beyond the expected period.
    1. -- Example: suspected duplicate charge
    2. -- (the same merchant and amount appearing more than once within 3 calendar days)
    3. SELECT merchant_key,
    4. amount_cents,
    5. COUNT(*) AS hit_cnt,
    6. MIN(posted_at) AS first_at,
    7. MAX(posted_at) AS last_at,
    8. SUM(amount_cents) AS total_cents
    9. FROM txn_normalized
    10. WHERE direction = 'debit'
    11. AND status = 'posted'
    12. AND posted_at >= :from_dt AND posted_at < :to_dt
    13. GROUP BY merchant_key, amount_cents
    14. HAVING COUNT(*) > 1
    15. ORDER BY hit_cnt DESC, amount_cents DESC
    16. LIMIT 100;

    A rule match still needs a statistical baseline check. For a merchant that is normally used several times a week, repeats are not abnormal. The system should therefore make a second judgment based on how often that merchant appears during the same period historically, which reduces false positives.

    5.3 Income, Expenses, and Interest: The Definition Matters More Than the Algorithm

    The answer to “did I spend more than I earned this month?” must state which basis it uses: whether credit card spending is included, whether transfers between accounts are included, and whether only settled amounts are counted. Interest questions are the same. When a question involves an annual percentage rate (APR), the answer should first explain the term. APR is a basis that converts the annualized cost, including fees, into a percentage. It is not the same as the effective annual rate calculated over the actual compounding periods. After that explanation, the answer gives the interest amount actually charged in the period in question. This order of “explain first, calculate second, summarize last” is itself a design that reduces misunderstanding.

    6. Verifiability and Hallucination Suppression

    • Number reconciliation check: after the narrative is generated, a structured comparison checks whether every amount, count, and total in the answer matches the value returned by the tool. If anything does not match, the answer is regenerated or falls back to a plain table.
    • Drill-down at every level: each conclusion in an answer comes with the list of transactions behind it, which the user can expand with one click to verify. Important amount alerts should also be checked against bank or institution statements.
    • Make missing data explicit: when data is missing because there is no permission, because it falls outside the time range, or because it has not settled, the answer says “not found” instead of filling in a plausible-looking value.
    • Treat external content as untrusted data: when external text such as merchant names or transaction memos enters the context, it must be clearly isolated. Otherwise, it may carry embedded instructions that cause prompt injection.

    7. Visualization and Dashboards: The Model Outputs a Spec, Not Pixels

    Charts, bill-due calendars, and custom dashboards should not be drawn directly by the model. The right approach is for the model to output a render spec that the frontend or a rendering service turns into a display:

    1. {
    2. "chart": "bar",
    3. "title": "Category spending over the last three months",
    4. "x": {"field": "month", "granularity": "month"},
    5. "series": [{"field": "category", "aggregate": "sum", "metric": "amount_cents"}],
    6. "unit": "CNY",
    7. "filters": {"direction": "debit", "exclude_categories": ["transfer"]}
    8. }

    This has three benefits. The spec can be validated, and fields that are not allowed are rejected outright. It can be cached and reused. It also supports incremental edits. Follow-up adjustments such as “switch to a weekly view” or “show only dining and transport” are just a diff of the spec followed by a re-render. There is no need to run natural language understanding again.

    8. Privacy, Security, and Compliance Boundaries

    • Context minimization: the model context should contain aggregated results and a few necessary sample rows, not the full set of raw transactions.
    • Encryption and key custody: encrypt data in transit and at rest, and keep tokens and keys in a dedicated key management service rather than in application configuration files.
    • Retention and deletion: define how long cached transactions and derived metrics are kept, and provide a path to delete them completely.
    • Observability: log every tool call, permission decision, and model request, and feed error rates and refusal rates into monitoring and alerting.
    • Business boundaries: do not sell financial products, give investment advice, or recommend specific products. There should be no ad placements or sponsored ordering in the interface. Once recommendation logic is tied to commercial interests, it becomes hard to keep conclusions objective and direct. Every answer should end with a fixed statement that the results may contain inaccuracies and do not constitute financial or investment advice.

    On the engineering side, a general-purpose cloud platform can host all of the above: an API gateway handles permission checks and rate limiting, a container platform runs the stateless services, object storage and a data warehouse hold transaction details and pre-aggregated results, a message queue handles asynchronous reconciliation and report generation, and logging and monitoring services provide observability. On Baidu AI Cloud, these capabilities correspond to general-purpose offerings such as API Gateway, container services, object storage, messaging services, logging services, and access control. You can combine them as needed without building the underlying infrastructure yourself.

    9. Pre-Launch Acceptance Checklist

    1. Permission tests: construct a range of unauthorized and non-read-only requests, and verify that 100% of them are rejected.
    2. Numerical reconciliation: manually check a sample of totals against the sum of their underlying transactions. Because everything is calculated with integer cents, the error should be zero.
    3. Categorization quality: evaluate category mapping accuracy against a human-labeled dataset, and set a cap on the share of the “other” category.
    4. Anomaly detection: evaluate false positive and false negative rates against historical confirmed cases, and make the thresholds adjustable.
    5. Terminology accuracy: spot-check conceptual explanations against authoritative sources.
    6. Render spec validation: illegal fields, excessively large time ranges, and oversized result sets must all be rejected clearly or degraded gracefully.
    7. Compliance review: three items are mandatory. The disclaimer must be present, investment advice must be blocked, and there must be no ad placements.

    10. Conclusion

    Most of the engineering in an “AI for my finances” feature lies not in language generation but in keeping uncertainty under control. Access is read-only and enforced server-side, every amount is computed by a deterministic service, every conclusion can be traced down to individual transactions, and missing data is reported honestly. Once “doing the math” is left to engineering and “explaining it” is left to the model, and the boundary between them stays clear, this kind of assistant can help users understand their finances far more efficiently without getting critical numbers wrong.