Files
MediaCrawler/mac-agent-os-main/03_knowledge/99_system/architecture/federation-operations-architecture.md
T
butubb 2112c1a870
Deploy VitePress site to Pages / build (push) Canceled after 0s
Deploy VitePress site to Pages / Deploy (push) Canceled after 0s
feat(monitor): 抖音 Web 接口客户端 —— 绕开爬虫子进程,直接发 HTTP
移植自 mac-agent-os 的 mediacrawler_adapter:不起子进程、不开页面,用浏览器里那份
登录态直接调抖音 Web 接口。产物键名照抄 store/douyin,所以 ingest 那条链路一个字不用改。

**目前能用的(真环境实测,非推断)**:

    profile/other : 200, 7075 字节  —— 博主主页指标(粉丝/获赞/作品数/昵称)
    aweme/detail  : 200, 45425 字节 —— 单条作品详情(含点赞/评论/收藏/分享)

**目前不能用的:作品列表 `aweme/post`。** 两个互相独立的原因:
  1. 这个接口被抖音单独升级成了真校验:不带 x-tt-argus 回 403「Uifid Not Found」,
     带上 dummy 值回 200 + **空 body**。也就是说「头在不在」骗得过,「真校验」过不了。
     同一套头打 profile/other 和 aweme/detail 都是通的 —— 抖音是挑着接口加保护的,
     挑中的恰好是「批量拉作品列表」这个最敏感的动作。
  2. 改走页面截获也不行:CDP 浏览器打开博主主页会落到「验证码中间页」(当天大量探测的
     代价,过几小时要重测)。

  所以现在的边界是:**已知作品的指标刷新能做,自动发现新作品做不了**。

**排查中控住变量后得到的两条事实**(都写进注释了):
  · `Accept` / `Accept-Language` / `Referer` 才是主页接口能返回真数据的原因 —— 只有
    UA+client hints+Cookie 时是 200 但仅 121 字节的空壳,补上这三个头变 7074 字节。
    (我先前猜的 sec-ch-ua 不是关键。)
  · 因此 UA 与 client hints 必须**成套地取自同一个浏览器**,所以 BrowserIdentity 一次
    从 CDP 取齐 cookie + UA + hints,而不是各自写死。

「200 + 空 body 必须当场报错」也是刻意写死的:放过去它会在下游变成「这个博主没作品」,
把一次失败伪装成一条正常结果 —— 爬虫那条路正是这么栽的,还被翻译成「账号被封」。

测试 +11:cookie 解析、请求头成套性(含 uifid 缺失/回退)、产物键名与 store 对齐、
以及 _get 的三条失败路径(空 body / 403 带网关原话 / 正常返回)。
2026-10-10 17:12:25 +08:00

15 KiB

type, domain, nature, tags, status, created, updated, version, supersedes
type domain nature tags status created updated version supersedes
concept system architecture
agentos
v3.0
federated
multi-machine
operations
orchestration
draft 2026-06-16 2026-06-16 1.0.0

AgentOS 联邦指挥台 — 操作架构设计 v1.0

版本: 1.0.0-draft | 2026-06-16 设计目标: 创建世界级的多机智能体编排系统,可扩展为大规模计算机军团


一、设计哲学

核心原则

  1. 指挥台只负责聚合和分发,不直接执行 — 所有操作在目标机器上运行
  2. 每台机器是自治的智能体 — 离线也能独立运行,在线时接受指挥台调度
  3. 操作即状态机 — 每个操作都有明确的声明周期,可追踪、可重试、可审计
  4. 先检后动 — 操作前检查资源状态,保证不会破坏正在运行的任务
  5. 双模交互 — Dashboard(图形)和 CLI(命令行)完全对等,同一套底层

参考架构

