Coding Agent with a persistent project
A coding Agent needs its project to survive when a session ends. This page keeps the project on a Volume of its own and gives each session a new Workspace bound to that Volume. The complete program is examples/go/coding-agent.
Prerequisites
- Go 1.27 or later, and a checkout of the Kibotos repository.
- The ctrl address, and an enrollment key for this program from
kibo enrollment create --operator. See Identity and enrollment.
Steps
1. Create the project's Volume
The Volume belongs to the project. A label lets your platform find it again after a restart:
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. Bind it to a session's Workspace
Each session creates a Workspace bound to the Volume. The expiration time keeps a crashed platform from leaving the Workspace running:
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. Work in the project directory
The session reads what earlier sessions left and runs its tools in the project directory. Set WorkingDirectory on each process:
stream, err := session.StartProcess(ctx, &ctrlv1.StartRequest{
Argv: argv,
WorkingDirectory: "/workspace",
Mode: &ctrlv1.StartRequest_Pipe{Pipe: &ctrlv1.ProcessPipeMode{}},
})4. End the session
Delete the Workspace and wait for the delete command to settle. deleteWorkspace in the example ends with Client.WaitWorkspaceDeleted. The Volume stays, because a binding to an existing Volume is not deleted with the Workspace. The next session binds it again:
if err := deleteWorkspace(ctx, client, workspaceID); err != nil {
return err
}5. Run the program
The program runs two sessions in a row and deletes the Volume at the end. Your platform keeps the Volume for as long as the project exists:
go run ./examples/go/coding-agent -endpoint https://ctrl.example.com:18092 \
-identity "$HOME/.local/state/kibotos-coding-agent" -enrollment-key-file coding-agent.keyThe second session finds what the first one wrote:
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-06gvz1fzpxy0d6qx59degv74q8With the E2B SDK
A Volume created by name works the same way. Mount it with volumeMounts, and deleting the sandbox keeps it:
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();Repeating Volume.create with the same name returns the same Volume, so you can call it at the start of each session. See Volumes.
Notes
- Only data on the Volume is guaranteed to survive. Packages installed elsewhere on the root file system are lost with the Workspace, so install them in a Template or on the Volume.
- The storage pool of a Volume decides which nodes can run a Workspace bound to it. See Volumes.
- A Workspace bound this way has no network access until you allow it. See Network policy.
Next steps
- Agent platform integration: identity, session mapping, and failure handling.
- Volumes, export, and restore: resize, rebind, and export a Volume.
- Expiration: stop or delete a Workspace automatically.
Agent platform integration
This page shows how to connect an Agent platform to Kibotos: where the Operator identity lives, how Agent sessions map to Workspaces and Volumes, and how the platform handles failures. The code uses the Go SDK. Programs in other languages make the same calls through the native API.
Running untrusted code
This page runs code you do not trust in a Workspace with no network access, a small resource limit, no Volume, and a time limit, then reads back a bounded result. The complete program is examples/go/untrusted-code.