我是祥瑞,万涂幻象多维表格社区的主理人,一个深耕飞书多维表格的 AI 落地实践者。

聊一件昨天发生的事儿。

距离 618 还有将近一个月的时间,每年这个点电商朋友群里都热闹得离谱。有人晒爆单,有人哭着说运营三个人贴单贴到半夜,有人求”谁会写脚本,帮我把订单自动同步到 ZTO 那边”。

电商朋友交流群里,618 临近的真实焦虑:拉新、冲 GMV、ROI 一低就被骂

我看着挺有意思的。一边是飞书多维表格已经能管订单管得明明白白了,一边是出单环节还在手工操作。两头明明都是现成的能力,中间就差一座桥。

之前写过一篇《飞书多维表格的工作流和自动化,到底什么时候用哪个》,那篇讲的是多维表格自带的两套体系,左下角的工作流和右上角的自动化,到底什么场景用哪个。今天这篇要往外推一层,聊的是更上一层的飞书集成平台 anycross。它跟多维表格内置的工作流不是同一个东西,是飞书生态里一个独立的产品,能力边界更广,最关键的是它能调外部 API。

更刺激的是,这套从 0 到端到端跑通的链路,我自己一行代码没写,连 anycross 画布都没拖过一下。全程是 Claude Code 自己干的,我只负责提需求和验收。从早上打开电脑到晚上跑通,一天,六条 anycross 工作流。

我尽量把这次”指挥 AI 搭系统”的过程还原下来。

我只说了一句需求

整件事的起点是早上一句话。

我对着 Claude Code 输入框敲了大概这么个意思:我手头有一个飞书多维表格做的订单系统,想让它自动调中通 ZTO API 出运单号、查物流、撤单。你看着办,能搭多少搭多少。

Claude Code 终端:一句话需求扔过去,它就开始自己读飞书 anycross 文档 + ZTO 开放平台 + 摸内部 webapi

需求就这一句。没给文档、没给 API key、没说每条 flow 长啥样。

接下来我就基本没怎么动键盘了。

Claude Code 自己去翻 ZTO 开放平台文档,确认了 createOrder / track.query / cancelOrder 三个核心接口的入参。然后自己摸到了飞书集成平台 anycross 的内部 webapi 路径,搞清楚了”怎么不用拖画布、用 PUT 接口直接生成工作流”的方法。再然后开始一条一条写 Python 脚本拼 anycross 工作流的 def,PUT 上去,发布,调试。

这个过程我中间瞄了几眼,主要是看它有没有走偏。它每搭完一条 flow 就回头跟我汇报一次:“flowId 是 xxx,已经跑通,下一步搭 Flow2 还是 Flow3,你定一下”。我说继续。它就继续。

一天搭了 6 条 flow

中午吃完饭回来一看,前三条 flow 已经在跑了。下午又干了三条。傍晚的时候,6 条工作流全部跑通。

先抛全景,免得后面看晕:

↔ 左右滑动查看完整表格
编号干啥用触发方式调谁
Flow1任务确认到中通取号网址触发器(webhook)ZTO createOrder
Flow2取号完成远程触发打单机网址触发器ZTO 电子面单接口
Flow3单号查物流轨迹网址触发器ZTO track.query
Flow4退货撤单调中通 cancel网址触发器ZTO cancelOrder
Flow5定时扫表查未签收定时触发器 10:00调 Flow3
Flow6运单号到位推消息表格自动化(不是 anycross)飞书消息

6 条 flow 串成的发货闭环:anycross 当胶水,多维表格当订单库 + 消息总线

这套结构本质是一个事件驱动的小型 ERP。每条 flow 解决一件事,相互之间靠多维表格做共享状态,靠 webhook 做协同。换个说法,多维表格在这套系统里既是订单仓库又是消息总线。

最让我觉得奇妙的是 Claude Code 自己拆任务的方式。我没说要拆成 6 条,它自己琢磨出来的。它的逻辑是:每个外部 API 一条 flow,定时任务单独一条 flow 调前面那条,消息推送交给多维表格自带的自动化(因为不需要走 anycross 那么重)。这种边界感不是我教的,它自己看着来。

下面挑核心三段讲清楚,剩下两段在后面补。

