Cleaners

What a Cleaner does

A Cleaner is a set of rules that runs over the rows a flow has already extracted. It standardises formats, converts currencies and units, translates text, computes new columns, looks values up against your own data, and can trigger actions when a row breaks a rule.

Extraction answers “what does this document say?”. A Cleaner answers “what shape does that have to be in before it can go into our systems?” — one date format, one currency, part numbers matched to your catalogue, a total that adds up.

A flowA Cleaner
Works onA documentThe rows a flow produced
ProducesRaw extracted fieldsNormalised, enriched and validated columns
Typical jobRead the invoiceConvert EUR to USD, reformat the dates, flag the total that does not match
Attached toNothing — it is the starting pointOne or more flows, or run on its own

Building a Cleaner

A Cleaner is built base fields first. Base fields are the columns coming in; everything else is computed on top of them. You can define them by hand, import them from a flow, or parse them from a spreadsheet header row.

  1. 1Go to Cleaners and create a new one. Name it after the data, not the document — Invoice line items rather than Cleaner 3.
  2. 2Choose a data source for the base fields: Manual to define them from scratch, From Flow to import an existing flow's output fields, or From File to read them from a CSV or Excel header row.
  3. 3Add computed fields — the enrichment types in the table below. This step is optional; a Cleaner with only base fields is a valid pass-through.
  4. 4Configure the sweep output: an email address, a webhook URL, or neither. Also optional.
  5. 5Link the Cleaner to a flow so every new run is swept automatically, or leave it standalone and run it against uploaded datasets.
Keep base fields in step with the flow

If you imported base fields from a flow and later change that flow's fields, use Sync from Flow on the Cleaner. It shows what is new, what changed type and what no longer exists, and applies the differences — rather than leaving the Cleaner reading columns that stopped being produced.

Field type reference

Every column in a Cleaner has a type that decides what it does. Base fields pass values through; the other types compute a value from the row, from your Buckets, or from an AI judgement. This is the complete set.

A Tavnit Cleaner detail page. The left rail lists every field type — Base Fields, AI Formatted, Date Format, Number Format, Calculated, Category, HS Code, Lookup, Bucket Check, Conditional Actions, Conditional, Currency, Translation, Unit Conv. and Summary — with a count beside each, next to the Cleaner's base field list.
Field types are grouped in the Cleaner's left rail, with a count showing how many of each this Cleaner uses.
Field typeWhat it produces
BaseA column from the incoming data, passed through to the output.
AI FormattedAn AI rewrite of a base column — normalising a supplier name, tidying an address, standardising a description.
Date FormatA date column re-rendered in one consistent output format, whatever shape it arrived in.
Number FormatA numeric column with a fixed number of decimals and your choice of separators.
CalculatedA value derived by formula from other columns in the same row.
CategoryAn AI classification into a fixed list of options you define — expense type, department, priority.
HS CodeAn AI tariff classification against the Panama tariff schedule (HS 2022).
LookupA value pulled from a Bucket by matching this row against it — a catalogue price, a customer code.
Bucket CheckA yes/no answer to whether this row already exists in a Bucket. Useful for de-duplication.
Conditional ActionsNot a value — a rule that fires actions when a row matches. See below.
ConditionalAn if/else value: branch on the row's contents and output a different value per branch.
CurrencyA monetary value converted to a target currency at current published rates.
TranslationText translated into a target language.
Unit ConversionA measurement converted between units — mass, length, volume, area, speed or data size.
SummaryAn aggregate computed across every row of the sweep, not per row.
Replace the column, or add a new one

Computed fields have an output mode. Replace overwrites the source column in place; new column keeps the original and writes the result alongside it. Keep the original when a reviewer will need to see what the document actually said — for example when converting currency.

A field can be excluded from the output while still being available to computed columns. That is how you use an intermediate value — a raw amount, a lookup key — without shipping it downstream.

Conditional Actions

A Conditional Actions field is a rule: when a row matches these conditions, do these things. It is the only field type that changes what happens to the run rather than what a cell contains, and it is how validation failures become something other than a number in a table.

ActionWhat it does
Skip rowDrops the matching row from the output entirely — the way to filter out subtotals, blank lines and header junk.
Send for reviewPauses the run for human review and assigns the reviewers you name on the action. The matching rows and fields are flagged in the review screen.
EmailSends a notification to the addresses you list, with a subject and body you write. One send per rule per run, not one per matching row.
WebhookPOSTs a notification to a URL you specify. Same one-send-per-rule behaviour.
Edit a Bucket rowWrites a value back into a Bucket row that a Lookup field matched — marking an order received, decrementing stock, setting a status.

Conditions are grouped, and groups combine with AND or OR, so you can express things like (total > 10,000 OR currency is not USD) AND supplier is not on the approved list. A rule with no conditions at all fires on every row.

Notifications fire even if the run is rejected

