Automation & workflows
Your repetitive tasks handed to reliable workflows, with AI where judgment is needed, and alerts when something goes wrong.
Not everything needs an agent. A large share of back-office work is solved by a well-designed workflow: I connect your tools, automate the repetitive chains (sorting, data entry, follow-ups, reporting) and only add AI where it brings judgment. All of it supervised: a workflow that fails should alert you, not carry on silently.
Key facts
0
manual rekeying on automated processes
7 days
for a first useful workflow in production
100%
of failures visible: alerts, logs, statuses
Automation & workflows
What I build
Business process automation
Email triage and dispatch, data entry, follow-ups, reporting: repetitive chains executed by workflows plugged into your tools.
n8n · Workflows · Back-office
AI-augmented workflows
AI inserted at the right step of the workflow to classify, extract, summarize or draft. The rest stays deterministic, and therefore predictable.
LLM · Classification · Extraction
Custom integrations
CRM, ERP, email, spreadsheets, internal tools: I connect them through APIs and webhooks, including when no off-the-shelf connector exists.
API · Webhooks · CRM · ERP
The promise
Repetitive work runs on its own, under control.
Demonstration
A supplier invoice stopped before the ledger
A building engineering firm receives supplier invoices by email, in as many formats as it has suppliers, then rekeys them by hand into its accounting tool. Someone checks the purchase order from memory, and a line billed on top ends up paid.
Invented caseThis case is not an engagement. It is invented end to end, and the code below is the real code that would run it.
HumanThe morning request
This morning's supplier invoices are in the accounting mailbox. I want the amounts pulled out, checked against the purchase order, and only what fails to match on my desk.
Tool callDocument extraction
{ "tool": "document.extract", "source": { "channel": "email", "mailbox": "accounting", "message_id": "AAMkAGI3f21b4c9a", "attachment": "august-invoice.pdf", "received_at": "2026-09-03T07:41:12+02:00" }, "expected_fields": [ "invoice_number", "date", "currency", "amount_ex_tax", "amount_inc_tax", "order_reference", "lines" ], "minimum_score_per_field": 0.85 }No per-supplier template. The document layout is not an assumption the system makes, it is an input it has to take as it comes.
Tool responseExtracted fields
{ "status": "extracted", "supplier_trade": "aluminium joinery manufacturer", "invoice_number": "F-2026-3184", "date": "2026-08-28", "currency": "EUR", "amount_ex_tax": 4968.40, "amount_inc_tax": 5962.08, "order_reference": "BC-2026-0771", "lines": [ { "description": "Aluminium frame, series 60", "quantity": 12, "unit_price_ex_tax": 386.20, "total_ex_tax": 4634.40 }, { "description": "On-site delivery charge", "quantity": 1, "unit_price_ex_tax": 334.00, "total_ex_tax": 334.00 } ], "scores": { "invoice_number": 0.98, "amount_ex_tax": 0.97, "order_reference": 0.93 }, "fields_below_threshold": [] }The agentReading the difference
The invoice carries the purchase order reference, read above the minimum score. So I read the order from the ERP by that reference rather than searching by supplier. It holds the twelve frames, not the delivery charge billed on top. I do not settle that difference myself: I pass both amounts to reconcile_invoice_with_order, which applies a written, tested tolerance.
Tool callCalling the reconciliation
{ "tool": "reconcile_invoice_with_order", "invoice": { "number": "F-2026-3184", "currency": "EUR", "amount_ex_tax": 4968.40 }, "purchase_order": { "reference": "BC-2026-0771", "read_by": "erp.orders.read", "status": "open", "currency": "EUR", "amount_ex_tax": 4634.40 } }The model does not judge the difference and does not supply the threshold. It calls a deterministic function whose tolerance owes nothing to how the invoice is worded.
AnswerBack to accounting
Invoice F-2026-3184 is not posted. It goes to human review: the difference with purchase order BC-2026-0771 is 334.00 EUR, against a tolerance of 15.00 EUR. The line at fault is named: an on-site delivery charge that is not on the order. Whoever opens the task sees both amounts, the offending line, and two ways out: accept the difference and post it, or send the invoice back to the supplier.
The run stops on an invoice that was never posted. That is the expected behavior: the automation knows what it cannot settle.
The reconciliation rule
"""Reconcile a supplier invoice with its purchase order."""
from dataclasses import dataclass
from decimal import Decimal
ABSOLUTE_TOLERANCE = Decimal("15.00")
RELATIVE_TOLERANCE = Decimal("0.01")
RELATIVE_REJECT_THRESHOLD = Decimal("0.25")
POST_TO_LEDGER = "post_to_ledger"
HUMAN_REVIEW = "human_review"
REJECT = "reject"
@dataclass(frozen=True)
class Decision:
status: str
difference: Decimal
tolerance: Decimal
reason: str
def _amount(source, field):
value = source.get(field)
if value is None:
raise ValueError("missing amount: " + field)
return Decimal(str(value))
def reconcile_invoice_with_order(invoice, purchase_order):
if invoice.get("currency") != purchase_order.get("currency"):
return Decision(REJECT, Decimal("0"), Decimal("0"), "currency mismatch")
invoice_amount = _amount(invoice, "amount_ex_tax")
order_amount = _amount(purchase_order, "amount_ex_tax")
difference = abs(invoice_amount - order_amount)
# The stricter of the two tolerances wins, otherwise a large purchase order
# buys the right to a large difference.
tolerance = min(ABSOLUTE_TOLERANCE, order_amount * RELATIVE_TOLERANCE)
if difference > order_amount * RELATIVE_REJECT_THRESHOLD:
return Decision(REJECT, difference, tolerance, "difference beyond a keying error")
if difference > tolerance:
return Decision(HUMAN_REVIEW, difference, tolerance, "difference above tolerance")
return Decision(POST_TO_LEDGER, difference, tolerance, "difference within tolerance")
An automation that is never allowed to stop does not remove the rekeying: it moves it to correcting ledger entries, later and at a higher price.
Automation & workflows
Before / after
The same tasks rekeyed by hand every day
A workflow that sorts, processes and files on its own
An automated workflow that fails silently
Failures that are visible, alerted and retried
Automation & workflows
The stack
n8n
Make
Zapier
Python
TypeScript
API
Webhooks
Claude
Automation & workflows
Straight answers
Which processes should be automated first?
High-volume, low-judgment repetitive tasks: email triage, data entry, follow-ups, reporting, syncing between tools. A quick audit identifies the ones with the biggest payoff, often within days.
n8n, Make, Zapier or custom code?
n8n for most cases: self-hostable, versionable, extensible with code. Make and Zapier for simple, quick needs. Custom code when the logic outgrows what a visual tool can maintain cleanly. I choose based on your case, not my habits.
What happens when a workflow fails?
It tells you. Alerts, logs, a status for every run, the ability to retry: I design how it fails before I design how it works. A workflow that fails silently costs more than the manual task it replaced.
Do my automations need AI?
Not always. When the rule is clear, a deterministic workflow is enough and costs less. AI comes in where judgment is needed: classifying an ambiguous email, extracting data from a document, drafting a reply.
Read on this topic
Contact
Ready to go from demo to production?
Reply within 24 hours · first conversation free, no strings attached.