<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tali Adler</title>
    <description>The latest articles on DEV Community by Tali Adler (@tali_from_portali).</description>
    <link>https://dev.to/tali_from_portali</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4114360%2F3f3da069-178f-4b41-a0e8-55d6035e593c.jpg</url>
      <title>DEV Community: Tali Adler</title>
      <link>https://dev.to/tali_from_portali</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tali_from_portali"/>
    <language>en</language>
    <item>
      <title>The 2 AM text that found a $2,340 double charge</title>
      <dc:creator>Tali Adler</dc:creator>
      <pubDate>Mon, 12 Oct 2026 17:45:45 +0000</pubDate>
      <link>https://dev.to/tali_from_portali/the-2-am-text-that-found-a-2340-double-charge-2968</link>
      <guid>https://dev.to/tali_from_portali/the-2-am-text-that-found-a-2340-double-charge-2968</guid>
      <description>&lt;p&gt;A founder texts an accounting agent at 2:07 AM: &lt;em&gt;"did we pay the vendors??"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The reply comes back in seconds: &lt;strong&gt;"Yes. Also, you were double-charged $2,340. Refund already requested."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That 8-second exchange is the whole pitch for agentic accounting, so here is what has to be true behind it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The workflow behind the text
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ingest payments continuously.&lt;/strong&gt; Bank feeds and card transactions land in one ledger instead of living in exports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Match vendor bills to payments.&lt;/strong&gt; Every payment is paired with the invoice it settles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flag anomalies.&lt;/strong&gt; Two charges, same vendor, same amount, close dates: duplicate candidate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Act, then report.&lt;/strong&gt; The agent drafts the refund request and tells you after, with the evidence attached for review.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nothing exotic. It is the reconciliation a bookkeeper does at month-end, run every night instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why legacy tools miss it
&lt;/h2&gt;

&lt;p&gt;Legacy software makes you export, re-enter and reconcile by hand. A duplicate charge sits in a CSV until someone has the hour to scan it. By then the refund window may be closing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where MCP fits
&lt;/h2&gt;

&lt;p&gt;Portali supports MCP integration, so the agent reads and acts on the ledger through a standard interface rather than screen scraping. The workflow comes first; MCP is just how the agent gets safe access to your data.&lt;/p&gt;

&lt;p&gt;Meet Tali, the AI assistant on the other end of that text, and see the reconciliation workflow: &lt;a href="https://portali.tech/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=boss_tali_short" rel="noopener noreferrer"&gt;portali.tech&lt;/a&gt;&lt;/p&gt;

</description>
      <category>accounting</category>
      <category>ai</category>
      <category>fintech</category>
      <category>automation</category>
    </item>
    <item>
      <title>Export, Re-Enter, Reconcile, Repeat: Breaking the Month-End Habit</title>
      <dc:creator>Tali Adler</dc:creator>
      <pubDate>Wed, 07 Oct 2026 14:43:56 +0000</pubDate>
      <link>https://dev.to/tali_from_portali/agentic-accounting-with-mcp-meet-tali-the-ai-assistant-inside-portali-3388</link>
      <guid>https://dev.to/tali_from_portali/agentic-accounting-with-mcp-meet-tali-the-ai-assistant-inside-portali-3388</guid>
      <description>&lt;p&gt;If you run month-end in traditional accounting software, you know the loop:&lt;/p&gt;

&lt;p&gt;Export the ledger to a spreadsheet. Re-enter or re-map the bank data. Reconcile line by line. Do it all again next month.&lt;/p&gt;

&lt;p&gt;The data already existed in your software. The software just was not built to connect the two ends. That is the gap most "automation" never touches, and it is why the close still eats a week.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the pain actually looks like
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Duplicate exports: the same transactions, cleaned up by hand, every single month&lt;/li&gt;
&lt;li&gt;Stale cash data: by the time the reconciliation is finished, the picture is already old&lt;/li&gt;
&lt;li&gt;Review by memory: nothing tells you &lt;em&gt;why&lt;/em&gt; a match was right, so you check it anyway&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The workflow we built instead
&lt;/h2&gt;

&lt;p&gt;Portali is agentic accounting software, and Tali is the AI assistant inside it. In practice the month looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connect your bank feed. Transactions flow in on their own.&lt;/li&gt;
&lt;li&gt;Tali matches them against your books and attaches the evidence behind each match.&lt;/li&gt;
&lt;li&gt;You review the exceptions and approve. Tali never quietly decides for you.&lt;/li&gt;
&lt;li&gt;Ask questions in plain English: cash position, open items, unusual categories. You get answers, not a spreadsheet hunt.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The boring, repetitive part is handled. The judgment calls stay yours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where MCP fits
&lt;/h2&gt;

&lt;p&gt;Portali speaks MCP (Model Context Protocol), so the AI agents you already use can read transactions, run reconciliations and query your books through a standard interface. No screen-scraping, no one-off integrations. It is plumbing, not the headline. The headline is that the month-end loop above stops being your job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who it is for
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;CPAs and bookkeepers who want faster closes without losing control&lt;/li&gt;
&lt;li&gt;Small business owners tired of re-entering data their software already has&lt;/li&gt;
&lt;li&gt;Developers building finance agents that need reliable access to real books&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The 17 second overview
&lt;/h2&gt;


&lt;div&gt;
    &lt;iframe src="https://www.youtube.com/embed/Ea6G0_aTtS0" width="315" height="560"&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;


&lt;p&gt;&lt;strong&gt;See the reconciliation workflow:&lt;/strong&gt; &lt;a href="https://portali.tech?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=reconciliation_workflow" rel="noopener noreferrer"&gt;portali.tech&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>accounting</category>
      <category>fintech</category>
      <category>bookkeeping</category>
    </item>
    <item>
      <title>The Missing Layer in Accounting Automation: A Reviewable Evidence Trail</title>
      <dc:creator>Tali Adler</dc:creator>
      <pubDate>Mon, 21 Sep 2026 15:01:45 +0000</pubDate>
      <link>https://dev.to/tali_from_portali/the-missing-layer-in-accounting-automation-a-reviewable-evidence-trail-4lk5</link>
      <guid>https://dev.to/tali_from_portali/the-missing-layer-in-accounting-automation-a-reviewable-evidence-trail-4lk5</guid>
      <description>&lt;h1&gt;
  
  
  The Missing Layer in Accounting Automation: A Reviewable Evidence Trail
&lt;/h1&gt;

&lt;p&gt;Most accounting automation demos stop at the impressive part: a system reads a document, extracts a value, and proposes an entry. That is useful, but it is not the hard part of operating finance software. The hard part is making the proposal reviewable after the context has disappeared.&lt;/p&gt;

&lt;p&gt;A month later, someone needs to answer simple questions: Which source created this number? What did the system infer? Who approved it? What changed between the first suggestion and the final posting? If the answer is a screenshot, a spreadsheet cell, or a vague log message, the workflow is fast only until the first audit question.&lt;/p&gt;

&lt;p&gt;This article describes a practical design for an evidence-linked accounting workflow, and why the review layer deserves to be treated as a product surface rather than an afterthought.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with an evidence object, not a journal entry
&lt;/h2&gt;

&lt;p&gt;A common implementation starts with a target object: an invoice, a bank transaction, or a journal entry. A more durable implementation starts with an evidence object that records what the system actually saw.&lt;/p&gt;

&lt;p&gt;At minimum, an evidence object should include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;source_type&lt;/code&gt;: invoice, bank feed, contract, email, or manual upload&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;source_id&lt;/code&gt;: the provider ID or immutable file reference&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;observed_at&lt;/code&gt;: when the source was retrieved&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;content_hash&lt;/code&gt;: a fingerprint that detects later replacement&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;extracted_fields&lt;/code&gt;: the values read from the source&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;confidence&lt;/code&gt;: a signal for routing, never a substitute for review&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;raw_location&lt;/code&gt;: where an authorized reviewer can inspect the original&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The content hash matters more than it first appears. If a vendor replaces a PDF or a connector replays a transaction with changed metadata, the workflow should create a new observation or raise an exception. Silently overwriting the old evidence breaks the chain of reasoning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate observation, proposal, and decision
&lt;/h2&gt;

&lt;p&gt;These are three different events:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Observation:&lt;/strong&gt; the system found a $12,400 invoice dated March 31.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proposal:&lt;/strong&gt; the system suggests office expense, cost center 410, and an accrual period of one month.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decision:&lt;/strong&gt; a named reviewer accepts, edits, or rejects that proposal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Combining them into one mutable record makes the workflow difficult to explain. Keep them as linked records, or at least as append-only revisions with explicit actors and timestamps. A reviewer should be able to see the original extraction beside the final decision, not just the latest state.&lt;/p&gt;

&lt;p&gt;This also improves debugging. If a classification rule is wrong, engineers can distinguish a parsing problem from a policy problem. Those require different fixes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build the review queue around exceptions
&lt;/h2&gt;

&lt;p&gt;A review queue should not be a dump of everything the system cannot decide. It should answer why a person is being asked to intervene. Useful exception reasons include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the amount exceeds a policy threshold&lt;/li&gt;
&lt;li&gt;the supplier is new or unmatched&lt;/li&gt;
&lt;li&gt;the accounting period is closed&lt;/li&gt;
&lt;li&gt;the source conflicts with an existing transaction&lt;/li&gt;
&lt;li&gt;required evidence is missing&lt;/li&gt;
&lt;li&gt;the model suggested a category outside its allowed policy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each item needs a next action, not just a red badge. For example, “request a purchase order,” “confirm tax treatment,” and “choose an open period” are operationally different tasks. The queue becomes much more valuable when it gives the reviewer the relevant evidence and the smallest decision required.&lt;/p&gt;

