关于 airtable
Airtable 技能指导通过 terminal 工具和 curl 调用 Airtable REST API,供 Hermes 用户读取、筛选和修改 bases 中的数据。内容涵盖令牌权限、字段格式、分页、批量写入及安全操作注意事项。
主要功能
- 01通过 curl 调用 Airtable REST API
- 02列出 bases 与表结构
- 03查询、筛选和排序记录
- 04创建、更新、删除及合并记录
- 05处理分页、限流与令牌权限
适用场景
- 01检查表结构后再修改记录
- 02按公式筛选并更新记录
- 03批量创建记录或执行幂等同步
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ nousresearch/ hermes-agent --skill airtable安装后在 Claude Code 中输入/airtable确认已加载。
详细介绍
Airtable — 基础、表格与记录
通过 terminal 工具使用 curl 直接调用 Airtable 的 REST API。无需 MCP 服务、OAuth 流程或 Python SDK——只需 curl 和个人访问令牌。
前提条件
- 在 https://airtable.com/create/tokens 创建个人访问令牌(PAT)(令牌以
pat...开头)。 - 授予以下作用域(最低要求):
data.records:read— 读取行data.records:write— 创建/更新/删除行schema.bases:read— 列出基础和表格
- 重要:在同一个令牌界面中,将你想访问的每个基础添加到令牌的访问列表中。PAT 按基础限定范围——在错误的基础上使用有效令牌会返回
403。 - 将令牌存储在
${HERMES_HOME:-~/.hermes}/.env中(或通过hermes setup设置):AIRTABLE_API_KEY=pat_your_token_here
注意:旧版
key...API 密钥已于 2024 年 2 月弃用。现在仅支持 PAT 和 OAuth 令牌。
API 基础知识
- 端点:
https://api.airtable.com/v0 - 身份验证标头:
Authorization: Bearer $AIRTABLE_API_KEY - 所有请求均使用 JSON(任何 POST/PATCH/PUT 请求体都需设置
Content-Type: application/json)。 - **对象 ID:**基础为
app...,表格为tbl...,记录为rec...,字段为fld...。ID 永不更改;名称可能更改。在自动化中优先使用 ID。 - **速率限制:**每个基础每秒 5 个请求。遇到
429时应退避。对单个基础突发发送请求会受到限流。
curl 基本模式:
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?maxRecords=5" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool
-s 会隐藏 curl 的进度条——每次调用都应保留此参数,以便工具输出对 Hermes 保持整洁。通过 python -m json.tool(始终可用)或 jq(若已安装)处理输出,便于阅读 JSON。
字段类型(请求体格式)
| 字段类型 | 写入格式 |
|---|---|
| 单行文本 | "Name": "hello" |
| 长文本 | "Notes": "multi\nline" |
| 数字 | "Score": 42 |
| 复选框 | "Done": true |
| 单选 | "Status": "Todo"(除非设置 typecast: true,否则名称必须已存在) |
| 多选 | "Tags": ["urgent", "bug"] |
| 日期 | "Due": "2026-04-01" |
| 日期时间(UTC) | "At": "2026-04-01T14:30:00.000Z" |
| URL/电子邮件/电话 | "Link": "https://…" |
| 附件 | "Files": [{"url": "https://…"}](Airtable 会获取并重新托管) |
| 关联记录 | "Owner": ["recXXXXXXXXXXXXXX"](记录 ID 数组) |
| 用户 | "AssignedTo": {"id": "usrXXXXXXXXXXXXXX"} |
在创建/更新请求体的顶层传入 "typecast": true,即可让 Airtable 自动转换值(例如即时创建新的选项,或将 "42" 转换为 42)。
常见查询
列出令牌可见的基础
curl -s "https://api.airtable.com/v0/meta/bases" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool
列出某个基础的表格和架构
curl -s "https://api.airtable.com/v0/meta/bases/$BASE_ID/tables" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool
在执行更改操作前使用此项——它会确认确切的字段名称和 ID,显示选项字段的 options.choices,并展示主字段名称。
列出记录(前 10 条)
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?maxRecords=10" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool
获取单条记录
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool
筛选记录(filterByFormula)
Airtable 公式必须进行 URL 编码。使用 Python 标准库处理——切勿手动编码:
FORMULA="{Status}='Todo'"
ENC=$(python -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "$FORMULA")
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?filterByFormula=$ENC&maxRecords=20" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool
常用公式模式:
- 精确匹配:
{Email}='[email protected]' - 包含:
FIND('bug', LOWER({Title})) - 多个条件:
AND({Status}='Todo', {Priority}='High') - 或:
OR({Owner}='alice', {Owner}='bob') - 非空:
NOT({Assignee}='') - 日期比较:
IS_AFTER({Due}, TODAY())
排序并选择特定字段
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?sort%5B0%5D%5Bfield%5D=Priority&sort%5B0%5D%5Bdirection%5D=asc&fields%5B%5D=Name&fields%5B%5D=Status" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool
查询参数中的方括号必须进行 URL 编码(%5B/%5D)。
使用命名视图
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?view=Grid%20view&maxRecords=50" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool
视图会在服务端应用其已保存的筛选和排序规则。
常见更改操作
创建记录
curl -s -X POST "https://api.airtable.com/v0/$BASE_ID/$TABLE" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"fields":{"Name":"New task","Status":"Todo","Priority":"High"}}' | python -m json.tool
单次调用最多创建 10 条记录
curl -s -X POST "https://api.airtable.com/v0/$BASE_ID/$TABLE" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"typecast": true,
"records": [
{"fields": {"Name": "Task A", "Status": "Todo"}},
{"fields": {"Name": "Task B", "Status": "In progress"}}
]
}' | python -m json.tool
批量端点每个请求最多处理 10 条记录。插入更多记录时,应按每批 10 条循环处理,并短暂休眠,以遵守每个基础每秒 5 个请求的限制。
更新记录(PATCH — 合并并保留未更改的字段)
curl -s -X PATCH "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"fields":{"Status":"Done"}}' | python -m json.tool
按合并字段进行插入或更新(无需 ID)
curl -s -X PATCH "https://api.airtable.com/v0/$BASE_ID/$TABLE" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"performUpsert": {"fieldsToMergeOn": ["Email"]},
"records": [
{"fields": {"Email": "[email protected]", "Status": "Active"}}
]
}' | python -m json.tool
performUpsert 会为合并字段值尚不存在的记录创建新记录,并为合并字段值已存在的记录打补丁。非常适合实现幂等同步。
删除记录
curl -s -X DELETE "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool
单次调用最多删除 10 条记录
curl -s -X DELETE "https://api.airtable.com/v0/$BASE_ID/$TABLE?records%5B%5D=rec1&records%5B%5D=rec2" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool
分页
列表端点每页最多返回 100 条记录。如果响应包含 "offset": "...",请在下次调用时传回该值。循环请求,直到该字段不存在:
OFFSET=""
while :; do
URL="https://api.airtable.com/v0/$BASE_ID/$TABLE?pageSize=100"
[ -n "$OFFSET" ] && URL="$URL&offset=$OFFSET"
RESP=$(curl -s "$URL" -H "Authorization: Bearer $AIRTABLE_API_KEY")
echo "$RESP" | python -c 'import json,sys; d=json.load(sys.stdin); [print(r["id"], r["fields"].get("Name","")) for r in d["records"]]'
OFFSET=$(echo "$RESP" | python -c 'import json,sys; d=json.load(sys.stdin); print(d.get("offset",""))')
[ -z "$OFFSET" ] && break
done
典型的 Hermes 工作流
- 确认身份验证。
curl -s -o /dev/null -w "%{http_code}\n" https://api.airtable.com/v0/meta/bases -H "Authorization: Bearer $AIRTABLE_API_KEY"— 预期结果为200。 - 查找基础。 列出基础(见上面的步骤),或者如果令牌缺少
schema.bases:read权限,请用户直接提供app...ID。 - 检查架构。
GET /v0/meta/bases/$BASE_ID/tables— 在修改任何内容之前,将准确的字段名称和主字段名称缓存在当前会话中。 - 先读后写。 对于“在 Y 条件下更新 X”,先使用
filterByFormula查找rec...ID,然后调用PATCH /v0/$BASE_ID/$TABLE/$RECORD_ID。切勿猜测记录 ID。 - 批量写入。 将相关的新建操作合并到一次包含 10 条记录的 POST 中,以满足每秒 5 次请求的限制。
- 破坏性操作。 无法通过 API 撤销删除。如果用户说“删除所有 X”,请复述筛选条件和记录数,并在执行前确认。
注意事项
filterByFormula必须进行 URL 编码。 含空格或非 ASCII 字符的字段名称也需要编码({My Field}→%7BMy%20Field%7D)。使用 Python 标准库(参见上面的模式),切勿手动转义。- 空字段不会出现在响应中。 缺少
"Assignee"键并不表示字段不存在,而是表示这条记录的值为空。得出字段缺失的结论前,请检查架构(步骤 3)。 - PATCH 与 PUT。
PATCH会将提供的字段合并到记录中。PUT会完全替换记录,并清除所有未包含的字段。默认使用PATCH。 - 单选选项必须存在。 如果字段的选项列表中没有
Shipping,写入"Status": "Shipping"会报错,返回INVALID_MULTIPLE_CHOICE_OPTIONS;除非传入"typecast": true(这会自动创建该选项)。 - 按基础限制令牌访问范围。 某个基础返回
403,而另一个基础正常,表示令牌的 Access 列表未包含该基础,而非权限范围或身份验证问题。请让用户前往 https://airtable.com/create/tokens 授予访问权限。 - 速率限制按基础计算,而非按令牌计算。 在
baseA上每秒 5 次请求、在baseB上每秒 5 次请求没有问题;仅在baseA上每秒 6 次请求则会触发限流。收到429时,请留意Retry-After标头。
Hermes 重要说明
- 始终使用
terminal工具运行curl。 不要使用web_extract(无法发送身份验证标头)或browser_exec(需要通过 UI 进行身份验证,而且速度较慢)。 - 加载此技能后,
AIRTABLE_API_KEY会从${HERMES_HOME:-~/.hermes}/.env自动传递到子进程 — 无需在每次调用curl前重新导出。 - 谨慎转义公式中的花括号。 在 heredoc 正文中,
{Status}会按字面值处理。在 shell 参数中,只要不处于{...}花括号展开上下文,{Status}就是安全的 — 但在将动态字符串拼接到 URL 之前,请通过python urllib.parse.quote处理。 - 使用
python -m json.tool美化输出(始终可用),而非jq(可选)。只有在需要筛选或投影时才使用jq。 - 分页按页进行,而非全局进行。 Airtable 的 100 条记录上限是硬限制,无法提高。请使用
offset循环请求,直到该字段不存在。 - 对于非 2xx 响应,请读取
errors数组 — Airtable 会返回结构化错误代码,例如AUTHENTICATION_REQUIRED、INVALID_PERMISSIONS、MODEL_ID_NOT_FOUND、INVALID_MULTIPLE_CHOICE_OPTIONS,准确说明问题所在。