移植自 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 带网关原话 / 正常返回)。
14 KiB
14 KiB
Dashboard 数据层 · 多智能体协同设计
版本: v1.0 | 2026-05-15 定位: AgentOS 多智能体系统 · 共享观测层
一、定位:不是 AVE 的面板,是 AgentOS 的观测层
Dashboard 不是 AVE 的附属工具。它应该是一套跨智能体的共享数据服务,任何 Agent(Claw、AVE、Matrix、Trae 等)都可以通过统一接口写入和查询。
现存 Agent 一览
| Agent | 目录 | 适合 Dashboard 跟踪什么 |
|---|---|---|
| 09_ave | 05_tools/09_ave/ |
视频生产任务、素材生成、API 调用 |
| 07_matrix | 05_tools/07_matrix/ |
抖音养号任务、蓝�运行、账号切换 |
| claw assistant | ~/.workbuddy/ |
各种自动化任务、CLI 执行的历史 |
| 02_browser / 05_crawl | 05_tools/ |
爬虫任务、页面采集记录 |
二、存储位置
根据 AgentOS 的目录结构约定:
| 类别 | 路径 | 说明 |
|---|---|---|
| 代码(可同步) | ~/workbuddy-agent-os/agent-sync/05_tools/10_dashboard/ |
多机共享,坚果云同步 |
| 数据(本地) | ~/workbuddy-agent-os/agent-local/runtime/dashboard/ |
本地 SQLite + 缓存,不同步 |
| 客户端库 | ~/workbuddy-agent-os/agent-sync/05_tools/10_dashboard/client.py |
Agent 导入用,写数据入口 |
| 后端服务 | ~/workbuddy-agent-os/agent-sync/05_tools/10_dashboard/server.py |
FastAPI 应用 |
| 前端页面 | ~/workbuddy-agent-os/agent-sync/05_tools/10_dashboard/templates/ |
HTML 单页应用 |
为什么数据放 agent-local 而不是 agent-sync?
- SQLite 不适合坚果云同步(并发写会导致 DB 损坏)
- 每台机器的生产数据天然不同,不应该同步
agent-local/runtime/已经是 AgentOS 为"运行时数据"预设的位置
三、多智能体数据模型
3.1 agents — 智能体注册表
CREATE TABLE agents (
id TEXT PRIMARY KEY, -- 'ave', 'matrix', 'claw', 'trae'
name TEXT NOT NULL, -- 'audio score video engine'
type TEXT DEFAULT 'tool', -- 'tool' | 'skill' | 'pipeline' | 'assistant'
version TEXT, -- 当前版本号
status TEXT DEFAULT 'active',
last_seen_at TEXT, -- 最后心跳时间
meta_json TEXT -- 扩展元数据
);
预注册的 Agent:
| id | name | type |
|---|---|---|
ave |
AudioScore Video Engine | tool |
matrix |
Matrix Account Manager | tool |
claw |
Claw AI Assistant | assistant |
memory |
Memory Manager | skill |
3.2 productions — 生产任务(跨 agent 通用)
这是核心表。不限于视频生产——任何 agent 的"一次任务执行"都是一条 production。
CREATE TABLE productions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
agent_id TEXT NOT NULL REFERENCES agents(id),
pipeline TEXT NOT NULL, -- 'ave:oral' | 'ave:beat-sync' | 'matrix:browse' | 'claw:research'
status TEXT DEFAULT 'running', -- 'running' | 'completed' | 'failed' | 'cancelled'
title TEXT, -- 人类可读名称
input_summary TEXT, -- JSON: 输入概览
output_summary TEXT, -- JSON: 输出概览
config_json TEXT, -- JSON: 完整参数快照
duration_sec REAL,
total_cost REAL DEFAULT 0.0,
currency TEXT DEFAULT 'CNY',
error_message TEXT,
tags TEXT, -- 逗号分隔,跨 agent 搜索用
created_at TEXT DEFAULT (datetime('now')),
completed_at TEXT
);
CREATE INDEX idx_productions_agent ON productions(agent_id);
CREATE INDEX idx_productions_status ON productions(status);
CREATE INDEX idx_productions_created ON productions(created_at);
3.3 production_steps — 步骤级跟踪
CREATE TABLE production_steps (
id INTEGER PRIMARY KEY AUTOINCREMENT,
production_id INTEGER REFERENCES productions(id) ON DELETE CASCADE,
agent_id TEXT NOT NULL,
step_name TEXT NOT NULL, -- 'parse_script' | 'tts' | 'kling_generate' | ...
step_type TEXT DEFAULT 'process', -- 'process' | 'api_call' | 'human_review' | 'decision' | 'wait'
status TEXT DEFAULT 'pending',
input_ref TEXT, -- 输入引用(文件路径 / URL)
output_ref TEXT, -- 输出引用
started_at TEXT,
ended_at TEXT,
duration_sec REAL,
cost REAL DEFAULT 0.0,
detail TEXT, -- 步骤详情 JSON
error_message TEXT,
metadata_json TEXT -- 扩展字段
);
CREATE INDEX idx_steps_production ON production_steps(production_id);
3.4 assets — 跨 agent 共享资产
所有 agent 生成的、可复用的数字资产统一注册在这里。关键设计:资产一旦注册,就属于全局资产池,任何 agent 都可以引用。
CREATE TABLE assets (
id INTEGER PRIMARY KEY AUTOINCREMENT,
asset_type TEXT NOT NULL, -- 'character_sheet' | 'bgm' | 'generated_clip' | 'script' | 'lora' | 'screenshot' | 'dataset'
name TEXT,
description TEXT,
file_path TEXT, -- 本地绝对路径
file_size INTEGER,
file_hash TEXT, -- SHA256,用于去重
source_agent TEXT REFERENCES agents(id),
source TEXT, -- 'generated' | 'imported' | 'downloaded' | 'user_provided' | 'pexels'
license TEXT, -- 版权信息
meta_json TEXT, -- JSON: 资产元数据
tags TEXT, -- 逗号分隔
created_at TEXT DEFAULT (datetime('now')),
UNIQUE(file_hash)
);
CREATE INDEX idx_assets_type ON assets(asset_type);
CREATE INDEX idx_assets_source ON assets(source_agent);
3.5 production_assets — 资产使用记录
CREATE TABLE production_assets (
production_id INTEGER REFERENCES productions(id) ON DELETE CASCADE,
asset_id INTEGER REFERENCES assets(id) ON DELETE CASCADE,
role TEXT DEFAULT 'input', -- 'input' | 'output' | 'intermediate' | 'reference'
PRIMARY KEY (production_id, asset_id)
);
3.6 agent_events — 智能体间事件总线
这是跨智能体通信的关键设计。一个 agent 完成某项任务后,可以通过事件通知其他 agent。
CREATE TABLE agent_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
source_agent TEXT REFERENCES agents(id),
target_agent TEXT, -- null = broadcast 给所有 agent
event_type TEXT NOT NULL, -- 'production.completed' | 'asset.created' | 'pipeline.ready' | 'error.occurred'
severity TEXT DEFAULT 'info', -- 'info' | 'warning' | 'error' | 'critical'
title TEXT,
payload_json TEXT, -- 事件负载 JSON
status TEXT DEFAULT 'pending', -- 'pending' | 'read' | 'acknowledged'
created_at TEXT DEFAULT (datetime('now')),
read_at TEXT
);
CREATE INDEX idx_events_target ON agent_events(target_agent);
CREATE INDEX idx_events_status ON agent_events(status);
CREATE INDEX idx_events_created ON agent_events(created_at);
3.7 ER 关系
agents ──1:N── productions ──1:N── production_steps
│ │
│ └── M:N ── assets (via production_assets)
│
└──1:N── agent_events (source)
└──?:1── agent_events (target)
四、客户端库设计
每个 Agent 通过 client.py 写入,不需要直接操作 SQLite。这是唯一的写入口。
# ~/workbuddy-agent-os/agent-sync/05_tools/10_dashboard/client.py
"""
Dashboard Client — 供所有 Agent 调用
用法:
from dashboard_client import DashboardClient
db = DashboardClient() # 自动连接 agent-local/runtime/dashboard/ave.db
# 注册自己
db.register_agent("ave", "AudioScore Video Engine", "tool")
# 开始一个 production
prod_id = db.start_production(
agent_id="ave",
pipeline="ave:oral",
title="知识讲座视频 #047",
config={"script": "lecture.yaml", "style": "knowledge_lecture"}
)
# 记录步骤
db.log_step(prod_id, "tts", "completed", cost=0.30, detail={"chars": 85})
db.log_step(prod_id, "render", "completed", cost=0.0)
# 注册资产
asset_id = db.register_asset(
asset_type="generated_clip",
name="clip_hermit_01.mp4",
file_path="/tmp/kling_hermit.mp4",
source_agent="ave",
tags=["kling", "hermit", "cinematic"]
)
# 关联资产到 production
db.link_asset(prod_id, asset_id, role="output")
# 完成 production
db.complete_production(prod_id, status="completed", total_cost=1.20)
# 发送事件通知
db.send_event("ave", "claw", "production.completed",
title="视频 #047 生成完成", payload={"prod_id": prod_id})
核心 API
| 方法 | 功能 | 被调用频率 |
|---|---|---|
register_agent(id, name, type) |
注册/更新 agent | 安装时一次 |
start_production(...) |
开始任务 | 每次 CLI 执行 |
log_step(...) |
记录步骤 | 每个步骤 |
update_step(...) |
更新步骤状态 | 异步步骤 |
complete_production(...) |
完成任务 | 每次完成/失败 |
register_asset(...) |
注册资产 | 每个新文件 |
link_asset(prod, asset, role) |
关联资产 | 每次资产使用 |
send_event(source, target, type, ...) |
发送事件 | 按需 |
五、后端 API 设计
FastAPI 服务,运行在 http://localhost:9132。
核心端点
GET /api/status # 服务健康检查
GET /api/summary # 总览指标(总数、本月、总成本、资产数)
GET /api/productions # 生产列表(支持 filter: ?agent=&status=&pipeline=&tags=)
GET /api/productions/{id} # 生产详情 + 步骤列表
GET /api/productions/{id}/assets # 生产关联的资产
GET /api/assets # 资产列表(支持 filter: ?type=&agent=&tags=&q=)
GET /api/assets/{id} # 资产详情 + 使用记录
GET /api/assets/{id}/productions # 该资产被哪些 production 用过
GET /api/agents # agent 列表
GET /api/agents/{id}/productions # 某个 agent 的所有 production
GET /api/events # 事件列表
GET /api/events?target={agent_id} # 发给某个 agent 的事件
GET /api/costs # 费用汇总(按 agent/策略/时间分组)
查询示例
# 查看 AVE 最近失败的 production
GET /api/productions?agent=ave&status=failed
# 搜索资产
GET /api/assets?q=定妆照&type=character_sheet
# 查看 matrix 本周的全部任务
GET /api/productions?agent=matrix&from=2026-05-08&to=2026-05-15
六、集成方式
6.1 AVE 集成(Sprint 1 要做)
在 main.py 的每个关键节点加 ~50 行调用。改动量极小:
# 在 video_factory.py 的入口
from dashboard_client import DashboardClient
db = DashboardClient()
# run_oral() 开始
prod_id = db.start_production("ave", "ave:oral", title, config=args)
# TTS 步骤完成
db.log_step(prod_id, "tts", "completed", cost=0.30)
# 素材搜索完成
db.log_step(prod_id, "search_material", "completed", detail={"count": 6})
# 合成完成
db.complete_production(prod_id, status="completed", total_cost=tracker.total)
6.2 Matrix 集成(Sprint 3 可选)
# 在 task_engine.py 的入口
prod_id = db.start_production("matrix", "matrix:browse", "抖音浏览 #102")
db.log_step(prod_id, "switch_account", "completed")
db.log_step(prod_id, "open_douyin", "completed")
db.log_step(prod_id, "browse_videos", "completed", detail={"count": 15})
db.complete_production(prod_id, status="completed")
6.3 Claw Assistant 集成(Sprint 3 可选)
通过 WorkBuddy 的 CLI 埋点,每次执行自动化任务自动记录。
七、数据生命周期
| 阶段 | 操作 | 位置 |
|---|---|---|
| 创建 | client.py 写入 |
agent-local/runtime/dashboard/ave.db |
| 读取 | HTTP API → 前端 Dashboard | FastAPI + HTML |
| 备份 | 随 agent-local 整体备份策略 | 暂不单独处理 |
| 清理 | >90 天的 production 自动归档 (可配置) | 归档到 agent-local/runtime/dashboard/archive/ |
| 跨机迁移 | 不同步。每台机器独立数据 | agent-local 不同步的设计 |
八、文件结构
agent-sync/05_tools/10_dashboard/
├── __init__.py
├── client.py # Agent 客户端库(唯一写入口)
├── models.py # SQLAlchemy ORM 或 raw SQL schema
├── server.py # FastAPI 应用
├── templates/
│ ├── index.html # 总览页
│ ├── productions.html # 生产列表
│ ├── detail.html # 生产详情
│ └── assets.html # 资产浏览器
├── static/
│ └── app.js # 前端交互逻辑
└── README.md # 使用说明
agent-local/runtime/dashboard/
├── ave.db # SQLite 主数据库
├── cache/ # 文件缓存
└── archive/ # 历史归档
九、为什么这样设计
9.1 为什么用 SQLite 而不是其他 DB?
| 数据库 | 适用性 | |
|---|---|---|
| SQLite | ✅ 单机多进程读、零运维、AgentOS 已有使用 | 选这个 |
| PostgreSQL | ❌ 太重,单机不需要 | |
| JSON 文件 | ❌ 不支持并发写、不支持查询 | |
| LevelDB/RocksDB | ❌ 没 SQL 查询,不支持关联 |
9.2 为什么用 HTTP API 而不是直接写 SQLite?
| 方式 | 问题 |
|---|---|
| 直接写 SQLite | 每个 agent 都要 import sqlite3 + 写 SQL,产生代码耦合 |
| 通过 API | agent 只需 import client.py + 调方法,后端封装所有 DB 逻辑 |
9.3 为什么 events 表放在这里而不是单独的消息队列?
轻量。当前多智能体在同一台机器上,SQLite 轮询足够。如果以后需要跨机器,可以从 events 表迁移到真正的消息队列(如 Redis pub/sub)。
十、开发量估算
| 模块 | 估计 | 说明 |
|---|---|---|
models.py (schema) |
0.2h | SQL 建表语句 |
client.py (核心 6 个方法) |
1h | ~150 行 Python |
server.py (API 端点) |
1h | ~200 行 FastAPI |
| AVE 埋点接入 | 0.5h | main.py + video_factory.py 加 ~50 行 |
| 合计 | ~2.7h | 一个下午可完成 |