&lt;p&gt;This is one area where Portali’s evidence-linked workflow approach is useful: the accounting proposal and the material supporting it can stay together while a person handles the exception. The value is not that a human disappears. The value is that the human spends time on judgment instead of hunting through tabs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make approval idempotent
&lt;/h2&gt;

&lt;p&gt;Review systems often fail at the handoff. A user clicks Approve, the network pauses, and the browser retries. If approval directly creates a journal entry without an idempotency key, the same decision can post twice.&lt;/p&gt;

&lt;p&gt;Use a key derived from the proposal revision and decision action, such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;approve:{proposal_id}:{proposal_revision}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The posting service should record that key before performing the side effect, or atomically with it when the storage layer supports transactions. A repeated request should return the existing result instead of creating another entry.&lt;/p&gt;

&lt;p&gt;Approval should also expire when its inputs change. If the source evidence, amount, period, or account mapping changes after review, create a new proposal revision and require a new decision. Never carry an approval forward just because the record still has an “approved” status.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure trust, not just throughput
&lt;/h2&gt;

&lt;p&gt;A dashboard that reports “10,000 transactions automated” can hide a painful process. Add metrics that describe review quality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;percentage approved without edits&lt;/li&gt;
&lt;li&gt;percentage reopened after approval&lt;/li&gt;
&lt;li&gt;median age of unresolved exceptions&lt;/li&gt;
&lt;li&gt;duplicate side effects prevented by idempotency&lt;/li&gt;
&lt;li&gt;evidence retrieval failures&lt;/li&gt;
&lt;li&gt;time from observation to final decision&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most useful metric may be the percentage of proposals that reviewers can resolve without leaving the workflow. That measures whether the system provides enough context to support an accounting decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  The practical takeaway
&lt;/h2&gt;

&lt;p&gt;Automation earns trust when it leaves a trail: source evidence, extracted facts, proposed treatment, human decision, and safe execution. The reviewable trail is not paperwork added after the “real” automation. It is the interface that makes automation usable in a controlled finance environment.&lt;/p&gt;

&lt;p&gt;Whether you are building an internal close tool or integrating an accounting product, model the evidence and the decision as first-class objects. Start with one exception type, make the provenance visible, add idempotent approval, and measure where people still need to leave the workflow. That is how a fast demo becomes a system a finance team can actually operate.&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>accounting</category>
      <category>automation</category>
      <category>ai</category>
    </item>
    <item>
      <title>Your Finance Agent Needs an Evaluation Harness, Not Just a Prompt</title>
      <dc:creator>Tali Adler</dc:creator>
      <pubDate>Mon, 21 Sep 2026 11:05:07 +0000</pubDate>
      <link>https://dev.to/tali_from_portali/your-finance-agent-needs-an-evaluation-harness-not-just-a-prompt-24kn</link>
      <guid>https://dev.to/tali_from_portali/your-finance-agent-needs-an-evaluation-harness-not-just-a-prompt-24kn</guid>
      <description>&lt;h1&gt;
  
  
  Your Finance Agent Needs an Evaluation Harness, Not Just a Prompt
&lt;/h1&gt;

&lt;p&gt;A finance agent can produce a convincing answer and still be wrong in the one way that matters: it can make a decision without enough evidence.&lt;/p&gt;

&lt;p&gt;That is why “add a better system prompt” is not a sufficient quality strategy for accounting automation. Prompts help define behavior, but they do not tell you whether a release reliably classifies transactions, preserves source evidence, routes ambiguity, and refuses to overreach.&lt;/p&gt;

&lt;p&gt;The practical answer is an evaluation harness: a small, repeatable test system that runs realistic finance cases through an agent and scores the result against explicit expectations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the decision, not the model
&lt;/h2&gt;

&lt;p&gt;Before choosing an LLM or tool framework, define what the agent is allowed to decide.&lt;/p&gt;

&lt;p&gt;For a transaction-review agent, a useful contract might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"suggest_category"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.91&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"evidence_ids"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"bank_tx_1842"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"receipt_883"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"needs_review"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Recurring software subscription matches the approved vendor pattern."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important fields are not only &lt;code&gt;action&lt;/code&gt; and &lt;code&gt;confidence&lt;/code&gt;. An evaluation harness should also check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the suggestion point to evidence that actually exists?&lt;/li&gt;
&lt;li&gt;Is the evidence relevant to the transaction?&lt;/li&gt;
&lt;li&gt;Does the agent flag missing or contradictory documentation?&lt;/li&gt;
&lt;li&gt;Does it stay inside the approved chart-of-accounts scope?&lt;/li&gt;
&lt;li&gt;Is the output deterministic enough to audit and compare?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A response that says “software expense” with no evidence may look useful in a demo. In production, it is an unreviewable assertion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build a case set with deliberate ambiguity
&lt;/h2&gt;

&lt;p&gt;Do not evaluate only clean examples. Clean examples measure whether the happy path works. They do not measure whether the agent knows when to stop.&lt;/p&gt;

&lt;p&gt;A compact starter dataset can contain 50 to 100 cases divided into four groups:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Routine cases:&lt;/strong&gt; recurring vendors, complete receipts, familiar amounts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing-evidence cases:&lt;/strong&gt; a bank transaction exists, but the receipt or invoice does not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conflicting cases:&lt;/strong&gt; the vendor name suggests one category while the attached document suggests another.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adversarial cases:&lt;/strong&gt; prompt injection inside a memo, unusual currencies, duplicate webhooks, or a transaction that falls outside the agent’s authority.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Store the expected behavior as structured data, not just a paragraph written by a reviewer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"case_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tx_missing_receipt_07"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expected_action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"request_evidence"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allowed_categories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"must_cite"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"must_not"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"post_journal_entry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mark_reconciled"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes a regression test possible. If a prompt or model change causes the agent to classify this case anyway, the build should show a failure immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Score behavior in layers
&lt;/h2&gt;

&lt;p&gt;A single “answer quality” score hides too much. Score the workflow in layers instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Schema validity&lt;/strong&gt; checks whether the output can be parsed and whether required fields are present. This catches malformed tool calls and half-finished responses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Evidence grounding&lt;/strong&gt; checks that every cited document or transaction exists and supports the claim. You can start with deterministic checks: valid IDs, matching account IDs, date-window constraints, and amount consistency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Policy compliance&lt;/strong&gt; checks authority boundaries. A suggestion may be acceptable while an automatic journal entry is not. The evaluator should distinguish “propose,” “request review,” and “execute.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decision quality&lt;/strong&gt; checks the actual accounting outcome against a reviewed label. Keep this separate from writing quality. A beautifully explained wrong category is still wrong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Operational behavior&lt;/strong&gt; checks latency, tool-call count, duplicate handling, and retry safety. A model that reaches the correct answer by creating three duplicate reconciliation records is not production-ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the tools, not only the text
&lt;/h2&gt;

&lt;p&gt;Finance agents rarely operate as chat-only systems. They read transactions, fetch documents, call categorization services, and write review tasks. Your harness should record each tool call as an event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;run_id=eval-2026-09-21-014
case_id=tx_duplicate_webhook_03
step=2 tool=lookup_transaction args_hash=...
step=3 tool=create_review_task result=task_551
step=4 tool=create_review_task result=already_exists
final_action=request_review
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That trace lets you test properties that are difficult to see in the final answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A repeated event produces one task, not two.&lt;/li&gt;
&lt;li&gt;A failed document lookup does not silently become “no document.”&lt;/li&gt;
&lt;li&gt;A tool timeout is represented as an exception state.&lt;/li&gt;
&lt;li&gt;A write operation has an idempotency key.&lt;/li&gt;
&lt;li&gt;The agent does not call a privileged tool when a read-only result is enough.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where conventional software testing and LLM evaluation meet. The language model may be probabilistic, but the side effects around it should be bounded and observable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run evaluations in CI and in production
&lt;/h2&gt;

&lt;p&gt;Run the curated case set on every prompt, model, tool-schema, and policy change. Keep a versioned baseline so you can compare releases instead of relying on memory.&lt;/p&gt;

&lt;p&gt;Then add production sampling. Select a small, privacy-aware sample of completed reviews, redact sensitive values where possible, and send them through the same evaluator. Track failures by category: unsupported claim, missing citation, incorrect escalation, duplicate write, and policy violation.&lt;/p&gt;

&lt;p&gt;A useful release gate might require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100% schema validity&lt;/li&gt;
&lt;li&gt;100% policy compliance on adversarial cases&lt;/li&gt;
&lt;li&gt;98% evidence-link validity&lt;/li&gt;
&lt;li&gt;zero duplicate writes in idempotency tests&lt;/li&gt;
&lt;li&gt;no regression in the reviewed decision set&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The exact thresholds depend on the workflow. The principle is stable: define the failure that would hurt, then make it measurable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the human review queue honest
&lt;/h2&gt;

&lt;p&gt;The goal is not to eliminate every review. It is to ensure that the agent sends the right work to review with enough context to resolve it quickly.&lt;/p&gt;

&lt;p&gt;A good review item includes the source transaction, proposed action, cited evidence, detected uncertainty, and a clear reason for escalation. Tools such as Portali can fit naturally into this pattern when the accounting workflow needs a shared place for source-linked decisions rather than another opaque automation layer. The product matters less than the design principle: every automated suggestion should remain inspectable.&lt;/p&gt;

