Skip to content
Finanly

Technology & AI

Governed intelligence on a canonical finance model.

Six layers, each with one job and hard boundaries between them. The result is a system where a plain-English question becomes a validated plan, a computed answer and a traceable row — and where nothing irreversible happens without a person.

Model proposes · platform validates · engine computesRLS per companyAppend-only audit

The stack

Six layers. One job each.

Bottom to top: where data comes from, where it lives, where it is posted, how it is governed, how it is reasoned about, and how it is controlled.

1 · Connectors

One stateless service per source, holding only its own credentials. Fetch and normalize; never persist. Nightly sync, webhooks, backfills — all idempotent.

8 live services

2 · Canonical store

A normalized finance model in Postgres: accounts, transactions, invoices, parties, products, shipments, payouts. Row-level security on every tenant table.

RLS · AES-GCM secrets

3 · Ledger of record

Double-entry postings live in ERPNext behind a connector. Finanly drafts, a human approves, an idempotent export posts once; statements are re-derived and parity-checked hourly.

19k+ entries in parity

4 · Semantic layer

Governed cubes, measures and dimensions over the canonical store. Statements, Report Studio, dashboards and the model all plan against the same definitions.

26 cubes · 124 measures · 756 dimensions

5 · Model layer

A private model behind an internal-only gateway proposes semantic plans and categorizations. core-api validates; the engine executes; the model never touches a connector.

Internal-only gateway

6 · Controls

Approvals and export batches, idempotency keys on every side-effect call, append-only audit events enforced by a database trigger, rate limits, undo.

Append-only audit trail

Most finance AI is a model with database access. Finanly is a governed model with a validator in front of it, an engine behind it and a person at the end.

Governed intelligence

How a question becomes a number you can audit.

Scroll through the four steps. Every frame is the real shape of the data at that step, with demo figures.

STEP 01

1 · The request

A plain-English question from the Business Intelligence page. Suggestion chips cover the questions founders ask most; anything else is fair game.

STEP 02

2 · The model proposes a plan

The private model receives the request and the governed vocabulary — measure names, dimensions, the chart of accounts — and returns a semantic plan. Three tools stop it inventing accounts, fields or dates.

STEP 03

3 · core-api validates

Every measure, dimension and period is checked against the semantic registry: 26 cubes, 124 measures, 756 dimensions. Unknown fields fail closed. The tenant is bound from the session, never from the model.

STEP 04

4 · The engine answers

Cube executes the validated plan on the canonical store and returns rows, totals and the plan. Save it, schedule it, pin it to a dashboard — or drill to the ledger rows.

Separation of powers

What proposes, what validates, what computes, who approves.

01

The model proposes

Reads the request and the governed vocabulary; returns a semantic plan or a categorization suggestion with a confidence.

Never reads raw ledger rows. Never calls a connector.

02

The platform validates

Checks every measure, dimension and period against the registry; binds the tenant from the session; fails closed on anything unknown.

Never trusts a field the model invented. Never widens a tenant boundary.

03

The engine calculates

Executes the validated plan on the canonical store and returns rows, totals and the plan that produced them.

Never computes outside governed measures. Never returns a figure without its rows.

04

A human approves

Accepts, edits, splits or rejects; approves export batches to the ledger. Every decision is reversible and audited.

Nothing irreversible happens without this step.

124governed measures the model can plan with
120questions tracked in the regression catalog
3stages: planning, validation and governed calculation
0connectors or rows reachable by the model

Three-tier classification

The model is the last resort, not the first guess.

Categorization runs exact history first, similarity second, and asks the model only to disambiguate — with the chart of accounts as a tool so it cannot invent an account. Every accepted line becomes history for the next two tiers.

Tier 1Exact matchconfidence 0.95 – 0.99

The normalized description matches a line you categorized before. Amount-aware: if two histories match, the closest amount wins.

Tier 2Similarityconfidence 0.75 – 0.94

Weighted token similarity against your tenant's history, with an amount tie-break when two candidates are near-equal.

Tier 3Private modelconfidence 0.75 – 0.89

Only when tiers 1–2 are unsure: the description plus the top 5 candidates go to the Finanly model to disambiguate. It picks; it does not invent accounts.

Data architecture

One canonical model, one ledger of record.

Finanly keeps its own normalized store for every source and every workflow, and posts double-entry results to a ledger of record through a connector. Both sides are checked against each other.

Canonical Postgres store

Accounts, transactions, invoices and lines, parties, products, shipments, payouts, disputes, GL entries. Row-level security on every tenant table; the application filters by tenant too — two layers, not one.

ERPNext as ledger of record

Postings, invoices, parties and stock live in a real double-entry ledger. Finanly is the surface and the brain; it does not pretend to be an independent ledger yet.

Parity, not trust

Balance sheet, P&L and trial balance are re-derived from the canonical store and compared with the ledger every hour. Drift is a visible gate, not a silent assumption.

Semantic layer (Cube)

Measures and dimensions are defined once and used by statements, Report Studio, dashboards and the model. The number agrees everywhere because it is computed in one place.

Jobs and schedules

Celery workers and a beat schedule: nightly sync, webhooks, backfills with explicit ranges, exports, report runs, parity checks, dispute tracking.

Append-only audit

A database trigger rejects updates and deletes on audit_events. Every irreversible action writes who, what, when and its idempotency key.

The model layer, honestly

What serves today. What is in development.

Production runs an open-weights language model privately on your hardware behind the internal gateway. Finanly's own finance-tuned model is in development and will drop into the same gateway — the plan-validate-execute contract around it does not change.

model cardThe Finanly model layer
Serving today
An open-weights language model, hosted privately on your hardware behind the internal gateway
In development
Finanly's own finance-tuned model (ledgers, chart-of-accounts vocabulary, reconciliation patterns, statements); drops into the same gateway
Input
Natural language — ask the way you would ask your controller — plus the governed vocabulary as tools
Output
Semantic plans (validated by core-api), categorization suggestions, narrative over computed figures
Runtime
Your own hardware; internal network only
Reachability
Called by core-api with a short-lived, tenant-scoped JWT
Tools
get_chart_of_accounts · get_cube_measures · resolve_period
Web
Self-hosted search for vendor enrichment lookups — search, not inference

FAQ

Straight answers

What happens when a question can't be answered?

Unsupported or ambiguous requests receive an explanation or a supported, clearly scoped alternative. Available answers depend on the current measures, source coverage and reviewed definitions; missing data is not a guessed zero.

Where does the model run?

On the same host as the stack, behind an internal-only gateway with no host port. core-api calls it with a short-lived token bound to one tenant. Nothing is sent to a public AI API.

Which model is it?

Today an open-weights general-purpose model; Finanly's own finance-tuned model is in development. We name the exact model in conversation rather than in marketing copy.

Is the semantic layer the same for every surface?

Yes. Statements, Report Studio, dashboards and the model all plan against the same cubes and measures, so a number does not change depending on where you look at it.

How is a company kept apart from another?

Row-level security in Postgres enforces tenant isolation underneath the application; the application also filters explicitly. Secrets are encrypted per tenant. The model sees one tenant per call.

What is idempotent, exactly?

Every side-effect endpoint — categorize, export, sync, revalue — requires an Idempotency-Key. A replay returns the stored response; the ledger connector uses the same key so a posting is created once; a changed payload under the same key is rejected.

What are the known limits?

Financial meanings depend on reviewed definitions and source coverage. Missing cost or history can make margins and duration metrics unavailable. Complex AI questions can take tens of seconds; a successful example is not a guarantee for every question.