拍按钮 30 秒出运单号

最爽的就是 Flow1 + Flow6 这一段,因为它能让你实实在在看到”机器替我干活”的画面。

整个链路是这样的:运营把订单状态改成”打包中”,多维表格里挂了一个按钮字段叫”取号”,拍下去之后多维表格自动化把订单内容打包成 webhook 请求发给 anycross,anycross 接到之后展开 12 个节点的链。

Flow1 anycross 画布,从网址触发器到加解密助手的链路一览

12 个节点干的事儿可以归成四块:

第一块是抽数据,从 webhook 入参里取订单记录的 record_id、收发件人、商品信息。

动态脚本节点:input 引用 webhook 入参,js_code 把入参重组成 ZTO 接口需要的 body 结构

第二块是签名,ZTO 接口走的是企业级签名,需要 appkey、appsecret、body、md5 拼出来一个 x-dataDigest 头。anycross 给了字符串助手 + 加解密助手两个节点,搭一下就成。

字符串助手拼 appkey + body + appsecret,加解密助手 md5 出 x-dataDigest 头

第三块是真发请求,HTTP Client 节点把组好的 body POST 给 https://japi.zto.com/zto.open.createOrder,等 ZTO 那边返回。

HTTP Client 节点:URL 是 ZTO createOrder,Body 引用 script-1 的 body,Headers 把签名头一并带上

第四块是回写。如果 ZTO 返回 message 是”成功”,从结果里拿 billCode 和 orderCode,回写到对应订单记录里。

分支节点判断 message == “成功”,命中后 bitable 节点把 billCode / orderCode 写回快递单表

这一切跑下来稳定在 4 到 5 秒。算上多维表格端按钮触发的延迟,端到端体感差不多 30 秒以内单号就出现了。

多维表格订单记录的运单号字段已经自动填好

更舒服的是 Flow6 这一截。

运单号一旦写回多维表格,就是一个字段变更事件。Claude Code 用多维表格自带的自动化挂了个监听,运单号字段非空就触发发送飞书消息,消息内容拼”订单 X 已出运单号 Y,请关注后续物流”,收件人通过 lookup 字段从订单主表里查到对应的业务负责人。

飞书消息推送:运单号一到,机器人立刻把单号 + 跟单提醒推给业务负责人

5 秒钟跑完,对应的同事在飞书里就能收到通知。

这一段的精妙之处不在技术多牛,而在分工特别合理:anycross 负责跨系统调外部接口,多维表格自动化负责表内事件推消息。各干各擅长的,谁也别越界。这个分工也是 Claude Code 自己拍板的,没等我提示。

物流轨迹自己往回写

订单出号只是开始,老板和客户更关心的是”我这个件儿现在到哪儿了”。

Flow3 解决”任意时刻查一个单号的物流”,Flow5 解决”每天自动把所有未签收的单子全部刷一遍”。

Flow3 是 10 个节点的链。webhook 接到 billCode 之后,组 body、签名、POST 给 https://japi.zto.com/zto.merchant.waybill.track.query,ZTO 返回的结构里有个 result 数组,里面是按时间倒序的轨迹节点。

Flow3 anycross 画布,10 个节点串成一条直链

广告媒流(小程序)-公众号

Claude Code 在这里专门写了个 script-2 节点解析返回值。逻辑是这样的:如果 result 是空数组(说明 ZTO 那边只建了单还没揽收),就把”物流状态”写成”待发送”,“最新轨迹”写”运单号已生成等待揽收扫描”。如果 result 有内容,就取最新一条节点的描述写进去,同时把节点对应的省市、操作时间也回填到表格的对应字段。

跑通之后效果是这样:你给 Flow3 webhook 打一个 POST 携带任意运单号,5 秒内多维表格里那一行的物流字段全部刷新。

物流状态字段:待发送 / 运输中 / 已揽收,由 Flow3 自动写入

光有手动查不够,因为没人会真的一条条去拍按钮。Flow5 干的就是兜底。

它用 anycross 的定时触发器配了个每天早上 10:00 跑一次,先去多维表格查一条物流状态不等于”已签收”的最早记录,提取 billCode 和 record_id,组 body 调 Flow3 的 webhook,相当于 Flow5 是 Flow3 的自动化触发器。