&lt;p&gt;An evaluation harness turns that principle into an engineering practice. Prompts still matter, models still matter, and good UX still matters. But the durable quality signal comes from repeatable cases, explicit authority boundaries, evidence checks, and side-effect tests.&lt;/p&gt;

&lt;p&gt;If your finance agent cannot pass those tests, it does not need a more persuasive demo. It needs a better harness.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>fintech</category>
      <category>automation</category>
      <category>testing</category>
    </item>
    <item>
      <title>The Month-End Close Is a Dependency Graph, Not a Checklist</title>
      <dc:creator>Tali Adler</dc:creator>
      <pubDate>Mon, 21 Sep 2026 05:05:03 +0000</pubDate>
      <link>https://dev.to/tali_from_portali/the-month-end-close-is-a-dependency-graph-not-a-checklist-2ajj</link>
      <guid>https://dev.to/tali_from_portali/the-month-end-close-is-a-dependency-graph-not-a-checklist-2ajj</guid>
      <description>&lt;h1&gt;
  
  
  The Month-End Close Is a Dependency Graph, Not a Checklist
&lt;/h1&gt;

&lt;p&gt;Month-end close is often managed as a list of tasks: reconcile the bank, post accruals, review accounts receivable, run the trial balance, and sign off. Checklists are useful, but they hide the thing that makes close difficult: most tasks are not independent.&lt;/p&gt;

&lt;p&gt;A bank reconciliation can change the cash balance. That change can affect an accrual review, a covenant calculation, or the explanation attached to a management report. An unresolved invoice mismatch can block revenue recognition. A late payroll file can make an otherwise complete close provisional.&lt;/p&gt;

&lt;p&gt;The practical improvement is to model close as a dependency graph. Each work item has inputs, evidence, a decision, and downstream consumers. That sounds more technical than a checklist, but it makes the close easier to operate and easier to explain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with a close item contract
&lt;/h2&gt;

&lt;p&gt;For each close item, define a small contract instead of only assigning an owner. A useful contract contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; what accounting question is being answered?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inputs:&lt;/strong&gt; which ledger accounts, statements, exports, or schedules are required?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evidence:&lt;/strong&gt; which source files or system events support the result?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decision:&lt;/strong&gt; what did the reviewer conclude?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Downstream impact:&lt;/strong&gt; which reports or tasks depend on the result?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exception rule:&lt;/strong&gt; what prevents automatic completion?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, “reconcile operating bank account” is too vague to be a reliable unit of work. A stronger item says: compare the general-ledger cash balance with the bank statement for the period, link each reconciling item to evidence, classify timing differences separately from errors, and route unexplained differences above a threshold to review.&lt;/p&gt;

&lt;p&gt;This structure gives an engineer enough information to build a workflow and gives an accountant enough information to review the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Represent dependencies explicitly
&lt;/h2&gt;

&lt;p&gt;A close system does not need a complicated graph database to get started. A relational model can represent dependencies with a few tables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;close_period
  id, entity_id, period_end, status

close_item
  id, period_id, code, owner, state, materiality_threshold

close_evidence
  id, close_item_id, source_type, source_ref, content_hash, captured_at

close_dependency
  upstream_item_id, downstream_item_id, dependency_type

close_decision
  id, close_item_id, reviewer, outcome, rationale, decided_at
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important detail is that evidence and decisions are first-class records. A status such as &lt;code&gt;complete&lt;/code&gt; is not enough. Someone reviewing the close later should be able to see what was compared, which source supported it, and why an exception was accepted or cleared.&lt;/p&gt;

&lt;p&gt;A dependency should also carry meaning. “Blocks” is different from “informs.” A payroll accrual may block final payroll expense reporting, while a cash forecast update may only inform the management pack. Treating every relationship as a hard block creates unnecessary delays.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use states that reflect accounting reality
&lt;/h2&gt;

&lt;p&gt;Binary states encourage bad automation. A close item is rarely just open or done. Consider a state machine such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;not_started -&amp;gt; waiting_for_input -&amp;gt; ready_for_review
ready_for_review -&amp;gt; approved
ready_for_review -&amp;gt; exception
exception -&amp;gt; waiting_for_input
exception -&amp;gt; approved_with_rationale
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;approved_with_rationale&lt;/code&gt; state matters. It distinguishes a reviewed judgment from an accidentally ignored issue. An immaterial variance might be acceptable, but the system should preserve who made that decision, when they made it, and the rationale they recorded.&lt;/p&gt;

&lt;p&gt;Automation can safely move an item from &lt;code&gt;not_started&lt;/code&gt; to &lt;code&gt;waiting_for_input&lt;/code&gt; when a period opens, or from &lt;code&gt;waiting_for_input&lt;/code&gt; to &lt;code&gt;ready_for_review&lt;/code&gt; when all required evidence arrives. It should be much more cautious about moving an accounting item to &lt;code&gt;approved&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make evidence idempotent
&lt;/h2&gt;

&lt;p&gt;Close data often arrives more than once. A bank export may be re-uploaded, an integration may replay an event, or an operator may correct a file and submit it again. If the workflow blindly creates a new evidence record every time, reviewers get duplicate amounts and confusing histories.&lt;/p&gt;

&lt;p&gt;Give each source event an idempotency key. Depending on the source, that key could combine the provider name, account, statement period, source document identifier, and content hash. On ingestion:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Calculate the key.&lt;/li&gt;
&lt;li&gt;Check whether it already exists.&lt;/li&gt;
&lt;li&gt;Store the original event if it does not.&lt;/li&gt;
&lt;li&gt;Record a revision if the content changed.&lt;/li&gt;
&lt;li&gt;Never silently overwrite the evidence used for an earlier decision.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a familiar pattern in payment systems, but it is just as valuable in accounting operations. A close workflow should be repeatable without changing its answer merely because a connector delivered the same event twice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turn the dashboard into a review queue
&lt;/h2&gt;

&lt;p&gt;The most useful close dashboard is not the one with the most charts. It is the one that helps a reviewer answer, “What needs my judgment today?”&lt;/p&gt;

&lt;p&gt;Prioritize items by blocked dependents, materiality, age, and exception type. Show the source evidence next to the proposed result. Let the reviewer accept, reject, request more information, or approve with rationale. Keep automated matches visible, but do not bury unresolved exceptions beneath a percentage that says the account is “98% reconciled.”&lt;/p&gt;

&lt;p&gt;This is also where a tool such as Portali can fit naturally into an accounting workflow: not as another place to copy a checklist, but as a workspace for connecting evidence, proposed accounting work, and explicit review decisions. The implementation details will vary by team, but the principle is stable: the system should preserve the path from source to conclusion.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical rollout plan
&lt;/h2&gt;

&lt;p&gt;Start with one high-volume, low-judgment process, such as bank reconciliation or accounts payable matching. Map its inputs and downstream consumers. Add evidence links and explicit exception states before attempting sophisticated automation.&lt;/p&gt;

&lt;p&gt;Next, measure three things: time waiting for inputs, time spent investigating exceptions, and the number of post-close adjustments. Those measures tell you whether the workflow is improving the close, rather than simply moving work into a new interface.&lt;/p&gt;

&lt;p&gt;Finally, add dependencies one at a time. A good dependency graph is not a reason to prevent progress everywhere. It is a way to show exactly which unresolved question matters, who can answer it, and what becomes trustworthy once it is answered.&lt;/p&gt;

&lt;p&gt;Month-end close becomes more predictable when the process reflects how accounting decisions actually work. Checklists tell you what to remember. Dependency-aware workflows tell you what is ready, what is blocked, and why the final numbers can be trusted.&lt;/p&gt;

</description>
      <category>accounting</category>
      <category>automation</category>
      <category>fintech</category>
      <category>devops</category>
    </item>
    <item>
      <title>Mortgage Rates Are a Finance-Data Stress Test, Not Just a Headline</title>
      <dc:creator>Tali Adler</dc:creator>
      <pubDate>Sun, 20 Sep 2026 11:02:07 +0000</pubDate>
      <link>https://dev.to/tali_from_portali/mortgage-rates-are-a-finance-data-stress-test-not-just-a-headline-2jgh</link>
      <guid>https://dev.to/tali_from_portali/mortgage-rates-are-a-finance-data-stress-test-not-just-a-headline-2jgh</guid>
      <description>&lt;h1&gt;
  
  
  Mortgage Rates Are a Finance-Data Stress Test, Not Just a Headline
&lt;/h1&gt;

&lt;p&gt;A headline about mortgage rates averaging around 7% sounds like a consumer-finance story. For anyone building financial software, it is also a useful systems test. A change in borrowing costs affects forecasts, customer behavior, covenant calculations, cash planning, and the assumptions hidden inside models that were considered ‘stable’ last month.&lt;/p&gt;

&lt;p&gt;Recent rate coverage is a reminder that finance teams should not treat economic news as something that lives outside their accounting workflow. The difficult part is not reading the headline. It is turning a changing external fact into a traceable decision without silently rewriting history.&lt;/p&gt;

&lt;p&gt;This article presents a practical design for doing that. It is aimed at engineers and finance operators building automation around close, forecasting, and management reporting.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real problem is not the number
&lt;/h2&gt;

