Airtable
通過 curl 使用 Airtable REST API。支持記錄的 CRUD、過濾和 upsert(更新或插入)。
技能元數據
| 來源 | Bundled(默認安裝) |
| 路徑 | skills/productivity/airtable |
| 版本 | 1.1.0 |
| 作者 | community |
| 許可證 | MIT |
| 平臺 | linux, macos, windows |
| 標籤 | Airtable, Productivity, Database, API |
參考:完整 SKILL.md
以下是 Hermes 在觸發此技能時加載的完整技能定義。這是技能激活時代理看到的指令。
Airtable — Base、表與記錄
通過 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— 列出 base 和表
- 重要: 在同一令牌界面中,將每個要訪問的 base 添加到令牌的訪問 (Access) 列表中。PAT 是按 base 限定作用域的 — 在錯誤的 base 上使用有效令牌將返回
403。 - 將令牌存儲在
~/.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: base 為
app...,表為tbl...,記錄為rec...,字段為fld...。ID 永不更改;名稱可能會變。在自動化中優先使用 ID。 - 速率限制: 每個 base 每秒 5 個請求。遇到
429時需退避。單個 base 上的突發請求將被限流。
基本 curl 模式:
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?maxRecords=5" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
-s 抑制 curl 的進度條 — 每次調用都保持設置此項,以便工具輸出對 Hermes 保持乾淨。通過 python3 -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)。
常見查詢
列出令牌可見的 base
curl -s "https://api.airtable.com/v0/meta/bases" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
列出 base 的表 + 架構
curl -s "https://api.airtable.com/v0/meta/bases/$BASE_ID/tables" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -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" | python3 -m json.tool
獲取單條記錄
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
過濾記錄 (filterByFormula)
Airtable 公式必須進行 URL 編碼。讓 Python 標準庫處理 — 切勿手動編碼:
FORMULA="{Status}='Todo'"
ENC=$(python3 -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" | python3 -m json.tool
有用的公式模式:
- 精確匹配:
{Email}='user@example.com' - 包含:
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" | python3 -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" | python3 -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"}}' | python3 -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"}}
]
}' | python3 -m json.tool
批量端點限制為每個請求最多 10 條記錄。對於更大的插入操作,請以 10 條為一批循環,並短暫休眠以遵守每個 base 每秒 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"}}' | python3 -m json.tool
通過合併字段 Upsert(無需 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": "user@example.com", "Status": "Active"}}
]
}' | python3 -m json.tool
performUpsert 創建合併字段值為新的記錄,修補合併字段值已存在的記錄。非常適合冪等同步。
刪除記錄
curl -s -X DELETE "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \
-H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -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" | python3 -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" | python3 -c 'import json,sys; d=json.load(sys.stdin); [print(r["id"], r["fields"].get("Name","")) for r in d["records"]]'
OFFSET=$(echo "$RESP" | python3 -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。 - 查找 Base。 列出 bases(上一步)或者如果令牌缺少
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(這將自動創建該選項)。 - 每個 Base 的令牌作用域。 如果一個 Base 返回
403而另一個正常,這意味著令牌的訪問列表未包含該 Base — 這不是作用域或身份驗證問題。引導用戶前往 https://airtable.com/create/tokens 授予權限。 - 速率限制是按 Base 而非按令牌計算的。
baseA每秒 5 次請求且baseB每秒 5 次請求是可以的;僅baseA每秒 6 次請求將會被限流。監控429響應中的Retry-After頭。
Hermes 重要注意事項
- 始終使用帶有
curl的terminal工具。 不要使用web_extract(它無法發送身份驗證頭)或browser_navigate(需要 UI 身份驗證且速度較慢)。 - 加載此技能時,
AIRTABLE_API_KEY會自動從~/.hermes/.env流入子進程 — 無需在每次curl調用前重新導出它。 - 仔細轉義公式中的花括號。 在 heredoc 主體中,
{Status}是字面量。在 shell 參數中,{Status}在{...}花括號擴展上下文之外是安全的 — 但在拼接到 URL 之前,請通過python3 urllib.parse.quote傳遞動態字符串。 - 使用
python3 -m json.tool(始終存在)進行美化打印,而不是jq(可選)。僅在需要過濾/投影時才使用jq。 - 分頁是按頁進行的,而非全局的。 Airtable 的 100 條記錄上限是硬性限制;無法提高它。循環使用
offset直到該字段 absent。 - 讀取非 2xx 響應中的
errors數組 — Airtable 返回結構化錯誤代碼,如AUTHENTICATION_REQUIRED、INVALID_PERMISSIONS、MODEL_ID_NOT_FOUND、INVALID_MULTIPLE_CHOICE_OPTIONS,這些代碼會準確告知你哪裡出錯了。