之所以一次只查一条不是查全部,是 Claude Code 自己定的策略:日单量小的时候 page_size=1 就够,每天 10:00 跑一轮,30 天下来未签收快递一定能轮到一遍。后面要扩成多条,把 page_size 调大 + script 改成接数组循环就完事儿。

Flow5 anycross 画布,定时触发器 → 查询未签收 → 取第 1 条 → 调 Flow3

到这一步,“我什么都不用做,物流自己往表格里跑”已经成立了。

退货撤单和远程打单

Flow2 和 Flow4 这两条目前是半成品,Claude Code 自己也很坦诚地标了出来。

Flow4 退货撤单

逻辑很简单:运营在多维表格把订单状态改成”已退货”,触发 webhook 调 ZTO 的 cancelOrder 接口,撤完之后回写”已撤单”字段。

接口侧的链路它已经按 Flow1 改造完了,骨架完整。卡点是 ZTO 那边的 zto.open.order.cancel 接口需要单独申请权限,审批周期大概 7 天,目前还在等。

Flow4 顶部状态条:未运行 + 有更新未发布,等 ZTO 接口审批一通过就能上线

它在这里偷了个懒得很巧妙的懒:先用 anycross UI 的接口创建一个空的 Flow4,让系统自动分配一个 webhook URL,再 PUT 改造 def 把节点结构都搭好。等审批一通过,进去改一个 http-client URL 字段就能上线,不需要从头建。这种”先占坑再补”的思路是它跟我商量过的,我觉得行。

Flow4 退货撤单画布,骨架完整但顶部状态显示”未发布”

Flow2 远程触发打单机

这条更有意思,本质是把电子面单从 ZTO 服务器直接推给本地的云打印机,运营这边一秒都不用碰。逻辑链路全部跑通了,签名、参数、body 一切正确,最后卡在 ZTO 返回的业务错”S01 二维码传参无效”上。

Flow2 顶部状态条:运行中,纯代码侧已经跑通

这个错不是代码问题,是因为我手头没有真实绑定的云打印机硬件,deviceId 和 qrcodeId 我填的是测试值。要彻底跑通需要在 ZTO 商户后台给打单机配好真硬件 ID,纯业务侧的事儿。

Flow2 远程触发打单机画布,链路完整但最末环节缺真实硬件 ID

这俩条留到 ZTO 那边权限和硬件都齐了,半天工作量补完。

路上踩的几个坑

最有意思的不是搭通,而是搭的过程里 Claude Code 自己怎么踩坑、怎么从日志里把根因揪出来。它每发现一个坑都跟我同步一次:“这里报错 X,我猜是 Y,正在试 Z”。我说继续。它就继续。

挑几个最有共鸣的说一下,希望你做的时候能省掉这些时间。

第一个坑:99991673 unauthorized

bitable 节点跑起来直接报”unauthorized app”,但更要命的是看不到 base 的调用日志,鉴权前置就挂了。Claude Code 起初也走了一段弯路,怀疑是权限没开、scope 没勾、token 失效,全否定之后开始挨个比对配置。

最后是它把 anycross 的应用凭证下拉点开看了眼,发现里面同名的 cli_xxx 居然有两个不同 ID。之前选的是另一个同名 app,那个 app 在我账号下根本看不见。换成我应用列表里能看到的那个 cli ID,秒过。

教训:anycross 选凭证认 cli ID 不认应用名。同租户内同名 app 完全可以共存,下拉全是 cli_xxx 一串看着都一样,闭着眼选注定踩雷。

应用凭证下拉里两个同名 app,cli ID 后缀不同;选错那条就是 99991673 unauthorized 的根因

第二个坑:success 不等于成功

这个坑活活让 Flow1 跑了三遍才发现。

Flow1 的逻辑里有个分支节点判断 ZTO 的返回值,Claude Code 一开始按英文 API 风格配的条件是 message === "success",凡是命中走 bitable 写回。结果不管多少次调用,bitable 永远没写。

最后它翻原始日志才发现,ZTO 的 createOrder 接口返回成功 message 是中文”成功”两个字,不是英文 success。习惯性按英文 API 写的判断条件永远不会命中,分支永远走 default。

