CRITICAL — Before starting, you MUST first use the Read tool to read ../lark-shared/SKILL.md, which contains authentication and permission handling
Applicable scenarios
- "Sync the new data from table A to table B" / "data synchronization"
- "Cross-table synchronization: collection table → follow-up table" / "cross-table synchronization"
- "Merge the data of these two tables" / "merge tables"
- "Migrate the data from table A to table B" / "data migration"
- "Monitor table XXX and notify me when there are new records" / "data synchronization between tables"
Prerequisites
Only user identityis supported. Before executing, ensure authorization has been granted:
lark-cli auth login --domain base
Workflow
{源表 base_token + table_id} → {目标表 base_token + table_id}
│
├── base +field-list (源表) ──────► 源表字段结构
│
├── base +field-list (目标表) ────► 目标表字段结构
│
├── AI 字段映射 ──────────────────► 源字段 ↔ 目标字段(用户确认)
│
├── base +record-list (源表) ────► 拉取源数据(分页,max 200/页)
│
├── base +record-list (目标表) ──► 拉取目标现有数据(用于去重)
│
├── AI 数据比对去重 ──────────────► 差异记录集(新增 + 更新)
│
└── base +record-upsert (目标表) ─► 写入差异数据(串行,间隔 1s)
Step 1: Get the table structure
Get the field lists of the source table and target table separately:
# 源表字段
lark-cli base +field-list \
--base-token "<src_base_token>" \
--table-id "<src_table_id>" \
--as user
# 目标表字段
lark-cli base +field-list \
--base-token "<tgt_base_token>" \
--table-id "<tgt_table_id>" \
--as user
Note: the two
+field-listcalls cannot be concurrent; they must be serial.
Step 2: AI generates the field mapping
Based on the field names and types of the two tables, the AI automatically generates a field mapping plan:
## 字段映射方案
| 源字段 | 源类型 | → | 目标字段 | 目标类型 |
|--------|--------|---|---------|---------|
| 客户名称 | text | → | 公司名称 | text |
| 联系电话 | text | → | 电话 | text |
| 状态 | select | → | 跟进状态 | select |
| 创建时间 | datetime | → | 录入日期 | datetime |
**去重字段**:客户名称(以此字段判断记录是否已存在)
请确认此映射方案。
Important:
- The field mapping plan must be confirmed with the user before executing synchronization
- Have the user specify the deduplication field (used to determine whether a record already exists)
- Only mapwritable fields(ignore formula, lookup reference, and system fields)
Step 3: Pull the source data
# 拉取源表全部记录(分页,每页最多 200 条)
lark-cli base +record-list \
--base-token "<src_base_token>" \
--table-id "<src_table_id>" \
--as user
# 如果数据量大,使用分页
lark-cli base +record-list \
--base-token "<src_base_token>" \
--table-id "<src_table_id>" \
--limit 200 \
--as user
Note: a maximum of 200 records per page. If the returned data contains pagination information, continue using offset to pull the next page.
Step 4: Pull the target data (for deduplication)
# 拉取目标表现有记录(获取去重字段值)
lark-cli base +record-list \
--base-token "<tgt_base_token>" \
--table-id "<tgt_table_id>" \
--as user
Step 5: AI comparison and deduplication
Compare the source data and target data, and determine based on the deduplication field:
- Added: records that exist in the source table but not in the target table
- Updated: records that exist in both the source table and target table, but have differences in field values
Generate a difference report:
## 同步预览
| 类型 | 数量 |
|------|------|
| 新增记录 | N |
| 需更新记录 | N |
| 无变化记录 | N |
| **总计** | **N** |
### 新增记录预览(前 5 条)
| 客户名称 | 联系电话 | 状态 |
|---------|---------|------|
### 需更新记录预览(前 5 条)
| 客户名称 | 字段 | 旧值 | 新值 |
|---------|------|------|------|
确认执行同步?
Step 6: Write the difference data
For each difference record, call +record-upsert(serial, with a 1-second interval):
Add record
lark-cli base +record-upsert \
--base-token "<tgt_base_token>" \
--table-id "<tgt_table_id>" \
--json '{"公司名称":"XX科技","电话":"13800138000","跟进状态":"新线索"}' \
--as user
sleep 1
Update record
First get the record_id of the target record, then update:
lark-cli base +record-upsert \
--base-token "<tgt_base_token>" \
--table-id "<tgt_table_id>" \
--record-id "<existing_record_id>" \
--json '{"跟进状态":"已联系"}' \
--as user
sleep 1
Note:
- At least 1 second interval between each call
- Date fields require a Unix millisecond timestamp (not a string)
- The personnel field format is
[{"id":"ou_xxx"}]- For single-select fields, pass the option name string
Fallback strategy
| Scenario | Fallback plan |
|---|---|
| Field type mismatch | Skip incompatible fields and synchronize only compatible fields |
| No matching field in the target table | Prompt the user to create the corresponding field in the target table |
| Data volume too large | Synchronize in batches (50 records per batch) |
| Write rate limit | Reduce to one record every 2 seconds |
| Field mapping unclear | Ask the user to confirm the mapping relationship |
Permission table
| Command | Required scope |
|---|---|
base +field-list |
bitable:app:readonly |
base +record-list |
bitable:app:readonly |
base +record-upsert |
bitable:app |
Reference
../lark-base/SKILL.md— Bitable atomic operations