# AI Invoice Processing

> Have an AI Agent read line items off PDF invoices, put the total in front of a person to approve, then write the rows to your database.

**The full picture · about 30 minutes · 4 steps**

An AI Agent reads line items off PDF and image invoices, whatever the vendor's layout. The extracted total goes to a person to approve, and only after approval do the line items reach your database.

The AI does the reading. The approval and the writing are ordinary steps, so nothing reaches your database that a person has not seen.

This is the most involved recipe here, and it brings together everything the earlier ones introduced. Work through one of those first if any piece is unfamiliar.

Gmail trigger → [AI Agent](/build/ai-features/ai-agent) → [Human Review](/build/action-steps/user-approval) → Airtable

## What you will use

- An **AI Agent**, for reading documents no fixed parser could handle.
- A **Human Review** step, which pauses the run until a person decides.
- **Run for each item**, to write one database row per line item.

## Prerequisites

- A connected **Gmail** or **Google Drive** account (to catch the inbound invoices).
- A connected **Notion**, **Airtable**, or **SQL Database** (to store the data).

---

## Building the Workflow

### 1. The Trigger: New Email with Attachment
Add a **Gmail** trigger. Set it to listen for new emails in your `billing@acmecorp.com` inbox that contain attachments.

### 2. The AI: Glow Agent (Extraction)

Standard parsing steps fail on unpredictable PDFs. Instead, drag an **AI Agent** step onto the canvas.

In the agent's **Primary goals**, reference the attachment from the trigger and say what to pull out of it:

> _"Read the attached invoice and return strict JSON with this shape: `{ \"vendor_name\": \"string\", \"total\": 0, \"due_date\": \"YYYY-MM-DD\", \"line_items\": [{ \"description\": \"string\", \"price\": 0 }] }`. Use numbers for total and price. Do not add fields that are not present on the invoice."_

Turn on **Parse JSON result** in the same step, so the steps that follow get an object rather than a block of text.

Insert the attachment from the Workflow data panel rather than typing a path: the field name comes from your trigger, not from us. The snippets here write the trigger as `1` and the agent as `2`; read the real numbers off your own steps.

### 3. The Safety Net: Human Review

You do not want AI blindly paying invoices or writing unverified data to your ERP.
Drag a **Human Review** step after the Agent.
Configure it to display the vendor name, due date, and formatted total using [Data Transformation](/build/core-concepts/data-transformation): `{{ 2.result.total | format_currency:"$" }}`. The workflow now pauses until someone on your finance team clicks **Approve** in the Glow dashboard.

### 4. The Loop: Process Line Items

Once approved, each line item needs to be saved to your database.
Add your database action step (e.g., **Airtable: Create Record**).
Open that step's repeat badge and switch it to **Each item**, then choose the list of line items the agent extracted: `{{ 2.result.line_items }}`.

**Every AI step stores its answer under `result`**, the Agent included, so the path is `2.result.…`. With **Parse JSON result** on you can reach inside it directly, as here. Open the agent's **Executions** tab and read the real shape before you map it: the field names come from the invoice, so they are whatever you asked the agent to return.

Map the current item's description and price into the Airtable fields with `{{ item.description }}` and `{{ item.price }}`.

**What this costs.** Each item spends one credit, so a 40-line invoice is 40 credits at this step alone. The number of items one step may process is capped by your plan: 50 on Free, 1,000 on Pro, 10,000 on Enterprise. Over the cap, the step is refused rather than quietly processing part of the invoice. For an invoice longer than your cap, split the extracted list into smaller batches before the loop, or move up a plan.

> **Why it is built this way.** The AI does one job: reading the invoice (Step
> 2). The approval (Step 3), the loop and the database write (Step 4) all run
> the same way every time. A misread total is caught by the person approving it,
> not by the model.

## Test and go live

### Use a known invoice

Send a test invoice with a vendor, total, due date and two line items you can check by eye. Run through the Gmail trigger's test flow and select its attachment from the Workflow data panel when configuring the agent.

### Check the structured result

Open the agent's stored output. Confirm `vendor_name`, `total`, `due_date` and `line_items` match the document, and that `line_items` is a list with exactly two records. Stop here if the shape or values differ; later steps depend on both.

### Approve and verify the writes

Open the Human Review email while signed in as a member of the workspace. Compare its summary with the source invoice, approve it, then confirm Airtable contains exactly two new rows with the expected descriptions and prices. Reject a second test run and confirm it writes no rows.

### Set the workflow Live

Switch the workflow to **Live**, send one controlled invoice from an approved sender and follow it through the review and database. Confirm the final run writes each line once before routing real invoices through it.

---

## What's Next?

👉 **[Build a workflow for your own process →](/build/which-step)**

You have completed the cookbook sequence. Start from the job you need to automate, and the guide will point you to the right steps.

Go deeper on the concepts this recipe uses:

- **[AI Agents](/build/ai-features/ai-agent)**: give an AI Step goals and tools.
- **[Human Review](/build/action-steps/user-approval)**: pause a workflow before an important action.
