Easel outputs目录设计与manifest编排:项目化归档的幕后实现原理
【免费下载链接】EaselAn open-source AI agent for social media — discover trends, create content, publish everywhere, and learn what works across Xiaohongshu, Douyin, Zhihu, Bilibili, and more.🎨一个开源的 AI 社交媒体智能体——发现热点趋势、创作内容、一键发布至各大平台,并学习分析哪些内容真正有效,覆盖小红书、抖音、知乎、哔哩哔哩等平台。项目地址: https://gitcode.com/gh_mirrors/easel3/Easel
Easel 是一个开源的 AI 社交媒体智能体:发现热点趋势、创作内容、一键发布到小红书、抖音、知乎、B 站等平台。当你连续生产几十个内容项目后,产物散落在各处是必然结果。Easel 用一套outputs 目录规约 + manifest(.easel.json)编排契约解决它——每个内容项目归档为一个独立目录,层间产物靠薄索引传递,归档过程安全、可预览、可断点续跑。
为什么 AI 内容智能体需要一套 outputs 目录规约
多智能体协作生产内容时,最大的工程难题不是"怎么生成",而是"产物放哪、怎么交接"。Easel 纵向编排有五个层:发现 → 策划 → 制作 → 发布 → 归因,早期各 SKILL 各写各的,结果就是 SKILL-SPEC.md 里描述的乱象:
- 目录结构不统一,中间件(帧序列、片段、构建脚本)和成品混放;
- 缺元数据,前端无法知道哪个目录是"成都文旅卡片"、哪个还是草稿;
- 上游结论靠对话"口传",下游要重新推导一遍。
Easel 的答案只有一句话:一个内容项目 =outputs/<主题>/一个目录。
Easel 项目化归档的三条核心规则
规则一:一个主题一个目录,成品与中间件分区
outputs/<主题>/ ├── note.md / final.mp4 / card_1.png 成品(用户要发/读的最终文件,放项目根) ├── assets/ 中间件:frames/ clips/ 构建脚本 原始素材 草稿 └── .easel.json 唯一元数据:展示头 + 层间产物契约(隐藏)这条规约在 SKILL-SPEC.md 的"产物管理"一节 有完整定义:项目名必须人类可读(中文也可以),测试产物统一进outputs/_scratch/,系统状态(登录态、发布日志)一律用_前缀目录,与内容项目严格隔离。
规则二:泛化目录名会被路径校验直接拒绝
光靠文档约定不够,Easel 把规约变成了代码级闸门。output_paths.py 提供validate_output_path(),任何新脚本写产物前必须先过校验:
- ✅
outputs/成都文旅/成品.md—— 放行; - ❌
outputs/成品.md—— 禁止散落在 outputs 根目录; - ❌
outputs/xhs/...、outputs/test/...、outputs/主题名/...—— 泛化名黑名单(GENERIC_PROJECT_NAMES); - ❌
outputs/主题/../../outside.md—— 路径穿越直接拒绝; - ⚠️
_前缀系统路径 —— 必须显式allow_system=True且只能使用已注册的目录(_login/_publish/_scratch等)。
对应测试 test_output_paths.py 逐条锁死了这些行为,包括"泛化名拒绝"的参数化用例。
规则三:manifest 是薄索引,不复制内容
manifest 只存两样东西:一行summary(给编排层路由用)和outputs[]文件路径(指向真实载荷)。跨层要传递的内容分成两类,都以文件形式落在项目目录里:产物(脚本/图/视频/文案)写文件后登记路径;决策与意图(基调、受众、钩子)写进brief.md再登记。对话里不传大块内容,链路可追溯、可重放。
manifest 编排:.easel.json 的幕后实现
每个项目目录下的 .easel.json 由 manifest.py 确定性读写,schema 分两部分:
① 展示头(供前端"内容库"富展示)
| 字段 | 作用 | 兜底 |
|---|---|---|
title | 人类可读标题 | 缺省 = 主题名 |
platform/kind | 平台 / 产物体裁(article、cards、video…) | 决定卡片图标与分组 |
status | 生命周期:draft / ready / published | 生命周期 chip |
cover | 封面文件名 | 缺省 = 首张成品媒体 |
deliverables | 最终成品清单 | 前端"成品区"高亮依据 |
② 层间产物契约steps[]:每步记录layer(discover/plan/produce/publish/attribute)、skill、outputs[]、upstream[]、summary,以及done/failed状态。
四个子命令覆盖了全部读写场景(细节见 manifest.py CLI 定义):
# 上游每步产出后登记(失败也登记,供断点续跑) python skills/shared/scripts/manifest.py record --topic 成都文旅 \ --layer plan --skill video-script --outputs script.md,brief.md \ --summary "3 幕结构,钩子在前 3s" # 下游步骤前取上游最近一步作为输入 python skills/shared/scripts/manifest.py latest --topic 成都文旅 --layer plan两个值得注意的工程细节:
- 原子写入:
atomic_write()先写临时文件再os.replace,manifest 永远不会处于半写状态(manifest.py); - 断点续跑:失败步登记
--status failed,已done的层产物还躺在outputs/里可直接复用,重跑时不用从头再来。manifest 自带selftest子命令,一条命令验证 record/latest/meta 全链路。
前端"内容库"如何消费这份 manifest
Web 端的内容库列表由 web/app.py 的 get_output_tree() 生成:只展示项目目录,跳过_前缀系统目录与根目录散文件,按最后修改时间倒序。每个目录再读一次展示头(_read_project_meta()),封面解析带三级兜底:
展示头声明的
cover→ 首个成品媒体 → 目录内首张图/视频
这意味着即使 agent 忘了登记cover,前端卡片依然有图可显示——规约有硬校验,展示有软兜底。
存量收敛与残渣清理:安全优先的迁移工具链
规约落地后,存量目录怎么收敛?Easel 提供了两个"安全优先"的脚本:
- migrate_outputs.py:默认 dry-run 只打印计划;
--apply增量回填.easel.json展示头(纯新增字段、不覆盖已有值、不动文件);加--reorganize才把公认中间件(frames/、构建脚本、同名重复 jpg)挪进assets/。脚本绝不删除任何文件。 - cleanup_outputs.sh:删除测试残渣的动作固化为带注释的脚本,默认 dry-run,每条删除都有理由,由人审阅后手动
--apply——因为仓库安全策略会拦截 AI 直接rmoutputs/。
日常产物管理则交给 asset-manager 技能:scan/search/archive/tag/report 五个操作全部固化为脚本,归档同样 dry-run 先行、冲突绝不覆盖、幂等可重跑。
小结
Easel 的 outputs 目录设计与 manifest 编排,本质上是把"多智能体产物管理"拆成了四层防线:
- 目录规约:一主题一目录,成品/中间件/元数据三区分离;
- 路径闸门:
validate_output_path()让违规路径在代码层就被拒绝; - manifest 契约:薄索引 + 原子写入 + 失败登记,链路可追溯、可断点续跑;
- 收敛工具链:迁移 dry-run 先行、清理脚本人工审阅,安全优先。
这套设计对任何做多智能体内容生产的团队都有参考价值——先把"产物放哪"变成确定性契约,智能体才能真正被放心地串成流水线。
【免费下载链接】EaselAn open-source AI agent for social media — discover trends, create content, publish everywhere, and learn what works across Xiaohongshu, Douyin, Zhihu, Bilibili, and more.🎨一个开源的 AI 社交媒体智能体——发现热点趋势、创作内容、一键发布至各大平台,并学习分析哪些内容真正有效,覆盖小红书、抖音、知乎、哔哩哔哩等平台。项目地址: https://gitcode.com/gh_mirrors/easel3/Easel
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考