Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 83 additions & 9 deletions apps/docs/content/docs/en/tools/airtable.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,63 @@ In Sim, the Airtable integration enables your agents to interact with your Airta

## Usage Instructions

Integrates Airtable into the workflow. Can create, get, list, or update Airtable records. Can be used in trigger mode to trigger a workflow when an update is made to an Airtable table.
Integrates Airtable into the workflow. Can list bases, list tables (with schema), and create, get, list, or update records. Can also be used in trigger mode to trigger a workflow when an update is made to an Airtable table.



## Tools

### `airtable_list_bases`

List all Airtable bases the user has access to

#### Input

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `offset` | string | No | Pagination offset for retrieving additional bases |

#### Output

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `bases` | array | List of Airtable bases |
| ↳ `id` | string | Base ID \(starts with "app"\) |
| ↳ `name` | string | Base name |
| ↳ `permissionLevel` | string | Permission level \(none, read, comment, edit, create\) |
| `metadata` | json | Pagination and count metadata |
| ↳ `offset` | string | Offset for next page of results |
| ↳ `totalBases` | number | Number of bases returned |

### `airtable_list_tables`

List all tables and their schema in an Airtable base

#### Input

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `baseId` | string | Yes | Airtable base ID \(starts with "app", e.g., "appXXXXXXXXXXXXXX"\) |

#### Output

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `tables` | array | List of tables in the base with their schema |
| ↳ `id` | string | Table ID \(starts with "tbl"\) |
| ↳ `name` | string | Table name |
| ↳ `description` | string | Table description |
| ↳ `primaryFieldId` | string | ID of the primary field |
| ↳ `fields` | array | List of fields in the table |
| ↳ `id` | string | Field ID \(starts with "fld"\) |
| ↳ `name` | string | Field name |
| ↳ `type` | string | Field type \(singleLineText, multilineText, number, checkbox, singleSelect, multipleSelects, date, dateTime, attachment, linkedRecord, etc.\) |
| ↳ `description` | string | Field description |
| ↳ `options` | json | Field-specific options \(choices, etc.\) |
| `metadata` | json | Base info and count metadata |
| ↳ `baseId` | string | The base ID queried |
| ↳ `totalTables` | number | Number of tables in the base |

### `airtable_list_records`

Read records from an Airtable table
Expand All @@ -49,8 +100,13 @@ Read records from an Airtable table

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `records` | json | Array of retrieved Airtable records |
| `records` | array | Array of retrieved Airtable records |
| ↳ `id` | string | Record ID |
| ↳ `createdTime` | string | Record creation timestamp |
| ↳ `fields` | json | Record field values |
| `metadata` | json | Operation metadata including pagination offset and total records count |
| ↳ `offset` | string | Pagination offset for next page |
| ↳ `totalRecords` | number | Number of records returned |

### `airtable_get_record`

Expand All @@ -68,8 +124,12 @@ Retrieve a single record from an Airtable table by its ID

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `record` | json | Retrieved Airtable record with id, createdTime, and fields |
| `metadata` | json | Operation metadata including record count |
| `record` | json | Retrieved Airtable record |
| ↳ `id` | string | Record ID |
| ↳ `createdTime` | string | Record creation timestamp |
| ↳ `fields` | json | Record field values |
| `metadata` | json | Operation metadata |
| ↳ `recordCount` | number | Number of records returned \(always 1\) |

### `airtable_create_records`

Expand All @@ -88,8 +148,12 @@ Write new records to an Airtable table

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `records` | json | Array of created Airtable records |
| `records` | array | Array of created Airtable records |
| ↳ `id` | string | Record ID |
| ↳ `createdTime` | string | Record creation timestamp |
| ↳ `fields` | json | Record field values |
| `metadata` | json | Operation metadata |
| ↳ `recordCount` | number | Number of records created |

### `airtable_update_record`

Expand All @@ -108,8 +172,13 @@ Update an existing record in an Airtable table by ID

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `record` | json | Updated Airtable record with id, createdTime, and fields |
| `metadata` | json | Operation metadata including record count and updated field names |
| `record` | json | Updated Airtable record |
| ↳ `id` | string | Record ID |
| ↳ `createdTime` | string | Record creation timestamp |
| ↳ `fields` | json | Record field values |
| `metadata` | json | Operation metadata |
| ↳ `recordCount` | number | Number of records updated \(always 1\) |
| ↳ `updatedFields` | array | List of field names that were updated |

### `airtable_update_multiple_records`