把 right value 改成中文”成功”,重发布,秒通。

教训:写 anycross 分支条件不要凭语义猜返回值,先调试一遍看真实输出,对着日志写判断。中文 API 就用中文比对,别脑补。

第三个坑:spel 表达式不支持函数

anycross 的 spel(也就是节点之间引用数据用的表达式)有个隐藏限制:通过 PUT def 接口写流程定义的时候,spel 表达式只能是 json_path 形式,比如 \_("\$.script-1.result.body"),函数调用、运算符、对象方法一律报错。

Claude Code 一开始想在 spel 里直接写 \_(\$.bitable-1.data.items.size()) 取数组长度,发布报错”unsupported expression node type [func_call]“。

绕过办法:把所有需要计算的逻辑都搬到一个动态脚本节点里,spel 只负责引用结果。比如先在 script-1 里 return {count: input.length},后面节点引用 \_("\$.script-1.result.count")。

教训:anycross 的 spel 不是你想的 SpEL 全集。复杂逻辑都进 script 节点,spel 只搬数据。

第四个坑:HOUR_TRIGGER 被拒

Flow5 最早想配每小时跑一次扫表,trigger_type 写 HOUR_TRIGGER 直接报错”unknown trigger_type or version=1.5”。

试了 MINUTE_TRIGGER 也不行。最后翻文档才确认 anycross 的定时触发器目前只支持 DAY_TRIGGER / WEEK_TRIGGER / MONTH_TRIGGER 三种,没小时和分钟级。

绕过办法:DAY_TRIGGER 配多个 execute_time。比如配 10:00 / 14:00 / 18:00 三个时间点,等价于一天扫三次。再密的频率就需要换思路,比如多维表格事件驱动而不是定时驱动。

cronjob 配置:DAY_TRIGGER 是合法选项,HOUR_TRIGGER 直接被引擎拒绝

教训:anycross 的能力不是你想象的全集,规划频率前先确认引擎支持。

写在最后

一天,6 条工作流,4 个被记下来的坑,一个端到端跑通的发货链路。

我把这次实验的关键节点跟万涂幻象的几个老学员复盘过一轮。大家最有感觉的反而不是 anycross 调接口那块,而是”原来 AI 真的能自己把这种业务系统拼出来”这件事本身。

回头看这次实验,最值得记下来的不是我具体搭了哪几条 flow,而是这一句:

AI agent 真正的价值,不是帮你写几段代码,而是把一个模糊的业务需求拆成可以运行的系统。

业务人在过去想要一套像样的系统,无非三条路。要么自己学半年代码硬上,要么花几万找外包,要么砸钱买 ERP。这三条路不是不行,是慢,是贵,是不灵活。

今天多了第四条路:把模糊需求扔给 AI agent,它替你读文档、拆任务、写代码、调接口、排坑、收尾。你的角色从”开发者”变成”指挥者 + 验收者”,能力放大十倍不止。

这条路的关键不在 AI 写代码有多快,而在它能把一个含糊的业务想法翻译成一组可以运行的工程节点。我说”自动调中通 API 出运单号、查物流、撤单”,它听完自己拆出 6 条 flow,自己定每条 flow 的边界,自己挑触发器和连接器。这一步是过去外包做不来的,因为外包要的是详细 PRD,AI agent 要的是模糊意图。

618 之前你如果是中小电商商家,与其多招两个临时工,不如花半天把你脑子里那个”我希望系统能…的”想法用一句话扔给 AI agent 试一下。它给你的可能不是完美方案,但很可能是一个能跑、能改、能慢慢长大的雏形。

工具的本意从来不是替代人,而是让人去做只有人能做的事。机器愿意拼系统,业务人才有时间去想清楚自己真正要什么。这才是 AI 时代该有的样子。

下一篇打算把 Claude Code 这次自己摸透 anycross 内部 webapi 的过程拆开讲,包括它是怎么从浏览器抓出 PUT def 接口、怎么逆出 connector 元数据接口的。如果你对哪一段更感兴趣,或者你也有想让 AI 帮你拼出来的业务系统,评论区告诉我,留言我都会看。

我是祥瑞,万涂幻象主理人,下一篇见。