An AI agent for Comarch Optima: automated posting that stops at the buffer
Why I'm Writing This
Three posts on this site now cover Comarch Optima from the developer's chair: what "the API" actually means, how a customer reservation really behaves, and the older piece on wiring Optima to a B2B portal. Between them they cover how data gets in and out. They don't answer the email that turns up a day after somebody reads them: fine, so what do you actually build on top of it?
If you run an accounting office on Optima, or your books are kept in one, the honest answer is narrower than "AI accounting" makes it sound. This post is that answer. It's the Optima counterpart of the enova365 posting article, and where the two diverge, the difference belongs to Optima, not to me.
Optima Already Posts Automatically. That Is Not the Problem
Start with what Optima already does, because most conversations about automating its bookkeeping skip straight past it. The Księga Handlowa module has had schematy księgowe, posting schemes, for as long as anyone reading this has used the product. A scheme takes an entry in the VAT register, reads its kategoria, its contractor and its deduction flag, and writes the debit and credit lines. Run it over a month of purchase invoices and the decrees appear. That's automatic posting. It works.
So the scheme isn't where the hours go. They go into three things the scheme never sees:
- Which category the entry carries. The category maps a cost to an account, a VAT deduction rule and a KPiR column. It comes from the contractor card's default, or from whoever typed the entry in. Get it wrong and the scheme posts it wrong, confidently, and the correction lands after somebody has already confirmed the entry.
- Which contractor the entry points at. A NIP with a typo. A second card for the same company. A card set up in a hurry with no default category on it at all.
- Whether the entry should exist. The same invoice arrives as a KSeF download, as a PDF the client emailed over, and as an XML from the client's own Handel module through Praca Rozproszona. Three doors, one invoice, and nothing in the scheme asks whether it has seen this one before.
Two numbers tell you how big the problem is on a given installation, and both are one export away. First: the share of active contractors with an empty default purchase category. In offices that never ran a clean-up I've seen anywhere between a third and two thirds. Second: the share of last month's purchase register entries whose category differs from the contractor's default. That second number is the count of manual decisions your people are already making, and it's the honest size of the automation target. Under five percent? Buy nothing. A quarter? Keep reading.
What Arrives, and Through Which Door
Optima is unusually well equipped on the input side. An agent should use the doors that already exist rather than cut new ones.
KSeF is built in. Optima downloads purchase invoices from KSeF itself and lists them for you to carry into Handel as an FZ or into the purchase VAT register. The fetching problem I wrote about for KSeF automation is largely solved here by Comarch. What nobody solved is what happens to the list: which entries get carried, when, with which category, and who notices the ones that have been sitting there for three weeks.
Comarch OCR handles the paper and PDF tail — the foreign supplier, the receipt — priced per page. Its output lands in the register looking like any other entry. Which means an OCR misread and a correct entry are indistinguishable to the scheme.
Praca Rozproszona carries documents from a client's sales database into the office's accounting database as XML. It's the door most accounting offices actually use, and it has the failure mode I keep coming back to: a directory nobody watches, where a file that failed to import leaves no more trace than a day with nothing to import.
So the agent's first job isn't extraction. It's reconciliation across doors: this KSeF invoice, this PDF and this XML entry are the same document, and this one over here is new. The key is the KSeF reference number where there is one, and seller NIP plus invoice number where there isn't.
The Accounting Office Problem: Forty Databases, One Agent
This is the part with no equivalent in the enova365 article, and it shapes the build more than any choice of model does.
In Optima, every client company is a separate SQL database. The Biuro Rachunkowe module gives the office one panel to switch between them, but underneath sit forty logins, forty sets of categories, forty contractor lists and forty sets of posting schemes. Three things follow from that.
Nothing transfers. A category convention the agent learns on client A means nothing on client B, where the same cost has a different category code and a different account. The agent's knowledge is per database and it has to be told so, explicitly. The first version I saw of somebody's "Optima AI" spent a week proposing client A's categories into client B's register before anyone spotted it.
Every login is a seat. As the API guide says, an integration that logs in counts as a user for licensing. Forty databases processed in parallel is forty seats you don't have. So the agent runs after hours, one database after another, and releases the seat before the first accountant walks in at eight. It's a scheduling constraint, it's perfectly liveable, and it has to be in the design on day one rather than discovered in week six.
The access lag multiplies. In the implementation-time post I called the days between "we agreed" and "the connector holds working read-only credentials" the access lag, and named it the best predictor of go-live. In an Optima office that lag is per database. Create forty read-only operators in one afternoon and you go live in weeks. Add them one at a time, as each client "gets around to it", and you're still onboarding at Christmas.
What the Agent Does, in Order
Five steps. Each one leaves something a person can look at.
- Deduplicate across doors. KSeF list, OCR output, Praca Rozproszona import, register entries: one document, one identity. Duplicates are the quiet error here — a doubled purchase invoice trips nothing, deducts VAT twice, and surfaces months later as a supplier balance that won't agree.
- Resolve the contractor by NIP. Never by name. A miss goes onto the exception list with the NIP, the extracted name and a proposed action. The agent doesn't create contractor cards on its own. A duplicate card is exactly the kind of small mistake that quietly corrupts reporting for a year.
- Verify the counterparty on the day it matters. Optima checks the white list when you pay. The agent checks it when you book — and those two dates are weeks apart, which is the whole argument in the white-list post. A failed check isn't a booking problem, it's a payment problem, so it reaches a person before the transfer goes out, not after.
- Propose the category and the deduction. From the contractor's default where there is one, from the history of that client's register where there isn't, with a confidence score and a one-line reason. Where the office uses analytical descriptions on the Księga Handlowa side, propose those as well. Low confidence is a routing signal, not a coin flip.
- Write where Optima treats things as provisional. On the Handel side that's unambiguous: an FZ in the buffer through the object model, category and attributes filled in, the same object model Comarch uses for its own products. On the accounting side, check what your version's object model exposes before you design anything around writing to the VAT register — the honest answer varies by build, and I'm not going to invent an API name to make this paragraph tidier. Where the register isn't reachable, the agent does two smaller things that still move the number: it fills the empty default categories on contractor cards so Optima's own imports pick them up, and it hands the per-document exceptions to a review list a person works through in the register.
Every proposal carries its reason. An attribute on the document, a line in the review list — whatever the surface, the accountant reads "same supplier, same category last eleven months" or "first invoice from this NIP, closest match is X", then confirms or corrects. Those corrections are the training signal. There isn't another one.
Where It Stops
The liability post drew four permission levels: read, propose, write, send or sign. Optima happens to have that level-three boundary built into its own data model already. Three times over.
A document in the buffer is editable, provisional, not yet a fact. A register entry nobody has run Księguj on hasn't touched the ledger. A decree in the buffer of the Księga Handlowa isn't in the journal yet. Each of those is a spot where Optima itself says: a person hasn't decided. The agent stops at all three, and it stays away from JPK entirely.
Which makes the rule short. The agent never confirms a document out of the buffer. Never runs Księguj. Never approves a decree. Never generates or sends a JPK file. Not after a trial period, not for low-value invoices, not when the confidence score looks great. The person doing those things is the person whose name is on the declaration — and the point of the agent is that when they click, what they're clicking on is already right.
The First Build Has No Downside
Don't start with writes. Start with a nightly read-only report, one per database, that puts three numbers in front of the office manager every morning:
- Stuck at the door: invoices on Optima's KSeF list not carried into the register after N days, plus files sitting in the Praca Rozproszona directory that never imported.
- Category drift: purchase register entries this month whose category is empty or differs from the contractor's default. That's your manual-correction count, and its trend is the only proof you will ever get that a later write-enabled agent is actually helping.
- Duplicates: pairs of register entries sharing a seller NIP and an invoice number.
Run it for a month. If the drift number comes back small and stable, you've learned cheaply that the office doesn't need this — and that's a good outcome, not a wasted month. If it's large, you have the argument, the baseline, and a list of exactly which contractors need a default category filled in. That last one is an afternoon's work, and it'll move the number further than any model will. Then, and only then, turn on proposals for a single client database, measure the override rate — the share of proposals the accountant changes — and widen once it drops under ten percent.
The metric that ties all of this back to the office's actual life comes from the month-end post: the share of a month's documents in the system by the 10th. If that share rises, the agent is earning its keep. If it doesn't, the bottleneck was never the posting.
If you run Optima, in an office or in a company, and you want somebody who has already walked into the forty-database problem to look at your installation before you commit to a date, get in touch. This is the kind of AI agent I build: read first, propose second, and the click stays with the person whose name is on the return.
Check a Polish VAT counterparty in seconds, free
KsięgoAI checks a NIP against the VAT white list and VIES, scores the risk and saves proof of due diligence. Works in Telegram and Claude.
Try KsięgoAI→Let’s talk about your project
Free 30-minute consultation. We’ll figure out if and how I can help.



