> For the complete documentation index, see [llms.txt](https://whitepaper.aitech.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://whitepaper.aitech.io/agentforge/tools/airtable.md).

# airtable

[Airtable](https://airtable.com/) combines the familiarity of spreadsheets with the structure of databases. With this integration, agents can **read**, **create**, and **update** Airtable records as part of guided, reliable workflows.

**What you can do**

* Fetch multiple records from a base and filter/sort them.
* Retrieve an individual record by its ID.
* Create new entries with typed fields and attachments.
* Update existing records (single or bulk) to keep Airtable in sync with actions your agents take.

**Where this shines**

* Centralizing a “source of truth” dataset for decisions.
* Human-in-the-loop reviews (agents propose updates, teams approve in Airtable).
* Enrichment and scoring pipelines (read → enrich → write-back).
* Campaign/task orchestration across teams.

## Usage Instructions

{% stepper %}
{% step %}

#### Read

Read records to gather context (filter or sort as needed).
{% endstep %}

{% step %}

#### Decide

Decide in your logic layer (classify, verify, enrich, or route).
{% endstep %}

{% step %}

#### Write-back

Update records or create new rows to persist outcomes.
{% endstep %}
{% endstepper %}

### Example Workflow: Read → Decide → Bulk Update

* **Step 1**: Read all *open*, *high-priority* tasks.
* **Step 2**: Decide what changes are needed (e.g., mark as processed).
* **Step 3**: Write back updates in bulk using one API call.

This pattern is useful for cleaning queues, re-scoring tasks, or updating statuses.

### Example Workflow: Idempotent Create (Upsert by Email)

* **Step 1**: Check for an existing record using a unique field like `Email`.
* **Step 2**: If the record exists → update it with new values.
* **Step 3**: If no record exists → create it fresh.

This ensures no duplicates and mimics an **“upsert”** pattern that Airtable doesn’t natively provide.

## Tools

### `airtable_list_records`

Read multiple records from an Airtable table.

#### Input

| Parameter       | Type      | Required | Description                                                      |
| --------------- | --------- | -------- | ---------------------------------------------------------------- |
| `baseId`        | string    | Yes      | ID of the Airtable base (e.g., `appXXXXXXXXXXXXXX`)              |
| `tableId`       | string    | Yes      | ID or name of the table (e.g., `tblXXXXXXXXXXXXXX` or `"Tasks"`) |
| `maxRecords`    | number    | No       | Maximum number of records to return                              |
| `filterFormula` | string    | No       | Airtable formula to filter (e.g., `AND({Status}='Open')`)        |
| `view`          | string    | No       | Use a view’s filters/sorts                                       |
| `sort`          | array     | No       | Sort by fields, e.g., `[{"field":"Due","direction":"asc"}]`      |
| `fields`        | string\[] | No       | Limit returned fields                                            |

#### Output

| Parameter      | Type   | Description                                    |
| -------------- | ------ | ---------------------------------------------- |
| `records`      | json   | Array of records `{ id, fields, createdTime }` |
| `metadata`     | json   | Request/table metadata                         |
| `totalRecords` | number | Count of records retrieved                     |

```json
{
  "records": [
    {
      "id": "rec0tK7W0ICQikuee",
      "createdTime": "2025-07-29T09:49:30.000Z",
      "fields": {
        "Design Name": "Mobile App Onboarding",
        "Submission Date": "2025-08-22",
        "Designer": "Bob Smith",
        "Comments": "Reviewed by the design team."
      }
    }
  ],
  "metadata": { "totalRecords": 1 }
}
```

### `airtable_get_record`

Retrieve a single record from an Airtable table by its **record ID**.\
This is useful when you already know the record’s identifier (for example, from a previous listing) and want the full details.

#### Input

| Parameter  | Type   | Required | Description                          |
| ---------- | ------ | -------- | ------------------------------------ |
| `baseId`   | string | Yes      | ID of the Airtable base              |
| `tableId`  | string | Yes      | ID or name of the table              |
| `recordId` | string | Yes      | Unique record ID (e.g., `rec123XYZ`) |

#### Output

| Parameter  | Type | Description             |
| ---------- | ---- | ----------------------- |
| `record`   | json | Retrieved record object |
| `metadata` | json | Operation metadata      |

#### Example Output

```json
{
  "record": {
    "id": "rec0tK7W0ICQikuee",
    "createdTime": "2025-07-29T09:49:30.000Z",
    "fields": {
      "Design Name": "Mobile App Onboarding",
      "Submission Date": "2025-08-22",
      "Designer": "Bob Smith",
      "Comments": "Reviewed by the design team. Needs minor adjustments in the color scheme."
    }
  },
  "metadata": { "recordCount": 1 }
}
```

### `airtable_create_records`

Create one or more new records in a target Airtable table.\
This tool is most useful when ingesting data from external workflows, collecting user submissions, or creating rows for downstream tracking.

#### Input

| Parameter  | Type    | Required | Description                                                  |
| ---------- | ------- | -------- | ------------------------------------------------------------ |
| `baseId`   | string  | Yes      | ID of the Airtable base                                      |
| `tableId`  | string  | Yes      | ID or name of the table                                      |
| `records`  | array   | Yes      | Array of `{ fields: { ... } }` objects                       |
| `typecast` | boolean | No       | Coerce values into field types (helpful for selects/lookups) |

#### Output

| Parameter  | Type | Description                    |
| ---------- | ---- | ------------------------------ |
| `records`  | json | Newly created records with IDs |
| `metadata` | json | Response metadata              |

#### Example Input

```json
[
  {
    "fields": {
      "Design Name": "Mobile App Onboarding",
      "Submission Date": "2025-08-22",
      "Designer": "Bob Smith",
      "Comments": "Reviewed by the design team. Needs minor adjustments in the color scheme."
    }
  }
]
```

#### Example Output

```json
{
  "records": [
    {
      "id": "rec0tK7W0ICQikuee",
      "createdTime": "2025-07-29T09:49:30.000Z",
      "fields": {
        "Design Name": "Mobile App Onboarding",
        "Submission Date": "2025-08-22",
        "Designer": "Bob Smith",
        "Comments": "Reviewed by the design team. Needs minor adjustments in the color scheme."
      }
    }
  ],
  "metadata": {}
}
```

### `airtable_update_record`

Update a **single record** in Airtable by its unique `recordId`.\
This is commonly used in workflows where an agent enriches, verifies, or modifies data in-place — for example, marking a lead as *Qualified*, updating the status of a task, or adding comments to an entry.

#### Input

| Parameter  | Type    | Required | Description                                                                                              |
| ---------- | ------- | -------- | -------------------------------------------------------------------------------------------------------- |
| `baseId`   | string  | Yes      | Airtable base ID (e.g., `appXXXXXXXXXXXXXX`)                                                             |
| `tableId`  | string  | Yes      | Table ID or name (e.g., `tblXXXXXXXXXXXXXX` or `"Tasks"`)                                                |
| `recordId` | string  | Yes      | Unique ID of the record to update                                                                        |
| `fields`   | object  | Yes      | A JSON object mapping field names to new values (inner dictionary only)                                  |
| `typecast` | boolean | No       | If true, Airtable will coerce values into field types (helpful for selects, lookups, and linked records) |

#### Output

| Parameter       | Type      | Description                             |
| --------------- | --------- | --------------------------------------- |
| `record`        | json      | The updated record object               |
| `metadata`      | json      | Information about the update operation  |
| `updatedFields` | string\[] | Array of field names that were modified |

#### Example Input

```json
{
  "recordId": "rec0tK7W0ICQikuee",
  "fields": {
    "Status": "Processed",
    "Comments": "Task completed successfully.",
    "Processed At": "2025-10-01T14:32:00.000Z"
  }
}
```

#### Example Output

```json
{
  "record": {
    "id": "rec0tK7W0ICQikuee",
    "createdTime": "2025-07-29T09:49:30.000Z",
    "fields": {
      "Design Name": "Mobile App Onboarding",
      "Status": "Processed",
      "Comments": "Task completed successfully.",
      "Processed At": "2025-10-01T14:32:00.000Z"
    }
  },
  "metadata": {
    "updatedFields": ["Status", "Comments", "Processed At"]
  }
}
```

### `airtable_update_multiple_records`

Update **multiple records** in Airtable within a single request.\
Use this for batch status changes, enrichment, and syncing external systems efficiently.

#### Input

| Parameter  | Type    | Required | Description                                                                                     |
| ---------- | ------- | -------- | ----------------------------------------------------------------------------------------------- |
| `baseId`   | string  | Yes      | Airtable base ID (e.g., `appXXXXXXXXXXXXXX`).                                                   |
| `tableId`  | string  | Yes      | Table ID or name (e.g., `tblXXXXXXXXXXXXXX` or `"Tasks"`).                                      |
| `updates`  | array   | Yes      | Array of update objects. Each item must include an `id` (record ID) and a `fields` map.         |
| `typecast` | boolean | No       | If `true`, Airtable coerces values into field types (useful for select, lookup, linked fields). |

Each update object should look like:

```json
{
  "id": "recXXXXXXXXXXXXXX",
  "fields": {
    "Status": "Processed",
    "Comments": "Updated in bulk run"
  }
}
```

#### Output

| Parameter          | Type   | Required | Description                                          |
| ------------------ | ------ | -------- | ---------------------------------------------------- |
| `records`          | json   | Yes      | List of updated record objects (IDs + fields).       |
| `metadata`         | json   | Yes      | Metadata about the operation.                        |
| `updatedRecordIds` | string | Yes      | AArray of record IDs that were updated successfully. |

#### Example Input

```json
{
  "updates": [
    {
      "id": "rec0tK7W0ICQikuee",
      "fields": {
        "Status": "Processed",
        "Processed At": "2025-10-02T10:15:00.000Z"
      }
    },
    {
      "id": "recDFByLwmeFEA3VI",
      "fields": {
        "Status": "Processed",
        "Processed At": "2025-10-02T10:15:00.000Z"
      }
    }
  ]
}
```

#### Example Output

```json
{
  "records": [
    {
      "id": "rec0tK7W0ICQikuee",
      "fields": {
        "Design Name": "Mobile App Onboarding",
        "Status": "Processed",
        "Processed At": "2025-10-02T10:15:00.000Z"
      }
    },
    {
      "id": "recDFByLwmeFEA3VI",
      "fields": {
        "Design Name": "Checkout Flow Improvement",
        "Status": "Processed",
        "Processed At": "2025-10-02T10:15:00.000Z"
      }
    }
  ],
  "metadata": {
    "updatedRecordIds": ["rec0tK7W0ICQikuee", "recDFByLwmeFEA3VI"]
  }
}
```

#### When to Use

* Bulk move tasks from Open → Processed.
* Apply enrichment (scores, segments) to many leads at once.
* Sync external systems that produce batch updates.
* Implement efficient read → decide → write-back pipelines.

#### Debugging Tips

* **Check IDs**: Prefer `tableId` (`tbl...`) in production. Table names can break if renamed.
* **Validate values**: Dates should be ISO 8601 (`YYYY-MM-DDTHH:mm:ssZ`). Ensure select options match exactly.
* **Log responses**: Keep track of Airtable’s error payloads. They often include hints about which field failed.
* **Reduce payloads**: Large bulk updates can trigger timeouts; split into multiple requests.
* **Use Views**: When filtering records, views encapsulate filter logic and reduce complexity in formulas.

### Best Practices

* Use **IDs instead of names** for stability.
* Add **timestamps** like `Updated At` or `Processed At` for traceability.
* Validate inputs before sending (email formats, select values).
* For upserts: **list → check by unique field → update or create**.
* Handle retries gracefully, especially with 429 rate limits.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://whitepaper.aitech.io/agentforge/tools/airtable.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
