Kibotos
场景

保留项目的编码 Agent

编码 Agent 需要在会话结束后保留项目。本页把项目放在独立的 Volume 上,并为每次会话创建绑定这个 Volume 的新 Workspace。完整程序是 examples/go/coding-agent。

前提条件

  • Go 1.27 或更新版本,以及 Kibotos 仓库的一份检出。
  • ctrl 地址,以及用 kibo enrollment create --operator 为这个程序生成的注册密钥(enrollment key),见身份与注册。

步骤

1. 创建项目的 Volume

Volume 属于项目。平台重启后可以用 label 重新找到它:

created, err := client.Volumes().CreateVolume(ctx, connect.NewRequest(&ctrlv1.CreateVolumeRequest{
	Metadata: &ctrlv1.CommandMetadata{CommandId: kibotos.NewCommandID("coding-agent")},
	Spec:     &ctrlv1.VolumeSpec{CapacityBytes: 1 << 30},
	Labels:   map[string]string{"example.com/project": "demo"},
}))

2. 绑定到会话的 Workspace

每次会话创建一个绑定这个 Volume 的 Workspace。设置到期时间后,平台崩溃也不会让 Workspace 一直运行:

request := &ctrlv1.CreateWorkspaceRequest{
	Metadata: &ctrlv1.CommandMetadata{CommandId: commandID},
	Spec: &ctrlv1.WorkspaceCreateSpec{
		Template:  &ctrlv1.TemplateSelector{TemplateId: templateID},
		Resources: &ctrlv1.ResourceRequest{CpuMillis: 1000, MemoryBytes: 512 << 20},
		Volume: &ctrlv1.WorkspaceVolumeBinding{
			Mode:      ctrlv1.WorkspaceVolumeMode_WORKSPACE_VOLUME_MODE_BOUND,
			VolumeId:  volumeID,
			MountPath: "/workspace",
		},
	},
	Expiration: &ctrlv1.WorkspaceExpirationPolicy{
		Timeout: durationpb.New(time.Hour),
		Action:  ctrlv1.WorkspaceExpirationAction_WORKSPACE_EXPIRATION_ACTION_DELETE,
	},
}

3. 在项目目录里工作

会话读取之前的会话留下的内容,并在项目目录里运行工具。为每个进程设置 WorkingDirectory:

stream, err := session.StartProcess(ctx, &ctrlv1.StartRequest{
	Argv:             argv,
	WorkingDirectory: "/workspace",
	Mode:             &ctrlv1.StartRequest_Pipe{Pipe: &ctrlv1.ProcessPipeMode{}},
})

4. 结束会话

删除 Workspace,并等删除命令完成:示例里的 deleteWorkspace 最后调用 Client.WaitWorkspaceDeleted。绑定已有 Volume 时,Volume 不随 Workspace 删除,下一次会话会重新绑定它:

if err := deleteWorkspace(ctx, client, workspaceID); err != nil {
	return err
}

5. 运行程序

程序连续运行两次会话,最后删除 Volume。你的平台在项目存续期间保留这个 Volume:

go run ./examples/go/coding-agent -endpoint https://ctrl.example.com:18092 \
  -identity "$HOME/.local/state/kibotos-coding-agent" -enrollment-key-file coding-agent.key

第二次会话能看到第一次写入的内容:

created Volume vol-06gvz1fz8nr2k87mzsg8741qwg for the project
first session runs in Workspace ws-06gvz1fzpxy0d6qx59degv74q8
the project is empty
second session runs in Workspace ws-06gvz1gdyxrk76207y0ajds63w
previous sessions left:
first session worked on ws-06gvz1fzpxy0d6qx59degv74q8

用 E2B SDK

按名称创建的 Volume 用法相同。用 volumeMounts 挂载,删除 sandbox 时它会保留:

import { Sandbox, Volume } from 'e2b';

const volume = await Volume.create('project-demo');

const first = await Sandbox.create('kibotos-minimal', {
  volumeMounts: { '/workspace': volume },
});
await first.files.write('/workspace/progress.log', 'first session\n');
await first.kill();

const second = await Sandbox.create('kibotos-minimal', {
  volumeMounts: { '/workspace': volume },
});
console.log(await second.files.read('/workspace/progress.log'));
await second.kill();

用同一个名称重复调用 Volume.create 会返回同一个 Volume,所以可以在每次会话开始时调用,见 Volume。

注意

  • 只有 Volume 上的数据保证保留。装在根文件系统其他位置的软件包随 Workspace 一起消失,所以要装进 Template 或 Volume。
  • Volume 所在的存储池决定哪些 node 能运行绑定它的 Workspace,见 Volume。
  • 这样绑定的 Workspace 在放行之前不能访问网络,见网络策略。

下一步

本页内容