# Delete by Path Source: https://docs.cloudsquid.io/api-reference/filesystem/delete-by-path delete /projects/{project_name}/files Delete the file or folder at a path. Folders are deleted recursively. **Destructive operation:** Folder deletion is recursive and permanent. The project root (`/`) cannot be deleted. ## What this does Deletes whatever exists at the given path. If the path is a folder, all files and subfolders within it are deleted recursively. Returns `204 No Content` on success with no response body. ## Example ```bash cURL theme={null} curl -X DELETE \ "https://api.cloudsquid.io/api/projects/my-project/files?path=/invoices/2024/jan.pdf" \ -H "X-API-Key: YOUR_API_KEY" ``` ```python Python theme={null} import requests response = requests.delete( "https://api.cloudsquid.io/api/projects/my-project/files", params={"path": "/invoices/2024/jan.pdf"}, headers={"X-API-Key": "YOUR_API_KEY"} ) assert response.status_code == 204 ``` ```javascript JavaScript theme={null} await fetch( "https://api.cloudsquid.io/api/projects/my-project/files?path=/invoices/2024/jan.pdf", { method: "DELETE", headers: { "X-API-Key": "YOUR_API_KEY" } } ); ``` Response: `204 No Content` (empty body) # Read by Path Source: https://docs.cloudsquid.io/api-reference/filesystem/read-by-path get /projects/{project_name}/files Resolve a path: returns a presigned URL for a file, or a listing for a folder. **Polymorphic response:** The response shape depends on what exists at the path. Check the `ftype` field — `"file"` returns a download URL, `"folder"` returns a listing of direct children. ## What this does Reads whatever exists at the given path. If the path resolves to a **file**, returns a File object with a short-lived presigned download URL (15-minute TTL). If it resolves to a **folder**, returns a Folder object listing its direct children. ## Examples ```bash cURL (file) theme={null} curl "https://api.cloudsquid.io/api/projects/my-project/files?path=/invoices/2024/jan.pdf" \ -H "X-API-Key: YOUR_API_KEY" ``` ```bash cURL (folder) theme={null} curl "https://api.cloudsquid.io/api/projects/my-project/files?path=/invoices/2024" \ -H "X-API-Key: YOUR_API_KEY" ``` ```python Python theme={null} import requests response = requests.get( "https://api.cloudsquid.io/api/projects/my-project/files", params={"path": "/invoices/2024"}, headers={"X-API-Key": "YOUR_API_KEY"} ) node = response.json() if node["ftype"] == "file": print(f"Download URL: {node['url']}") else: for entry in node["entries"]: print(f" {entry['ftype']}: {entry['name']}") ``` ```javascript JavaScript theme={null} const response = await fetch( "https://api.cloudsquid.io/api/projects/my-project/files?path=/invoices/2024", { headers: { "X-API-Key": "YOUR_API_KEY" } } ); const node = await response.json(); if (node.ftype === "file") { console.log("Download:", node.url); } else { node.entries.forEach(e => console.log(e.ftype, e.name)); } ``` File response (`200`): ```json theme={null} { "ftype": "file", "name": "jan.pdf", "size": 48210, "mimetype": "application/pdf", "modified_at": "2026-06-01T12:00:00Z", "url": "https://storage.googleapis.com/presigned?..." } ``` Folder response (`200`): ```json theme={null} { "ftype": "folder", "name": "2024", "entries": [ { "ftype": "file", "name": "jan.pdf", "size": 48210, "mimetype": "application/pdf", "modified_at": "2026-06-01T12:00:00Z", "url": "https://storage.googleapis.com/presigned?..." }, { "ftype": "folder", "name": "archive" } ] } ``` # Upload File by Path Source: https://docs.cloudsquid.io/api-reference/filesystem/upload-file-by-path put /projects/{project_name}/files Upload a file to a path inside the project filesystem. Parent folders are created automatically. **Conflict handling:** If a file already exists at the target path, the request fails with `409 Conflict`. Delete the existing file first if you need to overwrite it. ## What this does Uploads a file to the project filesystem at the specified `path` query parameter. Missing intermediate folders are created automatically (like `mkdir -p`). The request body uses the same `Document` schema as table file uploads. ## Example ```bash cURL theme={null} curl -X PUT \ "https://api.cloudsquid.io/api/projects/my-project/files?path=/invoices/2024/jan.pdf" \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "file": "'$(base64 -i jan.pdf)'", "filename": "jan.pdf", "mimetype": "application/pdf", "file_type": "binary" }' ``` ```python Python theme={null} import requests, base64 with open("jan.pdf", "rb") as f: encoded = base64.b64encode(f.read()).decode() response = requests.put( "https://api.cloudsquid.io/api/projects/my-project/files", params={"path": "/invoices/2024/jan.pdf"}, headers={"X-API-Key": "YOUR_API_KEY"}, json={ "file": encoded, "filename": "jan.pdf", "mimetype": "application/pdf", "file_type": "binary" } ) ``` ```javascript JavaScript theme={null} const response = await fetch( "https://api.cloudsquid.io/api/projects/my-project/files?path=/invoices/2024/jan.pdf", { method: "PUT", headers: { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ file: btoa(fileContent), filename: "jan.pdf", mimetype: "application/pdf", file_type: "binary" }) } ); ``` Response (`201 Created`): ```json theme={null} { "ftype": "file", "name": "jan.pdf", "size": 48210, "mimetype": "application/pdf", "modified_at": "2026-06-01T12:00:00Z", "url": "https://storage.googleapis.com/presigned?..." } ``` # API Introduction Source: https://docs.cloudsquid.io/api-reference/introduction Base URL, authentication, and your first API call. **Base URL:** `https://api.cloudsquid.io/api` ## Authentication Every request must include your API key in the `X-API-Key` header. API keys are project-scoped and generated in the Cloudsquid dashboard under **Project Settings → API Keys**. ```python Python theme={null} import requests headers = {"X-API-Key": "YOUR_API_KEY"} response = requests.get( "https://api.cloudsquid.io/api/projects", headers=headers ) ``` ```bash cURL theme={null} curl https://api.cloudsquid.io/api/projects \ -H "X-API-Key: YOUR_API_KEY" ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.cloudsquid.io/api/projects", { headers: { "X-API-Key": "YOUR_API_KEY" } }); const projects = await response.json(); ``` ## Your first call: list projects `GET /projects` returns all projects in your organisation. Use the `name` field as `project_name` in subsequent requests. ```json Response theme={null} [ { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "my-project", "created_at": "2024-01-15T10:30:00Z" } ] ``` ## Integration patterns Choose based on your use case: **Endpoints:** `/extract`, `/reconcile` One HTTP call. Blocks until processing is complete, then returns the full result. Best for interactive integrations and files that complete in under 60 seconds. **Endpoints:** `/files` → `/run` → `/run/{run_id}` Upload, start, poll. Returns immediately — you check status separately. Best for large files, batch workloads, and decoupled pipelines. ## Core concepts Extraction, Reconcile, and Storage tables — and when to use each. Choose between flash and pro models based on speed and accuracy requirements. The upload → start → poll pattern for extraction at scale. # Delete a Project Source: https://docs.cloudsquid.io/api-reference/projects/delete-projects delete /projects/{project_name} Delete a project. # Get All Projects Source: https://docs.cloudsquid.io/api-reference/projects/get-projects get /projects Get all projects in the organisation. # Create a New Project Source: https://docs.cloudsquid.io/api-reference/projects/post-projects post /projects Create a new Project. # Create Table Source: https://docs.cloudsquid.io/api-reference/tables/create-a-new-table post /projects/{project_name}/tables Create a new table (extraction, reconciliation, storage). # Create a Reconciliation Row Source: https://docs.cloudsquid.io/api-reference/tables/create-a-reonciliation-task post /projects/{project_name}/tables/{table_id}/tasks Create a Task without executing it. # Delete Table Source: https://docs.cloudsquid.io/api-reference/tables/delete-projects-tables delete /projects/{project_name}/tables/{table_id} Delete table with all the data inside. # Get Run Status and Result Source: https://docs.cloudsquid.io/api-reference/tables/get-ai-run-status-&-result get /projects/{project_name}/tables/{table_id}/run/{run_id} Poll an async AI run for its status and retrieve results when complete. Returns the current status of the run, and if the run is done, includes the extracted data or reconciliation results. **This is step 3 of 3** in the async run pattern. Poll this endpoint using the `run_id` returned by [Start AI Run](/api-reference/tables/request-starts-the-analyze-process-for-a-table) until `status` is `done` or `error`. See the full [async run pattern guide](/concepts/async-run-pattern) for a complete working example with a polling loop. ## Run status values | Status | Meaning | | --------- | ----------------------------------------------------------- | | `pending` | Queued, not yet started | | `running` | AI is actively processing | | `done` | Complete — `data` field is populated with extracted results | | `error` | Processing failed | ## Polling example ```python Python theme={null} import time, requests while True: result = requests.get( "https://api.cloudsquid.io/api/projects/my-project/tables/TABLE_ID/run/RUN_ID", headers={"X-API-Key": "YOUR_API_KEY"} ).json() if result["status"] == "done": print(result["data"]) break elif result["status"] == "error": raise RuntimeError("Extraction failed") time.sleep(3) ``` A poll interval of 2–5 seconds is appropriate for most workloads. # Get a Table Source: https://docs.cloudsquid.io/api-reference/tables/get-projects-tables get /projects/{project_name}/tables/{table_id} Retrieve a table and its metadata. # List all Tables Source: https://docs.cloudsquid.io/api-reference/tables/get-projects-tables-1 get /projects/{project_name}/tables List all tables inside the project # Get Table Data Source: https://docs.cloudsquid.io/api-reference/tables/get-projects-tables-data get /projects/{project_name}/tables/{table_id}/data Retrieve all data from a table. # Get Table Schema Source: https://docs.cloudsquid.io/api-reference/tables/get-projects-tables-schema get /projects/{project_name}/tables/{table_id}/schema Retrieve the data schema for a table. # Upload Data into Table Source: https://docs.cloudsquid.io/api-reference/tables/post-projects-tables-data post /projects/{project_name}/tables/{table_id}/data Upload JSON data into a table. # Update Table Schema Source: https://docs.cloudsquid.io/api-reference/tables/post-projects-tables-schema post /projects/{project_name}/tables/{table_id}/schema Update the data schema for a table. # Upload CSV to Storage Table Source: https://docs.cloudsquid.io/api-reference/tables/put-projects-tables put /projects/{project_name}/tables/{table_id} Overwrite or append csv data to a storage table. # Start AI run (asynchronous) Source: https://docs.cloudsquid.io/api-reference/tables/request-starts-the-analyze-process-for-a-table post /projects/{project_name}/tables/{table_id}/run Start AI processing for a row in an extraction or reconciliation table. This is an asynchronous operation; use the returned run_id to check status and retrieve results. **This is step 2 of 3** in the async run pattern. You need a `row_id` from [uploading a file](/api-reference/tables/upload-a-new-file-into-a-table) first. After starting the run, [poll for results](/api-reference/tables/get-ai-run-status-&-result) using the returned `run_id`. See the full [async run pattern guide](/concepts/async-run-pattern) for a complete working example. ## What this does Enqueues an AI job for the given row and returns immediately with a `run_id`. Processing happens asynchronously — the run status transitions from `pending` → `running` → `done` (or `error`). ## Zero retention mode Pass `"zero_retention": true` to run extraction without persisting intermediate results. Useful for privacy-sensitive workloads where you want the final output but not intermediate artifacts stored on Cloudsquid infrastructure. ## Example ```python Python theme={null} import requests response = requests.post( "https://api.cloudsquid.io/api/projects/my-project/tables/TABLE_ID/run", headers={"X-API-Key": "YOUR_API_KEY"}, json={"row_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"} ) run_id = response.json()["run_id"] ``` Pass `run_id` to `GET /run/{run_id}` to check status and retrieve results. # Upload File to Extraction Table Source: https://docs.cloudsquid.io/api-reference/tables/upload-a-new-file-into-a-table post /projects/{project_name}/tables/{table_id}/files Upload a file to an extraction table to create a new row associated with it. This doesn't start an extraction run - use the /run endpoint to start processing the file after uploading. **This is step 1 of 3** in the async run pattern. After uploading, use the returned `row_id` to [start a run](/api-reference/tables/request-starts-the-analyze-process-for-a-table), then [poll for results](/api-reference/tables/get-ai-run-status-&-result). For a single blocking call that handles everything, see [synchronous extraction](/api-reference/unified/synchronous-extraction-for-a-file-end-to-end). ## What this does Creates a row in the extraction table linked to the uploaded file, but does **not** start processing. The returned `row_id` is required for all subsequent operations on this file. ## Example ```bash cURL theme={null} curl -X POST \ "https://api.cloudsquid.io/api/projects/my-project/tables/TABLE_ID/files" \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "file": "'$(base64 -i invoice.pdf)'", "filename": "invoice.pdf", "mimetype": "application/pdf", "file_type": "binary" }' ``` Response: ```json theme={null} { "row_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6" } ``` Pass this `row_id` to `POST /run` to start extraction. # Data Extraction (synchronous) Source: https://docs.cloudsquid.io/api-reference/unified/synchronous-extraction-for-a-file-end-to-end post /projects/{project_name}/tables/{table_id}/extract Upload a file and extract its content. # Reconcile Data (synchronous) Source: https://docs.cloudsquid.io/api-reference/unified/synchronous-reconciliation-run post /projects/{project_name}/tables/{table_id}/reconcile Run reconciliation on data. # The agent runtime Source: https://docs.cloudsquid.io/concepts/agent-runtime Each agent works in its own environment — SQL over granted tables, project files, integration tokens, and the ability to run code when the task calls for it. The agent isn't a prompt with a document stapled to it. It gets **its own computer** — a VM where it can run commands, query databases, open files, and produce new ones for the duration of the work. That's what makes it possible to hand it a process instead of a task. A trained team member doesn't follow a fixed sequence of steps; they look things up, check an edge case, do a bit of arithmetic, and write the email. The runtime is what lets the agent do the same. ## What the agent can reach | | What it means | | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **SQL over granted tables** | The agent queries your storage and extraction tables directly — lookups, joins, counts, candidate checks. Only the tables granted under **Data Access** on that reconcile table. | | **Project files and folders** | It reads the documents in the case, the `SOP.md`, and anything else in the project's Files — and writes new files back. | | **Integration tokens** | Access-controlled credentials for connected systems, used from inside the environment. See [Integrations](/concepts/integrations). | | **Platform helpers** | Document reading including vision on PDFs and images, so scans, photos, and layout-heavy documents are workable. | | **Skills and MCP servers** | Reusable capabilities you've added to the project. See [Skills](/concepts/skills) and [MCP servers](/concepts/mcp-servers). | | **Web search** | For the cases where the answer isn't in your data. | Everything outside that list is closed. The environment is scoped to the project and the grants on the table — see [Governance](/concepts/governance). ## It runs code when the task calls for it There is no fixed pipeline behind a case. The agent decides what the work needs: * A 4,000-row spreadsheet attached to an email → it processes it as data, not as text. * Fifty candidate customers on a fuzzy name → it queries, normalizes, and compares in SQL. * A total that doesn't add up → it recomputes the line items and says which one is off. * A supplier who needs an answer → it drafts the reply with the case's facts in it. Different cases take different paths through the same procedure. That's the point: the SOP describes the process, and the runtime is general enough to execute it. ## Deliverables on demand Because the agent can write files, it can produce work products about its own work. Ask in the chat: > Give me an xlsx of all Order Match cases from last month with match status, which ones needed review, and the reason. It queries the table, does the analysis, and writes the xlsx into the project's Files — keep a `Reporting` folder for them so generated deliverables don't mix with incoming documents. This is on demand — you ask, it produces. It is not a scheduled report job. ## Model tiers Each reconcile table picks an **AI Model** tier in its **Configure** view: | Tier | Character | Use it for | | ------------ | -------------------------------- | --------------------------------------------------------------------------------------------------- | | **Fast** | Quick results, lower cost | High volume, clean inputs, mechanical matching where the rules are unambiguous | | **Balanced** | Best for most tasks | The default starting point for a new process | | **Powerful** | Most accurate, complex reasoning | Messy or visually complex documents, multi-step judgment, processes where a wrong call is expensive | Start on **Balanced**. Move to **Powerful** when you see the agent flagging cases a person would have resolved, or misreading hard documents. Move to **Fast** once a process is stable and the cases are uniform. Tiers apply to the agent — the reconcile table, the chat, agentic approval. **Tiers are not extraction pipelines.** Extraction tables and the extraction API use a separate set of model configurations (`cloudsquid-flash`, `cloudsquid-pro-v3`, and so on). Different subsystem, different names — see [Extraction pipelines](/concepts/pipelines). ## Everything lands in the trace Every query the agent ran, every file it opened, every action it took is recorded on the case. When a reviewer asks "why did it pick this customer", the answer isn't a summary written after the fact — it's the actual sequence of what happened. See [Review & approvals](/concepts/review-approvals) for what the reviewer sees. The procedure the runtime executes. What scopes the environment: grants, gates, and the audit trail. Tokens the agent uses from inside its environment. Where the trace shows up for a human. # Async Run Pattern Source: https://docs.cloudsquid.io/concepts/async-run-pattern Upload a file, start an AI run, and poll for results — the standard pattern for extraction at scale. Most extraction integrations follow a three-step pattern: upload the file, start a run, then poll until results are ready. This decouples ingestion from processing so your system doesn't have to block on a long-running AI call. ## Sync vs async — which to use? One HTTP call. Blocks until done, returns the result directly. Best for interactive integrations, small files, or when you need the result immediately. Use when processing typically completes in under 60 seconds. Upload, start, poll. Each step returns immediately. Best for large files, batch workloads, or when you want to decouple ingestion from processing. ## The three steps `POST /projects/{project_name}/tables/{table_id}/files` Send the file along with its metadata. This creates a row in the extraction table associated with the file but does **not** start processing. Returns: `{ "row_id": "uuid" }` — hold onto this. `POST /projects/{project_name}/tables/{table_id}/run` Pass the `row_id` from step 1. This enqueues the AI job and returns immediately. Returns: `{ "run_id": "uuid" }` — use this to poll. Optional: pass `"zero_retention": true` to run without persisting intermediate results. `GET /projects/{project_name}/tables/{table_id}/run/{run_id}` Poll until `status` is `done` or `error`. A typical poll interval is 2–5 seconds. Returns a `DataRow` with the current `status` and, when done, the extracted `data`. ## Run status values | Status | Meaning | | --------- | ----------------------------------------------- | | `pending` | Queued, not yet started | | `running` | AI is actively processing | | `done` | Extraction complete — `data` field is populated | | `error` | Processing failed | ## Full example ```python Python theme={null} import time, requests, base64 API_KEY = "YOUR_API_KEY" BASE = "https://api.cloudsquid.io/api" HEADERS = {"X-API-Key": API_KEY, "Content-Type": "application/json"} PROJECT = "my-project" TABLE_ID = "your-table-uuid" # Step 1: Upload with open("invoice.pdf", "rb") as f: file_b64 = base64.b64encode(f.read()).decode() upload = requests.post( f"{BASE}/projects/{PROJECT}/tables/{TABLE_ID}/files", headers=HEADERS, json={ "file": file_b64, "filename": "invoice.pdf", "mimetype": "application/pdf", "file_type": "binary" } ) row_id = upload.json()["row_id"] # Step 2: Start run run = requests.post( f"{BASE}/projects/{PROJECT}/tables/{TABLE_ID}/run", headers=HEADERS, json={"row_id": row_id} ) run_id = run.json()["run_id"] # Step 3: Poll while True: result = requests.get( f"{BASE}/projects/{PROJECT}/tables/{TABLE_ID}/run/{run_id}", headers=HEADERS ).json() if result["status"] == "done": print(result["data"]) break elif result["status"] == "error": raise RuntimeError("Extraction failed") time.sleep(3) ``` ```bash cURL theme={null} # Step 1: Upload ROW_ID=$(curl -s -X POST \ "https://api.cloudsquid.io/api/projects/my-project/tables/TABLE_ID/files" \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d "{\"file\": \"$(base64 -i invoice.pdf)\", \"filename\": \"invoice.pdf\", \"mimetype\": \"application/pdf\", \"file_type\": \"binary\"}" \ | jq -r '.row_id') # Step 2: Start run RUN_ID=$(curl -s -X POST \ "https://api.cloudsquid.io/api/projects/my-project/tables/TABLE_ID/run" \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d "{\"row_id\": \"$ROW_ID\"}" \ | jq -r '.run_id') # Step 3: Poll while true; do RESULT=$(curl -s \ "https://api.cloudsquid.io/api/projects/my-project/tables/TABLE_ID/run/$RUN_ID" \ -H "X-API-Key: YOUR_API_KEY") STATUS=$(echo $RESULT | jq -r '.status') if [ "$STATUS" = "done" ]; then echo $RESULT | jq '.data' break elif [ "$STATUS" = "error" ]; then echo "Extraction failed"; break fi sleep 3 done ``` ## File type options The `file_type` field controls how Cloudsquid reads the `file` value: | `file_type` | `file` field | Use when | | ----------- | --------------------------- | ----------------------------------------------- | | `binary` | Base64-encoded file content | Uploading directly from disk | | `uri` | Signed URL string | File is hosted remotely — Cloudsquid fetches it | | `multipart` | Array of parts | Email (RFC 822) with attachments | The `/extract` endpoint blocks until done and returns results in a single response. # From audit to prevention Source: https://docs.cloudsquid.io/concepts/audit-to-prevention The adoption path in three stages — start read-only on historical data, turn findings into recoveries, then run the same checks continuously on live events. Most teams don't start by automating a process. They start by finding out what's actually happening in it. That's the shape of adoption here, and it's deliberate: **proof before automation**. You see real findings from your own data before any process changes, before any system is connected, before anyone is asked to trust an agent with live work. Three stages. ## 1. Audit — start read-only Load historical exports and documents into a fresh project. Nothing is connected; nothing is live. The agent investigates the full population — not a sample — and every finding it reports carries its evidence: the rows it compared, the amounts, the documents. * **Isolated.** A new project with its own data, its own grants. No production system is touched. * **Full coverage.** Sampling was a capacity constraint, not a methodology. The agent checks every transaction because it can. * **Evidence per finding.** A finding without a trace is an opinion. Each one shows what was compared and why it's a problem. * **The worst case is a clean bill of health.** If the checks come back empty, you've learned something worth knowing, at no risk. This is where trust gets earned, because nothing is at stake yet. The cookbook: historical exports into a fresh project, a check-catalog SOP, findings with evidence. ## 2. Recover — findings become work Findings aren't a report you file. They arrive as cases in the [review](/concepts/review-approvals) queue, each with its evidence, and your team decides what to do with each one: raise the dispute, issue the correction, reclaim the credit. The work is real work — approvals, disputes, corrections — and it runs through the same review layer everything else does. What you recover in this stage is what justifies the next one. ## 3. Prevent — the same checks, continuously Here's the part that makes the sequencing worth it: **the checks don't change.** The SOP that found money in a 24-month lookback is the same SOP that runs on live events. What changes is when it runs: | | Audit stage | Prevention stage | | ------- | ------------------------------ | ----------------------------------------------------- | | Input | Historical exports, in a batch | Live events — inbox, tickets, syncs | | Timing | After the fact | Pre-payment, pre-approval | | Trigger | You run it | [Workflows](/concepts/integrations) fire on the event | | Output | Findings to investigate | Cases to approve before money moves | The controls stay on. [Approval gates](/concepts/review-approvals) still sit in front of anything that leaves the system. As confidence grows, [agentic approval](/concepts/review-approvals#agentic-approval-mode) takes the routine cases so your team sees the exceptions, and [RBAC](/concepts/governance) widens access as more of the org adopts the process. And once cases are being reviewed continuously, [the improvement loop](/concepts/improvement-loop) starts feeding reviewer decisions back into the SOP — so the checks get sharper exactly where they were wrong. ## Why this order Catching a duplicate payment after it went out is a recovery. Catching it before it goes out is a control. You want the second one — but you get there by proving the first one works on data nobody can dispute, because it's your own history. Starting at prevention means asking a team to trust an agent with live decisions before they've seen it be right about anything. Starting at audit means the first thing they see is money the agent found, with the evidence attached. Stage one, as a complete recipe. Stage three: the same checks, running continuously on incoming invoices. The control layer that stays on through all three stages. What turns a batch run into a continuous one. # Data access & governance Source: https://docs.cloudsquid.io/concepts/governance Per-table grants, approval gates, a full audit trail, zero retention, SOC 2, ISO 27001, and EU data residency. An agent that can work a real finance process is an agent with real access. The controls are what make that access something you can sign off on. ## Roles and scoping **Users and agents are both scoped to projects.** An agent isn't a superuser that happens to run inside your account — it's permissioned the way a team member is, and it can only reach the project it belongs to. Within a project, members carry a role that determines what they can do: | Role | Can | | ----------------- | -------------------------------------------------------------------------------------------------- | | **Reader** | Read the project — tables, files, and cases with their evidence | | **Reviewer** | Everything a Reader can, plus work the review queue: approve, reject, and comment on cases | | **Project Admin** | Everything in the project, including configuring agents, managing members, and adding integrations | Permissions are granular and scoped to capabilities — configuring agents, approving and rejecting, adding integrations — rather than being all-or-nothing per project. This is what lets you widen access as adoption grows: a controller who only reviews doesn't need the rights to reconfigure the agent, and a stakeholder who only wants to see findings doesn't need either. ## Per-table data access Every reconcile table has a **Data Access** list: the storage and extraction tables its agent may query. That list is the boundary. A table the agent wasn't granted doesn't exist as far as that agent is concerned. Grants are per table, not per project, so two processes in the same project can have different reach — an order-matching agent sees customer and item master; an invoice-audit agent sees POs and receipts. Neither sees the other's data. ## Per-table connector grants The same applies to connected systems. **Connectors** are granted on the reconcile table, so an agent can only use the integrations that process actually needs. Connecting an app to the project makes it available; granting it to a table makes it usable by that agent. ## Approval gates Nothing critical leaves the system on the agent's own authority: * Drafted emails are drafts until someone approves them. * Writes back into a connected system of record pass a gate. Once a process has proven itself, you can hand the routine approvals to an approval agent that checks results against the SOP — see [agentic approval](/concepts/review-approvals). The gate doesn't disappear; the routine cases stop needing a person. ## Full audit trail Every case carries what happened to it: the input it received, the queries the agent ran, the files it read and wrote, the actions it took, its reasoning, the review outcome, and who decided. This isn't a summary written after the fact. It's the record of the work, attached to the case, which is what makes an agent-worked process auditable in a way a person-worked one usually isn't. ## Zero retention For workloads where intermediate results must not be persisted, zero-retention mode runs the process without storing them. * **Per workflow** — toggle it in the workflow's settings. * **Per API run** — pass `"zero_retention": true` on the run request. Zero retention means you don't get the intermediate artifacts either. Use it where the compliance requirement demands it, not by default — the trace is most of what makes review work. ## Compliance and residency * **ISO 27001:2022 certified.** * **SOC 2 compliant** — controls are in place and operating. * **EU data residency** — processing in the EU for customers who require it. ## Least privilege, in one paragraph The design assumption is that the agent will be given exactly what the process needs and nothing else, and that everything it does with that access is visible afterwards. Grants are per table, connectors are per table, the environment is scoped to the project, actions that reach the outside world pass a gate, and the whole run is recorded on the case. When you widen a grant, you're making a deliberate decision, and you can see what was done with it. ## Two standing commitments **Your ERP stays the system of record.** cloudsquid works the process and produces the result; it doesn't become the place your financial data lives. **Nothing posts or pays without approval.** No booking, no payment, no outbound communication happens on the agent's authority alone. How gates and agentic approval work in practice. What the agent can reach, and what scopes it. # The improvement loop Source: https://docs.cloudsquid.io/concepts/improvement-loop Review feedback flows back into the SOP — the process gets better exactly where it failed, and every change is documented and approved. Every reviewed case is feedback. An approval confirms the SOP handled that case correctly. A rejection with a comment marks a place the SOP got it wrong or said nothing at all. The **improvement loop** is what turns that feedback into a better procedure: the agent reads the comments and approval outcomes across your cases, finds the patterns, and proposes a revision to the [SOP](/concepts/sops). A human approves the revision. The new version takes effect. ## The loop Following the current SOP. Some resolve cleanly, some get flagged, some get it wrong. Approve, reject, or mark for review — with a comment explaining the decision. Ask it to look at recent review outcomes. It reads the comments and statuses across cases and looks for patterns: the same correction three times, a category of case that always ends up in `Needs review`. As a concrete change with reasoning — "eight rejections in the last two weeks all correct the shipping method for AT deliveries; here's the rule I'd add, and here's where it goes in the priority order." The revision is a document change you read and sign off on. Then the new version applies to every case that follows. Ask for it in the chat when you want it: > Look at the last two weeks of reviews in Order Match. What are the reviewers correcting most often, and what would you change in the SOP to fix it? Show me the proposed change. ## Why this shape **It improves where it actually failed.** The feedback is attached to real cases with real documents, not to a hypothesis about what might go wrong. **Nothing drifts silently.** The agent does not quietly change how it behaves because it saw a correction. It proposes; a person approves; the SOP file records what changed and why. If someone asks in six months why orders to Austria route the way they do, the answer is in the file's history. **It compounds.** Each round moves cases from `Needs review` into clean automation — and the ones that stay flagged are increasingly the genuinely hard ones, which is where you want your reviewers' attention. ## Write comments the loop can use The quality of the loop is the quality of your rejections. Name the rule, not just the mistake. | Weak | Useful | | -------------------------- | --------------------------------------------------------------------------------------------------------- | | "Wrong" | "Wrong customer — two sites share this postal code; the VAT ID on the order distinguishes them." | | "Bad shipping method" | "We never ship express to AT. Standard road, always, regardless of the customer's default." | | "Should have flagged this" | "Two candidate items matched on description alone — that's never enough to auto-resolve; flag with both." | The second column is a rule the agent can turn into an SOP line. The first is only a score. When you find yourself typing the same correction a third time, that's the signal — ask the agent to propose the SOP change rather than fixing case four by hand. ## Relationship to agentic approval They're two different mechanisms and they work together: * **[Agentic approval](/concepts/review-approvals)** *enforces* the SOP. An approval agent checks each result against the procedure and the output, approving the clean ones and routing anything uncertain to a human. * **The improvement loop** *evolves* the SOP, using what humans decided on the cases that reached them. Enforcement without evolution means the same exceptions land on a human forever. Evolution without enforcement means a good procedure nobody applies consistently. Run both. How the procedure is written and revised. Where the feedback comes from — statuses, comments, approval gates. # Integrations Source: https://docs.cloudsquid.io/concepts/integrations Workflows for deterministic plumbing, agent tokens for contextual action — and how to choose between them. There are two ways cloudsquid connects to the rest of your stack, and they're for different jobs. Structured, Zapier-style flows. Triggers, syncs, and pushes. Deterministic: the same input takes the same path every time. Access-controlled credentials the agent uses directly from [its environment](/concepts/agent-runtime), for actions that depend on judgment. ## Workflows — the plumbing A workflow is a graph: a trigger, then a sequence of actions. Use it for the parts of the process that shouldn't require thought. **Triggers** start a workflow: | Trigger | Fires when | | ------------ | ------------------------------------------------------------------------ | | Email | A message arrives in a connected mailbox or a managed cloudsquid address | | Webhook | An external system posts to your workflow's URL | | Extraction | An extraction run finishes | | Table action | Someone triggers a flow on selected table rows | | Filesystem | A file lands in the project | | Schedule | On a cron schedule | | Manual | Someone runs it by hand | **Actions** do the work: run an extraction, run a reconcile table, call an agent, run Python, branch on a condition, loop over a list, write into a storage table, send an email, update a ticket. Plus connector actions for the app you've connected. Two shapes you'll build early: **Intake.** A support ticket arrives → fetch its attachments → create a case in the reconcile table → the agent works it → update the ticket with the outcome. ``` Zendesk ticket webhook ──▶ fetch attachments ──▶ reconcile table run ──▶ update ticket ``` **Master-data sync.** Keep the agent's reference data current without anyone exporting a CSV. ``` SharePoint (scheduled) ──▶ storage table (overwrite) ``` ## Agent tokens — the judgment calls Some actions can't be pre-wired, because what to do depends on what's in the case. Drafting the right reply to a supplier who sent a partial order isn't a template — it needs the facts of that case. For those, you connect the system and grant the agent a token. The agent then acts from inside its own environment: composing the email with the case's actual data, looking up the record it needs, checking the state of the system before it writes. **Once a system is integrated, the agent can query it directly** — including your ERP. There is no ceiling where the agent hands off to a fixed connector for the interesting part. What bounds it is the grant: which connectors this reconcile table may use, and what that token is allowed to do. Outbound actions still pass the [approval gate](/concepts/review-approvals). A drafted email is a draft until someone approves it. A case doesn't end when the agent sends something, either. When the response lands — the supplier answers, the ticket gets a reply — the agent picks the case back up and carries on from where it left off. ## Choosing between them | Use a workflow when | Use an agent token when | | ------------------------------------------------------- | ----------------------------------------------------------- | | The step is the same every time | What to do depends on the case | | You're moving data between systems on a schedule | You're composing something (a reply, a summary, a decision) | | You need a trigger — something must *start* the process | The action happens mid-process, as part of the agent's work | | The failure mode should be "retry" | The failure mode should be "flag it for a human" | In practice most deployments use both: a workflow brings the event in and pushes the final result out, and the agent uses tokens for everything in between. ## Connecting a system Connectors are managed per project under **Connect**. Connect an app once and it's available to that project's workflows and — where you grant it — to the agent. Beyond the native integrations, cloudsquid connects to hundreds of apps through Pipedream, so most systems your team already uses are reachable without custom work. For systems that expose an MCP server, see [MCP servers](/concepts/mcp-servers). ### Connecting Outlook Outlook connects per project. You can link multiple accounts to one project, and use the same account across projects. **Two ways to connect:** * **Ask the agent** — "Connect my Outlook account". It gives you an authentication link. * **Via Connect** — open the project's **Connect** panel and click **Connect** next to Outlook. Same authentication flow. Once authenticated, cloudsquid creates a folder in your mailbox named **cloudsquid\_\[projectname]**. Any email in that folder is picked up and appears in your project within seconds. **Routing mail into it:** * **By hand** — move or copy any email into the folder. * **By rule** — in Outlook, go to **Settings → Rules → Add new rule**, set your conditions (sender, subject keywords, has-attachment), and choose **Move to folder → cloudsquid\_\[projectname]**. Orders, invoices, or anything else then flow in without anyone touching them. **Managing accounts:** ask the agent "What Outlook accounts are connected?" to list them, or "Disconnect my Outlook account" with the address you want removed. The full intake recipe — mailbox to worked cases, including routing rules and reply drafting — is in the [inbox intake cookbook](/cookbooks/inbox-intake). A shared mailbox turned into structured, worked cases. How the agent uses tokens from inside its environment. Connector grants, approval gates, and zero retention. Extending what the agent can reach. # MCP servers Source: https://docs.cloudsquid.io/concepts/mcp-servers Connect external MCP servers to extend what your project's agent can reach. The Model Context Protocol (MCP) is an open standard for exposing tools to an AI agent. If a system you use runs an MCP server — an internal service, a vendor's hosted server, something your team built — you can connect it to a project and its tools become available to that project's agent. This is the extension point for anything the built-in connectors and [skills](/concepts/skills) don't already cover. ## Adding a server MCP servers are managed per project in the **Customize** panel (**Connect** in the sidebar), under the **MCP Servers** tab. Add a server with its URL and, where it needs one, its authentication. Once connected, the server's tools appear to the agent alongside its native ones. The agent picks the right tool for the task the same way it picks any other — from the tool's name and description. ## Access control applies An MCP server is access like any other. It's added to a specific project, so agents in other projects can't use it, and what a tool can do is bounded by the credentials you gave the server. Actions that reach the outside world still pass the same [approval gates](/concepts/review-approvals) as any other outbound action, and every tool call the agent makes is recorded on the case's trace. Packaged instructions and code, the other extension point. Native connectors, workflows, and agent tokens. # Extraction pipelines Source: https://docs.cloudsquid.io/concepts/pipelines Model configurations for extraction tables and the extraction API — choose between cloudsquid-flash and cloudsquid-pro based on your accuracy and speed requirements. **Scope:** pipelines apply to **extraction tables and the extraction API only**. The reconcile-table agent does not use pipelines — it uses model tiers (**Fast / Balanced / Powerful**), configured per table under **AI Model**. See [the agent runtime](/concepts/agent-runtime). The two sets of names are not interchangeable. A pipeline is the AI model configuration used for an extraction run. You set a default pipeline per extraction table via the settings API, and it applies to every run on that table unless overridden. ## Comparison | Pipeline | Speed | Accuracy | Best for | | --------------------- | --------------- | -------- | ---------------------------------------------------------------- | | `cloudsquid-flash` | Fastest | Good | High-volume, cost-sensitive, simple schemas | | `cloudsquid-flash-v3` | Fast | Better | **Default starting point** — good balance of speed and quality | | `cloudsquid-pro-v2` | Slower (10–30s) | High | Complex documents, nested schemas | | `cloudsquid-pro-v3` | Slower | Highest | Dense or visually complex layouts, highest accuracy requirements | Start with `cloudsquid-flash-v3` for all new tables. Switch to `cloudsquid-pro-v3` only if accuracy on complex document layouts is insufficient. ## Bounding boxes Enabling `bounding_boxes` adds source-location metadata to each extracted value — a reference back to the exact position in the original document. Useful for auditability and human review workflows, but increases processing time regardless of pipeline. ## How to set a pipeline Use the extraction settings endpoint to update a table's active pipeline. ```python Python theme={null} import requests requests.patch( "https://api.cloudsquid.io/api/projects/my-project/tables/TABLE_ID/extraction-settings", headers={"X-API-Key": "YOUR_API_KEY"}, json={ "active_pipeline": "cloudsquid-flash-v3", "bounding_boxes": False, "review_mode": False } ) ``` ```bash cURL theme={null} curl -X PATCH \ "https://api.cloudsquid.io/api/projects/my-project/tables/TABLE_ID/extraction-settings" \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"active_pipeline": "cloudsquid-flash-v3", "bounding_boxes": false, "review_mode": false}' ``` How reconcile, storage, and extraction tables work together. The three-step upload → start → poll flow. Model tiers for the reconcile-table agent — a different subsystem. Set up an extraction table end to end. # Projects Source: https://docs.cloudsquid.io/concepts/projects A project is the workspace for one domain of work — its files, tables, SOPs, integrations, and the agent that works them. A **project** is the unit of work in cloudsquid. It holds one domain of work — Order Entry, AP Invoice Audit, Customer Master Data — with everything that process needs in one place, and an agent that operates inside it. If you're used to thinking in tools, think of a project as the desk of one team member: their filing cabinet, their reference data, their written procedure, their inbox, and their access badges. ## What's in a project Folders and files: incoming documents, your `SOP.md`, exports, and anything the agent produces. The agent reads and writes here. Reconcile tables (where processes run), storage tables (your master data), extraction tables (document structuring). Triggers, syncs, and pushes — the deterministic plumbing around the process. Connectors, skills, and MCP servers available to this project's agent. **Project Settings** covers the project-level basics: name, members, and project-wide configuration. ## The agent lives in the project There is no separate "agent object" to configure. Every project has an agent you talk to in the chat panel, and it operates on that project: * It sees the project's **files and folders** — including your SOP. * It can query the tables it has been **granted** access to. Grants are per reconcile table, in **Data Access** — see [Governance](/concepts/governance). * It can use the project's **connectors, skills, and MCP servers**. * It runs in [its own environment](/concepts/agent-runtime), so it can actually work: run SQL, analyze a spreadsheet, open a PDF, draft an email. The project boundary is a real boundary. An agent in `Order Entry` cannot read `Payroll`'s files or tables. ## SOPs live in Files The project's procedure is a Markdown file, `SOP.md`, at the root of the project's Files. The agent loads it automatically and follows it. **One project = one process = one SOP.** The project *is* the process scope. That's what makes "which rules applied to this case" always answerable, and it's the rule that decides how you carve up your work: * A **different process** means a **different project**. * **Steps of the same process** are **tasks in one reconcile table**, sharing the one SOP — not projects, and not separate tables. Supporting documents — routing rules, code lists, worked examples — can live alongside `SOP.md` as separate files, referenced from it so the agent knows to open them. See [SOPs](/concepts/sops). See [SOPs](/concepts/sops) for how to write one and how the agent helps. ## The agent produces deliverables into the project The agent doesn't only fill in table rows. Ask it for something in the chat — a summary of last week's cases, a reconciliation report, a cleaned-up export — and it does the analysis and writes the file into the project's Files, where you (and your team) can download it. This is on demand, not a scheduled job: you ask, it produces. Give the outputs a home — a `Reporting` folder in Files keeps generated deliverables out of your incoming documents. ## When to split into multiple projects Use one project per **process and audience**. Split when: * **The reference data differs.** Order matching needs customer and item master; invoice audit needs POs and receipts. Different data, different grants. * **The procedure differs.** A project has one `SOP.md`, so two genuinely different procedures are always two projects. This is the clearest signal of the four. * **The reviewers differ.** Project boundaries are also access boundaries — put a process where the people who review it can reach it and others can't. * **The connected systems differ.** Keep an ERP-connected process separate from an unconnected sandbox. Keep them together when it's the same process at a different volume or in a different language — that's one project, and often one reconcile table with more tasks. ## Where to go next Reconcile, storage, and extraction tables — and how they chain. Teaching the agent your process in plain Markdown. What the agent can reach and how it does the work. Data access grants, approval gates, and the audit trail. # Review & approvals Source: https://docs.cloudsquid.io/concepts/review-approvals Statuses, assignment, evidence, and approval gates — with an approval agent for the routine cases and humans for the exceptions. Review is not a step bolted onto the end. It's where the process is actually controlled: every case arrives with its source data, what the agent did, and why — and someone decides. Nothing critical leaves the system without an approval. ## Statuses A case moves through a lifecycle you can filter and report on: | Status | Meaning | | -------------- | ------------------------------------------------------------------------------- | | `Pending` | Queued, not yet picked up | | `Running` | The agent is working the case | | `Agent Done` | The agent finished; no review outcome yet | | `Needs review` | Flagged — by the agent, an approval agent, or a human — and waiting on a person | | `Approved` | Reviewed and accepted | | `Rejected` | Reviewed and refused | | `Error` | The run failed | | `Archived` | Closed out and hidden from the working views | `Needs review` is the interesting one. It is not a failure state — it's the agent declining to decide something it can't decide safely. See [honest uncertainty](#honest-uncertainty) below. ## Assignment Cases can be assigned to people, so a queue is a queue and not a shared mailbox nobody owns. * **Assign** a case to a reviewer. * **Assigned to me** — a reviewer's working list. * **Unassigned** — everything nobody has picked up. Filter on it so cases don't sit unclaimed. Combine with status filters for the views your team actually works from: *Needs review · Unassigned* is where a controller starts their morning. ## What a case shows Open a case and you get the evidence, not a verdict: * **Source document** — the original file, alongside the result. * **Input data** — what came in: the payload, the file references, the trigger. * **Output fields** — the structured result the agent produced. * **Reasoning** — what the agent concluded and why, in its own words. * **The actions taken** — the queries it ran, the files it read and wrote, the emails it drafted. * **References** — the master-data records it matched against, so you can check the match rather than trust it. A reviewer's job is to check the reasoning against the source, not to redo the work. ## Comments Reviewers comment on a case — with @-mentions to pull in a colleague and attachments where they help. Comments aren't just a paper trail. **The agent reads them.** A rejection that names the rule ("we never ship express to AT") becomes something the agent can apply and, later, propose as an SOP change through [the improvement loop](/concepts/improvement-loop). ## Approval gates Some actions wait for a human by design: * **Outbound communication** — an email the agent drafted is a draft until someone approves it. * **Critical pushes** — writing a result back into a connected system of record. The agent does the work up to the gate: the reply is written, the fields are filled, the case is ready. A person's decision is the last step, not the whole job. Your ERP stays the system of record. Nothing posts, pays, or leaves without an approval. ## Agentic approval mode Once a process is stable, having a person confirm every clean case stops being control and starts being throughput cost. Turn on **Auto Review** on the reconcile table and a second agent — an approval agent — checks each result before it reaches a human. It sees the agent's output and its reasoning, checks them against the [SOP](/concepts/sops), and looks for duplicates already in the table. Then it decides: | Decision | When | | ---------------- | ----------------------------------------------------------------------------------------------------- | | **Approved** | The agent was confident, nothing was flagged, no duplicates — the case can continue | | **Needs review** | The agent flagged uncertainty, escalated, hit a conflict, or a duplicate was found — a human takes it | | **Rejected** | The output is unusable — broken or nonsensical values — and the case is blocked | It defaults to `Needs review` when it isn't sure, and attaches a one-line comment saying why. You keep the exceptions; it clears the routine. Turn Auto Review on after you've reviewed a few hundred cases by hand and your SOP reflects what you learned. Enabling it on a young process just automates an unfinished procedure. ## Honest uncertainty When the agent can't resolve something safely, it says so and shows its work: > Two candidate customers match "Meridian Handels" at postal code 8010 — customer 40118 (Meridian Handels GmbH, Ostbahnstrasse 14) and customer 40233 (Meridian Handels GmbH, Ostbahnstrasse 14a). The order carries no VAT ID or contact email to distinguish them. Flagged with both candidates. That case gets `Needs review` with the candidates listed. No customer number was invented. This is the system working. An agent that guesses to keep its automation rate up is worse than useless in a finance process — the wrong answer costs more than the missing one. Cases that stay flagged are telling you where your procedure is genuinely ambiguous, which is exactly the input the [improvement loop](/concepts/improvement-loop) needs. Turning review feedback into a better SOP. Grants, gates, audit trail, and data residency. Where stop-and-escalate rules are written. The Auto Review toggle and the rest of a reconcile table's configuration. # Skills Source: https://docs.cloudsquid.io/concepts/skills Packaged instructions, reusable code, and templates that teach a project a new capability. A **skill** is a package the agent can pick up and use: instructions, reusable code, and templates bundled together. It's the same idea as Claude skills — a capability you hand the agent once and it applies whenever the task calls for it. Where an [SOP](/concepts/sops) says *how this process works*, a skill says *how to do this thing* — and it can be used by any process that needs it. ## Skill or SOP? | | **SOP** | **Skill** | | ------------ | -------------------------------------------------- | ----------------------------------------------------- | | Scope | One process | Reusable across processes | | Content | Decision rules, tolerances, escalation | Instructions plus code and templates | | Example | "Match on name + postal code, email as tiebreaker" | "Generate the weekly automation report in our format" | | Changes when | The process changes | The capability changes | Rules of thumb: * If it's a **judgment call about this process**, it belongs in the SOP. * If it's a **repeatable piece of work with a fixed output shape** — a report format, a document template, a transformation you'd otherwise re-explain — make it a skill. * If you find yourself pasting the same instructions into two different projects, that's a skill. ## What's in a skill A skill is a folder containing a `SKILL.md` file with the skill's name and description, followed by the instructions themselves. Supporting files — scripts, templates, examples — live alongside it in the folder and the instructions point at them. The name and description matter: they're how the agent knows the skill exists and when to reach for it. "Weekly automation report — produces the ops summary xlsx from a reconcile table's cases" is discoverable. "Report helper" is not. Skills can carry **secrets** (an API key a script needs). Those are stored encrypted and injected as environment variables when the agent runs, so they never sit in the instruction text. ## Managing skills Skills are managed per project in the **Customize** panel (**Connect** in the sidebar), under the **Skills** tab, alongside **Connectors** and **MCP Servers**. You can: * **Upload a skill folder** containing a `SKILL.md` at its root. * **Create one with the agent** — describe the capability in the chat and have it write the skill. Once added, the skill is available to that project's agent — it appears in the agent's context with its name and description, and the agent opens the full instructions when it needs them. Start by writing the instructions as a chat message that worked. When you've had to send it twice, turn it into a skill. Process rules, as opposed to reusable capabilities. The other way to extend what the agent can do. # SOPs: teaching the agent your process Source: https://docs.cloudsquid.io/concepts/sops Your standard operating procedure as a Markdown file the agent follows — readable, diffable, approvable, and written together with the agent. An **SOP** is your process, written down. In cloudsquid it's a Markdown file — `SOP.md` — in the project's Files. The agent loads it and follows it on every case. That choice matters more than it looks. Because the procedure is a file: * **Anyone can read it.** Your controller can check what the agent will do without opening a config screen or learning a rule syntax. * **Changes are diffable.** "What changed after last month's mismatch?" is answerable. * **It's approvable.** A process change is a document change someone signed off on. * **The agent can improve it.** It reads your review comments and proposes revisions — see [the improvement loop](/concepts/improvement-loop). You are not configuring software. You are training a new team member, and the SOP is what you hand them. ## Anatomy of a good SOP A good SOP reads like something you'd hand a new hire on day one — specific, ordered, and explicit about when to stop. Name the fields and where they come from. "The buyer's VAT ID is on the order header, sometimes in the footer" saves the agent a guess on every case. Not "match the customer" but a sequence: try this, then this, then this. Order encodes priority, and priority is most of the judgment. "Amount may differ by up to 2% or €10, whichever is smaller" is a rule. "Roughly the same" is not. The most valuable lines in the file. Say exactly when the agent must stop, flag, and list candidates instead of deciding. One or two real cases with the expected outcome. Examples resolve ambiguity that prose can't. ### A concrete fragment Here's what a real match section looks like — from an order-matching SOP: ```md theme={null} ## Customer matching ### Step 1 — Name + address Match the buyer block against `customer_master` on company name AND postal code. Normalize before comparing: - Strip legal-form suffixes: GmbH, AG, Ltd, B.V., S.p.A., Inc. - Expand or strip umlauts both ways: ü ⇄ ue, ö ⇄ oe, ä ⇄ ae, ß ⇄ ss - Ignore case, punctuation, and extra whitespace - Treat "Str.", "Strasse", "Straße" as equivalent A match on normalized name + postal code is a **confident match**. ### Step 2 — Email tiebreaker If Step 1 returns more than one candidate, compare the sender address and any contact email on the document against `customer_master.email`. An exact email match resolves the tie. A domain-only match does not — several sites of one group share a domain. ### Step 3 — Decide or flag - Exactly one confident match → set `customer_number`, `match_status: matched`. - Two or more candidates after Step 2 → set `match_status: ambiguous`, write the candidate customer numbers into `match_candidates`, and stop. Do not pick one. - No candidate → set `match_status: unmatched` and note in the comment what you searched for. Do not create a customer. **Never** invent a customer number. An unmatched order is a normal outcome; a wrong customer number is a shipment to the wrong company. ``` Note what's doing the work: the normalization list, the numbered order, and the last paragraph. That's the difference between an agent that guesses and an agent you can trust. ## The lifecycle: the agent drafts, you correct You don't write the first draft from a blank page. Point it at your master data and a handful of real documents and ask for an SOP. It reads them and proposes a procedure grounded in what's actually in your files — the field names you use, the shapes your documents come in. A good draft ends with **open questions**: "Two customers share this address — how do you distinguish them?" "Do partial deliveries get one case or several?" These are exactly the questions a new hire would ask in week one. Not an engineer — the person who actually knows the process. They answer in the chat; the agent revises the file. The SOP carries a version stamp and the latest approver, so process changes stay reviewable. Keep both in a header line at the top of the file. The open-questions step is where most of the value is. An agent that says "I don't know how you handle this" is telling you where your process was ambiguous all along. ## Editing by chat You don't have to hand-edit the file. Ask: > We've decided: express shipping to Austria always goes via road, never air. Update the SOP. The agent edits `SOP.md`, explains what it changed, and — importantly — flags decisions it had to make on your behalf: "I put this under shipping resolution as a hard rule, above the customer default. Confirm that outranks a customer's standing air preference." Review that flag before you move on. It's the agent showing its work on the one thing it couldn't know. ## SOPs vs. the Operating Procedures field Two different things, easily confused: | | **Operating Procedures** (table setting) | **`SOP.md`** (file) | | -------- | ---------------------------------------- | ---------------------------- | | Where | The reconcile table's **Configure** view | The project's Files | | Length | One or two lines | As long as the process needs | | Contains | The standing instruction and a pointer | The actual procedure | | Changes | Rarely | As the process is refined | Keep **Operating Procedures** to something like `Match incoming orders according to the SOP.` and put everything else in the file. A procedure buried in a text box isn't reviewable, isn't diffable, and can't be improved by the loop. ## One SOP per project **One project, one process, one SOP.** It's `SOP.md`, at the root of the project's Files, and it's what the agent loads and follows. This is a constraint worth keeping. One procedure per project means there's never a question about which rules applied to a case. If you find yourself wanting a second SOP, you have a second process — give it its own [project](/concepts/projects). Two things that are *not* exceptions to this: * **Language copies.** `SOP.md` and `SOP_DE.md` can sit side by side. That's the same procedure in two languages so the team that owns it can read it in theirs — one process definition, two renderings. Not two SOPs. * **Supporting documents.** When a process gets big, don't split the SOP — split the *detail* out of it. A routing table, a code list, a set of worked examples go in their own files alongside `SOP.md`, referenced from it so the agent knows to open them. The procedure stays in one place; the lookup material lives next to it. Steps of one process aren't separate SOPs either — they're separate tasks in one [reconcile table](/concepts/tables), sharing this file. How review feedback turns into SOP revisions. The PO matching cookbook ships a full, copy-paste SOP. Where the SOP's stop-and-escalate rules show up. Reusable capabilities, as opposed to this process's rules. # Tables: reconcile, storage, extraction Source: https://docs.cloudsquid.io/concepts/tables Reconcile tables run your processes, storage tables hold your master data, extraction tables structure documents at volume. Every project contains tables, and tables are typed. The type determines what a table is for, what operations it supports, and how the agent uses it. Start with the one that does the work. ## Reconcile tables A **reconcile table** is where a process runs. Each row is one **case**: an event came in, the agent worked it following your [SOP](/concepts/sops), and the row holds the result — output fields, the reasoning, the actions taken, and a review status. An order arrives as a PDF. That's one row. The agent reads the document, queries your customer master, applies the match rules, fills `customer_number` and `match_status`, notes why, and hands the case to review. **What you configure** (in the table's **Configure** view): | Setting | What it does | | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | | **Operating Procedures** | The agent's standing instruction for this table. Keep it short and point at the SOP — the real procedure belongs in `SOP.md`. | | **Output Fields** | The structured result the agent produces per case. Each field has a name, a type, and a description the agent reads. | | **Data Access** | Which storage and extraction tables this agent may query. It can only touch what you grant. | | **Connectors** | Which connected systems this agent may use from its environment. | | **AI Model** | The model tier for this table: **Fast**, **Balanced**, or **Powerful**. See [the agent runtime](/concepts/agent-runtime). | | **File Outputs** | Lets a case produce files, not just field values — a drafted document, an export, a generated report. | | **Auto Review** | Turns on [agentic approval](/concepts/review-approvals): a second agent validates each result before it needs a human. | **Input.** A case can carry files (documents to work from), structured data (a JSON payload), or both. Reconcile tables take files directly — you do not need an extraction table in front of them. **Statuses.** A case moves `Running → Agent Done`, then through review to `Approved`, `Needs review`, or `Rejected`. See [Review & approvals](/concepts/review-approvals). **Unit of work.** Usually one reconcile table per process. If your process has distinct steps that each deserve their own record, model the steps as tasks in one shared table rather than splitting into many tables. **Key API operations:** * Create a task (without running it) → `POST /projects/{name}/tables/{id}/tasks` → returns `task_id` * Run reconciliation synchronously → `POST /projects/{name}/tables/{id}/reconcile` * Use the [async run pattern](/concepts/async-run-pattern) with the `row_id` from a task **Input format:** `AgentJobInput` — pass `files` (references to extraction table rows by UUID) and/or `data` (arbitrary JSON payload). *** ## Storage tables A **storage table** holds reference data: your customer master, item master, price lists, PO headers, carrier codes, GL mappings. It's the "against what" of every matching process. The agent queries storage tables directly with SQL from its environment — it is not handed a pre-filtered slice. That means it can look up, join, count, and check candidates the way an analyst would, but only in the tables you granted under **Data Access**. **Make your columns legible.** The agent reads your schema to understand your data. `postal_code` and `vendor_item_number` are useful; `col_7` and `f3` are not. Add a description to any column whose name isn't self-explanatory. **Keeping it fresh.** Load a CSV by hand, push rows via the API, or sync from a source system on a schedule with a [workflow](/concepts/integrations). **Key API operations:** * Upload or overwrite a CSV → `PUT /projects/{name}/tables/{id}` (mode: `overwrite` or `append`) * Insert rows as JSON → `POST /projects/{name}/tables/{id}/data` * Read rows → `GET /projects/{name}/tables/{id}/data` *** ## Extraction tables An **extraction table** turns documents into structured rows at volume. One row per file, one column per extraction task, a schema you define. It's a helper, not a process: it structures, it doesn't decide. **When it earns its place:** high document volume with a stable shape, where pre-structuring is cheaper and faster than having the agent read every file from scratch — or when structured rows are the deliverable themselves. **What it gives you:** * Nested output: a header record plus its line items in one row. * A side-by-side source view — every value next to the page it came from. * **Run AI** on selected rows only, so re-running after a schema change is cheap. * Optional **bounding boxes** (where in the document each value came from) and **Review mode** (a human approval gate before rows are considered final). **Settings:** `active_pipeline` (see [Extraction pipelines](/concepts/pipelines)), `bounding_boxes`, `review_mode`. **Key API operations:** * Upload a file → `POST /projects/{name}/tables/{id}/files` → returns `row_id` * Start an AI run → `POST /projects/{name}/tables/{id}/run` → returns `run_id` * Poll for results → `GET /projects/{name}/tables/{id}/run/{run_id}` * Extract synchronously → `POST /projects/{name}/tables/{id}/extract` See the [extraction quickstart](/quickstart-extraction). *** ## How they chain **The common case — files straight into the process:** ``` documents ──▶ reconcile table ──▶ review ──▶ output │ └── queries ──▶ storage tables (master data) ``` The reconcile table takes the files, the agent reads them, queries master data, and produces the case. Two table types, no pre-processing step. **Adding extraction, when volume calls for it:** ``` documents ──▶ extraction table ──▶ reconcile table ──▶ review ──▶ output (structured rows) │ └── queries ──▶ storage tables ``` Extraction structures the documents first; the reconcile table receives rows instead of raw files. Same process, less work per case — worth it once you're running thousands of similar documents. Start without the extraction table. Add it when per-case latency or cost tells you to, not before. *** The procedure the reconcile agent follows. Statuses, evidence, assignment, and approval gates. Model configurations for extraction tables and the extraction API. The three-step upload → start → poll flow. # Cookbooks Source: https://docs.cloudsquid.io/cookbooks/index Complete recipes for real finance and operations processes — each with a copy-paste starter SOP, sample data, and a full walkthrough. A cookbook is a complete recipe for one process: the architecture, a working starter `SOP.md` you can copy into your project today, sample data, and a walkthrough from setup to reviewed cases. They exist because the hard part of a new process isn't clicking through the setup — it's knowing what a good procedure looks like. So every cookbook ships one. ## What's in each cookbook Who has this problem and what it costs them. The flow, end to end. Tables, master data, integrations, model tier. A complete, copy-paste procedure. Change the field names to yours and it runs. Setup, first cases, and what good looks like in review — including one case the agent correctly refuses to auto-resolve. Editing the SOP by chat, running the improvement loop, then triggers, agentic approval, and thresholds. ## The promise Copy the SOP, adapt the field names, run your first cases today. The starter is a real procedure, not a stub — and it's a good starting point for [the improvement loop](/concepts/improvement-loop) to refine against your actual review feedback. All sample data in these cookbooks is invented — companies, products, codes, and values. Replace it with your own. ## Available cookbooks **Start here.** Point an agent at 12–24 months of your own AP history, read-only, and get evidence-backed findings. Nothing connects to a production system. Purchase orders arrive in every shape. Match buyer to customer master, line items to item master, resolve shipping, draft the confirmation. Cross-reference vendor invoices against POs and receipts. Catch duplicates, price and quantity mismatches, and missed credits — continuously. Turn a shared mailbox into structured, worked cases — routing, attachments, special requests, and drafted replies. **Run an audit** and **vendor invoice audit** are the same checks at two stages: one looks backward over history, the other runs on invoices as they arrive. See [from audit to prevention](/concepts/audit-to-prevention) for why that order matters. More recipes are on the way: vendor statement reconciliation, master-data sync and dedup, the month-close pattern, and agent-generated reporting. Start with the quickstart — it builds a miniature version of the PO matching recipe in about 15 minutes. # Invoice automation: vendor invoice audit Source: https://docs.cloudsquid.io/cookbooks/invoice-audit Cross-reference vendor invoices against POs and receipts — catch duplicates, price and quantity mismatches, and missed credits, with a starter SOP you can copy. ## The job AP receives vendor invoices and pays them. Somewhere between the PO, the goods receipt, and the invoice, things drift: a price that isn't the one that was agreed, a quantity billed that was never delivered, a credit note that was issued and never applied, the same invoice submitted twice under two numbers. Checking every invoice against its PO and receipt is exactly the work nobody has time for, which is why it's usually sampled — and why the errors that get through are systematic rather than random. This is the **continuous** sibling of [run an audit](/cookbooks/run-an-audit). That recipe runs these checks backward over 12–24 months of history to find money already lost; this one runs them on invoices as they arrive, before payment. Most teams do the lookback first — see [from audit to prevention](/concepts/audit-to-prevention). ## What you'll build ``` vendor invoices ──▶ Invoice Audit (reconcile table) ──▶ review ──▶ approved / disputed │ ├── queries ──▶ PO Master (storage) ├── queries ──▶ Goods Receipts (storage) └── queries ──▶ Credit Notes (storage) ``` * Each invoice becomes a case. * The agent matches it to its PO, checks the received quantities, compares line prices against agreed prices, looks for duplicates and unapplied credits, and produces an audit verdict. * Clean invoices come back `pass`. Everything else comes back with the specific discrepancy, the amount at stake, and the evidence. ## Ingredients | | | | ------------------- | -------------------------------------------------------------------------------------- | | **Reconcile table** | `Invoice Audit` | | **Storage tables** | `po_master`, `goods_receipts`, `credit_notes`, `vendor_master` | | **Model tier** | **Balanced**; **Powerful** for multi-page invoices with long line detail | | **Integrations** | Optional: `invoices@` mailbox intake, and a push of the verdict back to your AP system | | **Auto Review** | Enable only for `pass` verdicts under your escalation threshold | ## The starter SOP ```md theme={null} # SOP — Vendor invoice audit Version 1.0 · Owner: Accounts Payable · Last approved by: , ## Purpose Verify each vendor invoice against its purchase order and goods receipt before it is approved for payment. Report discrepancies with evidence. Do not correct the invoice. Do not approve payment. ## Step 1 — Match the invoice to a PO Match in this order, stop at the first hit: 1. PO number quoted on the invoice → exact match in `po_master`. 2. Vendor + invoice line articles + date window (invoice date minus 90 days) → single open PO with matching articles. 3. No match → `po_match_status: unmatched`, list up to five candidate PO numbers with vendor, date, and open amount. Stop here. Confirm the vendor on the matched PO equals the invoicing vendor in `vendor_master`. If not, flag — never override the vendor. ## Step 2 — Duplicate detection Before checking anything else, look for a duplicate: - **Exact duplicate**: same vendor + same invoice number → `duplicate: true`, verdict `fail`, name the earlier case. Stop. - **Near duplicate**: same vendor + same total amount + invoice dates within 10 days, different invoice number → `duplicate: suspected`, verdict `needs_confirmation`. List the other invoice. Do not decide. - Same vendor and amount more than 10 days apart with different articles is not a duplicate — recurring charges look like this. ## Step 3 — Quantity check against receipt For each invoiced line, compare the billed quantity to the received quantity in `goods_receipts` for that PO line. - Billed ≤ received → pass. - Billed > received → `quantity_variance` with the difference. Partial deliveries are normal; billing ahead of receipt is not. - No receipt at all for the PO line → flag as `not_received`. Service lines without a receipt are expected — say so rather than failing them. ## Step 4 — Price check against the PO Compare each invoiced unit price to the agreed price on the PO line. Tolerance: the smaller of **2%** or **10.00** per unit. - Within tolerance → pass. - Above tolerance → `price_variance` with agreed price, billed price, the per-line difference, and the total exposure across the invoice. - Below the agreed price → report it too. An unexplained discount is a data problem worth knowing about. Currency must match the PO. A different currency is always a flag, never a conversion. ## Step 5 — Credit note check Search `credit_notes` for open credits from this vendor that reference this PO, this invoice, or any of its articles. Any open credit not applied on the invoice → `unapplied_credit` with the credit number and amount. ## Step 6 — Verdict Set exactly one: - `pass` — matched to a PO, no duplicate, quantities and prices within tolerance, no unapplied credits. - `needs_confirmation` — resolved, but a human should confirm before payment: suspected near-duplicate, a variance inside tolerance but on a high-value line, a service line with no receipt, or a price variance the vendor has a documented reason for. - `fail` — a definite problem: exact duplicate, unmatched PO, vendor mismatch, quantity billed over received, price variance above tolerance, or an unapplied credit. The middle bucket matters. Most invoices are not clean-or-broken — they are fine but worth a glance. Do not push those into `pass` to look tidy, and do not push them into `fail` and bury the real problems. ## Escalation thresholds - Total exposure above **5,000.00** → always a human, whatever the verdict. - Any new vendor with no prior invoices → always a human. - More than three flagged lines on one invoice → escalate the whole invoice rather than reporting line by line. ## Outputs Fill every output field. In the comment, state: which PO it matched and how, what you checked, every discrepancy with its amount, and the total exposure. A reviewer should be able to decide without opening the PDF. ``` ## Walkthrough Create `po_master`, `goods_receipts`, `credit_notes`, and `vendor_master` as **Storage** tables. Keep them current with a scheduled [workflow](/concepts/integrations) against your ERP — stale PO data produces false variances, which is the fastest way to lose your reviewers' trust. `Invoice Audit`, with **Operating Procedures**: `Audit incoming vendor invoices according to the SOP.` **Output Fields**: `invoice_number`, `vendor`, `po_number`, `po_match_status`, `duplicate`, `quantity_variance`, `price_variance`, `unapplied_credit`, `total_exposure`, `verdict`, `flags`. Grant **Data Access** to all four storage tables. Run last month's invoices — a set where you know what was clean and what wasn't. It calibrates the tolerances and shows you what the agent flags that your process currently misses. Work the `fail` cases first, then `needs_confirmation`. Comment with the rule, not the outcome: "this vendor's framework agreement supersedes the PO price — check the agreement before flagging" is something the SOP can absorb. ### What good looks like **A clean pass:** > Matched invoice INV-77301 to PO 4500219 on the quoted PO number; vendor Halvard Supply matches. No duplicate — no other Halvard invoice at 3,412.00 in the last 90 days. All 4 lines received in full. Prices match the PO exactly. No open credits for this vendor. Verdict: pass. Exposure: 0.00. **A case the agent correctly refuses to resolve:** > Invoice INV-77354 from Halvard Supply, 3,412.00, dated 4 days after INV-77301 for the same amount. Different invoice number and different article on line 2 (ART-5590 vs ART-5591), so this is not an exact duplicate — but the amount and window match the near-duplicate rule. `duplicate: suspected`, verdict `needs_confirmation`. Both invoices listed. Not deciding: the article difference could be a genuine second delivery or a re-issue with a typo, and the vendor's remittance history doesn't distinguish them. The agent did the whole comparison and then stopped exactly where the evidence stopped. That's a ten-second decision for AP instead of a twenty-minute investigation. ## Iterating Vendor-specific reality is what the starter SOP can't know. It arrives through review comments: > Reviewers keep overriding price variances for Halvard Supply — they have a framework agreement with quarterly price steps that the PO doesn't reflect. Add a rule: for vendors with a framework agreement, check the agreement price before flagging a variance, and flag the PO as stale instead. Then run [the improvement loop](/concepts/improvement-loop) monthly against the accumulated review feedback. ## Hardening Route `invoices@` into the project so cases are created as invoices arrive. Enable **Auto Review** so clean invoices under your threshold clear automatically and AP works the exceptions. A workflow writes the audit result onto the invoice in your AP system. It stays the system of record; nothing pays without approval. At volume, structure invoice headers and line items first, then audit the rows. The same checks over 12–24 months of history — read-only, and usually where teams start. Why the lookback comes first, and what changes when these checks go continuous. All vendor names, invoice numbers, article numbers, and amounts in this cookbook are invented. Replace them with your own data. # Order processing: PO matching Source: https://docs.cloudsquid.io/cookbooks/po-matching Purchase orders arrive in every shape. Match the buyer to customer master, line items to item master, resolve shipping, draft the confirmation — with a starter SOP you can copy. ## The job Purchase orders arrive by email and ticket in every shape a customer feels like sending: a clean PDF from an ERP, a free-text email that says "same as last time plus 200 of the blue ones", a phone photo of a signed order form. Someone in order entry reads each one, finds the customer in the ERP, matches every line to an article number, works out the shipping, and types it in. It's high volume, it's judgment-heavy in exactly the places that are hard to script, and a mistake ships the wrong goods to the wrong company. ## What you'll build ``` order documents ──▶ Order Match (reconcile table) ──▶ review ──▶ confirmation draft │ ├── queries ──▶ Customer Master (storage) └── queries ──▶ Item Master (storage) ``` * Orders land as cases in a reconcile table — from upload, a mailbox, or a ticket webhook. * The agent reads the document (including photos and scans), matches the buyer against customer master, matches every line against item master, resolves the shipping method, and fills the output fields. * Anything it can't resolve confidently is flagged **with its candidates** rather than guessed. * Clean cases carry a drafted order confirmation, waiting on approval. ## Ingredients | | | | ------------------- | ------------------------------------------------------------------------------------------ | | **Reconcile table** | `Order Match` — where the process runs | | **Storage tables** | `customer_master`, `item_master` — granted read access | | **Model tier** | **Balanced** to start; **Powerful** if your documents are photos or dense multi-page forms | | **Integrations** | Optional: a mailbox or ticket webhook to trigger cases. Start with manual upload. | | **Auto Review** | Off at first. Turn it on once your SOP reflects a few hundred reviewed cases. | **Master data shape** (invent your own column names to match your system): ``` customer_master: customer_number, company_name, street, postal_code, city, country_code, contact_email, vat_id, default_shipping_agent item_master: article_number, description, vendor_item_number, unit, pack_size, weight_kg, hazard_class ``` ## The starter SOP Create this as `SOP.md` in your project's Files. Change the field names to yours; the structure is the part that matters. ```md theme={null} # SOP — Incoming order matching Version 1.0 · Owner: Order Entry · Last approved by: , ## Purpose Turn an incoming purchase order document into a structured, verified order record: the right customer, the right articles, the right shipping method. Flag anything that cannot be resolved confidently. Never guess. ## Field mapping — what to read off the document | Output field | Where to find it on the order | |---------------------|--------------------------------------------------------| | order_number | Buyer's PO number. Header, often top right. | | order_date | Header. Formats vary — see Conventions. | | customer_number | Resolved by matching, not read off the document. | | buyer_name | The company in the buyer/bill-to block. | | buyer_address | Street, postal code, city, country of the buyer block. | | contact_email | Sender address, or the contact block on the document. | | delivery_address | Ship-to block if present, otherwise the buyer address. | | requested_date | Delivery/arrival date requested by the buyer. | | shipping_agent_code | Resolved by the shipping rules below. | | line_items | One entry per ordered position. | ## Conventions - Dates are DD.MM.YYYY unless the document is clearly US-formatted (month name spelled out, or a value > 12 in the first position). - Quantities are pieces unless a unit is stated. Note the stated unit. - Prices are net. If the document says "incl. VAT", record it and flag. ## Step 1 — Customer: name + address Match the buyer block against `customer_master` on company name AND postal code. Normalize before comparing: - Strip legal-form suffixes: GmbH, AG, Ltd, B.V., S.p.A., Inc., KG - Handle umlauts both ways: ü ⇄ ue, ö ⇄ oe, ä ⇄ ae, ß ⇄ ss - Ignore case, punctuation, and extra whitespace - Treat "Str.", "Strasse", "Straße" as equivalent - Common abbreviations are equal: "Intl" = "International", "&" = "und" A match on normalized name + postal code is a **confident match**. ## Step 2 — Customer: email tiebreaker If Step 1 returns more than one candidate, compare the sender address and any contact email on the document against `customer_master.contact_email`. An exact email match resolves the tie. A domain-only match does NOT — several sites of one group share a domain. ## Step 3 — Customer: decide or flag - Exactly one confident match → set `customer_number`, `customer_match_status: matched`. - Two or more candidates after Step 2 → `customer_match_status: ambiguous`, put the candidate customer numbers in `match_candidates`, stop. - No candidate → `customer_match_status: unmatched`, note what you searched for in the comment. Do NOT create a customer. **Never invent a customer number.** An unmatched order is a normal outcome. A wrong customer number is a shipment to the wrong company. ## Step 4 — Line items, in priority order For each ordered position, try in this order and stop at the first hit: 1. **Exact article number** — the buyer quotes our `article_number`. 2. **Vendor/supplier item number** — matches `item_master.vendor_item_number`. 3. **Buyer-prefixed number** — strip a leading customer prefix (e.g. "AC-", "KM/") and retry rules 1 and 2. 4. **Description match** — only when 1–3 fail. Requires a clear match on product type AND size/variant. Set `line_confidence: low` and say in the comment which description matched what. 5. **No match** — set `line_status: unmatched`, list up to five candidate article numbers with their descriptions. Do not pick one. A quantity or unit that does not fit the article's `pack_size` is not an error to correct — record it as stated and flag the line. ## Step 5 — Shipping method Resolve `shipping_agent_code` by the first rule that applies: 1. Buyer explicitly requests express, next-day, or a named carrier → use it. 2. Any line has a `hazard_class` → hazardous-goods carrier. This overrides an express request; if the buyer asked for express, note the conflict. 3. Total order weight over 500 kg → freight carrier. 4. Otherwise → the customer's `default_shipping_agent`. 5. No rule resolves and no customer default exists → leave empty and flag. ## Escalation — always stop and flag - No order number or no order date on the document. - Customer ambiguous or unmatched (Step 3). - Any line unmatched, or matched only by description (Step 4 rules 4–5). - Requested delivery date is in the past. - Total on the document does not equal the sum of the lines. - The document says "incl. VAT" or quotes prices that differ from ours. Flagging is a correct outcome, not a failure. List the candidates and what you checked so the reviewer can decide in seconds. ## Outputs Fill every output field. In the comment, state in plain sentences: how the customer was matched, how many lines matched by which rule, which shipping rule fired, and what — if anything — you flagged and why. ``` ## Walkthrough Create `customer_master` and `item_master` as **Storage** tables and load your CSVs. Give every column a name the agent can read — `postal_code`, not `col_7` — and add descriptions where a name isn't self-explanatory. Create `Order Match` as a **Reconcile** table. In **Configure**: * **Operating Procedures**: `Match incoming purchase orders according to the SOP.` * **Output Fields**: `order_number`, `order_date`, `customer_number`, `customer_match_status`, `match_candidates`, `contact_email`, `delivery_address`, `requested_date`, `shipping_agent_code`, `line_items` (array), `flags`. Describe each one — the agent reads the descriptions. * **Data Access**: grant `customer_master` and `item_master`. * **AI Model**: **Balanced**. Paste the starter SOP above into `SOP.md` in the project's Files, then ask the agent in chat to review it against your actual master data: > Read SOP.md, then look at customer\_master and item\_master. Does the SOP reference fields that don't exist, or miss fields you'd need? List open questions. It will tell you where your data doesn't match the template — that's the fastest way to adapt it. Upload five or six real orders, deliberately mixed: two clean PDFs, one free-text email, one photo, one with an article the buyer numbers differently. Add a task per order and let them run. Open each finished case with the source document beside the result. Check the reasoning against the document, not the other way around. ### What good looks like **A fully automated case.** A clean PDF from a regular customer: > Matched buyer "Kestrel Instrumente GmbH", postal code 44227, to customer 30412 on normalized name + postal code — single candidate, no tiebreaker needed. All 6 lines matched on exact article number. No hazard class, total weight 84 kg, no express request → customer default agent `SPD-02`. Order total 4,180.00 EUR equals the sum of lines. No flags. Six lines, one query path, nothing ambiguous. This is the case Auto Review will eventually clear without you. **A case the agent correctly refuses to resolve.** A photo of a signed order form: > Buyer block reads "Meridian Handels", postal code 8010. Two candidates in customer\_master: 40118 (Meridian Handels GmbH, Ostbahnstrasse 14) and 40233 (Meridian Handels GmbH, Ostbahnstrasse 14a). The document carries no VAT ID and no contact email, and the sender domain matches both records. Cannot resolve — `customer_match_status: ambiguous`, candidates 40118 and 40233. > > Line 3 "blue housing, 40mm" matched no article number or vendor number. Closest by description: `ART-88120` (Housing 40mm, blue), `ART-88122` (Housing 40mm, blue, reinforced). Description alone is not sufficient per Step 4 — `line_status: unmatched`, both listed. Two flags, both correct, both resolvable by a human in about ten seconds because the candidates are right there. That's the output you want from a hard case — not a confident guess. ## Iterating Fix the procedure, not the case. When a reviewer corrects the same thing twice, change the SOP by chat: > Reviewers keep correcting orders from Kestrel: they use their own item numbers with a "KM/" prefix and we match them by description instead. Add the prefix to the buyer-prefix rule in Step 4. The agent edits `SOP.md`, explains the diff, and flags any decision it had to make for you. After a few weeks of reviews, run [the improvement loop](/concepts/improvement-loop): > Look at the last month of reviews in Order Match. What are reviewers correcting most often, and what SOP change would fix it? ## Hardening Replace manual upload with a mailbox or a Zendesk ticket webhook: ticket in → attachments fetched → case created → ticket updated with the outcome. Once your SOP reflects real review feedback, enable **Auto Review** so full clean matches clear automatically and your team sees only the flagged cases. At high volume with stable document shapes, an extraction table structures orders first and the reconcile table works rows instead of raw files. Create tasks and poll for results programmatically when the trigger lives in your own system. **Thresholds worth setting explicitly** as you harden: the amount above which a case always goes to a human regardless of confidence, the number of unmatched lines that sends the whole order to review, and whether a new customer number ever auto-resolves (it shouldn't). All names, article numbers, carrier codes, and values in this cookbook are invented. Replace them with your own master data. # Run an audit Source: https://docs.cloudsquid.io/cookbooks/run-an-audit Point an agent at 12–24 months of your own AP history, read-only, and get evidence-backed findings — duplicates, unapplied credits, split invoices, bank-detail changes. **Read-only, start to finish.** This recipe loads historical exports into a fresh project. Nothing here connects to a production system, and nothing here writes anywhere. The worst outcome is a clean bill of health. ## The job Nobody knows exactly what's leaking out of their AP process, because checking every transaction against every other one was never possible by hand. So it gets sampled, and sampling finds the errors that happen to be in the sample. This recipe runs the checks across the full population — 12 to 24 months of it — and reports what it finds with the evidence attached. It's the first stage of [audit to prevention](/concepts/audit-to-prevention): prove the checks work on data nobody can dispute before anything runs on live events. ## What you'll build ``` historical exports ──▶ storage tables ──▶ Audit Findings (reconcile table) │ one task per check │ findings + evidence ──▶ review ──▶ xlsx report ``` One reconcile table, one SOP, and **each check runs as its own task** in that table — all of them sharing the same data access and the same procedure. This is the month-close pattern: the process is one thing, and its steps are tasks rather than separate tables. ## Ingredients | | | | ------------------- | ----------------------------------------------------------------------------------------------------------------------- | | **Project** | A fresh one. `AP Audit 2025-2026` — isolated data, isolated grants. | | **Storage tables** | `ap_ledger`, `vendor_master`, `payment_runs`. Optional: `supplier_statements`, `contracts`, plus invoice PDFs in Files. | | **Reconcile table** | `Audit Findings` — one task per check | | **Model tier** | **Powerful**. Audit reasoning is exactly the case for it, and this is a batch job — latency doesn't matter here. | | **Integrations** | None. That's the point of this stage. | | **Auto Review** | Off. Every finding gets human eyes in an audit. | **What to export.** Ask whoever runs your ERP for 12–24 months of: ``` ap_ledger: invoice_id, vendor_id, invoice_number, invoice_date, posting_date, amount_net, amount_gross, currency, po_number, cost_center, entity, payment_status vendor_master: vendor_id, vendor_name, tax_id, bank_iban, bank_last_changed, parent_vendor_id, entity payment_runs: run_id, run_date, invoice_id, amount_paid, entity credit_notes: credit_id, vendor_id, credit_number, amount, issue_date, applied_to_invoice_id, status contracts (opt.): vendor_id, article_or_service, agreed_price, unit, valid_from, valid_to ``` Column names don't have to match these — the agent reads your schema. They do have to be legible: `bank_last_changed` works, `dt_fld_09` doesn't. ## The starter SOP ```md theme={null} # SOP — AP leakage audit (read-only lookback) Version 1.0 · Owner: Controlling · Last approved by: , ## Purpose Investigate a historical AP population for recoverable money and control failures. Report findings with evidence. This is a READ-ONLY audit: never propose a posting, never modify a record, never contact a vendor. ## Scope The period loaded into the project's storage tables. State the exact date range and row count in every finding report so results are reproducible. ## Output format — every finding, without exception | Field | Content | |---------------------|--------------------------------------------------| | check | Which check below produced this | | finding | One sentence: what is wrong | | row_references | Every source row id involved — never summarize | | amount | Money at stake, with currency | | confidence | high / medium / low, with the reason | | recommended_action | What a human should do next | A finding without row references is not a finding. If you cannot point at the rows, report it as an observation and mark confidence low. ## Check 1 — Exact duplicates Same vendor + same invoice number → duplicate. Same vendor + same amount + same invoice date, different invoice number → duplicate. Evidence required: both invoice_ids, both payment statuses, amount. Report paid duplicates and unpaid duplicates separately — only the paid ones are recoverable. ## Check 2 — Near duplicates Same vendor + same amount, invoice dates within 10 days, different invoice number. Also flag same amount + same PO across different invoice numbers. Evidence required: both rows, the date gap, the PO if present. Confidence is never high here. Recurring identical charges (rent, subscriptions, retainers) are normal — check whether the pair repeats monthly before flagging, and say so. ## Check 3 — Cross-entity duplicates The same invoice paid by two entities, or by a parent and a subsidiary. Match on vendor tax_id (NOT vendor_id — the same vendor has different ids per entity) + invoice number, or tax_id + amount + date window. Evidence required: both entity codes, both vendor_ids, the shared tax_id. This check finds money the single-entity checks structurally cannot. ## Check 4 — Unapplied credit notes Credit notes with status open, or with no applied_to_invoice_id, where the vendor has since been paid. Evidence required: credit_id, amount, issue date, age in days, and the payments made to that vendor after the issue date. Sort by age. A two-year-old open credit is a different conversation from a two-week-old one. ## Check 5 — Bank detail changes near a payment run Any vendor whose bank_iban changed within 30 days before a payment to that vendor. Evidence required: vendor_id, change date, payment run date and id, the amount paid, the days between. This is a fraud-pattern check, not an error check. Report every hit regardless of amount, and never conclude fraud — report the pattern and let a human investigate. ## Check 6 — Split invoices under an approval threshold Two or more invoices from one vendor, within 7 days, that individually sit below an approval threshold and together sit above it. Ask for the thresholds if they are not in the data. Do not assume them. Evidence required: all invoice_ids, individual amounts, the total, the threshold it crosses. Legitimate causes exist (partial deliveries, milestone billing). Report the pattern, mark confidence medium, and name the plausible innocent explanation you considered. ## Check 7 — Price vs contract Only run when `contracts` is loaded. Compare invoiced unit price against the agreed price valid on the invoice date. Tolerance: the smaller of 2% or 10.00 per unit. Evidence required: invoice row, contract row, both prices, the variance per unit and in total. Skip lines with no matching contract — say how many you skipped rather than guessing at a price. ## Rules that apply to every check - Never guess an amount. If the data does not support a number, say so. - Never merge two findings to make a bigger one. - A check that finds nothing is a result. Report it explicitly with the row count examined — silence is not evidence of absence. - If a check cannot run because data is missing, say which column was missing rather than skipping quietly. - Report counts and totals per check, plus the population size, so the whole audit reconciles. ``` ## Walkthrough New project. Create each export as a **Storage** table and upload the CSV. If you have invoice PDFs, put them in **Files** — checks 1, 2, and 7 get sharper when the agent can open the document behind a row. A **Reconcile** table with **Operating Procedures**: `Run the audit checks defined in the SOP. Read-only.` **Output Fields**: `check`, `finding`, `row_references`, `amount`, `currency`, `confidence`, `recommended_action`, `population_examined`. Grant **Data Access** to every storage table you loaded. Model tier **Powerful**. Paste the starter SOP into `SOP.md`, then ask in chat: > Read SOP.md, then look at the storage tables. Which checks can run against this data as-is, which need a column I haven't loaded, and what's the row count and date range per table? It tells you what's runnable before you run anything. Load what's missing, or drop the check. Create a task for Check 1 alone. Duplicates are the easiest to verify by hand, so it's the cheapest way to confirm the agent is reading your schema correctly. Check a few findings against the ERP yourself. One task per check. They share the SOP and the data access, so nothing is configured twice. ### What good looks like **A real finding, with its evidence:** > **Check 3 — Cross-entity duplicates.** Invoice `MV-4471` from Marloe Verpackung (tax ID DE••1882) was paid twice: once by entity DE01 as vendor 21044 on 2025-11-14 (payment run PR-2211, 8,940.00 EUR) and once by entity AT02 as vendor 30871 on 2025-12-02 (PR-2249, 8,940.00 EUR). Same invoice number, same amount, same tax ID, different vendor records — which is why the per-entity duplicate check did not catch it. Rows: ledger 118422, 121907; payment runs PR-2211, PR-2249. Amount at stake 8,940.00 EUR. Confidence: high. Recommended action: raise a recovery claim against Marloe Verpackung for the AT02 payment. Every number points at a row. A controller can verify this in the ERP in two minutes. **A check that correctly finds nothing:** > **Check 5 — Bank detail changes near a payment run.** Examined 1,247 vendor records against 38 payment runs in the period. Nine vendors had a bank\_iban change during the window; none fell within 30 days before a payment to that vendor — closest was 63 days (vendor 20115, change 2025-08-03, next payment 2025-10-05). No findings. Population examined: 1,247 vendors, 38 runs, 14,902 ledger rows. This is a result, not a blank. It says what was checked, how much of it, and what the near-miss was — which is what makes "nothing found" believable. **A finding the agent correctly refuses to call:** > **Check 6 — Split invoices.** Three invoices from Kestrel Instrumente within 5 days (4,800.00, 4,950.00, 4,200.00 EUR; total 13,950.00). No approval thresholds are present in the loaded data, so I cannot say whether this total crosses one — the pattern is reported, the conclusion is not. The innocent explanation I considered: all three reference PO 4500219 with different delivery notes, which is consistent with a phased delivery. Confidence: low. Recommended action: confirm your approval threshold, then check whether phased delivery against one PO is expected for this vendor. The agent did the arithmetic and then declined to allege something the data doesn't support. ## The findings report When the checks are done, ask for the deliverable: > Produce an xlsx of the audit: a summary sheet with each check, rows examined, findings, and total amount at stake; then one sheet per check with the full findings and their row references. It writes the file into the project's **Files**. That's the artifact you take to the meeting — and because every row reference is in it, it survives being questioned. ## Iterating Your first run will find things that aren't findings. That's normal, and it's fixed in the SOP, not by hand: > Check 2 is flagging our monthly software subscriptions as near duplicates. Add a rule: identical amounts recurring at a monthly cadence from the same vendor are expected, not near duplicates — exclude them and report the count excluded. Note the last clause. Excluding something silently is how an audit loses credibility; excluding it and saying how many were excluded is how it keeps it. ## What to do with the findings The audit is stage one. The checks that found money are the checks worth running continuously — before payment rather than after it: The three-stage path: audit, recover, prevent. Read this next. The continuous sibling of this lookback — the same checks, running on invoices as they arrive. What turns a batch run into a live trigger. Grants, roles, and the audit trail behind every finding. All vendor names, tax IDs, invoice numbers, amounts, and row ids in this cookbook are invented. # Developer Setup Source: https://docs.cloudsquid.io/development Get your API key and make your first API call. ## Get your API key All API requests are authenticated with a project-scoped API key. 1. Open your project in the [Cloudsquid platform](https://app.cloudsquid.io). 2. Go to **Settings** → **API Keys**. 3. Click **Generate New Key**, give it a name, and copy it immediately — it won't be shown again. Keep your API key secret. Do not commit it to source control. Use environment variables in production. ## Authentication Every request requires your API key in the `X-API-Key` header. **Base URL:** `https://api.cloudsquid.io/api` ## Your first API call List all projects in your organisation — a simple read-only call to confirm everything is working. ```python Python theme={null} import requests response = requests.get( "https://api.cloudsquid.io/api/projects", headers={"X-API-Key": "YOUR_API_KEY"} ) print(response.json()) # [{"id": "...", "name": "my-project", "created_at": "..."}] ``` ```bash cURL theme={null} curl https://api.cloudsquid.io/api/projects \ -H "X-API-Key: YOUR_API_KEY" ``` A `200` response with a JSON array confirms your key is valid and your organisation has at least one project. ## Next steps Understand table types, pipelines, and the async run pattern before building your integration. Full endpoint reference with request and response schemas. # cloudsquid Documentation Source: https://docs.cloudsquid.io/index AI agents that work your finance and operations processes — with your SOPs, your data, and your approval. cloudsquid gives every finance and operations process an operator: an AI agent with its own computer — SQL access to your project's tables, workspace files, and access-controlled tokens to your systems — a plain-Markdown SOP it helped write, and a review layer where every case carries its source data, actions, and reasoning. Nothing critical leaves without approval. An event arrives — an email, a ticket, a dump of invoices. The agent picks it up, works it the way a trained team member would — querying your master data, analyzing attachments, drafting the follow-up email — and produces a structured, evidence-backed result. You (or a reviewing agent) approve what matters. ## Start here From empty project to an agent-worked, human-approved process in \~15 minutes. Complete recipes for real use cases — each with a starter SOP you can copy into your project. Projects, tables, SOPs, the agent runtime, review & approvals. Drive extraction and reconciliation programmatically. ## How it fits together 1. **Data comes in** — files (PDFs, emails, spreadsheets, images) and structured master data, via upload, integrations, or scheduled syncs. 2. **The agent works the process** — in its own environment, following your project's SOP: extracting, matching, checking, taking integrated actions like drafting emails. 3. **Everything lands in review** — every case carries its source data, the actions taken, and the reasoning. Humans approve critical steps; an approval agent can handle the routine ones. 4. **The process improves** — the agent reads your review comments and approval outcomes, and proposes SOP updates so the process gets better over time. 5. **Results flow out** — structured outputs (JSON, files) pushed to your systems or kept for download; ask the agent for a report and it produces the file. Your ERP stays the system of record. ## The pieces Your process, in versioned Markdown the agent follows — and helps you write. Where events become worked cases with structured outputs. Statuses, assignments, evidence, and approval gates — human or agentic. Review feedback flows back into the SOP — the process learns. Workflow triggers and syncs, plus access-controlled tokens the agent uses directly. Per-table data access, zero retention, SOC 2 & ISO 27001, EU residency. Questions? Email [info@cloudsquid.io](mailto:info@cloudsquid.io) — or ask the agent in the bottom-right corner of the platform. # Quickstart: your first agent-worked process Source: https://docs.cloudsquid.io/quickstart From empty project to an agent-worked, human-approved process in about 15 minutes. In this guide you'll build a miniature **order-matching** process: order documents come in, an agent matches them against your customer master data following an SOP, and hands you evidence-backed cases to approve. You'll touch every core piece: a project, master data, a reconcile table, an SOP the agent helped write, and the review flow. You'll need a cloudsquid account and two kinds of sample data: a handful of order documents (PDFs or email files) and a small customer list as CSV. No integrations required for this guide. ## 1. Create a project Everything lives in a **project**: your files, your tables, your SOPs, and the agent that works them. 1. From the home screen, click **New** and name the project (e.g. `Order Entry Sandbox`). 2. You land in the project workspace: **Files** and **Tables** in the sidebar, the agent available bottom-right. ## 2. Add your master data The agent matches incoming documents *against* something — that something is a storage table. 1. Create a table and choose **Storage** , name it `Customer Master Data`. 2. Upload your CSV of customers (number, name, address, email). 3. Column names matter: the agent reads the schema to understand your data — `Postal_Code` beats `col_7`. Add column descriptions where names aren't self-explanatory. ## 3. Create the reconcile table — where the process lives This is the core of cloudsquid: a **reconcile table** turns events into worked cases. 1. Create a **Reconcile** table, e.g. `Order Match`. 2. In **Configure**, set up: * **Operating Procedures** — keep it to one line: `Match incoming orders according to the SOP.` The real logic goes in the SOP file (next step). * **Output Fields** — what the agent should produce per case: e.g. `customer_match_status`, `customer_number`, `order_number`, `contact_email`, delivery fields. Give each field a clear description — the agent reads them. * **Data Access** — grant the agent read access to `Customer Master Data`. The agent can only touch what you grant. * **AI Model** — start with **Balanced**; switch to **Powerful** for hard documents. ## 4. Write the SOP — with the agent SOPs are plain Markdown files in your project. You don't write them from scratch: 1. Open the agent chat and ask it to draft one: > Look at Customer Master Data and the order files in the project. Draft an SOP.md for matching incoming orders to customers: match on buyer name + address first, use email as a tiebreaker, and flag anything ambiguous for review instead of guessing. List open questions you can't resolve from the data. 2. The agent writes `SOP.md` — real procedure, not prose: match steps, fallbacks, when to stop and escalate. Where it isn't sure, it lists **open questions** for you. 3. Answer what you can, ask it to revise. The SOP carries a version stamp and the latest approver, so process changes stay reviewable. This loop — agent drafts, your process expert corrects, the file versions — is how real deployments onboard. Teaching, not configuring. ## 5. Run the process 1. Upload two or three order documents to the project's **Files** (or drop them straight into the reconcile table). 2. Add a task per order. The agent picks each one up: reads the document (vision included), queries your master data, applies the SOP's match steps, and fills the output fields. Status moves **Running → Agent Done**. ## 6. Review the case Open a finished task. This is the review interface — where your controllers will live: * **Source document** on one side, the **agent's comment** on the other: what it matched, how, and why. * If the agent couldn't resolve something safely, it says so and lists the candidates instead of guessing. That case gets **Needs review** — that's the system working, not failing. * **Approve** the case, or reject it with a comment — the agent reads comments. Once you trust a process, routine approvals can be handed to an **approval agent** that reviews results against the SOP; you keep the exceptions. And as review comments accumulate, the agent can propose SOP updates based on them — see [the improvement loop](/concepts/improvement-loop). ## 7. Bonus: ask for a report The agent has a computer, not just a queue — it can produce deliverables about its own work. In the agent chat: > Summarize the cases in Order Match as a short report: how many matched automatically, what needed review, and why. It analyzes the table and writes the file into the project's **Files**. Real deployments get their weekly automation reports exactly this way — on demand, not as a scheduled job. ## Where to go next Full recipes with copy-paste starter SOPs: PO matching, invoice audit, inbox intake. Trigger this process from a shared inbox, Zendesk, or SharePoint instead of manual upload. For high-volume document batches, an extraction table structures files before reconciliation. Statuses, assignment, agentic approval mode. # Quickstart: extraction Source: https://docs.cloudsquid.io/quickstart-extraction Turn a batch of documents into structured rows — as its own job, or as input to a reconcile process. Use an **extraction table** when you need structured data out of documents at volume: one file per row, a schema you define, structured values in the columns. It works as a standalone job (export the rows, push them to a webhook), or as the upstream step that feeds a [reconcile table](/concepts/tables) where an agent works the actual process. If you're building a *process* — matching, checking, deciding, drafting — start with the [agent quickstart](/quickstart) instead. Reconcile tables can read files directly; you only need an extraction table when document volume makes pre-structuring worth it. ## 1. Create an extraction table 1. In your project, create a new table and choose **Extraction**. 2. Give it a name and create it. You land in the extraction table interface: your table in the center, the agent chat available for schema work. ## 2. Upload files * **Drag and drop** files into the center of the table, or click **Add Files** to pick them from your computer. * **API upload** — send files directly via the [API](/concepts/async-run-pattern). * **Workflow connectors** — pull files automatically from connected systems (SharePoint, a shared mailbox, S3). See [Integrations](/concepts/integrations). Uploaded files appear as rows with the status **Waiting for run**. PDFs, images, spreadsheets, audio, and video are supported. ## 3. Define your extraction schema Each column is one extraction task. You don't have to write them by hand: 1. In the agent chat, describe what you need pulled out of these files. 2. The agent reads your files and your description, then proposes columns. 3. Click **Apply Schema** to add them to the table. Column names and descriptions matter — the model reads them. `invoice_total_net` with a one-line description beats `col_4`. Nested lists (invoice line items, order positions) are supported as array columns, so one file can produce a header record plus its line items. ## 4. Run the extraction 1. Select one or more rows. 2. Click **Run AI**. 3. Extracted values appear in the table as each run finishes. ## 5. Review and refine * **File viewer** — open a row to see the original document side by side with the extracted values, so you can check any value against its source. * **Iterate with the agent** — ask it to add, remove, or adjust columns, then re-run. * **Manual edits** — add columns directly, or use the column menu to edit an existing extraction task. * **Re-run after edits** — select the rows you want reprocessed and hit **Run AI** again. Only the selected rows are reprocessed. ## 6. Settings worth knowing * **System prompt** — high-level guidance applied to every extraction on this table (e.g. "dates are DD.MM.YYYY", "amounts are net unless stated"). * **Pipeline** — the model configuration used for runs. See [Extraction pipelines](/concepts/pipelines) for the trade-offs. * **Bounding boxes** — records where in the source document each value came from. Useful for audit and human review; slower on every run. * **Review mode** — adds a human approval gate on extracted rows. See [Review & approvals](/concepts/review-approvals). * **Bulk actions** — select multiple rows to export or delete them. ## 7. Get the data out * **CSV or Excel** — export the whole table or just the selected rows. * **Webhook delivery** — push each finished row to an endpoint of your choice. * **API** — poll for results with the [async run pattern](/concepts/async-run-pattern), or use the synchronous `/extract` call for one-file-at-a-time integrations. * **Into a process** — feed the rows into a [reconcile table](/concepts/tables), where an agent works them against your master data following an [SOP](/concepts/sops). ## Where to go next Structured rows are the input. The agent quickstart shows what works them. Pick the right pipeline for your accuracy and speed requirements. Upload → start → poll, the standard pattern for extraction at scale. Feed the table from a mailbox, SharePoint, or a webhook instead of manual upload.