Expand All @@ -127,7 +196,12 @@ Update multiple existing records in an Airtable table

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `records` | json | Array of updated Airtable records |
| `metadata` | json | Operation metadata including record count and updated record IDs |
| `records` | array | Array of updated Airtable records |
| ↳ `id` | string | Record ID |
| ↳ `createdTime` | string | Record creation timestamp |
| ↳ `fields` | json | Record field values |
| `metadata` | json | Operation metadata |
| ↳ `recordCount` | number | Number of records updated |
| ↳ `updatedRecordIds` | array | List of updated record IDs |


Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ const SCOPE_DESCRIPTIONS: Record<string, string> = {
'offline.access': 'Access account when not using the application',
'data.records:read': 'Read records',
'data.records:write': 'Write to records',
'schema.bases:read': 'View bases and tables',
'webhook:manage': 'Manage webhooks',
'page.read': 'Read Notion pages',
'page.write': 'Write to Notion pages',
Expand Down
25 changes: 22 additions & 3 deletions apps/sim/blocks/blocks/airtable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const AirtableBlock: BlockConfig<AirtableResponse> = {
description: 'Read, create, and update Airtable',
authMode: AuthMode.OAuth,
longDescription:
'Integrates Airtable into the workflow. Can create, get, list, or update Airtable records. Can be used in trigger mode to trigger a workflow when an update is made to an Airtable table.',
'Integrates Airtable into the workflow. Can list bases, list tables (with schema), and create, get, list, or update records. Can also be used in trigger mode to trigger a workflow when an update is made to an Airtable table.',
docsLink: 'https://docs.sim.ai/tools/airtable',
category: 'tools',
bgColor: '#E0E0E0',
Expand All @@ -21,10 +21,13 @@ export const AirtableBlock: BlockConfig<AirtableResponse> = {
title: 'Operation',
type: 'dropdown',
options: [
{ label: 'List Bases', id: 'listBases' },
{ label: 'List Tables', id: 'listTables' },
{ label: 'List Records', id: 'list' },
{ label: 'Get Record', id: 'get' },
{ label: 'Create Records', id: 'create' },
{ label: 'Update Record', id: 'update' },
{ label: 'Update Multiple Records', id: 'updateMultiple' },
],
value: () => 'list',
},
Expand All @@ -38,6 +41,7 @@ export const AirtableBlock: BlockConfig<AirtableResponse> = {
requiredScopes: [
'data.records:read',
'data.records:write',
'schema.bases:read',
'user.email:read',
'webhook:manage',
],
Expand All @@ -59,15 +63,17 @@ export const AirtableBlock: BlockConfig<AirtableResponse> = {
type: 'short-input',
placeholder: 'Enter your base ID (e.g., appXXXXXXXXXXXXXX)',
dependsOn: ['credential'],
required: true,
condition: { field: 'operation', value: 'listBases', not: true },
required: { field: 'operation', value: 'listBases', not: true },
},
{
id: 'tableId',
title: 'Table ID',
type: 'short-input',
placeholder: 'Enter table ID (e.g., tblXXXXXXXXXXXXXX)',
dependsOn: ['credential', 'baseId'],
required: true,
condition: { field: 'operation', value: ['listBases', 'listTables'], not: true },
required: { field: 'operation', value: ['listBases', 'listTables'], not: true },
},
{
id: 'recordId',
Expand All @@ -83,13 +89,15 @@ export const AirtableBlock: BlockConfig<AirtableResponse> = {
type: 'short-input',
placeholder: 'Maximum records to return',
condition: { field: 'operation', value: 'list' },
mode: 'advanced',
},
{
id: 'filterFormula',
title: 'Filter Formula',
type: 'long-input',
placeholder: 'Airtable formula to filter records (optional)',
condition: { field: 'operation', value: 'list' },
mode: 'advanced',
wandConfig: {
enabled: true,
prompt: `Generate an Airtable filter formula based on the user's description.
Expand Down Expand Up @@ -206,6 +214,8 @@ Return ONLY the valid JSON object - no explanations, no markdown.`,
],
tools: {
access: [
'airtable_list_bases',
'airtable_list_tables',
'airtable_list_records',
'airtable_get_record',
'airtable_create_records',
Expand All @@ -215,6 +225,10 @@ Return ONLY the valid JSON object - no explanations, no markdown.`,
config: {
tool: (params) => {
switch (params.operation) {
case 'listBases':
return 'airtable_list_bases'
case 'listTables':
return 'airtable_list_tables'
case 'list':
return 'airtable_list_records'
case 'get':
Expand Down Expand Up @@ -278,6 +292,11 @@ Return ONLY the valid JSON object - no explanations, no markdown.`,
},
// Output structure depends on the operation, covered by AirtableResponse union type
outputs: {
// List Bases output
bases: { type: 'json', description: 'List of accessible Airtable bases' },
// List Tables output
tables: { type: 'json', description: 'List of tables in the base with schema' },
// Record outputs
records: { type: 'json', description: 'Retrieved record data' }, // Optional: for list, create, updateMultiple
record: { type: 'json', description: 'Single record data' }, // Optional: for get, update single
metadata: { type: 'json', description: 'Operation metadata' }, // Required: present in all responses
Expand Down
8 changes: 7 additions & 1 deletion apps/sim/lib/auth/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2155,7 +2155,13 @@ export const auth = betterAuth({
authorizationUrl: 'https://airtable.com/oauth2/v1/authorize',
tokenUrl: 'https://airtable.com/oauth2/v1/token',
userInfoUrl: 'https://api.airtable.com/v0/meta/whoami',
scopes: ['data.records:read', 'data.records:write', 'user.email:read', 'webhook:manage'],
scopes: [
'data.records:read',
'data.records:write',
'schema.bases:read',
'user.email:read',
'webhook:manage',
],
responseType: 'code',
pkce: true,
accessType: 'offline',
Expand Down
8 changes: 7 additions & 1 deletion apps/sim/lib/oauth/oauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,13 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
providerId: 'airtable',
icon: AirtableIcon,
baseProviderIcon: AirtableIcon,
scopes: ['data.records:read', 'data.records:write', 'user.email:read', 'webhook:manage'],
scopes: [
'data.records:read',
'data.records:write',
'schema.bases:read',
'user.email:read',
'webhook:manage',
],
},
},
defaultService: 'airtable',
Expand Down
18 changes: 11 additions & 7 deletions apps/sim/tools/airtable/create_records.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ export const airtableCreateRecordsTool: ToolConfig<AirtableCreateParams, Airtabl
},

request: {
url: (params) => `https://api.airtable.com/v0/${params.baseId}/${params.tableId}`,
url: (params) =>
`https://api.airtable.com/v0/${params.baseId?.trim()}/${params.tableId?.trim()}`,
method: 'POST',
headers: (params) => ({
Authorization: `Bearer ${params.accessToken}`,
Expand All @@ -55,30 +56,33 @@ export const airtableCreateRecordsTool: ToolConfig<AirtableCreateParams, Airtabl
return {
success: true,
output: {
records: data.records || [],
records: data.records ?? [],
metadata: {
recordCount: (data.records || []).length,
recordCount: (data.records ?? []).length,
},
},
}
},

outputs: {
records: {
type: 'json',
type: 'array',
description: 'Array of created Airtable records',
items: {
type: 'object',
properties: {
id: { type: 'string' },
createdTime: { type: 'string' },
fields: { type: 'object' },
id: { type: 'string', description: 'Record ID' },
createdTime: { type: 'string', description: 'Record creation timestamp' },
fields: { type: 'json', description: 'Record field values' },
},
},
},
metadata: {
type: 'json',
description: 'Operation metadata',
properties: {
recordCount: { type: 'number', description: 'Number of records created' },
},
},
},
}
14 changes: 11 additions & 3 deletions apps/sim/tools/airtable/get_record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const airtableGetRecordTool: ToolConfig<AirtableGetParams, AirtableGetRes

request: {
url: (params) =>
`https://api.airtable.com/v0/${params.baseId}/${params.tableId}/${params.recordId}`,
`https://api.airtable.com/v0/${params.baseId?.trim()}/${params.tableId?.trim()}/${params.recordId?.trim()}`,
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.accessToken}`,
Expand All @@ -65,11 +65,19 @@ export const airtableGetRecordTool: ToolConfig<AirtableGetParams, AirtableGetRes
outputs: {
record: {
type: 'json',
description: 'Retrieved Airtable record with id, createdTime, and fields',
description: 'Retrieved Airtable record',
properties: {
id: { type: 'string', description: 'Record ID' },
createdTime: { type: 'string', description: 'Record creation timestamp' },
fields: { type: 'json', description: 'Record field values' },
},
},
metadata: {
type: 'json',
description: 'Operation metadata including record count',
description: 'Operation metadata',
properties: {
recordCount: { type: 'number', description: 'Number of records returned (always 1)' },
},
},
},
}
6 changes: 6 additions & 0 deletions apps/sim/tools/airtable/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import { airtableCreateRecordsTool } from '@/tools/airtable/create_records'
import { airtableGetRecordTool } from '@/tools/airtable/get_record'
import { airtableListBasesTool } from '@/tools/airtable/list_bases'
import { airtableListRecordsTool } from '@/tools/airtable/list_records'
import { airtableListTablesTool } from '@/tools/airtable/list_tables'
import { airtableUpdateMultipleRecordsTool } from '@/tools/airtable/update_multiple_records'
import { airtableUpdateRecordTool } from '@/tools/airtable/update_record'

export {
airtableCreateRecordsTool,
airtableGetRecordTool,
airtableListBasesTool,
airtableListRecordsTool,
airtableListTablesTool,
airtableUpdateMultipleRecordsTool,
airtableUpdateRecordTool,
}

export * from './types'
Loading