首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >OpenClaw + 豆包 + 扣子 + 飞书落地:四层分工的工程边界,不在“打通”,在“谁被允许做什么”

OpenClaw + 豆包 + 扣子 + 飞书落地:四层分工的工程边界,不在“打通”,在“谁被允许做什么”

原创
作者头像
用户12339161
发布于 2026-10-29 11:17:05
发布于 2026-10-29 11:17:05
1270
举报

这套组合最常见的叙事是“飞书对话、扣子编排、豆包推理、OpenClaw执行,四件套一接就通了”。但从落地工程的视角看,真正的分水岭不在连通性,而在每一层是否被赋予了正确的权限边界,以及越权动作是否有代码级的拦截。四者的合理分工是:飞书是交互入口,用户在哪里说话,入口就在哪里;扣子是编排与模型路由层,负责工作流、知识库和自定义模型接入;豆包是推理引擎,承担中文场景下的生成与规划;OpenClaw是执行网关,把“说出来的决定”变成“做出来的动作”。问题在于,当这四层串联之后,一个来自飞书群聊的自然语言请求,可能一路穿透到OpenClaw的Shell或浏览器工具。如果没有边界,打通得越顺畅,越危险。

飞书入口:会话身份必须绑定到执行身份,而不是“一个群共享一个Agent”

飞书与OpenClaw的集成有两条路径:Webhook回调与长连接。Webhook模式下,飞书事件被推送到OpenClaw的hooks端点,需要一段转换逻辑把飞书的消息体映射为OpenClaw的标准agent请求。关键字段是sessionKey:它决定哪个用户在执行层拥有独立的会话上下文。如果所有飞书群消息共用同一个sessionKey,A用户的指令和B用户的上下文就会混在一起,执行层的工具权限也无法按人隔离。

以下转换函数将飞书发送者的user_id绑定到sessionKey,确保每个用户拥有独立的执行会话,而不是按群共享:

代码语言:javascript
复制
def transform_feishu_event(body: dict) -> dict:
    sender_id = body["event"]["sender"]["sender_id"]["user_id"]
    message = body["event"]["message"]["content"]
    return {
        "message": f"飞书消息: {message}",
        "name": "Feishu",
        "sessionKey": f"hook:feishu:{sender_id}",  # 按人隔离,不按群共享
        "wakeMode": "now",
        "deliver": True,
    }

sessionKey的绑定是执行层权限隔离的第一道前提。没有它,后续的工具策略和审批都无法按主体生效。

扣子编排与豆包路由:凭证按租户隔离,Base URL必须精确

扣子承担的是工作流编排和模型路由。调用扣子工作流的API端点是POST /v3/workflows/run,鉴权走Authorization: Bearer {PAT}。在扣子内部接入豆包,SaaS版在工作流LLM节点填写豆包方舟的Base URL和Key;需要注意豆包通用模型与编码模型的Base URL是隔离的,混用会导致401或404。一个可执行的调用封装必须携带幂等键,并将凭证从代码中剥离:

代码语言:javascript
复制
import os, httpx

COZE_PAT = os.environ["COZE_PAT"]          # 不入库、不进代码
BASE = "https://api.coze.cn"

async def run_workflow(workflow_id: str, params: dict, idem_key: str) -> dict:
    headers = {"Authorization": f"Bearer {COZE_PAT}",
               "Idempotency-Key": idem_key}   # 同一意图重试不重复执行
    async with httpx.AsyncClient(timeout=120) as c:
        r = await c.post(f"{BASE}/v3/workflows/run",
                         json={"workflow_id": workflow_id,
                               "parameters": params},
                         headers=headers)
        r.raise_for_status()
        return r.json()

扣子侧的凭证管理必须与租户绑定,不能用一个全局PAT服务所有租户。豆包的ark_api_key和base_url同样应按租户或按环境隔离,而不是硬编码在工作流节点里。

OpenClaw执行网关:默认不暴露,敏感动作必须过审批

OpenClaw的Gateway是整个执行链路的控制平面,默认端口是18789。安全基线的第一原则非常明确:Gateway禁止暴露到公网,必须绑定loopback,远程访问只通过SSH隧道或Tailscale,而不是开放端口。这意味着飞书Webhook不能直接打到公网上的Gateway端口,而应经由反向代理或隧道转发到本地回环地址。

第二层边界是工具策略与人工审批。OpenClaw的沙箱和工具系统可以限制Agent能调用的工具范围,但更关键的是:哪些动作必须停下来等人批准。扣子工作流中的“人工审核节点”接入飞书审批时,不能靠轮询数据库或“暂停等待”,而应由飞书审批状态变更事件触发后续流程。以下门禁函数将“执行动作是否被允许”的判定放在OpenClaw的工具调用之前,未获批准的敏感工具直接拒

代码语言:javascript
复制
SENSITIVE_TOOLS = {"execute_bash", "browser", "write_file"}
APPROVED_ACTIONS: set[str] = set()   # 由飞书审批回调写入

def guard_tool_call(session_key: str, tool: str, action_id: str) -> None:
    if tool not in SENSITIVE_TOOLS:
        return
    if action_id not in APPROVED_ACTIONS:
        raise PermissionError(
            f"session={session_key} tool={tool} 未获批准,禁止执行"
        )

action_id应由扣子工作流在发起审批时生成,飞书审批通过后由回调写入APPROVED_ACTIONS,OpenClaw在执行前机械校验。执行权限由代码持有,不由Agent的自我判断持有。

落地的真实门槛:四层打通之后,边界是否仍然成立

北京金谷园饺子馆的案例提供了一个有意义的参照:顾客通过OpenClaw或扣子安装“金谷园饺子馆Skill”,即可查询位置、Wi-Fi、外卖信息并完成排队取号。这个场景之所以能落地,不是因为四件套“接上了”,而是因为排队取号是一个边界清晰的动作:它有明确的工具接口、有可验证的结果、且不涉及任意Shell执行或跨租户数据访问。反过来,当一个飞书群里的自然语言请求要求“把昨天所有未付款订单的客户名单导出来并群发”,真正决定系统能否安全运行的,不是豆包能不能理解这句话,而是sessionKey是否绑定了正确的用户、扣子的凭证是否属于当前租户、OpenClaw的工具白名单是否放行了文件读取、敏感动作是否经过了审批门禁。

OpenClaw + 豆包 + 扣子 + 飞书的工程成熟度,最终不以“四层是否连通”衡量,而以四件事是否同时成立来衡量:飞书入口的sessionKey按用户隔离而非按群共享;扣子与豆包的凭证按租户和环境隔离且Base URL精确匹配;OpenClaw Gateway绑定loopback、不暴露公网;敏感工具调用在执行前必须通过代码级审批门禁。当这四道边界由代码持有、模型无法绕过时,“打通”才从一次演示变成一条可以交付给真实用户的生产链路。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 飞书入口:会话身份必须绑定到执行身份,而不是“一个群共享一个Agent”
  • 扣子编排与豆包路由:凭证按租户隔离,Base URL必须精确
  • OpenClaw执行网关:默认不暴露,敏感动作必须过审批
  • 落地的真实门槛:四层打通之后,边界是否仍然成立
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档