&lt;p&gt;Suppose a finance team sees a report that average mortgage rates are back around 7%. A spreadsheet user might update an assumption cell from &lt;code&gt;6.75%&lt;/code&gt; to &lt;code&gt;7.00%&lt;/code&gt; and move on. That creates several questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which source produced the new value?&lt;/li&gt;
&lt;li&gt;Was it an average rate, a quoted rate, or a particular product?&lt;/li&gt;
&lt;li&gt;What date and timezone apply?&lt;/li&gt;
&lt;li&gt;Which forecasts are allowed to use it?&lt;/li&gt;
&lt;li&gt;Which reports already used the old assumption?&lt;/li&gt;
&lt;li&gt;Who approved the change?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without those answers, the number is not really data. It is an untraceable edit. The same problem appears in smaller forms during month-end close: a vendor price change, a revised payment term, or a new bank fee can alter a forecast while leaving no useful explanation for the next reviewer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Model external news as an event
&lt;/h2&gt;

&lt;p&gt;A robust workflow should represent a news-derived input as an immutable event before it becomes an assumption. A minimal record might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"market_rate_observation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"metric"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"average_mortgage_rate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.07&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"unit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"decimal_rate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"observed_on"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-19"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://money.com/current-mortgage-rates/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Money"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"captured_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-20T08:00:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reported_average"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending_review"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important fields are not just &lt;code&gt;value&lt;/code&gt; and &lt;code&gt;metric&lt;/code&gt;. &lt;code&gt;source_url&lt;/code&gt;, capture time, interpretation, and review status are what make the event useful later. If the source changes or disappears, the workflow still has a record of what the team actually saw.&lt;/p&gt;

&lt;p&gt;Do not overwrite the previous observation. Append a new event and let downstream logic decide whether it is relevant. This makes comparisons possible and prevents a revised assumption from pretending it was always true.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate observation, proposal, and decision
&lt;/h2&gt;

&lt;p&gt;One of the safest patterns for financial automation is a three-stage pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Observation:&lt;/strong&gt; an external source reports a value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proposal:&lt;/strong&gt; a rule or agent explains which forecast or account may be affected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decision:&lt;/strong&gt; an authorized person accepts, edits, or rejects the proposal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An agent can be very good at the second stage. It can identify debt-sensitive expenses, compare the new observation with the assumption currently used, and calculate an approximate variance. It should not silently commit a material accounting or planning change merely because the arithmetic is straightforward.&lt;/p&gt;

&lt;p&gt;A proposal might say: “The observed rate is 25 basis points above the assumption used in the Q4 interest forecast. Recalculate scenarios A and B. No journal entry is suggested.” That is much safer than a vague alert saying “rates changed.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Make the calculation reproducible
&lt;/h2&gt;

&lt;p&gt;Every proposal should include the inputs and formula used. For a simple interest estimate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;annual_interest_delta = principal * (new_rate - old_rate)
period_delta = annual_interest_delta * days_in_period / 365
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system should preserve the principal value, both rates, the day-count convention, and the version of the model. A reviewer should be able to reproduce the result without trusting an opaque confidence score.&lt;/p&gt;

&lt;p&gt;This is also where idempotency matters. If the same article is ingested twice, it should not create two forecast adjustments. Give each observation a stable fingerprint based on the source, metric, observation date, and normalized value. Duplicate events can be linked to the original rather than processed again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design the review queue around exceptions
&lt;/h2&gt;

&lt;p&gt;Most finance teams do not need a person to approve every unchanged metric. They need attention directed toward meaningful exceptions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the change exceeds a configured basis-point threshold;&lt;/li&gt;
&lt;li&gt;the source is new or untrusted;&lt;/li&gt;
&lt;li&gt;the affected account is material;&lt;/li&gt;
&lt;li&gt;the proposed impact crosses a reporting boundary;&lt;/li&gt;
&lt;li&gt;two sources disagree;&lt;/li&gt;
&lt;li&gt;the system cannot determine whether the metric applies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A review queue should show the evidence, proposed impact, affected period, calculation, and available actions in one place. “Approve” should mean approve this specific proposal, not approve future changes forever.&lt;/p&gt;

&lt;p&gt;Tools such as Portali are useful in this part of the workflow because the goal is not simply to automate data entry. The goal is to connect source evidence to a proposed finance action and leave a reviewable trail when a human makes the final call.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical implementation checklist
&lt;/h2&gt;

&lt;p&gt;If you are adding this capability to an internal finance system, start small:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define an event schema for external observations.&lt;/li&gt;
&lt;li&gt;Store source evidence and capture timestamps.&lt;/li&gt;
&lt;li&gt;Keep observations immutable.&lt;/li&gt;
&lt;li&gt;Add a proposal layer with explicit formulas.&lt;/li&gt;
&lt;li&gt;Use stable fingerprints for deduplication.&lt;/li&gt;
&lt;li&gt;Route only material or ambiguous changes to review.&lt;/li&gt;
&lt;li&gt;Record the reviewer, decision, and decision time.&lt;/li&gt;
&lt;li&gt;Recalculate downstream reports from versioned inputs.&lt;/li&gt;
&lt;li&gt;Test late, duplicated, and contradictory source data.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The broader lesson from a mortgage-rate headline is not that every news item belongs in the ledger. It is that finance software needs a disciplined boundary between “the world changed,” “the system estimates an impact,” and “the business accepted a decision.” Keeping those stages separate makes automation faster to investigate, safer to operate, and much easier to explain during the next close.&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>finance</category>
      <category>accounting</category>
      <category>automation</category>
    </item>
    <item>
      <title>Don't Let the Agent Post the Journal Entry: Designing Approval Boundaries for Finance AI</title>
      <dc:creator>Tali Adler</dc:creator>
      <pubDate>Sun, 20 Sep 2026 05:03:42 +0000</pubDate>
      <link>https://dev.to/tali_from_portali/dont-let-the-agent-post-the-journal-entry-designing-approval-boundaries-for-finance-ai-2g1f</link>
      <guid>https://dev.to/tali_from_portali/dont-let-the-agent-post-the-journal-entry-designing-approval-boundaries-for-finance-ai-2g1f</guid>
      <description>&lt;h1&gt;
  
  
  Don't Let the Agent Post the Journal Entry: Designing Approval Boundaries for Finance AI
&lt;/h1&gt;

&lt;p&gt;AI agents are getting good at the parts of finance work that used to require a person to copy values between systems: finding invoices, matching transactions, explaining variances, and drafting reconciliations.&lt;/p&gt;

&lt;p&gt;That progress creates an awkward engineering question: &lt;strong&gt;where should an agent be allowed to act, and where should it only prepare a decision for a human?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In accounting workflows, the most useful answer is rarely “autonomous” or “manual.” It is a set of explicit approval boundaries backed by evidence, deterministic rules, and an audit trail.&lt;/p&gt;

&lt;p&gt;This article walks through a practical design for an agent-assisted close workflow. The examples use invoice and bank-transaction matching, but the same pattern applies to expense review, revenue operations, and fintech support workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with a proposal, not a side effect
&lt;/h2&gt;

&lt;p&gt;A dangerous agent tool looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ledger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createJournalEntry&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;6100&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;12840.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;March software expenses&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The call is easy to write, but it collapses several different decisions into one irreversible operation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which source records support the amount?&lt;/li&gt;
&lt;li&gt;Is the period open?&lt;/li&gt;
&lt;li&gt;Does the proposed account require approval?&lt;/li&gt;
&lt;li&gt;Has another worker already posted an entry?&lt;/li&gt;
&lt;li&gt;Who is accountable if the source data is incomplete?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead, make the agent produce a typed proposal first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;JournalProposal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;debit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;credit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;sourceIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;approvalState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;approved&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rejected&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The proposal is a durable object. It can be inspected, compared with previous proposals, approved, rejected, or regenerated. Posting is a separate command that accepts only an approved proposal ID.&lt;/p&gt;

&lt;p&gt;That separation is more important than the model you use. A better prompt cannot compensate for an API that lets an uncertain suggestion mutate the ledger directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build the evidence bundle before asking for a decision
&lt;/h2&gt;

&lt;p&gt;An agent should not return a confidence score without showing what produced it. For a transaction match, an evidence bundle might contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"transaction_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bank_8421"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"candidate_invoice_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"inv_1092"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"signals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"amount_match"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vendor_match"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"date_delta_days"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"currency_match"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"missing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source_links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"/bank/transactions/bank_8421"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"/ap/invoices/inv_1092"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model can summarize this bundle in plain language, but the application should calculate critical facts itself. Amount equality, period status, duplicate detection, and debit-credit balance are poor candidates for free-form model judgment.&lt;/p&gt;

&lt;p&gt;A useful rule is: &lt;strong&gt;let the model interpret evidence, but let deterministic code establish the invariants.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This also makes review faster. A reviewer should be able to answer “why is this proposed?” without opening six unrelated tabs or trusting a paragraph generated from hidden context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use risk tiers instead of one global confidence threshold
&lt;/h2&gt;

&lt;p&gt;A 98% match confidence does not mean the same thing for every action. Posting a small recurring software invoice is different from changing a revenue account or closing a period.&lt;/p&gt;

&lt;p&gt;Define risk using business attributes, not only model output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;requiredApproval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proposal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JournalProposal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;periodClosed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blocked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proposal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;senior_review&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isRevenueAccount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;accounting_review&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;accounting_review&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proposal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.98&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auto_approve_eligible&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;standard_review&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;“Auto-approve eligible” still does not have to mean “post immediately.” It can mean the proposal enters a queue where a policy engine, rather than a language model, performs the final check. If your organization is not ready for that, every tier can remain human-approved while the workflow still saves preparation time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make tools narrow, typed, and observable
&lt;/h2&gt;

