Paperclip 公司配置怎么导出导入:包结构、collision 策略与「导入后不自动跑」
配好一家公司之后,迟早会碰到同一个需求:换一套环境重来一遍。可能是本地调通了要挪到服务器,可能是想把一套「工程团队」的编制复用到第二个项目上,也可能只是想把配置放进 Git 做版本管理。
这时候第一反应往往是备份数据库。但 Paperclip 给的路子不是这个——它把公司导出成一个可读的 markdown 目录,导入的时候再从目录还原。这个选择带来的直接后果是:导出的东西你能用编辑器打开、能 diff、能提到 GitHub 上让别人 fork;同时也意味着有一部分运行期数据根本不会跟着走。
搞不清哪些跟着走、哪些不跟,是这套机制最容易翻车的地方。下面按导出、导入、导入后三段来拆。
导出包长什么样
导出产物遵循 Agent Companies 规范,是一个 markdown 优先的目录结构:
my-company/
├── COMPANY.md # Company metadata
├── agents/
│ ├── ceo/AGENT.md # Agent instructions + frontmatter
│ └── cto/AGENT.md
├── projects/
│ └── main/PROJECT.md
├── skills/
│ └── review/SKILL.md
├── tasks/
│ └── onboarding/TASK.md
└── .paperclip.yaml # Adapter config, env inputs, routines
各文件的角色是分开的:COMPANY.md 放公司名、描述和元数据;AGENT.md 放 agent 的身份、角色和指令正文;SKILL.md 与 Agent Skills 生态兼容,不需要为了 Paperclip 加额外的顶层字段;.paperclip.yaml 是可选的旁挂文件(sidecar),装 Paperclip 自己那部分——适配器类型、env 输入声明、预算、routine 触发器。
这个分层不是随便切的。规范文档明确说明包格式是 vendor-neutral 的,目标是任何 agent-company 运行时都能用,不只服务 Paperclip。所以基础包必须在没有 .paperclip.yaml 的情况下依然可读,不认识这个厂商扩展的工具应该直接忽略它。
有个细节值得先说破:导入导出指南里画的目录树写的是 agents/ceo/AGENT.md,而规范文档第 3、4 节列的保留文件名是 AGENTS.md(复数)。两份官方文档在这个文件名上不一致,具体以哪个为准,文档里没有交代。真要动手写包,建议先跑一次导出看实际产物。
导出命令与那个默认值的坑
paperclipai company export <company-id> --out ./my-export
选项如下:
| 选项 | 说明 | 默认值 |
|---|---|---|
--out <path> | 输出目录(必填) | — |
--include <values> | 逗号分隔集合:company、agents、projects、issues、tasks、skills | company,agents |
--skills <values> | 只导出指定 skill slug | 全部 |
--projects <values> | 只导出指定项目短名或 ID | 全部 |
--issues <values> | 导出指定 issue 标识或 ID | 无 |
--project-issues <values> | 导出属于指定项目的 issue | 无 |
--expand-referenced-skills | 把 skill 文件内容内联进包,而不是保留上游引用 | false |
注意 --include 的默认值:只有 company,agents。也就是说不带参数直接跑一条 export,projects、tasks、skills 全都不在包里。想要完整的一份,得自己写全:
# Export everything including tasks and skills
paperclipai company export abc123 --out ./full-export --include company,agents,projects,tasks,skills
跟着走的东西包括:公司名/描述/元数据、agent 的名字角色汇报关系和指令、项目定义与工作区配置、任务或 issue 的描述(在 include 里的时候)、skill 包(引用形式或内联内容)、以及 .paperclip.yaml 里的适配器类型和 env 输入声明。
**不会跟着走的是:密钥值、机器本地路径、数据库 ID。**文档用的词是 never exported。这条要跟密钥管理那套一起理解——导出包里只有「这里需要一个叫 ANTHROPIC_API_KEY 的东西」这样的声明,值得你在目标环境重新配一遍。同理,适配器的类型会导出,但绑定到具体 provider 的 secret 引用(secretId、version、type: secret_ref 这类)规范明确要求不导出。
「这次导出不包含什么」:保真度报告
Web 界面里也有对应的 Export 与 Import 页面,挂在公司设置导航下。Export 页可以逐个文件挑选要不要进包,文件树上方有一块叫 “Not included in this export” 的面板,也就是导出保真度报告,列出这个包带不走的数据,比如附件、审批、成本历史、活动日志条目,其中有阻断性问题的会被高亮。
这块面板对应一个独立的接口 GET /api/companies/{companyId}/export/fidelity,可以脱离界面单独调。
这是我认为整个导入导出设计里最该被注意的一点:它不假装导出是全量备份,而是主动把缺口摆出来。所以把 export 当灾备手段之前,先看一眼这份报告——成本历史和活动日志不跟着走,意味着这两条审计线是留在原环境的,换环境等于从零开始记。
导入:三类来源与目标模式
导入支持本地目录、GitHub URL、GitHub 简写三类来源:
# From a local folder
paperclipai company import ./my-export
# From a GitHub URL
paperclipai company import https://github.com/org/repo
# From a GitHub subfolder
paperclipai company import https://github.com/org/repo/tree/main/companies/acme
# From GitHub shorthand
paperclipai company import org/repo
paperclipai company import org/repo/companies/acme
选项:
| 选项 | 说明 | 默认值 |
|---|---|---|
--target <mode> | new(建新公司)或 existing(并入已有公司) | 按上下文推断 |
--company-id <id> | --target existing 时的目标公司 ID | 当前上下文 |
--new-company-name <name> | --target new 时覆盖公司名 | 取自包 |
--include <values> | 同 export 的六个集合值 | 自动检测 |
--agents <list> | 逗号分隔的 agent slug,或 all | all |
--collision <mode> | 命名冲突处理:rename、skip、replace | rename |
--ref <value> | GitHub 导入的 git ref(分支、标签或 commit) | 默认分支 |
--dry-run | 只预览不实际导入 | false |
--yes | 跳过交互式确认 | false |
--json | 以 JSON 输出结果 | false |
--target 不写的时候 Paperclip 会推断:提供了 --company-id(或上下文里已有一个)就走 existing,否则走 new。这个推断规则在脚本里要格外小心——同一条命令在有上下文和没上下文的环境里,行为是两种。
冲突策略三选一,只在并入已有公司时才有意义:rename 是默认,加后缀避让(例如 ceo 变成 ceo-2);skip 跳过已存在的实体;replace 覆盖已有实体,只在非安全导入下可用,走 CEO API 拿不到这个选项。
交互式跑(不带 --yes 也不带 --json)时,导入命令会先出一个勾选界面,让你逐项挑 agent、项目、skill 和任务。
先 dry-run,看四件事
paperclipai company import org/repo --target existing --company-id abc123 --dry-run
预览会给出四块信息:包里有多少 agent/项目/任务/skill;导入计划里哪些会被创建、重命名、跳过、替换;导入后可能需要填值的环境变量;以及潜在问题的警告,比如缺失的 skill 或未解析的引用。
规范这一层对「未解析的引用」有更细的要求。包里可以用 sources 指向上游内容而不把字节复制进来,源对象长这样:
sources:
- kind: github-file
repo: owner/repo
path: path/to/file.md
commit: 0123456789abcdef0123456789abcdef01234567
sha256: 3b7e...9a
attribution: Owner Name
license: MIT
usage: referenced
usage 三种取值区分得很清楚:vendored 是字节在包里,referenced 是指向上游不可变内容,mirrored 是本地缓存但归属仍算上游。严格模式下 github-file 和 github-dir 必须带 commit,只给分支名的引用允许在开发模式使用但要告警。解析时的顺序是本地相对路径、(工具允许时的)本地绝对路径、固定的 GitHub ref、通用 URL;带 commit 的 GitHub 引用要验证 sha256 和 blob,对不上就 fail closed。
导入器必须把这几类情况暴露出来:文件缺失、哈希不匹配、license 缺失、需要联网抓取的上游内容、以及 skill 或 scripts 里的可执行内容。最后这条尤其值得留意——你从 GitHub fork 一份别人的公司包,里面的 skill 可能带 scripts/ 目录。
从 GitHub 导入建议一律带 --ref 钉住分支、标签或 commit:
paperclipai company import org/repo --ref v2.0.0 --dry-run
导入完不会自己跑起来
这是设计上最省心的一点。导入的 agent 一律以定时心跳禁用的状态落地;包里声明的「被指派时唤醒/按需唤醒」行为会保留,但定时运行要等 board operator 手动重新打开。
在这之上还有一层:导入请求可以带 pauseAutomations,让 agent 和 routine 完全暂停落地。Web 界面 Import 页上那个 “Start imported agents and routines paused” 复选框默认就是勾上的,对应 API 层的 pauseAutomations: true。导入完成后会出现一块 “Activate imported agents and routines” 面板,把所有暂停落地的东西列出来,由你挑着恢复 agent、激活 routine——不点就什么都不会跑。
对着一堆带 cron 触发器的 routine,这个默认值救命。规范里 Paperclip 扩展的 routine 是这样声明的:
routines:
monday-review:
triggers:
- kind: schedule
cronExpression: "0 9 * * 1"
timezone: America/Chicago
要是导入即生效,一份团队模板导进来的瞬间就可能触发一批定时任务。
CLI 底下用的接口也都是公开的:
| 动作 | 接口 |
|---|---|
| 导出公司 | POST /api/companies/{companyId}/export |
| 导出保真度报告 | GET /api/companies/{companyId}/export/fidelity |
| 预览导入(已有公司) | POST /api/companies/{companyId}/imports/preview |
| 应用导入(已有公司) | POST /api/companies/{companyId}/imports/apply |
| 预览导入(新公司) | POST /api/companies/import/preview |
| 应用导入(新公司) | POST /api/companies/import |
CEO agent 可以走 /imports/preview 和 /imports/apply 这两条安全路由,规则是强制非破坏性的:replace 被拒绝,冲突只能用 rename 或 skip 解决,issue 一律新建。让 agent 自己去导入配置这件事,边界是被代码卡死的,不靠提示词自觉。
什么时候别用它,以及还没解决的
**别把 export 当备份。**保真度报告已经把话说明白了:附件、审批、成本历史、活动日志这些不进包。真要做灾备,得另外考虑数据库层面的方案,文档在这篇里没有涉及。
规范本身还是 draft。版本号写的是 agentcompanies/v1-draft。文档还提到 Paperclip 应该把这套 markdown-first 模型作为主要可移植格式硬切换过去,paperclip.manifest.json 不再作为兼容性要求保留——按这个说法,旧格式的迁移路径文档里没有给。
**锁文件是可选的。**工具可以生成 company-package.lock.json 来缓存已解析的引用、记录最终哈希、支持可重现安装,但它是生成物不是编写输入,markdown 包始终是唯一真相源。所以「同一个包两次导入结果一定一致吗」这个问题,在没有锁文件的情况下取决于上游有没有被钉住。
替换语义要自己想清楚。--collision replace 会覆盖已有实体,文档没有说覆盖前有没有备份或者能不能回滚。往一家在跑的公司里合并包之前,先 --dry-run 看清导入计划里哪些条目落在 replaced 那一栏。
如果你还没建过公司,先从建第一家公司的完整步骤开始,把结构跑通了再来考虑打包搬运——导出的是配置,配置本身合不合理,包格式帮不了你。
延伸阅读
- 从头读起:Paperclip 是什么:一个自己不跑 Agent 的控制平面,怎么管住一整家 AI 公司
- 本专题共 40 篇,完整分组目录见专题页
- Paperclip 实验特性开关怎么用:官方标为实验性的功能,开之前要想清楚什么
- Paperclip 适配器怎么选:五类接入方式的前提、限制与官方对照表
本文依据 Paperclip 官方仓库(github.com/paperclipai/paperclip,MIT 协议)的 docs/ 用户文档
与 doc/ 下的规范、运维与连接器手册整理,核对日 2026-08-17。
我们没有部署或运行过 Paperclip,因此不涉及界面外观与操作手感;
部分规范文档描述的是目标架构而非当前实现,文中已就地标注,不构成对实际行为的保证。
请以仓库最新内容为准。