Email and webhook actions are dispatched as soon as the rule matches — before any review pause. That is deliberate: alert me when this happens should not depend on whether a reviewer later approves the run.

Worked example. On an invoice Cleaner, add a Conditional Actions field with two rules. The first matches rows where the line total does not equal quantity × unit price and sends the run for review. The second matches any invoice over your approval threshold and emails the finance lead. Everything else flows straight through to the Bucket without a human touching it.

Calculated fields and formulas

A Calculated field evaluates an arithmetic expression against the row it is on. Reference other columns by name in braces, and start the formula with an equals sign if you like — both ={Quantity} * {Unit Price} and {Quantity} * {Unit Price} work.

SupportedNotes
+ − * / % **Add, subtract, multiply, divide, remainder, power. Parentheses group as usual.
{Field Name}A reference to another column in the same row. Spaces in the name are fine.
Numbers written as textCoerced automatically, so “1,234.50” behaves as a number.
Blank cellsCount as zero, so a missing optional column does not fail the row.

Formulas are arithmetic only — there are no functions, no text operations and no conditionals. For if/else logic use a Conditional field; for totals across rows use a Summary field. Dividing by zero fails that row rather than silently returning a blank, so guard columns that can legitimately be zero.

Summary fields

Summary fields aggregate across every row in the sweep instead of computing per row. They answer “what is the total of this document?” without you having to sum the rows downstream.

AggregationResult
SumTotal of a numeric column
AverageMean of a numeric column
MedianMiddle value of a numeric column
Min / MaxSmallest and largest value
CountHow many rows have a value in that column
Count uniqueHow many distinct values appear

HS Code classification

The HS Code field assigns a customs tariff code to each row from its product description. It works down the Panama tariff schedule (HS 2022) — section, then chapter, then heading, then national tariff line — applying the chapter legal notes rather than pattern-matching a description against a code list.

  • Pick which columns the classifier reads — usually the product description, sometimes with material or use alongside it. Leave it unset and the whole row is used.
  • Add instructions for the cases your catalogue gets wrong: how to treat kits, spare parts, or goods that could sit in two chapters.
  • Rows are classified independently, so one hard row does not affect the others.
It is a classification, not a ruling

Tariff classification is a judgement call that customs authorities make. Treat the output as a strong first pass to be checked, not as a filing-ready declaration — this is a good candidate for human review before delivery.

Shaping and delivering the output

Between the computed columns and delivery, a Cleaner can drop junk rows, reshape long data into wide, choose which columns ship, and send the result to an email address or a webhook.

SettingWhat it does
Skip rowsDiscards the first N rows or all empty rows of a manual upload before cleaning — for spreadsheets with title rows above the header.
PivotReshapes rows into wide format at delivery: one column per distinct label, plus optional per-row summary columns. Stored rows stay in long format.
Output fieldsChooses which columns appear in the output. Excluded columns are still usable by computed fields.
Email outputSends the cleaned result to an address after each sweep.
WebhookPOSTs the cleaned result to a URL after each sweep. HTTPS only — see webhooks.
Pivot does not reach Buckets

Pivot applies to the webhook payload, the email output and downloads. Bucket exports always receive the un-pivoted rows, so the stored table keeps one row per record.

Sweeps and credits

A sweep is one execution of a Cleaner over a batch of rows. Sweeps run automatically when a linked flow finishes, or on demand when you upload a dataset to clean. Each sweep is billed on the number of non-empty cells it processed, not the number of documents.

How a sweep startsWhen to use it
Linked to a flowEvery run of that flow is swept as soon as extraction completes. This is the normal setup.
Manual uploadClean a CSV or Excel file that did not come from a flow — a supplier price list, a legacy export.

Cleaning credits are charged per 500 non-empty cells, rounded up, with a one-credit minimum. Empty cells are not counted, so a wide table with many optional columns costs less than its dimensions suggest. Every sweep records the cells processed and the credits it used.

Open a sweep from the Cleaner's Sweep History to see the rows it produced, the credits it consumed, and per-row errors — a formula that divided by zero, a lookup that matched nothing, a value that failed validation. Errors are attached to the row that caused them, so a single bad row does not fail the sweep.

Where a Cleaner sits in the pipeline

Cleaning happens after extraction and before delivery. That order matters: everything downstream — the review screen, the webhook payload, the Bucket rows, an agent's input variables — sees the cleaned output, not the raw extraction.

  1. 1The flow extracts rows from the document.
  2. 2The linked Cleaner sweeps those rows: formats, conversions, lookups, computed columns.
  3. 3Conditional Actions fire — rows are dropped, notifications go out, review may be requested.
  4. 4If review was triggered, the run pauses and a reviewer sees the cleaned table.
  5. 5On completion, results are delivered: email, webhook, Bucket, form fill, or a chained agent.

The Pipeline Map shows this for your own workspace, including which flows share a Cleaner.