Cell 导入导出

wesgine 支持将 Cell 导出为可移植的 tar.gz 包,并在另一个引擎实例中导入,实现跨环境迁移。


概述

Cell 是 wesgine 的可移植单元——它不仅是运行时实例,还是可打包的快照。导出/导入机制让 Cell 能够:


导出流程

SDK 方式

// 导出 Cell 为 tar.gz 流
reader, err := hyp.Cells().Export(ctx, "my-cell")
if err != nil {
	log.Fatal(err)
}
defer reader.Close()

// 写入文件
f, _ := os.Create("my-cell-export.tar.gz")
defer f.Close()
io.Copy(f, reader)

HTTP 方式

# 导出 Cell
curl -o my-cell-export.tar.gz \
  http://localhost:9091/admin/cells/my-cell/export \
  -H "Authorization: Bearer <admin-token>"

导出内容

默认包含:

内容路径说明
元数据meta.dbCell 配置、Agent 定义
会话数据sessions.db历史对话、消息
运行时状态state.dbTraces、观测数据
技能skills/已安装的 Tier C 技能
知识库knowledge/KB 文件和索引
工作区文件workspace/Agent 产出文件

默认排除:

内容说明
.scratch/临时计算域(Run 结束后 GC)
.cell.lock进程排他锁

导出选项

// 排除 workspace(减小包体积)
reader, err := hyp.Cells().Export(ctx, "my-cell", ExportOpts{
	SkipWorkspace: true,
})

tar.gz 格式

导出文件是标准 tar.gz 压缩包,内部结构:

my-cell-export.tar.gz
├── cell-manifest.json      # 导出元信息(版本、时间、引擎版本)
├── spec.json               # CellSpec 快照(密钥已脱敏)
├── meta.db                 # Cell 元数据库
├── sessions.db             # 会话数据库
├── state.db                # 运行时状态库
├── skills/                 # 技能包
│   ├── skill-a/
│   └── skill-b/
├── knowledge/              # 知识库文件
│   ├── sources/
│   └── files/
└── workspace/              # 工作区产出(可选)
    └── {actor}/

cell-manifest.json

{
  "version": "1.0",
  "cell_id": "my-cell",
  "exported_at": "2026-09-14T12:00:00Z",
  "engine_version": "v1.0.0",
  "checksum": "sha256:abc123...",
  "includes": {
    "sessions": true,
    "knowledge": true,
    "skills": true,
    "workspace": true
  }
}

密钥处理

导出时 spec.json 中的密钥自动脱敏:

{
  "private_providers": [
    {
      "name": "openai",
      "api_key_ref": {
        "source": "inline",
        "value": "***REDACTED***"
      }
    }
  ]
}

导入后需要重新配置 Provider 密钥。


导入流程

SDK 方式

// 从文件导入
f, _ := os.Open("my-cell-export.tar.gz")
defer f.Close()

cellID, err := hyp.Cells().Import(ctx, f, ImportOpts{})
if err != nil {
	log.Fatal(err)
}

log.Printf("Cell 已导入: %s", cellID)

HTTP 方式

# 导入 Cell
curl -X POST http://localhost:9091/admin/cells/import \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @my-cell-export.tar.gz

# 覆盖已存在的 Cell
curl -X POST "http://localhost:9091/admin/cells/import?overwrite=1" \
  -H "Authorization: Bearer <admin-token>" \
  --data-binary @my-cell-export.tar.gz

导入选项

type ImportOpts struct {
	// 覆盖已存在的同 ID Cell
	Overwrite bool

	// 重命名 Cell ID(避免冲突)
	NewCellID string
}

导入后操作

导入完成后,通常需要:

  1. 重新配置 Provider 密钥:导出时密钥已脱敏
cell, _ := hyp.Cells().Get("imported-cell")
// 通过 UpdateSpec 重新配置 Provider
hyp.Cells().UpdateSpec(ctx, "imported-cell", SpecPatch{
	PrivateProviders: []config.ProviderConfig{
		{
			Name:    "openai",
			APIKeyRef: config.SecretRef{Source: "inline", Value: "sk-new-key"},
		},
	},
})
  1. 验证 Cell 状态
curl http://localhost:9091/cells/imported-cell/state \
  -H "Authorization: Bearer <token>"
  1. 测试连通性
curl -X POST http://localhost:9091/cells/imported-cell/providers/test \
  -H "Authorization: Bearer <token>" \
  -d '{"provider": "openai"}'

数据完整性

导出时校验

导入时校验

SQLite 备份机制

导出使用 VACUUM INTO(原子快照)而非文件拷贝:

// 内部实现(INV-RESIL-05)
resilience.SQLiteBackup(sourceDB, targetPath)

为什么不用 cp:直接拷贝 .db 文件会忽略 -wal 和 -shm 文件,导致数据不一致。Cell 有 meta.db、sessions.db、state.db 三个数据库,必须全部使用原子快照。


跨环境迁移

开发 → 生产

# 在开发环境导出
curl -o dev-cell.tar.gz http://dev:9091/admin/cells/dev-cell/export \
  -H "Authorization: Bearer <dev-admin-token>"

# 在生产环境导入
curl -X POST http://prod:9091/admin/cells/import \
  -H "Authorization: Bearer <prod-admin-token>" \
  --data-binary @dev-cell.tar.gz

# 重新配置生产 Provider
curl -X PATCH http://prod:9091/admin/cells/dev-cell \
  -H "Authorization: Bearer <prod-admin-token>" \
  -d '{"private_providers": [...]}'

Cell 模板化

利用导出/导入实现 Cell 模板:

# 创建模板 Cell(配置好 Agent、Skill、治理策略)
# 导出为模板
curl -o template.tar.gz http://localhost:9091/admin/cells/template/export

# 为新部门导入模板
curl -X POST "http://localhost:9091/admin/cells/import" \
  -d @template.tar.gz
# 导入后重命名或修改 ID

灾难恢复

# 定期备份
#!/bin/bash
BACKUP_DIR="/backups/wesgine/$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"

# 导出所有 Cell
for cell_id in $(curl -s http://localhost:9091/admin/cells | jq -r '.[].id'); do
  curl -o "$BACKUP_DIR/${cell_id}.tar.gz" \
    "http://localhost:9091/admin/cells/${cell_id}/export" \
    -H "Authorization: Bearer <admin-token>"
done

# 保留最近 30 天
find /backups/wesgine -mtime +30 -delete

最佳实践

  1. 定期导出作为备份策略,结合 cron 自动化
  2. 导出前确认 Cell 无活跃 Run,避免数据不一致
  3. 大型知识库 Cell 使用 SkipWorkspace 减小包体积
  4. 模板化 Cell 实现快速部署新租户
  5. 保留导出的 manifest 用于追溯和审计

注意事项