来源 借鉴点
Selenium Grid Hub-Node 中央调度 + 分布式执行节点
Kubernetes Job/Pod 声明式任务 + 状态机 + 日志聚合
Apache Airflow DAG 操作依赖管理 + 重试 + 告警
Erlang/Elixir Actor 每台机器 = 一个 Actor,通过消息通信
Unix Pipeline 每个操作 = 一个进程,stdin/stdout/stderr

二、系统架构:三层模型

┌──────────────────────────────────────────────────────────────────┐
│                    Layer 1: Command Center                        │
│  (Dashboard Web UI + CLI)                                        │
│                                                                  │
│  功能: 聚合展示 + 命令输入 + 日志查看 + 状态监控                │
│  位置: chengzigedeAir (master)                                   │
│  也支持: 任何机器浏览器打开看板,或本地 CLI 直接执行              │
└──────────────────────┬───────────────────────────────────────────┘
                       │ HTTP / WebSocket / SSE
┌──────────────────────┴───────────────────────────────────────────┐
│                    Layer 2: Orchestration Bus                     │
│                                                                  │
│  - federation API (REST): /api/federation/*                      │
│  - event stream (SSE):   /api/events                             │
│  - remote exec (SSH):    /api/federation/exec                    │
│  - log aggregation:      每台机器推送日志到中心存储              │
└──────────────────────┬───────────────────────────────────────────┘
                       │ SSH / HTTP / Tailscale
      ┌────────────────┼────────────────┐
      ▼                ▼                ▼
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Machine A  │ │ Machine B  │ │ Machine C  │
│ chengzige  │ │ 5kecheng   │ │ 7kecheng   │
├────────────┤ ├────────────┤ ├────────────┤
│ Layer 3a   │ │ Layer 3a   │ │ Layer 3a   │
│ Agent Daemon│ │ Agent D.  │ │ Agent D.   │
│ (guardd)   │ │ (guardd)   │ │ (guardd)   │
├────────────┤ ├────────────┤ ├────────────┤
│ Layer 3b   │ │ Layer 3b   │ │ Layer 3b   │
│ Camoufox   │ │ Camoufox   │ │ Camoufox   │
│ Browser    │ │ Browser    │ │ Browser    │
└────────────┘ └────────────┘ └────────────┘

每台机器上的 Agent Daemon (guardd)

每台机器运行一个常驻后台进程 guardd,职责:

职责 说明
心跳上报 每 300s 写一次 heartbeat.json,含 CPU/内存/磁盘/任务状态
操作队列 接收指挥台下发的操作,排队执行
资源锁 管理浏览器实例/账号的使用状态,防止冲突
日志推送 操作日志实时推送到中心日志存储
状态归零 操作完成后清理浏览器进程、还原环境

三、操作状态机

所有操作的通用生命周期

                  ┌──────────┐
                  │  pending  │  ← 用户下发操作,等待调度
                  └────┬─────┘
                       ↓
                  ┌──────────┐
         ┌──────→│ checking │  ← 检查目标机器状态、资源可用性
         │       └────┬─────┘
         │            ↓
         │       ┌──────────┐
         │       │preparing │  ← 关闭旧浏览器、清理缓存、锁资源
         │       └────┬─────┘
         │            ↓
         │       ┌──────────┐
         │    ┌─→│ running  │  ← 操作执行中(浏览器打开/脚本运行)
         │    │  └────┬─────┘
         │    │       ↓
         │    │  ┌──────────┐     ┌──────────┐
         │    │  │completed │ 或  │  failed  │  ← 成功完成或出错
         │    │  └────┬─────┘     └────┬─────┘
         │    │       ↓                ↓
         │    │  ┌──────────┐     ┌──────────┐
         │    │  │ cleaning │     │ cleaning │  ← 清理资源、释放锁
         │    │  └────┬─────┘     └────┬─────┘
         │    │       ↓                ↓
         │    │  ┌──────────┐     ┌──────────┐
         │    └──│  done    │     │  error   │
         │       └──────────┘     └──────────┘
         │
         └── 任何阶段都可被"取消"或"超时"
             超时后进入 cleaning → error

状态转换规则

转换 触发条件 动作
pending → checking 调度器获取执行权 读取目标机器心跳、检查是否有其他任务在跑
checking → preparing 资源检查通过 发送 prepare 命令到目标机器
checking → pending 资源忙 重新排队,等待重试
checking → failed 目标机器离线 标记失败,通知用户
preparing → running 准备完成 执行具体操作
running → completed 正常结束 收集结果
running → failed 异常退出 收集错误信息
* → cleaning 任何非 done 状态的完成 执行清理脚本
cleaning → done 清理完成 更新最终状态
* → failed 超时(默认 30min) 强行终止,清理

四、资源管理

资源类型

资源 粒度 冲突规则
浏览器实例 每机器 1 个 Camoufox 全局互斥——同一台机器不能开两个浏览器
账号登录态 每个 account_id 同一账号不能同时被两个操作使用
身份指纹 每个 identity_dir 同一身份不能同时被两个浏览器使用
键盘/鼠标 每机器独占 远程操作时锁定本地输入(可选)

资源锁实现

# 每台机器上的  guardd 维护的锁表
locks = {
    "browser": {"held_by": "task_001", "acquired_at": "2026-06-16T18:00:00"},
    "account:douyin_01": {"held_by": "task_001", "acquired_at": "..."},
    "identity:douyin_01_camo": {"held_by": "task_001", "acquired_at": "..."},
}

状态归零 (Pre-flight Reset)

每个操作执行前,目标机器必须执行:

  1. 检查是否有残留浏览器进程 — pkill -f camoufox (如果有, kill)
  2. 检查是否有残留的 Playwright 进程 — pkill -f playwright
  3. 检查账号登录锁 — 清除该账号的锁
  4. 清理临时文件 — 删除上次操作的临时缓存
  5. 重置代理状态 — 恢复默认代理配置
  6. 确认资源可用 — 返回"已就绪"状态

五、操作类型全表

操作 类型 机器 状态管理 并发 超时
账号登录 A 本机浏览器 assigned_machine 锁 browser + 锁 account 1 账号/次 120s
养号执行 A 本机浏览器 assigned_machine 锁 browser + 锁 identity 1 身份/次 60min
信息采集 B 远程脚本 任意在线机器 只读,无需锁 并发 60s
内容发布 A 本机浏览器 assigned_machine 锁 browser + 锁 account 1 账号/次 300s
环境同步 B 远程脚本 指定机器 互斥(同一机器不能同时同步) 1 台/次 120s
对账检查 B 远程脚本 指定机器 只读,无需锁 并发 60s
远程Shell B 远程脚本 指定机器 无锁 并发 30s
状态监控 C 聚合 所有机器 只读 并发 10s

六、日志与审计

日志结构

每个操作产生一条结构化日志:

{
  "operation_id": "op_20260616_001",
  "type": "account_login",
  "target_machine": "5kechengdeAir",
  "target_account": "douyin_01",
  "status": "completed",
  "states": [
    {"state": "pending", "time": "18:00:00"},
    {"state": "checking", "time": "18:00:01"},
    {"state": "preparing", "time": "18:00:02"},
    {"state": "running",  "time": "18:00:05"},
    {"state": "completed","time": "18:01:15"},
    {"state": "cleaning", "time": "18:01:16"},
    {"state": "done",     "time": "18:01:17"}
  ],
  "output": "login successful, cookie saved",
  "error": null,
  "triggered_by": "dashboard_user",
  "duration_sec": 77
}

日志聚合

  • 每台机器的 guardd 实时推送日志到中心 /api/logs/push
  • Dashboard 提供日志查看器: 按机器/操作/时间/状态过滤
  • 日志保留 30 天,自动归档

七、并发与互斥策略

场景 策略
用户点「养号」时机器已在养号 拒绝,提示"5kecheng 正在养号中,是否停止当前任务?"
用户点「登录」时浏览器已打开 先关闭浏览器,再重新打开
两台机器同时给同一账号发命令 不可能——账号只属于一台机器(ORACLE.yaml)
用户从 Dashboard 和 CLI 同时操作 共享同一资源锁表,后到者等待或拒绝
机器离线时下发操作 缓存到队列,机器上线后自动执行(可选)

八、安全与锁定

远程操作时的机器锁定

当通过 Dashboard 远程控制 5kechengdeAir 执行浏览器操作时:

安全措施 实现
键盘锁定 操作开始时,5kecheng 本地键盘暂时屏蔽(防止误触)
屏幕提示 5kecheng 显示器显示"正在被远程控制"的提示
强制停止 任何时候按 Ctrl+C 或点击「停止」终止操作
超时自动释放 30min 无活动自动关闭浏览器并释放锁

注意

键盘锁定是进阶功能。初期先实现资源锁+状态机,锁定后续再做。


九、Dashboard 落地计划

Phase 1: 状态感知 (优先级最高)

  • 三台机器心跳检测 (guardd 已有)
  • 机器状态条: 每个视图顶部显示三台机器在线/离线/忙碌
  • 账号级别的忙碌状态 (是否正在被操作)

Phase 2: 操作路由 (当前)

  • accountLogin() 加 owner_machine 判断 + 远程执行
  • clearCookies() 加 owner_machine 判断
  • deleteAccount() 加 owner_machine 判断
  • 按钮状态: 远程账号显示"需在 XX 机器操作"或"远程执行"

Phase 3: 状态机引擎

  • 统一的操作队列: pending → checking → running → done
  • 资源锁: 账号级别和浏览器级别
  • 操作前的 state reset (清理旧进程)
  • 操作日志存储 + 查看器

Phase 4: 高级功能

  • 键盘锁定 / 屏幕提示
  • 离线队列 / 上线自动执行
  • 操作 DAG (先后依赖)
  • 多用户协作

附录: 参考的原始架构文档

本文设计参考了以下原有系统文档中的思想:

文档 关键借鉴
architecture/federated-multi-machine-architecture.md 7大协同子系统(心跳/事件/任务/加密/知识/升级/传输)、guardd 7模块、三层数据架构
archive/CORE-ARCHITECTURE.md 目录职责边界、agent-local/agent-sync 分离原则、软链接映射、技能分类
dashboard-v4-design.md cross_machine/data/ WPRA 写入规范、9个内置插件规范、机器感知设计、24h TTL 过期策略
COMMAND-CENTER-PLAN.md (99_system/) 命名空间分层(agentos matrix/ave/crawl/fleet/serve)
cross_machine/ARCHITECTURE-v2.md (04_memory/) WPRA 写分区·读聚合模型、Git 冲突消除方案

本次设计新增的概念

概念 来源 说明
操作状态机 新建 pending→checking→preparing→running→completed→cleaning→done 完整生命周期
资源锁 新建 浏览器级/账号级/身份级互斥,防止冲突操作
状态归零 新建 操作前自动清理残留进程、释放锁、重置环境
操作路由 新建 根据 owner_machine 将操作路由到对应机器执行
双模对等 新建 Dashboard 和 CLI 共享同一套底层 API

十一、关键设计决策记录

决策 选项 选择 理由
操作同步还是异步? 同步等待 / 异步队列 混合: 短操作(<10s)同步,长操作异步 登录等短操作需要实时反馈
远程执行通道 SSH / HTTP / WebSocket SSH (现有) + HTTP API (未来) SSH 已打通,HTTP 需要额外服务
状态存储 Redis / SQLite / 文件 文件 (现有 heartbeats/目录) 零依赖,随 Git 同步
浏览器管理 每机器 1 个 / 多实例 1 个 Camoufox,轮流使用 指纹一致性,避免被检测
CLI 与 Dashboard 关系 主从 / 对等 对等—同一套底层 API CLI 无网络时也能用