1. Invoice lines → supplier portal draft, human submits
A VA opens a PDF invoice on one screen and the customer's supplier portal on the other, and retypes 400 line items — code, description, quantity, unit price, tax code — over two days. Transposed digits surface a month later as a rejected payment, and the same invoice format arrives again next month.
Trigger: Email (invoice received) / Webhook (document dropped)
How the workflow runs
- Trigger
Invoice arrives. An Email trigger on the AP inbox, or a Webhook from your document drop, starts the run with the invoice file.
- Knowledge
Load the field map. A Knowledge node supplies the portal's field map and this customer's coding rules — which portal field each invoice column feeds, and which tax codes are valid.
- Loop
For each invoice line. A Loop node iterates the line items. 400 lines is 400 small, isolated, individually-checkable passes rather than one enormous prompt that quietly drops row 287.
- Agent
Economy extractor per line. A cheap extractor turns one line into strict JSON {code, description, qty, unitPrice, taxCode, confidence}. Running once per line, its tier sets the cost of the whole job.
- Code
Validate and total. A Code node re-computes line totals and the invoice total arithmetically — never trusting the model's arithmetic — and a user-defined SpEL tool flags rows outside tolerance or below the confidence floor.
- Condition
Ambiguous line?. A Condition node routes flagged rows to the premium arbiter and lets clean rows through — so the expensive model sees the handful of genuinely unclear lines, not all 400.
- Agent
Premium arbiter on the unclear rows. A stronger model resolves the ambiguous minority: a merged description cell, a missing tax code, a credit line that reads like a charge.
- Tool (MCP)
Fill the portal form (browser-automation MCP). A Tool (MCP) node drives a browser-automation MCP server — a Playwright-style server registered in the platform's MCP registry — to enter the validated rows into the portal form. VegaDūta ships no built-in browser; this connector IS the mechanism. It fills, and it stops short of submit.
- Approval
A human clicks submit. An Approval node holds the completed draft with a field-by-field diff against the source invoice. Submission is the irreversible act, so a person performs it. The portal login itself is done by that person or via a secrets-managed integration — never typed by an agent.
- Output
File the evidence. An Output node records the submitted reference, the approver and the timestamp back to your AP system via a Tool (MCP) node, and notifies the requester on Email or Slack.
Channels & connectors
- Webhook
- Slack
- Knowledge base
- Approval / HITL
- Tool (MCP → browser-automation server)
- Tool (MCP → AP / accounting system)
Outcome
The portal form arrives pre-filled and arithmetically reconciled with a per-field diff against the source invoice, and a human spends their time checking and submitting rather than typing.
Why it helps
The mechanism is per-line isolation plus deterministic arithmetic: each line is extracted in its own small pass so a long invoice cannot silently lose a row, and totals are computed in code rather than by a model, so a transposed digit surfaces as a tolerance flag before submission instead of as a rejected payment a month later.
Build spec
2 agents — 1 economy line extractor (once per line, via the Loop node) + 1 premium arbiter (only on flagged lines). The form-filling itself is a Tool (MCP) node against a browser-automation server, not an agent capability. · Pattern: Loop (per line) → economy extract → Code validates arithmetic → Condition escalates only flagged rows → premium arbiter → MCP browser fills the draft → human submits
System prompt (paste-ready)
You extract ONE invoice line into strict JSON: {code, description, qty (number), unitPrice (number), lineTotal (number), taxCode, confidence (0-1), issue|null}. Use ONLY this line and the field map from Knowledge. Never infer a missing tax code from what is typical — leave it null and set a low confidence. Never round, never re-compute a total to make it agree, and never carry a value down from the line above. If the line is a credit, a discount or a header row rather than a chargeable item, say so in `issue` and do not force it into the item schema. You prepare a draft only: you never submit anything, and you never enter a password, card number or government ID into any field.Agent roles & model tiers
Line extractor (per line) — Economy tier — 400 lines means 400 invocations; this single tier choice dominates the cost of the entire job
One line → schema-valid JSON against the Knowledge field map. Nulls plus low confidence instead of plausible guesses. No arithmetic reconciliation, no value carried over from the previous line.
Ambiguity arbiter (flagged lines only) — Premium tier — affordable precisely because it sees the handful of unclear rows rather than the full invoice
Resolve one flagged line using the full invoice context and the coding rules. If it remains genuinely unclear, return NEEDS_HUMAN with the specific question — an honest escalation is cheaper than a wrong line in a submitted invoice.
MCP connectors
- Browser-automation MCP (Playwright-style server registered in the MCP registry) — the ONLY way this platform drives a real portal form: navigate, fill, screenshot. There is no built-in browser. It is scoped to fill fields and is not permitted to click the submit control
- AP / accounting system (invoice record, submitted reference) — via a Tool (MCP) node; no first-party connector
- Email / Slack — intake and notification channel
Built-in tools
- knowledge_search (built-in) — the portal field map and this customer's coding rules
- http_request (built-in) — where the portal exposes a documented API, prefer it over browser automation; an API is more reliable and better behaved than driving a UI
- User-defined tool `line_tolerance` (SpEL): input.lineTotal > input.qty * input.unitPrice * 1.01 || input.lineTotal < input.qty * input.unitPrice * 0.99 ? 'MISMATCH' : 'OK' — the AP lead sets their own tolerance band, and can tighten it, without a developer
- User-defined tool `field_ready_flag` (SpEL): input.confidence < 0.85 || input.taxCode == null ? 'REVIEW' : 'READY' — the confidence floor is the team's own number, expressed as data
Guardrails
- No agent ever types a password, card number, bank detail or government ID into a form. The portal login is performed by the human approver, or by a secrets-managed integration under your own account — credentials are never placed in a prompt, a field map, or an agent's reach
- Every submission goes through the Approval node. The browser-automation MCP is scoped to fill fields only; the irreversible submit control is clicked by a person looking at a field-by-field diff against the source invoice
- This portal is your own customer relationship, accessed under access you legitimately hold and within its Terms of Service — automation is used where the portal permits it, and where it does not, the workflow stops at the prepared draft for manual keying
- Rate-limited and honestly identified: the browser session paces its interactions, backs off on errors, and does not retry in a tight loop against a live portal
- No bot-detection bypass and CAPTCHAs are NEVER solved — a challenge hands the session to the human approver, who completes it themselves; the workflow waits rather than working around it
- No personal data harvesting: only the invoice fields the portal requires are processed, nothing about individuals is retained beyond the record, and the extracted payload is not reused for any other purpose
- Arithmetic is computed in the Code node, never accepted from a model, and the invoice total must reconcile before the draft can reach the Approval node at all
- Idempotent per invoice id — a resent email or a retried run never produces a second draft, and the submitted reference is written back once
- The SpEL user-defined tools are data-transform expressions over the tool's JSON input — no method calls, no constructors, no bean/type references, no loops in the grammar — so an AP lead encoding their own tolerance band writes a formula, not code, and it cannot become an execution risk
Cost strategy
This is the volume case that makes cost tiering obvious: 400 lines on a premium model is an absurd bill for what is fundamentally field-lifting off a structured document. Economy tier on the per-line extractor, deterministic arithmetic in the Code node (free), and the premium model reserved for the dozen rows the tolerance and confidence flags actually raise. Cap the extractor's output tokens — the per-line schema is tiny — and set a per-invoice budget so a scanned document that OCRs into noise fails loudly instead of burning through 400 expensive calls.
Output & delivery
The Loop extracts every line with the economy model → the Code node reconciles totals and the SpEL flags fire → the Condition node sends only flagged rows to the premium arbiter → a Tool (MCP) node drives the browser-automation server to fill the portal form and stops before submit → the human approver checks the field-by-field diff and clicks submit themselves → an Output node writes the reference, approver and timestamp back to the AP system and notifies on Email or Slack.