&lt;p&gt;Agent tool design is security design. Prefer several small tools over one privileged “do finance” function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;search_source_records(filters)&lt;/code&gt; returns read-only records.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;create_reconciliation_proposal(input)&lt;/code&gt; stores a proposal.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;request_approval(proposalId)&lt;/code&gt; changes workflow state.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;post_approved_proposal(proposalId, idempotencyKey)&lt;/code&gt; performs the side effect.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;record_review(proposalId, decision, reason)&lt;/code&gt; stores human reasoning.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every tool call should log the actor, timestamp, input references, output references, and authorization result. Do not log raw credentials or entire documents by default. Store stable IDs and links to the source system instead.&lt;/p&gt;

&lt;p&gt;The posting tool also needs idempotency. A worker may time out after the ledger accepts a request, then retry. The idempotency key should be derived from the proposal and posting operation, not generated afresh on every attempt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`post:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;proposal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:v&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;proposal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ledger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postApprovedProposal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proposal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;idempotencyKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without this, “reliable retry” can become duplicate accounting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat the exception queue as a product surface
&lt;/h2&gt;

&lt;p&gt;The workflow is not successful because an agent produced a high number of matches. It is successful when people can resolve the uncertain remainder quickly and understand why those items were routed to them.&lt;/p&gt;

&lt;p&gt;An exception should include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The proposed action.&lt;/li&gt;
&lt;li&gt;The evidence used.&lt;/li&gt;
&lt;li&gt;The exact rule or missing data that blocked automation.&lt;/li&gt;
&lt;li&gt;Suggested next actions.&lt;/li&gt;
&lt;li&gt;A place to record the final decision.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That last piece matters. “Rejected” is less useful than “rejected because the invoice belongs to the prior period.” Review decisions become feedback for rules, reporting, and future agent evaluations.&lt;/p&gt;

&lt;p&gt;At Portali, this is the practical distinction between adding an AI chat box to accounting software and building an evidence-linked workflow. The interface can stay simple, but every suggestion should lead back to its source records and its review state. More context is available at &lt;a href="https://portali.tech" rel="noopener noreferrer"&gt;portali.tech&lt;/a&gt;, but the architectural principle stands independently of any product: keep the decision visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure the boundary, not just the model
&lt;/h2&gt;

&lt;p&gt;Track metrics that tell you whether the approval design is working:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Proposal acceptance rate by workflow and risk tier.&lt;/li&gt;
&lt;li&gt;Percentage of proposals with complete source evidence.&lt;/li&gt;
&lt;li&gt;Average time from exception creation to resolution.&lt;/li&gt;
&lt;li&gt;Duplicate or reversed postings.&lt;/li&gt;
&lt;li&gt;Human edits between proposal and approval.&lt;/li&gt;
&lt;li&gt;Reasons for rejection and escalation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A model benchmark may improve while the accounting workflow gets worse. For example, a more confident model could increase acceptance while hiding a rise in period errors. Operational metrics expose that tradeoff.&lt;/p&gt;

&lt;h2&gt;
  
  
  A safer definition of autonomy
&lt;/h2&gt;

&lt;p&gt;For finance agents, autonomy should mean fewer repetitive decisions for people, not fewer people in the control loop. The durable pattern is straightforward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read source systems through narrow, read-only tools.&lt;/li&gt;
&lt;li&gt;Produce an evidence-linked proposal.&lt;/li&gt;
&lt;li&gt;Validate invariants with deterministic code.&lt;/li&gt;
&lt;li&gt;Route the proposal according to explicit risk policy.&lt;/li&gt;
&lt;li&gt;Require approval before consequential side effects.&lt;/li&gt;
&lt;li&gt;Post with idempotency and a complete audit trail.&lt;/li&gt;
&lt;li&gt;Learn from review outcomes without silently changing policy.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That design lets an agent move quickly without making the ledger mysterious. The best finance automation is not the system that acts most often. It is the system that makes safe action obvious, risky action deliberate, and every decision explainable after the close is over.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>fintech</category>
      <category>accounting</category>
      <category>automation</category>
    </item>
    <item>
      <title>The Accounting Feature That Matters Most: Turning Evidence Into a Reviewable Workflow</title>
      <dc:creator>Tali Adler</dc:creator>
      <pubDate>Sat, 19 Sep 2026 05:02:10 +0000</pubDate>
      <link>https://dev.to/tali_from_portali/the-accounting-feature-that-matters-most-turning-evidence-into-a-reviewable-workflow-pfe</link>
      <guid>https://dev.to/tali_from_portali/the-accounting-feature-that-matters-most-turning-evidence-into-a-reviewable-workflow-pfe</guid>
      <description>&lt;h1&gt;
  
  
  The Accounting Feature That Matters Most: Turning Evidence Into a Reviewable Workflow
&lt;/h1&gt;

&lt;p&gt;Most accounting teams do not have a data problem. They have a decision problem.&lt;/p&gt;

&lt;p&gt;The invoice is somewhere. The bank transaction exists. A prior-period journal entry is available. The real work is figuring out whether those pieces belong together, what should happen next, and how another person can understand the decision later.&lt;/p&gt;

&lt;p&gt;That is why one of the most useful capabilities in a finance platform is not another dashboard. It is an evidence-linked workflow: a way to connect source material, proposed accounting treatment, and human review without turning the close into a black box.&lt;/p&gt;

&lt;p&gt;Portali’s source-linked workflow is designed around that problem. The idea is simple: every accounting action should carry enough context to answer three questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What evidence led to this proposal?&lt;/li&gt;
&lt;li&gt;What decision was made?&lt;/li&gt;
&lt;li&gt;What still needs a person’s attention?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why a normal task list is not enough
&lt;/h2&gt;

&lt;p&gt;A task called “reconcile software expense” tells you almost nothing. It does not say which transactions are included, which contract or invoice was used, whether the amount changed from last month, or why the reviewer approved the treatment.&lt;/p&gt;

&lt;p&gt;A task list records activity. An evidence-linked workflow records reasoning.&lt;/p&gt;

&lt;p&gt;That distinction becomes important as soon as a close has exceptions. A recurring vendor may suddenly bill for implementation services. A payment may be split across entities. A transaction may look like a duplicate but actually be a renewal. These cases cannot be safely handled by matching text alone.&lt;/p&gt;

&lt;p&gt;The workflow should make the normal path fast while making the uncertain path visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  The capability in practice
&lt;/h2&gt;

&lt;p&gt;Imagine a month-end review for a cloud infrastructure vendor.&lt;/p&gt;

&lt;p&gt;A useful workflow can collect the relevant bank transaction, the invoice, the prior-period treatment, and the account history into one review item. It can then propose a classification, show the confidence or matching signals behind that proposal, and leave the reviewer with an explicit choice: approve, edit, reject, or request more evidence.&lt;/p&gt;

&lt;p&gt;The important part is not that software made a suggestion. The important part is that the suggestion remains attached to its supporting material and final decision.&lt;/p&gt;

&lt;p&gt;A practical review item might contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Vendor: Example Cloud Services
Period: August 2026
Amount: $4,820.00
Proposed account: Hosting expense
Evidence: bank transaction, invoice, July posting
Reason: recurring vendor and consistent description
Reviewer action: approved with split between hosting and implementation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is much more useful than a green “matched” badge. It gives the next reviewer a compact explanation instead of forcing them to reconstruct the investigation from five systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design the happy path and the exception path separately
&lt;/h2&gt;

&lt;p&gt;A common automation mistake is treating every record as if it deserves the same level of friction. It does not.&lt;/p&gt;

&lt;p&gt;For predictable recurring items, the workflow can use prior decisions and stable evidence to reduce manual work. For unusual amounts, new vendors, missing documents, or changes in description, it should route the item to a review queue.&lt;/p&gt;

&lt;p&gt;That queue is not a failure state. It is where the system protects the ledger from false certainty.&lt;/p&gt;

&lt;p&gt;A good exception item should answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What made this item unusual?&lt;/li&gt;
&lt;li&gt;Which evidence is missing or conflicting?&lt;/li&gt;
&lt;li&gt;What is the safest next action?&lt;/li&gt;
&lt;li&gt;Who owns the decision?&lt;/li&gt;
&lt;li&gt;Can the decision be reused next period?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Capturing the answer matters. If a reviewer explains that a vendor’s annual renewal includes a one-time setup fee, that explanation can become useful context for the next close instead of disappearing into a chat thread.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make automation reversible
&lt;/h2&gt;

&lt;p&gt;Finance workflows need an audit trail, but they also need operational safety. A proposed classification should not silently become an irreversible posting just because a model was confident.&lt;/p&gt;

&lt;p&gt;A safer pattern is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Gather evidence.&lt;/li&gt;
&lt;li&gt;Generate a proposal.&lt;/li&gt;
&lt;li&gt;Check policy and exceptions.&lt;/li&gt;
&lt;li&gt;Request approval when needed.&lt;/li&gt;
&lt;li&gt;Apply the approved action.&lt;/li&gt;
&lt;li&gt;Preserve the evidence and decision together.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This structure makes it possible to retry a failed step without duplicating a posting. It also lets a reviewer correct an earlier proposal without losing the original context.&lt;/p&gt;

&lt;p&gt;In Portali, the value of the workflow is therefore less about replacing accounting judgment and more about giving judgment a reliable place to happen. The platform can help organize evidence and surface patterns, while the accountable person remains visible in the approval path.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small implementation checklist
&lt;/h2&gt;

&lt;p&gt;Whether you are building this internally or evaluating a finance tool, start with one narrow workflow, such as recurring vendor expense review.&lt;/p&gt;

&lt;p&gt;Check that it can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Link a proposal to its source documents and transactions.&lt;/li&gt;
&lt;li&gt;Show the reason for a match or classification.&lt;/li&gt;
&lt;li&gt;Separate automatic approvals from human review.&lt;/li&gt;
&lt;li&gt;Record edits, approvals, and rejected proposals.&lt;/li&gt;
&lt;li&gt;Preserve an idempotent reference for any downstream posting.&lt;/li&gt;
&lt;li&gt;Reuse approved context without hiding new exceptions.&lt;/li&gt;
&lt;li&gt;Export a readable explanation for audit or handoff.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of these are missing, the system may still save clicks, but it will not necessarily make the close easier to trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real feature is explainability
&lt;/h2&gt;

&lt;p&gt;Accounting teams do not need automation that merely looks finished. They need workflows that make finished work defensible.&lt;/p&gt;

&lt;p&gt;That is the promise of an evidence-linked accounting workflow: fewer searches, clearer exceptions, safer automation, and decisions that remain understandable after the person who made them has moved on.&lt;/p&gt;

&lt;p&gt;Portali’s approach is a useful reminder that a finance product’s most valuable feature may be the connective tissue between a source, a proposal, and a decision. When that connection is designed well, month-end becomes less about chasing context and more about reviewing the work that actually deserves attention.&lt;/p&gt;

&lt;p&gt;You can explore that kind of workflow at &lt;a href="https://portali.tech" rel="noopener noreferrer"&gt;portali.tech&lt;/a&gt;. The point is not to automate judgment away. It is to give judgment better evidence, better boundaries, and a durable record.&lt;/p&gt;

</description>
      <category>accounting</category>
      <category>fintech</category>
      <category>automation</category>
      <category>ai</category>
    </item>
    <item>
      <title>The Automation Gap Is a Finance Workflow Problem, Not a Spreadsheet Problem</title>
      <dc:creator>Tali Adler</dc:creator>
      <pubDate>Sat, 19 Sep 2026 03:02:23 +0000</pubDate>
      <link>https://dev.to/tali_from_portali/the-automation-gap-is-a-finance-workflow-problem-not-a-spreadsheet-problem-55n6</link>
      <guid>https://dev.to/tali_from_portali/the-automation-gap-is-a-finance-workflow-problem-not-a-spreadsheet-problem-55n6</guid>
      <description>&lt;p&gt;Recent fintech research has put a useful number on an old frustration: UK businesses are still losing several days a month to manual finance administration. The headline is easy to interpret as a spreadsheet indictment. In practice, spreadsheets are rarely the root cause. The deeper problem is that finance work is a chain of handoffs, exceptions, approvals, and evidence checks that no single system models well.&lt;/p&gt;

&lt;p&gt;That distinction matters to engineers building financial products. Replacing a spreadsheet with a dashboard does not remove the work. It often just moves the same reconciliation, chasing, and review tasks into a prettier interface. The better target is the workflow around the number.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hidden cost is coordination
&lt;/h2&gt;

&lt;p&gt;Consider a routine supplier payment review. Someone downloads a bank statement, someone else checks an invoice, a third person asks whether the purchase was approved, and a manager reviews an exception in a chat thread. The final accounting entry may take seconds. The surrounding coordination can consume hours.&lt;/p&gt;

&lt;p&gt;This is why “automation rate” is a weak metric on its own. A process can automatically import 98% of transactions and still feel manual if the remaining 2% are ambiguous, high-value, or impossible to explain later. Those cases create queues, duplicate questions, and last-minute close pressure.&lt;/p&gt;

&lt;p&gt;A useful finance workflow should answer four questions for every material decision:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What source records were considered?&lt;/li&gt;
&lt;li&gt;What rule or model produced the proposal?&lt;/li&gt;
&lt;li&gt;Who reviewed or changed it?&lt;/li&gt;
&lt;li&gt;What should happen if the same event arrives again?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The fourth question is the engineering detail that gets missed most often. Financial integrations retry. Webhooks arrive out of order. A bank feed may restate a transaction. Without idempotency and a stable event identity, “automation” can create duplicate work or duplicate entries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design the exception path first
&lt;/h2&gt;

&lt;p&gt;A common implementation pattern is to optimize the happy path and add an exception screen later. For finance, reverse that order. Start by defining what an operator needs when the system is uncertain.&lt;/p&gt;

&lt;p&gt;An exception record might contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bank_2026_09_19_004821"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1840.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"currency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GBP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"candidate_account"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"software_expense"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.71&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"evidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"bank:004821"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"invoice:INV-8821"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Vendor changed legal name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"needs_review"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important fields are not decorative metadata. &lt;code&gt;event_id&lt;/code&gt; supports deduplication. &lt;code&gt;evidence&lt;/code&gt; lets a reviewer inspect the underlying facts. &lt;code&gt;reason&lt;/code&gt; tells the next person why the system stopped. &lt;code&gt;state&lt;/code&gt; makes ownership and queue behavior explicit.&lt;/p&gt;

&lt;p&gt;A reviewer should be able to accept the proposal, edit it, reject it, or request more evidence. Each action should append an event rather than silently overwrite history. That gives the finance team a usable audit trail and gives engineers a reproducible way to debug production behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep automation proposals separate from accounting decisions
&lt;/h2&gt;

&lt;p&gt;AI and rules engines are good at producing candidates. They are less useful when their suggestions are treated as invisible truth. A practical architecture separates three layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Observed facts:&lt;/strong&gt; imported transactions, invoices, contracts, and timestamps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proposed interpretation:&lt;/strong&gt; a suggested match, category, accrual, or anomaly flag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accepted decision:&lt;/strong&gt; the reviewed result that affects the ledger or reporting output.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation makes it possible to improve a model without rewriting the company’s history. It also lets a controller ask a precise question: “What did the system suggest on Tuesday, and why did we override it?”&lt;/p&gt;

&lt;p&gt;Products such as Portali are interesting in this context because the valuable feature is not merely importing finance data. The useful capability is tying a proposed action to its source evidence and its review state, so an operator can move from “something needs attention” to “here is the decision and why it is safe.” That is a workflow improvement, not a sales promise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure minutes returned to the team
&lt;/h2&gt;

&lt;p&gt;If a finance automation project is working, measure more than straight-through processing. Track:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;median time from exception creation to resolution&lt;/li&gt;
&lt;li&gt;percentage of exceptions with complete source evidence&lt;/li&gt;
&lt;li&gt;duplicate events prevented by idempotency&lt;/li&gt;
&lt;li&gt;number of follow-up messages per close item&lt;/li&gt;
&lt;li&gt;percentage of accepted proposals later reversed&lt;/li&gt;
&lt;li&gt;time spent preparing explanations for reviewers or auditors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These metrics expose whether the system is actually reducing coordination. A lower message count and faster exception resolution may be more valuable than another percentage point of automatic categorization.&lt;/p&gt;

&lt;h2&gt;
  
  
  The practical takeaway
&lt;/h2&gt;

&lt;p&gt;The current automation gap is not proof that finance teams need one more generic dashboard. It is evidence that financial work needs better representations of uncertainty, ownership, evidence, and decisions.&lt;/p&gt;

&lt;p&gt;For engineers, that means treating the exception queue as a first-class product surface, designing for retries from day one, and preserving the difference between a machine proposal and a human-approved accounting outcome. For finance teams, it means asking vendors to demonstrate the review path, not just the import flow.&lt;/p&gt;

&lt;p&gt;The spreadsheet is often where the symptoms become visible. The real opportunity is to build a system where every important number has a source, every uncertain interpretation has an owner, and every decision can be explained without reconstructing a week of chat history.&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>accounting</category>
      <category>automation</category>
      <category>ai</category>
    </item>
    <item>
      <title>A Better Month-End Starts With Evidence, Not More Checklists</title>
      <dc:creator>Tali Adler</dc:creator>
      <pubDate>Fri, 18 Sep 2026 23:01:34 +0000</pubDate>
      <link>https://dev.to/tali_from_portali/a-better-month-end-starts-with-evidence-not-more-checklists-3d91</link>
      <guid>https://dev.to/tali_from_portali/a-better-month-end-starts-with-evidence-not-more-checklists-3d91</guid>
      <description>&lt;h1&gt;
  
  
  A Better Month-End Starts With Evidence, Not More Checklists
&lt;/h1&gt;

&lt;p&gt;Month-end close rarely breaks because a team forgot that reconciliation exists. It breaks because the team cannot answer a smaller, more important question quickly:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What evidence supports this number, and what decision did we make about it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question is where accounting practice, workflow design, and product engineering meet. A close process can have a hundred checklist items and still leave reviewers hunting through email, spreadsheets, exports, and chat threads. The problem is not a lack of tasks. It is a lack of context attached to each task.&lt;/p&gt;

&lt;p&gt;This article walks through a practical pattern for building an evidence-first close workflow. The example is a recurring bank reconciliation, but the same design works for accruals, prepaid expenses, revenue cutoffs, and intercompany balances.&lt;/p&gt;

&lt;h2&gt;
  
  
  The checklist is not the unit of work
&lt;/h2&gt;

&lt;p&gt;A typical close checklist might say:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reconcile operating account&lt;/li&gt;
&lt;li&gt;Review outstanding items&lt;/li&gt;
&lt;li&gt;Post adjusting entries&lt;/li&gt;
&lt;li&gt;Obtain approval&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are useful milestones, but they are poor data structures. They do not tell the next person which statement was used, which period was covered, why an item was left open, or whether the proposed journal entry is still valid.&lt;/p&gt;

&lt;p&gt;A more useful unit is an &lt;strong&gt;accounting decision&lt;/strong&gt; with four parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Scope:&lt;/strong&gt; account, entity, and period.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evidence:&lt;/strong&gt; the source document, transaction set, or report.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decision:&lt;/strong&gt; cleared, accrued, reclassified, deferred, or left open.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reason:&lt;/strong&gt; a short explanation that another reviewer can understand.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once those fields exist, the checklist becomes a view over structured work instead of the place where all context goes to disappear.&lt;/p&gt;

&lt;h2&gt;
  
  
  A concrete workflow for one reconciliation
&lt;/h2&gt;

&lt;p&gt;Suppose the bank statement shows a $12,400 difference from the general ledger. An evidence-first workflow should not jump directly to “investigate variance.” It should create a review item containing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"account"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1010 Operating Cash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"period"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-08"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"difference"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"bank_statement_2026_08.pdf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gl_detail_2026_08.csv"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"proposed_action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"review"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"open"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system can then group likely causes: deposits in transit, outstanding checks, bank fees, timing differences, or coding errors. Automation is helpful here, but it should produce a proposal, not pretend that a pattern match is an accounting conclusion.&lt;/p&gt;

&lt;p&gt;A reviewer might accept a $9,800 deposit in transit, identify a $2,400 bank fee, and reject a suggested reclassification for the remaining $200. Each outcome should remain attached to the same evidence bundle. That gives the close a durable trail: what was observed, what was proposed, what changed, and who accepted the decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design the exception path first
&lt;/h2&gt;

&lt;p&gt;The happy path is easy to demo. The exception path is what determines whether a finance workflow earns trust.&lt;/p&gt;

&lt;p&gt;For every automated suggestion, define at least three outcomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Accept:&lt;/strong&gt; the evidence is sufficient and the proposed treatment is correct.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edit:&lt;/strong&gt; the suggestion is useful, but an amount, account, or explanation needs changing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reject and explain:&lt;/strong&gt; the suggestion is not appropriate, with a reason that improves future review.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is more useful than a binary approved/rejected flag. It also makes metrics meaningful. You can measure how often proposals are accepted unchanged, how often they need edits, and which source types create the most review work. Those measurements tell you where to improve mappings and controls.&lt;/p&gt;

&lt;p&gt;In a tool such as portali.tech, the valuable feature is not simply that a document can be uploaded or a task can be assigned. It is the connection between source evidence, proposed treatment, and explicit human review. That connection reduces the time spent reconstructing history when a controller asks, “Why did we book this?”&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep automation idempotent
&lt;/h2&gt;

&lt;p&gt;Close workflows are often rerun. A bank feed may refresh, a file may be uploaded twice, or a reviewer may reopen a period after a correction. If each run creates a new journal proposal, the system quickly becomes noisy and unsafe.&lt;/p&gt;

&lt;p&gt;Use a stable key for each proposed item, such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;company + account + period + source_transaction_id + rule_version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On rerun:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;update an existing open proposal when the source is unchanged;&lt;/li&gt;
&lt;li&gt;create a new revision when the source or rule version changes;&lt;/li&gt;
&lt;li&gt;never silently overwrite an accepted decision;&lt;/li&gt;
&lt;li&gt;preserve the previous explanation when a new reviewer takes over.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is ordinary application engineering, but it has an accounting consequence: reproducibility. A reviewer should be able to see why the system showed a different proposal yesterday without guessing which process ran in the background.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make the review queue useful
&lt;/h2&gt;

&lt;p&gt;A queue sorted only by creation time is not a close workflow. Prioritize by risk and aging. A simple score can combine materiality, days outstanding, account sensitivity, and confidence in the proposed match:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;priority = materiality_weight
         + aging_weight
         + sensitivity_weight
         - confidence_weight
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact formula is less important than making it visible and adjustable. A $200 item in a high-risk revenue account may deserve attention before a $5,000 routine timing difference in cash.&lt;/p&gt;

&lt;p&gt;The queue should also show the reviewer what they need without another search: the evidence links, the proposed entry, the matching transactions, prior decisions for similar items, and the next action. Good workflow design removes navigation, not judgment.&lt;/p&gt;

&lt;h2&gt;
  
  
  A close that can explain itself
&lt;/h2&gt;

&lt;p&gt;The strongest month-end process is not the one with the most automation. It is the one that can explain each material number with less manual archaeology.&lt;/p&gt;

&lt;p&gt;Start small: choose one account, capture the evidence and decision fields, add accept/edit/reject outcomes, and make reruns safe. Then measure review time and recurring exception types before expanding to another account.&lt;/p&gt;

&lt;p&gt;Checklists still matter. They tell the team what should happen. Evidence-linked decisions tell the team what actually happened. That distinction is the difference between a close that merely reaches a deadline and a close that remains understandable after the people who performed it have moved on.&lt;/p&gt;

</description>
      <category>accounting</category>
      <category>automation</category>
      <category>fintech</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The Close Starts With a Question: Building Source-Linked Accounting Workflows</title>
      <dc:creator>Tali Adler</dc:creator>
      <pubDate>Fri, 18 Sep 2026 21:05:27 +0000</pubDate>
      <link>https://dev.to/tali_from_portali/the-close-starts-with-a-question-building-source-linked-accounting-workflows-13f0</link>
      <guid>https://dev.to/tali_from_portali/the-close-starts-with-a-question-building-source-linked-accounting-workflows-13f0</guid>
      <description>&lt;h1&gt;
  
  
  The close starts with a question: building source-linked accounting workflows
&lt;/h1&gt;

&lt;p&gt;Month-end close rarely breaks because someone cannot add two numbers. It breaks because a number arrives without enough context. A balance changed, a payment was matched, or an accrual was posted, and three days later nobody can answer a simple question: &lt;strong&gt;what evidence supports this?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That question is where accounting software and engineering software increasingly meet. The useful automation is not just a bot that creates journal entries. It is a workflow that keeps the source, decision, reviewer, and final output connected.&lt;/p&gt;

&lt;p&gt;This article walks through that pattern using a common pain point: reconciling a high-volume account when the underlying transactions come from several systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hidden cost of an unlinked reconciliation
&lt;/h2&gt;

&lt;p&gt;Imagine a reconciliation ending with this row:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Account: Operating cash
Period: August 2026
Difference: $18,420.00
Status: Resolved
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The row looks finished, but it is not very useful. Resolved by whom? Which bank statement line was involved? Was the difference a timing item, a duplicate, or a manual adjustment? Is there a supporting document? Can another reviewer reproduce the conclusion?&lt;/p&gt;

&lt;p&gt;When that context lives in email, spreadsheets, and chat, every review becomes archaeology. The team may still close on time, but the process gets slower and riskier each month.&lt;/p&gt;

&lt;p&gt;A better design treats every material accounting decision as an object with a small audit trail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"account"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Operating cash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"period"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-08"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;18420.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source_refs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"bank:stmt-2026-08-31"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"erp:batch-8841"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"proposed_reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Timing difference"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.87&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reviewer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important fields are not fancy. They make the work inspectable.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical pattern: source, proposal, decision
&lt;/h2&gt;

&lt;p&gt;The most useful workflow I have seen separates three stages.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Source
&lt;/h3&gt;

&lt;p&gt;First, preserve the inputs exactly as received. Store the statement line, ledger transaction, invoice, payment record, or API response with a stable reference. Do not overwrite the original value when normalizing it. Keep both the raw representation and the fields used for matching.&lt;/p&gt;

&lt;p&gt;This is the accounting equivalent of immutable event data. If a parser improves next month, you can reprocess the original input rather than trying to reconstruct it from a spreadsheet.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Proposal
&lt;/h3&gt;

&lt;p&gt;Next, let rules or an AI-assisted process propose a match or explanation. A proposal should include the reasoning signals, not just a label. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;amount matches within a defined tolerance&lt;/li&gt;
&lt;li&gt;transaction dates are within five business days&lt;/li&gt;
&lt;li&gt;counterparty names normalize to the same vendor&lt;/li&gt;
&lt;li&gt;a related invoice is already approved&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A proposal is not a posting. That distinction matters. It gives the system permission to be helpful without giving it permission to silently change the books.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Decision
&lt;/h3&gt;

&lt;p&gt;Finally, a person or an explicit policy makes the decision. Record who approved it, when, what changed, and which evidence they reviewed. If the proposal was rejected, preserve that rejection too. Negative decisions are valuable training data and valuable audit evidence.&lt;/p&gt;

&lt;p&gt;This model also makes idempotency easier. A retry can safely regenerate a proposal because the decision is a separate state transition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Portali fits
&lt;/h2&gt;

&lt;p&gt;A feature spotlight for portali.tech is its source-linked way of organizing accounting work around the item that needs a decision, rather than around a collection of disconnected files. The practical benefit is small but important: a reviewer can move from a flagged transaction to the supporting context without asking someone to find an attachment or explain which spreadsheet tab is current.&lt;/p&gt;

&lt;p&gt;That is especially useful for teams that have outgrown manual checklists but are not ready to replace every system of record. The accounting platform can remain the place where entries are posted. The workflow layer can make the path to that entry visible and reviewable.&lt;/p&gt;

&lt;p&gt;The design principle is worth borrowing even if you build the tooling yourself: automate the gathering and comparison of evidence, but keep the accounting decision explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation details that prevent future pain
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use stable identifiers
&lt;/h3&gt;

&lt;p&gt;Display names change. Vendor names are corrected. Bank descriptions are inconsistent. Match on stable source IDs whenever possible, and keep a human-readable label only for display.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make transitions append-only
&lt;/h3&gt;

&lt;p&gt;Instead of changing &lt;code&gt;pending&lt;/code&gt; to &lt;code&gt;approved&lt;/code&gt; with no history, append a decision event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"work_item"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"recon-18420"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"approved"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"actor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"j.smith"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-01T14:32:11Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"note"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bank settlement posted one day after period end"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Append-only history is easier to audit and easier to debug than a single mutable status field.&lt;/p&gt;

&lt;h3&gt;
  
  
  Put limits around automation
&lt;/h3&gt;

&lt;p&gt;Define thresholds before turning on auto-approval. For example, auto-match only when the amount, currency, source account, and counterparty all agree. Route anything outside that policy to review. An AI suggestion can improve prioritization, but it should not quietly expand the policy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Measure review quality, not only speed
&lt;/h3&gt;

&lt;p&gt;Track the percentage of items resolved without rework, the age of open exceptions, the number of proposals rejected, and the time from source arrival to approved decision. A faster close with more unexplained adjustments is not an improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  The payoff
&lt;/h2&gt;

&lt;p&gt;Source-linked workflows change the close from a race to collect screenshots into a sequence of explainable decisions. Engineers get clear state transitions and retry behavior. Accountants get evidence in the place where the question is being answered. Managers get a better view of what is truly complete.&lt;/p&gt;

&lt;p&gt;The best accounting automation is not the system that removes every human touch. It is the system that makes each remaining human touch focused, informed, and easy to verify.&lt;/p&gt;

</description>
      <category>accounting</category>
      <category>automation</category>
      <category>fintech</category>
      <category>ai</category>
    </item>
    <item>
      <title>The Fed Just Moved Rates. Your Finance Automation Needs a Better Event Model.</title>
      <dc:creator>Tali Adler</dc:creator>
      <pubDate>Fri, 18 Sep 2026 19:01:00 +0000</pubDate>
      <link>https://dev.to/tali_from_portali/the-fed-just-moved-rates-your-finance-automation-needs-a-better-event-model-4f5f</link>
      <guid>https://dev.to/tali_from_portali/the-fed-just-moved-rates-your-finance-automation-needs-a-better-event-model-4f5f</guid>
      <description>&lt;h1&gt;
  
  
  The Fed Just Moved Rates. Your Finance Automation Needs a Better Event Model.
&lt;/h1&gt;

&lt;p&gt;A rate decision is usually discussed as a macroeconomic event: the central bank changes its target range, markets reprice, and businesses revisit forecasts.&lt;/p&gt;

&lt;p&gt;For finance and accounting systems, it is also an operational event.&lt;/p&gt;

&lt;p&gt;On September 16, 2026, the Federal Reserve raised its benchmark target range by 25 basis points to 3.75%–4%, according to reporting from CNBC. The interesting engineering question is not whether a company should predict the next move. It is how software should turn a public rate change into a controlled, reviewable set of accounting and finance actions.&lt;/p&gt;

&lt;p&gt;That distinction matters. A spreadsheet can absorb a new assumption in seconds. A production finance workflow has to answer harder questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which instruments and schedules are actually affected?&lt;/li&gt;
&lt;li&gt;Which rate source was used, and when was it retrieved?&lt;/li&gt;
&lt;li&gt;Is the new value an observed fact, an approved assumption, or a forecast?&lt;/li&gt;
&lt;li&gt;Which journal entries, disclosures, and cash forecasts need review?&lt;/li&gt;
&lt;li&gt;Can another person reconstruct the decision three months later?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where event-driven design meets accounting discipline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat the announcement as an immutable event
&lt;/h2&gt;

&lt;p&gt;The first mistake is overwriting a setting such as &lt;code&gt;base_rate = 4.00&lt;/code&gt;. That destroys context. Instead, store the announcement as an immutable event with enough metadata to reproduce the calculation.&lt;/p&gt;

&lt;p&gt;A minimal event might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"central_bank_rate_decision"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"effective_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"announced_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-16T18:00:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"jurisdiction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"US"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"target_lower_bound"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3.75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"target_upper_bound"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"unit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"percent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.federalreserve.gov/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source_retrieved_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-18T08:15:00Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The event is a fact. A company’s selected discount rate, borrowing forecast, or cash-planning assumption is a separate object derived from that fact. Keeping those layers separate prevents an automation from presenting a judgment call as if it came directly from the Fed.&lt;/p&gt;

&lt;p&gt;It also makes corrections safer. If the source parser was wrong, you can invalidate or supersede one event without rewriting every downstream record.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build a dependency graph, not a giant “recalculate” button
&lt;/h2&gt;

&lt;p&gt;A rate change rarely affects everything. It affects specific contracts, accounts, models, and reporting outputs.&lt;/p&gt;

&lt;p&gt;Model those relationships explicitly. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rate decision
  -&amp;gt; variable-rate credit facility
      -&amp;gt; next interest accrual
      -&amp;gt; cash forecast
      -&amp;gt; covenant dashboard
  -&amp;gt; lease or valuation model
      -&amp;gt; discount-rate review task
  -&amp;gt; treasury report
      -&amp;gt; management commentary draft
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each edge should carry a rule and an owner. A variable-rate loan may be eligible for automatic recalculation because its contract says SOFR plus a fixed spread. A valuation model may only create a review task because the discount rate is a policy decision, not a mechanical pass-through.&lt;/p&gt;

&lt;p&gt;This design gives you a useful middle ground between manual work and reckless automation: calculate what is deterministic, route what requires judgment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate calculation from approval
&lt;/h2&gt;

&lt;p&gt;A reliable workflow should produce a proposed result before it posts anything consequential.&lt;/p&gt;

&lt;p&gt;For an interest accrual, the calculation service can produce:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;principal: 2,000,000
spread: 2.25%
reference rate: 4.00%
annualized rate: 6.25%
days in period: 30
proposed interest: 10,274.00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The approval layer then checks the contract, day-count convention, effective date, and materiality threshold. If the result passes policy, it can be posted automatically. If not, the system creates an exception with the inputs attached.&lt;/p&gt;

&lt;p&gt;This is more than a control requirement. It is a debugging strategy. When finance users question a number, they need the exact inputs and rule version that produced it, not a black-box statement that “the system recalculated.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Make freshness and provenance visible
&lt;/h2&gt;

&lt;p&gt;Public financial data has a lifecycle. A source may publish a decision, revise a page, or expose the same number through several feeds. Your workflow should record:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The canonical source URL.&lt;/li&gt;
&lt;li&gt;Retrieval timestamp.&lt;/li&gt;
&lt;li&gt;Effective timestamp.&lt;/li&gt;
&lt;li&gt;Parser or connector version.&lt;/li&gt;
&lt;li&gt;Normalized value and original text.&lt;/li&gt;
&lt;li&gt;The downstream jobs triggered by the event.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A small provenance record can prevent a large reconciliation problem. It also lets an engineer distinguish a stale input from a broken calculation.&lt;/p&gt;

&lt;p&gt;When you display the result, show freshness next to the number. “4.00%, retrieved 08:15 UTC, effective Sept. 17” is much more useful than “current rate: 4.00%.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Use idempotency everywhere
&lt;/h2&gt;

&lt;p&gt;Central-bank announcements are likely to arrive through more than one path: an API poll, an email parser, a news feed, or a human upload. Your consumer must assume duplicates.&lt;/p&gt;

&lt;p&gt;Create a stable idempotency key from the jurisdiction, event type, effective date, and normalized decision identifier. Every downstream action should also have its own key, such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interest-accrual:loan-1842:2026-09-17
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the event is delivered twice, the system should not double-create a journal entry or send two review requests. Store the processing status and the input event ID with each action so operators can inspect what happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a practical close checklist looks like
&lt;/h2&gt;

&lt;p&gt;For the next month-end close, a rate-event workflow can create a focused checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Refresh variable-rate debt schedules.&lt;/li&gt;
&lt;li&gt;Compare calculated interest with lender statements.&lt;/li&gt;
&lt;li&gt;Review cash forecast assumptions.&lt;/li&gt;
&lt;li&gt;Identify models using policy-controlled discount rates.&lt;/li&gt;
&lt;li&gt;Attach source and effective-date evidence to the close package.&lt;/li&gt;
&lt;li&gt;Route exceptions with a named owner and due date.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That checklist is small enough to operate and specific enough to audit. It avoids the common failure mode where “macro update” becomes an unbounded task assigned to the entire finance team.&lt;/p&gt;

&lt;p&gt;Tools such as portali.tech are useful in this layer when they connect operational data, accounting work, and review evidence in one workflow. The value is not a flashy prediction. It is giving the team a traceable path from external event to proposed action to approved result.&lt;/p&gt;

&lt;h2&gt;
  
  
  The engineering takeaway
&lt;/h2&gt;

&lt;p&gt;A rate decision is not just a number to copy into a dashboard. It is a time-stamped event with uncertain downstream scope.&lt;/p&gt;

&lt;p&gt;Design the system around that reality: preserve the source event, model dependencies, calculate deterministically, ask for approval where judgment is involved, expose provenance, and make every consumer idempotent.&lt;/p&gt;

&lt;p&gt;That approach works for central-bank rates, tax notices, payment-provider changes, and other external facts that quietly change accounting operations. Good finance automation does not erase the chain of reasoning. It makes the chain easier to follow.&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>accounting</category>
      <category>automation</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
