Extraction
Extraction
Extraction reads a picture, a screenshot or a PDF into rows, checks each row against what is already recorded, and lets you look before anything is written. A receipt becomes a cost, a bank statement becomes a cost per payment, and a registrar's panel updates the expiry dates you track. Read, check, let a person look, write: the order is the point.
In the sidebar under Money → Extraction. Needs: Services, Costs, Vaults, and a vision or document-reading connection set up under AI. Handles money: when an agent writes a reading, a person approves it first.
What you see
Reading something
At the top (with extraction:write):
- What is it? picks the recipe. Leave it on Work it out from the picture and the picture is looked at once to see what it is, then read as that.
- Paid from names the account the money came out of, when you know it.
- A box for instructions. It is optional when the picture is worked out, and required for the open recipe.
- A drop zone: paste a screenshot, drop a picture or a PDF, or click to choose a file.
Pictures can also come from the linked Telegram bot or the web chat. They land in the same list. Several screenshots sent together on Telegram (an album) are read as one batch, and the lines they share are counted once.
Who reads the page
Receipts and statements go to a document reader when one is set up in the Document reading order card on the AI page. Rows are made from its text, and each amount must be found on the page exactly as printed. Lines the reader was unsure of are marked, show the part of the page they came from, and wait for you. When no document reader can read the file, the picture model reads it, and the reading says why in its first sentence. A reading says who read it.
The statement's own totals, line count and page subtotals, and a receipt's tax, are checked and reported. They are never "fixed" for you.
The recipes
| Recipe | Reads | Writes after you approve |
|---|---|---|
| Receipt or invoice | One purchase: who was paid, the total, the currency, the date | One cost, filed under a project |
| Invoice (Bills inbox) | A supplier invoice that arrived by mail | Used by Bills inbox to draft a bill |
| Bank statement or transaction list | Every line of a bank, card or wallet list, from an app screenshot or a PDF | A cost per payment out, or a movement between your vaults. Money coming in is listed, not written. |
| Registrar / hosting panel | Domains and their expiry dates | New expiry dates on services you already track |
| Anything — tell it what to do | The picture against what you asked | Proposed actions, each asked about on its own |
The open recipe is the fallback. Only the named recipes check for duplicates and write a whole reviewed batch under one approval, so prefer them wherever one fits.
The list of readings
Readings are listed newest first, with the recipe, when it was read, and a status: ready (waiting for review), committed, failed or discarded. You see your own readings. An administrator sees everyone's.
One reading
Click a reading to open it. The picture or PDF is on one side and the rows on the other:
- a summary: what was read, what is new, and the totals per currency;
- on a statement, From: the account the statement is of, and a Balances badge saying whether the statement's own running balances agree with the lines read;
- Check notes on the reading as a whole;
- suggestions for what could be done next, each with a Do this button. Writing the rows does none of them;
- each row's fields, which you can edit in place;
- on a row that looks like something already recorded, the record it resembles: its date, amount and vault;
- problems (nothing is written for that row until it is fixed) and Check warnings (it is written as it stands, once you accept it);
- on a receipt, Which project?: the project the cost goes under;
- what the row will do: "Will call
costs.log", for example, or "Nothing will be written for this row".
Clean rows arrive accepted. A row with a warning or an unsure line arrives pending, and a row with a problem has nothing to write. A line held because the page was read before, or because it is shared by two screenshots of an album, has Keep: one press keeps it.
What you can do
Read a receipt or statement
- Open Money → Extraction.
- Leave What is it? on Work it out from the picture, or pick the recipe.
- Pick Paid from if you know which account paid.
- Paste or drop the file. The reading opens as soon as it is done.
Nothing is written yet.
Review the rows
- Correct any field that was misread. The row is checked again at once and shows what is now wrong with it, if anything.
- Press Accept on rows to write and Reject on rows to leave out.
- On a row held back because it looks already recorded, press Same payment if it is. It is rejected and remembered, so the next statement showing that line holds it as recorded without asking.
File a receipt under a project
A receipt's cost is proposed under a project: from a domain on the receipt, or from the payee's last project for you. When nothing knows, you are asked. On Telegram you get buttons: No project, Other… (type a name), or Split across several projects (a split always adds up to the total). Your choice is kept through later corrections and remembered for that payee. A receipt already filed offers Open instead.
Say what a statement line is
Every payment out on a statement has a class:
| Class | Is | Written as |
|---|---|---|
| Cost | Spending | A cost |
| Bank fee | A bank's charge, still spending | A cost, under the payee rule's category or "Bank fee" |
| Cash withdrawal | Money moved to your cash | A move from the statement's account to your cash vault in that currency |
| Transfer to… | Money moved to one of your vaults | A move to the vault you name, in the same currency only |
Pick the class on the line. Tick Remember for this payee and the choice becomes the payee's rule, so its next lines arrive classed. Your choice wins over a payee rule, a payee rule wins over an agent's, and with none of them a line is a cost. What the bank labelled the line ("ATM", say) is shown as a hint and never applied by itself.
Spending and movements are never added together. The summary and the approval show costs and moves apart.
Tie a statement to its account
A withdrawal or transfer can only be written once the reading knows which account the money left. The statement's printed card ending or account number is looked up in the list of numbers kept by Vaults.
- If nothing matches, withdrawals and transfers are held with "Which account is this statement from?". Cost lines are not affected.
- Choose the account under From:. Every unwritten line is checked again against it, and the printed number is added to that vault's list, so the next statement of that card asks nothing.
Import a statement into the books
A statement reading can also go into Books for reconciliation. Preview it first: you see the lines as the books would import them, the period, whether the balances agree, and which lines are left out or would be refused. Then import it. This needs the books' reconcile permission (ledger:reconcile). Importing the same statement twice adds nothing.
Write the rows
Press Write N row(s). The button is off while an accepted row still has something to fix.
Each row is checked again just before it is written. A row whose record is already there writes nothing new and shows "already recorded". The commit must match what the screen showed: if the reading changed since you opened it, the write is refused and you look again.
Throw a reading away
An agent or the API can discard a reading, picture and all, when none of it should be written. Rows it already wrote stay written. There is no button for this on the page.
Who can do what
| Permission | Label | Lets you |
|---|---|---|
extraction:read | See extracted records | See the page, your readings and the pictures they were read from, and preview a statement as the books would import it. |
extraction:write | Read images and commit rows | Read new files, correct, accept and reject rows, set a statement's account or a receipt's project, import a statement into the books, and write or discard a reading. |
Writing a row also runs the tool behind it, such as costs.log, as you. So you need what that tool needs too.
What runs on its own
Nothing in this module runs on a schedule. A reading happens when a file is sent, and writing happens when a person says so. Every reading made from Telegram is counted as such in Costs.
Needs
Services (infra), Costs and Vaults must be switched on. Reading needs an AI connection that can see pictures, and works best with a document reader set up on the AI page.
For agents
An agent can read a picture it was sent, list and correct the rows with the person, and propose the commit. Extraction handles money, so these guardrails hold for every agent and every model:
- A person approves the write. When an agent calls
extraction.commit,extraction.setAccount,extraction.setProject,extraction.settleBatchorextraction.importToLedger, a person is asked first. The commit's approval card is built from the stored rows: their count, their totals per currency, the moves apart, the lines read unsure, and the tools they run. An agent's call toextraction.readis classed as spending, since it calls a model, and asks too. - Figures come from the reading. A reply about a picture opens with the reading's own summary. The agent's text is kept only if every amount, date and count in it is in the reading.
- The person decides held-back rows. An agent's
extraction.updateRowon a row that looks already recorded is refused. So is reclassing a line the person or a payee rule classed. An agent may accept an unsure line only when the running balance confirms it. - One way to write a statement. While a reading has unwritten rows, an agent in a chat cannot log those same amounts directly as costs. It is told to commit the reading, so the duplicate checks still hold.
extraction.updateRow and extraction.discard are classed as reads for approvals: they change the review, not any record.
Read only: extraction.recipes (what can be read), extraction.list (readings), extraction.get (one reading), extraction.ledgerPreview (a statement as the books would import it).
Review: extraction.updateRow (correct, accept or reject a row), extraction.discard (throw a reading away).
Change, asks a person first: extraction.read (spends: calls a model), extraction.settleBatch (count an album's shared lines once), extraction.setAccount (which vault a statement is of), extraction.setProject (which project a receipt goes under), extraction.importToLedger (import a statement into the books), extraction.commit (write the accepted rows).
Over MCP the same tools are named extraction__read, extraction__commit and so on (see API keys and MCP access). A caller with an API key follows its own approval policy, as whoever made the key chose. The guardrails above protect the deployment's own agents.