资讯动态

Odysseus Agent 迁移清单:用 agent-migration.v1 从其他 Agent 安全导入记忆、技能与会话

发布时间:2026/9/5 21:07:59 来源:尧图企业网站定制
Odysseus Agent 迁移清单用 agent-migration.v1 从其他 Agent 安全导入记忆、技能与会话【免费下载链接】odysseusSelf-hosted AI workspace.项目地址: https://gitcode.com/gh_mirrors/ody/odysseus本文围绕 docs/agent-migration.md 展开讲解 Odysseus 自托管 AI 工作区如何从 OpenClaw、Hermes、ChatGPT 导出包或一个 Markdown 笔记文件夹等外部 Agent 中迁移状态而不盲信其全部数据通过来源中立的agent-migration.v1JSON 清单把记忆、技能、会话与归档文档分层归一化。读完后你将掌握清单的完整 schema 与字段语义、scripts/agent_migration_manifest.py 的全部命令行参数与默认值、各输入源的归一化规则以及未来导入器应遵循的分阶段 apply 策略。安全迁移路径与总体架构Odysseus 的核心目标是能从另一个 Agent 学习但不盲目信任它的整个状态。文档给出的安全迁移链路是一条五段式流水线source agent export - source adapter - agent-migration.v1 manifest - preview - apply其中清单manifest被刻意设计为来源中立OpenClaw、Hermes、一个 Markdown 笔记文件夹或任何其他 Agent 都可以各自实现自己的 adapter但 Odysseus 只需要理解归一化后的清单而不必理解每个来源的私有格式。这条链路的分工在源码中有明确体现scripts/agent_migration_manifest.py 的模块 docstring 声明该辅助工具intentionally read-only——它不导入 Odysseus 应用包、不写data/、不调用 LLM、不应用任何东西只把常见的 Agent 导出格式转换为可移植的 JSON 清单scripts/agent_migration_manifest.py#L2-L7。常量SCHEMA_VERSION agent-migration.v1scripts/agent_migration_manifest.py#L22是清单与未来导入器之间的唯一契约。为什么不能把所有东西都导入成记忆这是整篇文档的设计原点值得单独展开。持久记忆durable memory应该保持紧凑且有用。长笔记、日志、会话转录、项目归档都是有价值的上下文但它们并不都是记忆。好的迁移方案要把两层分开Archive documents归档文档保存源材料用于搜索、阅读和后续提取Memory candidates记忆候选短小的事实或偏好在写入 Odysseus 记忆之前可以先被审阅。这样做的好处是让 Odysseus 既有的记忆审阅流程保持原样同时给它提供了更好的待审源材料。这一分层直接映射到清单的两种 item kindarchive_document与memory二者的 content 字段都是可选的归档层甚至可以只保留元数据。Manifest 结构与字段语义agent-migration.v1是一个 JSON 对象完整形状如下继承自 docs/agent-migration.md{ schema_version: agent-migration.v1, generated_at: 2026-06-06T00:00:00Z, source: { name: example-agent, kind: generic }, summary: { item_count: 3, counts_by_kind: { memory: 1, skill: 1, conversation_thread: 1, archive_document: 1 }, warning_count: 0 }, items: [], warnings: [] }结合 scripts/agent_migration_manifest.py 中的build_manifest()scripts/agent_migration_manifest.py#L506-L558可以确认各字段的生成规则generated_at由utc_now_iso()生成是去掉微秒、以Z结尾的 UTC ISO 时间戳source.name/source.kind来自--source-name/--source-kind参数kind是 adapter 类型标签如generic、openclaw、hermes只供人读和 adapter 分发不影响清单结构summary.item_count是items总长度counts_by_kind按 item 的kind计数warning_count与warnings数组一一对应每条 warning 形如{path: ..., message: ...}指向具体输入文件上的具体问题重复、缺失、被跳过的符号链接等。item 的稳定 ID 与四种 kind文档强调每个 item 有一个稳定的id、一个kind、来源元数据以及足够让未来导入器在 apply 前预览的内容。源码中stable_id()用kind source_name 各部分值拼接后取 SHA-256 前 16 位十六进制格式为{kind}:{hash}scripts/agent_migration_manifest.py#L66-L68保证同一来源、同一文件、同一条目重复生成清单时 ID 不变便于幂等导入。首版支持的 item kind 及其字段kind内容关键字段与可选性memory记忆候选text、category、source与 provenance 元数据skill一个SKILL.md文件content全文 解析出的 frontmatter 元数据name、category、sha256conversation_thread归一化后的会话线程消息内容可选默认只保留线程元数据、消息数、时间戳和哈希避免清单膨胀或内嵌私密转录文本archive_document长文源材料内容可选默认只保留路径/哈希/大小元数据用只读助手构建清单完整命令行参考构建清单的入口命令继承自文档示例python3 scripts/agent_migration_manifest.py \ --source-name old-agent \ --source-kind generic \ --memory-json /path/to/memories.json \ --skills-dir /path/to/skills \ --conversation-json /path/to/conversations.json \ --archive /path/to/notes \ --output /tmp/agent-migration.json该助手不写data/、不调用 LLM、不导入 Odysseus 模块、不修改源只写 JSON。结合parse_args()scripts/agent_migration_manifest.py#L561-L617完整参数表如下四个输入参数均可重复传入actionappend因此一条命令可合并多个来源参数默认值说明--source-nameagent-export人类可读的来源名称会写入每条 item 的source字段--source-kindgeneric来源 adapter 类型如generic、openclaw、hermes--memory-json无记忆 JSON 导出可以是数组也可以是包含memories/memory/items/data列表的对象--skills-dir无包含SKILL.md的目录递归扫描--archive无作为归档文档保留的文本/Markdown/JSON 文件或目录--conversation-json无会话导出 JSON支持通用消息列表和 ChatGPT 风格的conversations.json--include-archive-content关闭把归档文档内容嵌入清单默认只有元数据--max-archive-bytes256000使用--include-archive-content时单文件最大内嵌字节数--include-conversation-content关闭嵌入归一化后的会话消息默认只有线程元数据--max-conversation-messages2000使用--include-conversation-content时单会话最大内嵌消息数--output无输出到 stdout写入清单 JSON 的路径main()会自动创建父目录--compact关闭输出无缩进的紧凑 JSON排序键、ensure_asciiFalseMemory JSON 的两种可接受形状--memory-json既接受纯字符串数组也接受对象里包含text等键的条目[ A plain memory string, { text: A categorized memory, category: preference, source: old-agent } ]或一个在memories、memory、items、data任一键下包含列表的对象docs/agent-migration.md 与 scripts/agent_migration_manifest.py#L104-L109。源码中的collect_memory_json()scripts/agent_migration_manifest.py#L112-L148给出了完整的归一化规则文本抽取依次尝试text、content、memory、value键抽不到文本的条目会被跳过并产生skipped memory at index N: missing text警告按text.strip().lower()的 SHA-256 去重重复条目产生skipped duplicate memory at index N警告category缺失或为空时归一为factsource缺失时回退到--source-name原条目中的id、timestamp、created_at、updated_at、source、tags、pinned键会被原样搬进metadata并加source_前缀scripts/agent_migration_manifest.py#L92-L101同时补充source_path与source_index两个 provenance 字段。Skills递归扫描 SKILL.md技能输入按SKILL.md文件名递归扫描例如从 Hermes 技能目录构建清单python3 scripts/agent_migration_manifest.py \ --source-name hermes \ --source-kind hermes \ --skills-dir ~/.hermes/skills \ --output /tmp/hermes-skills-manifest.jsoncollect_skill_dir()scripts/agent_migration_manifest.py#L368-L405的解析与防护规则用parse_skill_frontmatter()scripts/agent_migration_manifest.py#L350-L365做极简 frontmatter 解析只识别key: value行跳过注释和空行值剥离外层引号name取 frontmatter 的name缺失时回退到SKILL.md所在目录名category缺失时回退到general每个技能 item 携带全文content、sha256和完整 frontmatter 字典format固定为SKILL.md安全边界skills 根路径是符号链接直接整体跳过skills path is a symlink; skipped单个符号链接的SKILL.md也跳过——测试 tests/test_agent_migration_manifest.py#L80-L104 验证了这两条防止清单借助链接越权读取目录之外的私密技能文件。值得一提的是SKILL.md正是 Odysseus 自身技能的存储格式services/memory/skill_format.py 定义了更完整的 frontmatter schemaname、description、version、category、tags、platforms、requires_toolsets、status、confidence、source、teacher_model、owner、created等和正文小节When to Use / Procedure / Pitfalls / Verification技能落盘在data/skills/category/name/SKILL.md见 services/memory/skills.py 头部注释。迁移清单里解析出的 frontmatter 元数据尤其是name与category正是文档所述技能导入前做名称/类别冲突检查所需的信息。Archive默认只带元数据显式嵌入内容归档文档默认 metadata-only。要嵌入文本内容需要显式打开python3 scripts/agent_migration_manifest.py \ --source-name notes-export \ --archive /path/to/markdown-notes \ --include-archive-content \ --output /tmp/notes-manifest.json从源码结构看collect_archive_paths()scripts/agent_migration_manifest.py#L442-L503的行为边界包括文本判定looks_textual()先查扩展名白名单TEXT_EXTENSIONS.cfg、.conf、.csv、.json、.log、.md、.markdown、.py、.rst、.toml、.txt、.yaml、.ymlscripts/agent_migration_manifest.py#L23-L37再用mimetypes猜测text/*或application/json非文本文件被跳过并告警元数据每个归档 item 记录source_path、size_bytes和分块64 KiB计算的sha256内容嵌入仅在--include-archive-content且文件不超过--max-archive-bytes默认 256000 字节时读取文本超过上限会告警skipped archive content over N bytes但保留元数据 itemUTF-8 解码失败时用errorsreplace重试并在 metadata 中标记decoded_with_replacement符号链接防护归档根路径和子树中任何符号链接都会被跳过并告警tests/test_agent_migration_manifest.py#L120-L145 覆盖了链接文件和链接根目录两种越权场景。Conversations通用格式与 ChatGPT mapping 导出会话导出同样是 metadata-only 默认python3 scripts/agent_migration_manifest.py \ --source-name chatgpt-export \ --source-kind chatgpt \ --conversation-json /path/to/conversations.json \ --output /tmp/chatgpt-conversations-manifest.json首版支持的通用会话 JSON 形如[ { id: thread-1, title: Project plan, messages: [ {role: user, content: Can we design this?}, {role: assistant, content: Yes, start with a narrow slice.} ] } ]同时它也识别 ChatGPT 从conversations.json导出的mapping风格。要嵌入归一化消息python3 scripts/agent_migration_manifest.py \ --source-name chatgpt-export \ --source-kind chatgpt \ --conversation-json /path/to/conversations.json \ --include-conversation-content \ --max-conversation-messages 2000 \ --output /tmp/chatgpt-conversations-with-content.jsoncollect_conversation_json()scripts/agent_migration_manifest.py#L283-L347的关键规则顶层形状接受数组或包含conversations/conversation/items/data列表的对象单个会话对象会被自动包成单元素列表消息发现顺序先尝试chatgpt_mapping_messages()scripts/agent_migration_manifest.py#L237-L254——遍历mapping下每个节点的message按create_time缺失时用节点下标排序重建时序source_format标记为chatgpt_mapping找不到时依次尝试messages、chat_messages、turns键消息归一化角色统一映射human/user→userassistant/ai/bot/model→assistantsystem/tool保留文本从content字符串、part 列表、parts字典或text/body/message键中抽取时间戳经normalize_timestamp()归一unix 秒转 UTC ISO空文本消息被丢弃线程元数据source_path、source_index、source_format实际命中的格式来源、message_count、全部消息文本的text_sha256、content_included布尔值以及source_id来自id/uuid/conversation_id和归一化后的source_create_time/source_created_at/source_update_time/source_updated_at内容上限开启嵌入后消息数超过--max-conversation-messages的会话会整体放弃内容item 保留content_included为False并产生skipped conversation content at index N: over M messages警告——测试 tests/test_agent_migration_manifest.py#L253-L280 验证了这一行为。文档对为什么内容嵌入必须是显式的给出了解释导出的聊天历史可能非常大且私密所以默认清单只承载元数据、哈希和消息计数。文档还预告了演进方向未来的来源专用 adapter 可以增加 ZIP 遍历、附件元数据和 provider 专属的 project/workspace 字段同时仍然发出同一种conversation_threaditem——这正是adapter 可以来源专用核心清单不可以原则的落地。推荐的 apply 行为导入器应如何消费清单文档对未来的 Odysseus 导入器给出了明确的行为规范清单必须被视为不受信任的用户提供的数据并且分阶段应用先展示 dry-run 摘要计数、警告、重复项和抽样条目写入任何东西之前先备份当前data/状态归档文档作为文档或其他可搜索源导入而不是作为记忆导入会话线程先作为可搜索的归档上下文导入并保留指向源线程的引用不要把整段转录变成记忆记忆候选先展示审阅再通过正常记忆路径保存技能只在名称/类别冲突检查之后导入默认跳过 secrets凭证需要显式的、provider 专属的流程。这条流程与仓库现有实现是衔接的例如备份/导入路由 routes/backup_routes.py 在导入skills时就只对当前用户自己的已加载技能做去重避免拿全部租户的技能做比对造成跨租户误判并通过skills_manager.add_skill()落盘为SKILL.md文件routes/backup_routes.py#L111-L150技能管理路由位于 routes/skills_routes.py。清单里的warnings数组每条含path与message正是 dry-run 摘要阶段现成的输入。来源 Adapter 的职责边界文档最后一节划清了 adapter 与核心清单的边界Adapters can be source-specific. The core manifest should not be.例如OpenClaw adapter 可以了解 OpenClaw 的 workspace 文件Hermes adapter 可以了解~/.hermes/config.yaml与~/.hermes/skillsChatGPT adapter 可以了解conversations.json、上传文件元数据和图片附件目录Claude adapter 可以了解 Claude 的导出形状和项目边界而 generic adapter 只需要认识记忆 JSON、会话 JSON、SKILL.md和 Markdown 文件夹。非标准目录结构应该是 adapter 的实现细节而不是 Odysseus 必须理解的强制概念。从当前实现看--source-kind只是清单上的标签构建脚本本身完全来源中立——这个核心稳定、adapter 可插拔的分层是让 Odysseus 未来对接任意 Agent 生态的关键设计。小结验证与延伸阅读这套机制有完整测试覆盖tests/test_agent_migration_manifest.py 逐条验证了记忆字符串/对象双形态与精确去重、SKILL.md扫描与符号链接跳过、归档内容与符号链接防护、通用与 ChatGPT mapping 会话的元数据/内容两档导入、消息上限截断、缺失路径告警以及main()端到端写出schema_version agent-migration.v1的清单。对希望动手验证的读者建议路径是准备一份小型的memories.json和一个含SKILL.md的目录按本文的命令行参考运行一次只读构建检查summary.counts_by_kind与warnings再对照items中各类字段的默认值如 memory 的category缺省fact、skill 的category缺省general、max-archive-bytes缺省 256000。相关延伸阅读docs/agent-migration.md设计原文、scripts/agent_migration_manifest.py构建器实现、services/memory/skill_format.pySKILL.md 完整 schema、tests/test_agent_migration_manifest.py行为契约。【免费下载链接】odysseusSelf-hosted AI workspace.项目地址: https://gitcode.com/gh_mirrors/ody/odysseus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价