尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

DeerFlow IM Channel Connections 实战指南:用户自有渠道的连接绑定、消息分发与文件管线

DeerFlow IM Channel Connections 实战指南:用户自有渠道的连接绑定、消息分发与文件管线 DeerFlow IM Channel Connections 实战指南用户自有渠道的连接绑定、消息分发与文件管线【免费下载链接】deer-flowAn open-source long-horizon SuperAgent harness that researches, codes, and creates. With the help of sandboxes, memories, tools, skill, subagents and message gateway, it handles different levels of tasks that could take minutes to hours.项目地址: https://gitcode.com/GitHub_Trending/de/deer-flow本文是 DeerFlow 中IM Channel Connections用户自有 IM 渠道连接体系的技术实战指南。该特性允许在 Telegram、Slack、Discord、飞书/Lark、钉钉、微信、企业微信 WeCom 与 Buzz 上把某个平台账号/工作区绑定到某一个 DeerFlow 用户从而让经渠道发起的每一次运行都落进该用户的专属桶记忆、上传文件、产物与自定义 Agent。读完本文你将掌握Connect 一次性绑定码的完整时序、数据库层面实现的单一活跃归属者不变量、绑定后消息从入站到出站的完整分发链路、同步/流式两类渠道的差异化运行策略以及config.yaml中每个开关含 Buzz 的订阅模型与信任模型的真实含义与运维后果。原始设计文档见 IM_CHANNEL_CONNECTIONS.md高层索引配置旋钮、消息流、组件清单见 AGENTS.md 中 IM Channels System 一节以及渠道子系统自己的 AGENTS.md。一、特性概览绑定层在 bot 凭证之上补上了什么DeerFlow 的 IM 渠道连接在语义上是一个**按 DeerFlow 用户的绑定层**它叠在既有的channels.*出站/入站 bot 凭证之上而不是重新发明一套出站传输。因此本地部署与私有化部署可以复用 DeerFlow 已经支持的全部出站通道且整套实现不需要公网 IP、OAuth 回调 URL也不需要向渠道平台注册 webhook——所有传输都建立在各平台已有的长连接/轮询/Socket Mode 机制之上。为什么有了 bot 凭证还不够绑定层在既有凭证能力之外新增了三样东西归属者身份Owner identity—— 每一个(provider, external account, workspace)三元组都唯一映射到一个 DeerFlow 账号owner_user_id。由此连接发起的每个 run都运行在该归属者的桶里记忆、上传、产物、自定义 Agent 均按此隔离。一次性绑定码One-time bind codes—— 浏览器 Connect 流程铸造一个短期随机码secrets.token_urlsafe(16)600 秒 TTL、单次使用且只在发起用户的浏览器中展示。各平台 worker 在应用allowed_users过滤之前消费/connect codeTelegram 使用 deep link 方式的/start code因此尚未进入白名单的用户也能完成首次绑定。严格的归属转移Strict ownership transfer—— 最近一次成功的绑定后到者胜upsert_connection会撤销其他归属者针对同一外部身份的有效行。数据库层的部分唯一索引uq_channel_connection_active_identityWHERE status ! revoked让该不变量在并发写入下也是无竞态race-free的。一句话概括安全边界Connect 码是绑定时刻的防线不是聊天时刻的防线。绑定完成后普通消息仍由既有的allowed_users按原样把关。二、Connect 绑定码流程浏览器发起、worker 消费、manager 不碰码关键设计约束是浏览器发起provider worker 消费码调度中心ChannelManager永远看不到码本身。在存储实现上channel_connections/sql.pyconsume_oauth_state使用一次条件 UPDATE只有能把consumed_at从 NULL 翻转为当前时刻的那个 writer 才算赢两个 worker 并发消费同一码时只有一个能成功——这就是单次使用的无竞态落地点。码在数据库中不以明文落盘而是先经 SHA-256 哈希hash_state再以state_hash作为主键存储见 model.py 中ChannelOAuthStateRow。三、单一活跃归属者数据库索引才是真话整个归属转移体系的核心论点是应用代码永远不需要显式地撤销上一任归属者。原因是当一次重新使用同一身份的 upsert 触发唯一约束冲突而失败后失败方会输掉这场竞争并在下一次重试时对着现在已可见的 revoked 状态行动。尘埃落定之后的状态是新连接connection_idB、ownerB、statusconnected旧连接connection_idA、ownerA、statusrevoked。源码层面可以看到两层配合channel_connections/model.py普通唯一约束uq_channel_connection_owner_provider_identityowner_user_id provider external_account_id workspace_id保证同一归属者不会为同一外部身份重复建行部分唯一索引uq_channel_connection_active_identityprovider external_account_id workspace_idWHERE status ! revoked保证任何时刻、全库范围内一个外部身份至多只有一条未撤销行SQLite 与 PostgreSQL 均支持这种 partial unique index。而 sql.py 中的upsert_connection把事务拆成了先撤销其他归属者的 active 行连带删除其channel_credentials再提交自己的 connected 行冲突时回滚并最多重试 3 次_UPSERT_MAX_ATTEMPTS 3每次重试都重读当前可见状态因此并发归属转移在真实竞争下也能收敛。同一个不变量还保护着find_connection_by_external_identity查找——它是ChannelManager._get_bound_identity_rejection判断这条消息是否来自已绑定身份的底层依据。因为未撤销的行在任何时刻只会解析到唯一归属者所以这条查找天然不会出现一身份映射多归属者的歧义。四、绑定之后Provider 消息如何走完全程一旦连接绑定成功每条入站消息都会经由ChannelManager走同一条路径。Slack/Discord无流式与飞书/Telegram有流式只在run 边界处分叉4.1 入站容量与过载行为三个顶层channels设置控制着 MessageBus/manager 的生命周期默认值、语义与启动校验分别实现在 service.py、message_bus.py 与 manager.py 中配置项默认值含义channels.inbound_queue_maxsize1000排队消息 provider 侧仍在做最终身份/ack 准备的预留之和channels.max_concurrency5常驻ChannelManagerworker 的精确数量channels.shutdown_grace_period_seconds3主动 handler 被取消前允许的排空graceful draining时间上限active handler 在这些 worker内联执行inline所以突发流量不会造成每条消息一个 task。由此可得 manager 实际持有的最大在途 intake 待处理容量 固定 worker 数是有上界的。一个值得注意的实现细节是准入admission永不等待队列空间。因为让生产者协程等待队列腾位只会把无界积压搬到队列外面并不会缓解过载。因此在容量打满时Slack、Discord、飞书/Lark、钉钉、Telegram、微信、WeCom在 DeerFlow 发出工作确认working acknowledgment之前就丢弃新消息MessageBus以限速方式输出一条带累计拒绝计数的告警日志Buzz保持该渠道的按渠道回放水位per-channel replay watermark不变并重连让 relay 的历史回放机制把该事件重新投递进来GitHub webhook 扇出返回503GitHub 侧把投递记为失败运维人员或恢复任务可通过 GitHub 的 Recent Deliveries 界面或 REST redelivery API 手动重试GitHub 不会自动重试失败的投递。4.2 优雅停机先关准入、后断传输关停顺序决定了会不会出现handler 用已关闭的传输发消息。实现上先关闭准入admission并取消后续 watcher但保持 provider 传输存活让 worker 在shutdown_grace_period_seconds内把已接受消息排空宽限期耗尽后取消 active handler、丢弃从未开始的队列条目并 await 每一个 manager 持有的 worker 与 watcher。从 SDK 线程提交的 provider 协程同样被保留、取消并 await之后该渠道才会拆除 SDK 资源——因此一次成功的停机会保证没有任何 owned handler 还能使用已关闭的传输。Gateway 外层停机超时仍是进程级的总预算如果它取消了清理动作服务会保留其传输与单例而不是虚报成功停机或掩盖未完成的归属清理。五、同步 vs 流式渠道一切分歧源于一个能力位两种路径在ChannelRunPolicy.supports_streaming处分叉。该能力位来自ChannelManager里的渠道能力登记表CHANNEL_CAPABILITIESmanager.py也见渠道实现各自声明的supports_streaming()例如 telegram.py、feishu.py、wecom.py、buzz.py同步渠道supports_streamingfalseSlack、Discord、DingTalk—— manager 调用runs.wait()阻塞等待从最终 state 中抽取 AI 文本然后一次性publish_outbound(is_finalTrue)。流式渠道supports_streamingtrueFeishu/Lark、Telegram、WeCom—— manager 调用runs.stream(messages-tuple values)逐 chunk 以节流方式publish_outbound(is_finalFalse)各平台用各自的进行中载体呈现中间结果Telegram 编辑占位消息、飞书 patch 运行中的卡片、WeCom 走PUT /v1.0/card/streaming最终再发布is_finalTrue。GitHub 是一个特殊分支它的渠道策略是fire_and_forgetTrue见 run_policy.py 中的ChannelRunPolicy描述符以及 github/run_policy.py 的登记manager 只需runs.create()并在 run 进入pending后即返回不做任何出站回复——因为 GitHub agent 是在自己的沙箱里通过ghCLI 直接回帖的。完整 GitHub 流程见 GITHUB_AGENTS.md。5.1 ChannelRunPolicy一份策略数据类承载全部渠道差异从源码看CHANNEL_RUN_POLICY是一个渠道名 → 策略注册表新增一个 webhook/特殊渠道只需注册一行策略而不是改动 manager 的多处方法run_policy.py。值得了解的字段包括is_interactiveFalse 时关闭澄清提问适配无人同步在场的自主长任务、default_recursion_limit把recursion_limit抬到max(现有值, 配置值)GitHub 这类长跑任务需要更高上限普通聊天回合则保持全局默认、credentials_provider向run_context注入平台专用凭证的异步钩子异常会被捕获降级为只读运行、requires_bound_identityFalse 时跳过按发送者的绑定身份闸门——webhook 渠道用 HMAC 做真实性认证没有/connect握手、fire_and_forget与serialize_thread_runs等。六、归属者作用域的文件存储Owner-scoped File StorageChannelManager在_handle_chat顶部只解析一次存储归属者_channel_storage_user_id(msg)会做安全化处理sanitized owner id并在无绑定身份的渠道上回退到safe(msg.user_id)与_resolve_run_params的 run 身份保持一致只有当任何身份都不可用时才返回None。这个值被贯穿到整个文件管线同时用作run_context[user_id]run 身份同时用作 memory、uploads、outputs 的存储桶。于是 agent 读写的桶永远是渠道文件被暂存的那个桶——二者不会错位缓存下来的归属者值在阻塞路径runs.wait与流式路径_handle_streaming_chat之间是复用的——即使未来某个Channel.receive_file返回了被改写过的InboundMessageuploads 与产物投递依然命中同一个桶。七、IM 附件管线下载、落桶、注入与发现入站文件图片、文档先经各渠道自己的Channel.receive_file做provider 特定物化。物化后存在两条路走共享元数据路径的附件由_ingest_inbound_files暂存元数据写入HumanMessage.additional_kwargs.files然后UploadsMiddleware为当前消息注入一段current_uploads上下文块部分 provider 在下载时直接消费自己的描述符把占位符或消息文本改写为最终的虚拟路径或一条失败提示。历史上传不会在后续轮次被自动注入agent 需要借助list_uploaded_files工具主动发现历史文件。飞书/Lark 的入站资源流在被持久化或同步进非本地沙箱之前有一个20,000,000 字节上限超限资源与个别文件的路径失败会以失败占位符形式呈现在消息文本中而不会中断同一条入站消息里后续附件的处理。八、配置详解两步启用 一个必须知晓的升级语义8.1 第一步在既有的channels块中配置各平台 bot实际的 IM bot 凭证仍然位于既有的channels块环境变量$VAR形式由AppConfig.resolve_env_variables在加载时递归展开见 app_config.py完整示例可对照 config.example.yamlchannels: inbound_queue_maxsize: 1000 max_concurrency: 5 shutdown_grace_period_seconds: 3 telegram: enabled: true bot_token: $TELEGRAM_BOT_TOKEN slack: enabled: true bot_token: $SLACK_BOT_TOKEN app_token: $SLACK_APP_TOKEN discord: enabled: true bot_token: $DISCORD_BOT_TOKEN feishu: enabled: true app_id: $FEISHU_APP_ID app_secret: $FEISHU_APP_SECRET dingtalk: enabled: true client_id: $DINGTALK_CLIENT_ID client_secret: $DINGTALK_CLIENT_SECRET wechat: enabled: true bot_token: $WECHAT_BOT_TOKEN wecom: enabled: true bot_id: $WECOM_BOT_ID bot_secret: $WECOM_BOT_SECRET buzz: enabled: true relay_url: wss://buzz.example.com private_key: $BUZZ_PRIVATE_KEY # hex or nsec1…8.2 第二步在channel_connections中开启用户绑定channel_connections: enabled: true # Auth-enabled deployments require ordinary IM messages to come from a # connected DeerFlow user by default. Set this to false only for legacy # operator-owned/open-bot deployments that intentionally route unbound # platform users to platform-ID user buckets. require_bound_identity: true telegram: enabled: true bot_username: $TELEGRAM_BOT_USERNAME slack: enabled: true discord: enabled: true feishu: enabled: true dingtalk: enabled: true wechat: enabled: true wecom: enabled: true buzz: enabled: true几个关键语义channel_connections不复制 provider 密钥。它只控制浏览器侧的 Connect UI并存储按用户的绑定记录。Telegram 需要bot_username的唯一理由是让前端能拼出 deep link。配置模型见 channel_connections_config.py顶层的enabled与require_bound_identity之下每个渠道是独立的子配置其中telegram.configured取决于bot_username是否非空其余渠道只要enabled即为 configured。强制绑定身份语义当channel_connections.enabled与require_bound_identity同时为 true启用认证的部署会在创建 DeerFlow thread/run之前拒绝普通的未绑定 IM 消息用户必须先在 DeerFlow Settings 里完成渠道连接。而关闭认证的本地模式仍会把渠道消息路由给默认用户需要恢复旧式 open-bot 行为时显式设置require_bound_identity: false即可。8.3 升级注意事项重要require_bound_identity的默认值是true。这意味着升级前已开启channel_connections.enabled: true的认证部署在本字段引入后会开始拒绝普通的未绑定 IM 消息。对于刻意允许未绑定平台用户创建 DeerFlow run 的旧式 operator-owned/open-bot 部署请在升级之前显式设置require_bound_identity: false并重启服务。8.4 各平台的 Connect 操作流程Telegram前端生成一次性短码 → Connect 按钮打开https://t.me/bot_username?startcode→ 既有 Telegram 长轮询 worker 收到/start code把该 Telegram chat/user 绑定到当前 DeerFlow 用户。Slack前端生成一次性短码 → UI 提示Send /connect code to the DeerFlow Slack bot.→ 既有 Slack Socket Mode worker 收到消息后绑定该 Slack user/team。Discord前端生成一次性短码 → UI 提示Send /connect code to the DeerFlow Discord bot.→ 既有 Discord Gateway worker 收到消息后绑定该 Discord user/guild。飞书/Lark、钉钉、微信、WeCom前端生成一次性短码 → UI 提示Send /connect code to the DeerFlow Provider bot.→ 已运行的 long-connection 或轮询 worker 收到消息后绑定平台 user/workspace 身份。Buzz见下一节单独展开。对带allowed_users白名单的 providerTelegram、Slack、钉钉、微信等有效的/connect code或 Telegram 的/start code会在白名单检查之前被消费。这是有意为之尚未进入白名单、bot 因此从未见过其平台身份的用户仍然可以完成第一次由浏览器发起的绑定。绑定完成后allowed_users继续如常把关普通非绑定消息。九、Buzz无开发者控制台的特殊成员身份Buzz 与上述 bot/app 凭证渠道不同——它没有独立的开发者控制台DeerFlow 以普通成员身份加入 relay。需要为这个身份生成一对 Nostr 密钥以下所有描述都指其hex 公钥。9.1 两步式 onboarding缺一不可Relay 成员身份与渠道成员身份是两回事只做第一步会产生一个能连上、能通过认证、但收不到任何东西的 connector把 pubkey 注册为 relay 成员buzz-admin add-member --pubkey hex。这一步让该身份能够认证NIP-42并能发布消息。把它加入应参与的每个渠道buzz channels add-member --channel uuid --pubkey hex --role bot。聊天事件只会投递给渠道成员且 relay 会拒绝任何p-mentions 非成员的消息报错mentioned pubkeys are not channel members——缺这一步connector 既听不到 mention 也答不了 mention。配置上只认两个键channels.buzz.relay_url与channels.buzz.private_keyhex 或nsec1…再开启channel_connections.buzz。Connect 时前端生成一次性短码UI 提示Send /connect code to the DeerFlow Buzz bot.Buzz relay-loop worker 收到以 DM 或双方共同所在渠道 mention 发送的消息后把发送者的 Nostr pubkey 绑定到当前 DeerFlow 用户。两个重要事实渠道是自动发现的不需要写进config.yaml。每次连接时 connector 会向 relay 查询该身份属于哪些渠道并逐一下订之后新加入的渠道实时生效relay 下发 membership 通知即开始监听移除即停止无需重启或重连。日志里出现channel discovery returned no channels说明第 2 步没做。依赖buzzextrauv sync --extra buzz为coincurve库。detect_uv_extras.py以及通过 backend/Dockerfile 的 Docker/生产构建会在config.yaml中channels.buzz.enabled: true时自动探测并保留该 extra——这和browserextra 为browser_navigate被自动探测的方式一致。9.2 Buzz 订阅模型Buzz relay 只向渠道作用域的订阅投递聊天事件因此 connector 的订阅形态是刚性的全局REQ {kinds:[9]}会被接受并应答EOSE但不会扇出任何聊天事件单条订阅也无法覆盖多个渠道多值#h匹配不到任何东西。所以在每次连接、NIP-42 认证完成后订阅过滤器用途buzz-discovery{kinds:[39000]}历史查询精确列出该身份所属的全部渠道每个渠道一条已存事件随后EOSE。提供各渠道的名称与类型——DM 的 mention 豁免也读取这里。不要用#p收窄它——那会什么都匹配不到。buzz-membership{kinds:[44100,44101], #p:[our pubkey], since: …}实时成员资格通知。44100added立刻订阅新渠道44101removed关闭对应渠道订阅。这就是新增渠道无需重启的原因。buzz-chat-uuid{kinds:[9], #h:[uuid], since: …}每个已发现渠道一条——唯一真正能收到消息的形态。值得运维人员记住的五个推论回放按渠道分别跟踪。每个渠道有自己的since水位只有 DeerFlow 实际处理过的事件才会推进它。若共用一条水位繁忙渠道会把游标拖过安静渠道的未读消息导致重连后跳过它们而按渠道游标的最坏代价只是重复投递manager 的入站去重会吸收永远不会漏消息。成员资格事件只存在于实时流。relay会存储44100/44101若不设since每次连接都会把整段成员资格历史当作刚刚发生重放对每条已存储的 add 重跑一次渠道发现一次连接会看到多条channel discovery complete渠道还会被记为unnamed重订已被移除的渠道并短暂退订仍在的渠道。因此订阅锚定在 socket 打开的瞬间并往前留 60 秒余量让连接/认证握手期间发生的成员变化或 relay 时钟偏差仍能被捕捉。渠道订阅数有上限256。渠道列表来自网络与其他远端输入一样有界。触顶时新渠道会被拒绝并在per-channel subscription limit reached告警中点名而不会驱逐任何在工作的订阅。relay 关闭的订阅会被重新打开每次连接最多重试 3 次。relay 丢弃订阅时 socket 上是静默失败的聊天订阅哑掉一个渠道、buzz-membership让 DeerFlow 再也学不到入退群、buzz-discovery杀死完整性清扫。所以CLOSED帧不只是被记录而是被恢复静默的订阅总会以 WARNING 级被点名。当 relay 明示原因说明该订阅已不属于你时NIP-01/NIP-42 的auth-required:/restricted:/blocked:/invalid:前缀或 buzz-relay 自己的吊销措辞恢复会被跳过——因为重发同一条 REQ 只会和 relay 对抗其余任何原因包括不带任何原因的CLOSED都被当作小故障重试以 3 次尝试为兜底之后保持静默直到下次重连从零重建。已知边界单渠道在断连期间积压超过 2000 条未读会丢掉最旧的一批。relay 把单订阅历史投递上限设为 2000 条且最新优先即使带since也如此。DeerFlow 只处理收到的部分渠道水位随之越过其余消息——那些更旧的消息永远不被投递也不被重试。设计中其余所有缺口都偏向重复投递由入站去重吸收这是唯一会跳过的遗留情形且需要断连 单渠道 2000 条积压两个条件同时成立。9.3 Buzz 信任模型在团队自营的 relay 上relay 运营者未必等于 DeerFlow 运营者所以必须分清什么被密码学验证、什么只是被信任已验证每次入站事件都在密码学上成立DeerFlow 从收到的载荷重算每个事件的 NIP-01 id并用 BIP-340 Schnorr 签名对照声明中的pubkey做验证验证通过前事件不能影响任何东西。因此 relay 无法改写成员消息、无法把一位作者的签名搬到另一载荷上、也无法冒称一个它不掌握密钥的已白名单作者。这一点同样适用于/connect绑定——relay 无法把别人的 pubkey 绑到攻击者的 DeerFlow 账号。验证失败的事件会被丢弃并告警。被信任未验证kind-39000 渠道元数据的作者身份。Buzz 用 relay 自己的密钥对发布渠道发现事件但现有配置没有标识这把密钥relay_url是网络地址而非签名密钥DeerFlow 只能证明该事件被某个成员签名。由于渠道发现与订阅恰好由这些事件驱动一条伪造的 kind-39000 会有两个而非一个后果它可以把渠道标记为type: dm从而放宽该渠道的require_mention要求它可以让 DeerFlow为一个伪造者指定的渠道打开聊天订阅——因为 DeerFlow 监听的渠道集合就是它持有元数据的渠道集合。两者都无法让任何东西被执行。allowed_users白名单与逐事件签名验证是两条独立的闸门无论渠道类型如何、订阅如何被打开非白名单作者一律被丢弃。(2) 的爆炸半径是relay 把自己流量读回给一个忽略它的订阅者且受 256 订阅上限约束只拒绝新订阅、不驱逐在工作的订阅诱导出来的订阅顶不掉真实渠道。伪造的 kind-44100 成员通知同理只是其p标签会在本地被重新核对所以它至少必须点名本身份。如果你需要在一个不能全信成员的 relay 上让 mention 要求不可伪造就把这些渠道排除在mention_free_channels之外并把 DM 检测当作便利功能而非安全边界。默认拒绝的白名单与其他 provider空allowed_users 允许所有人不同channels.buzz.allowed_users刻意是默认拒绝——空列表意味着没人能触发 runDeerFlow 会就此打一条启动告警。应把每个允许触达 agent 的成员 pubkeyhex 或npub1…加进去。个别丢弃只在 DEBUG 级记录。绑定身份pubkey 一旦完成/connect其入站消息就解析到该连接并在绑定 DeerFlow 用户身份下运行记忆、文件、产物都落在该用户桶里。绑定按 relay 主机隔离——同一个 pubkey 在不同 relay 上是不同身份必须分别绑定。绑定码使用 128 位随机性10 分钟后过期且单次使用。十、运行时模型四张 SQL 表与身份字段连接记录落在deerflow.persistence.channel_connections下的 SQL 表中模型定义见 model.pySQL 仓库见 sql.py表职责channel_connections归属用户、provider 身份、workspace/guild/team、状态、元数据channel_oauth_states一次性 Connect 码与 Telegram deep-link 状态channel_conversations连接作用域的 IM 会话 → DeerFlow thread 映射channel_credentials为未来的 provider-token 流程预留本地/私有绑定流程不使用解析到某条连接的入站消息携带connection_id、owner_user_id、workspace_id三个字段。ChannelManager把owner_user_id用作 DeerFlow run 用户 id同时保留原始平台用户 id 为channel_user_id。运行时 provider 凭证是部署级 bot 秘密不是用户所有的连接凭证。它们既可以来自config.yaml的channels.*也可以来自浏览器运行时配置流程——后者通过ChannelRuntimeConfigStore持久化让本地/私有部署无需编辑 YAML 即可配置 bot。运行时存储的本地回退是明文 JSON 文件owner-only 文件权限0600仅当 DeerFlow 数据目录已被视为秘密存储时才使用它。微信扫码登录的认证状态遵循同一本地运行时模型并可能把二维码导出的 bot token 持久化在渠道状态目录里。十一、安全笔记汇总浏览器 API 保持已认证与 CSRF 防护Connect 码 128 位随机、短时效、单次使用运行时 provider bot token 是共享部署秘密。运行时设置响应会脱敏密码字段变更运行时/渠道 worker 的 API 需要 admin 用户存储的按连接凭证使用channel_credentials加密路径。若存量的凭证材料无法解密DeerFlow 将其视为不可用而不是使用损坏的秘密ChannelCredentialCipher基于 Fernet见 sql.py本地明文运行时凭证回退0600已在上一节说明在部署专用 secret backend 之前非本地部署应优先使用由部署管理的环境/配置秘密allowed_users不是绑定时刻防线。由于 Connect 码在白名单之前被处理见 8.4 节任何持有有效码的人都能消费它——不只是白名单用户。绑定安全因此完全系于码的机密性128 位随机、10 分钟过期、单次使用、只显示在发起用户浏览器中从不回显到聊天。请把 Connect 码当作一次性密码不要转发。一个外部身份——(provider, external account, workspace/team/guild)——至多一个活跃归属者。最近一次成功绑定胜出绑定一个已被另一 DeerFlow 用户持有的身份会转移归属权并撤销前任的绑定连同其存储的凭证。这在数据库层强制两个用户竞速绑定同一身份不可能双双处于已连接状态provider bot token 仍留在channels.*永不返回给浏览器本实现不新增任何公共 provider 回调或 webhook 路由。十二、测试与源码索引如何继续深入上述机制的许多不变量都可以在测试中找到可验证的落点例如归属转移/凭证加解密/一次性码消费等仓库行为backend/tests/test_channel_connections_repository.py浏览器 Connect API 的路由与权限backend/tests/test_channel_connections_router.py、backend/tests/test_channel_connections_config.py各 provider 的绑定与消息处理backend/tests/test_telegram_channel_connections.py、backend/tests/test_slack_channel_connections.py、backend/tests/test_discord_channel_connections.py、backend/tests/test_additional_channel_connections.py、backend/tests/test_buzz_channel.py过载、去重与去重后消息处理backend/tests/test_channels.py。核心代码入口调度与绑定闸门在 manager.py_channel_storage_user_id、_handle_chat、_handle_streaming_chat、_get_bound_identity_rejection、CHANNEL_CAPABILITIES有界队列在 message_bus.py渠道策略描述符在 run_policy.py持久化在 channel_connections/sql.py。总体而言浏览器铸造一次性码 → provider worker 消费并绑定 → 数据库保证单一活跃归属者 →ChannelManager按归属者身份隔离地跑 run、存文件、回消息这条主线清晰、独立、无回调依赖正是它让 IM 渠道在本地与私有部署中也能拥有完整的多用户归属语义。【免费下载链接】deer-flowAn open-source long-horizon SuperAgent harness that researches, codes, and creates. With the help of sandboxes, memories, tools, skill, subagents and message gateway, it handles different levels of tasks that could take minutes to hours.项目地址: https://gitcode.com/GitHub_Trending/de/deer-flow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表