Labels and annotations
Labels and annotations are your own key-value data on Workspaces, Volumes, Egresses, and Resolvers. This page shows how to set and change them, and how to find resources by label.
Overview
Each of these resources has two string-to-string maps where upper-layer callers store their own data. ctrl does not interpret them and does not use them for placement, authorization, or billing. The rules follow Kubernetes.
| LabelsA key-value pair that a caller attaches to an object such as a Workspace or a Volume. You can filter lists by label. | AnnotationsA key-value pair that a caller stores on an object such as a Workspace or a Volume. Kibotos only stores annotations; to filter lists, use labels. | |
|---|---|---|
| Purpose | Short values you filter by | Arbitrary values stored and returned as is |
| Filterable | Yes | No |
Warning
Labels and annotations are not secrets. Any caller that can read the resource, and kibo, can see them. Do not put tokens, keys, or values derived from them in labels or annotations, and do not use a label for access control.
Setting at creation
Pass --label and --annotation when you create a Workspace, Volume, Egress, or Resolver:
kibo workspace create --template "$template_id" --label team=infra --annotation note='nightly build'
kibo volume create --capacity 10G --label team=infra
kibo egress create --address proxy.example.com:1080 --label team=infra
kibo resolver create --https https://dns.example.com/dns-query --label team=infra- Both flags are repeatable and take the form
key=value. - The value is split at the first
=only, so an annotation value can contain=.key=means an empty value. - Giving the same key twice is rejected before the request is sent.
- Labels and annotations are written in the same transaction as the create command and are part of its idempotency check. Replaying the same command ID with different data is a conflict.
Filtering by label
Pass -l or --label to kibo workspace list, volume list, egress list, or resolver list:
kibo workspace list --label team=infra --label tier=gold
kibo volume list --include-deleted -l team=infra
kibo egress list -l team=infra- Each entry requires the label to exist with a byte-for-byte equal value. All entries must match.
- Annotations are not used for filtering.
- On Workspace and Volume lists, you can combine label filters with the other filters and
--include-deleted. Deleted Workspaces and Volumes still return both maps and can match. - The next-page hint from
kibocarries the same filter.
Updating
set replaces the labels or annotations of a resource, and clear removes all of them:
kibo workspace labels set "$workspace_id" team=infra tier=gold
kibo workspace labels clear "$workspace_id"
kibo workspace annotations set "$workspace_id" note='nightly build'
kibo volume labels set "$volume_id" team=infra
kibo volume annotations clear "$volume_id"
kibo egress labels set "$egress_id" team=infra
kibo resolver labels set "$resolver_id" team=infraWarning
An update replaces the whole map. Keys you leave out are deleted; nothing is merged. To add one label, pass all existing labels together with the new one.
- When the content is the same as the current content, the update succeeds and the revision does not change.
- A deleted Workspace or Volume does not accept updates and returns
failed_precondition.
Revisions
Every update carries an expected revision. If it does not match the current revision, the update returns aborted and the content does not change.
- Labels and annotations each have their own revision. They do not affect each other or any other revision of the resource, such as the resources revision and the binding revision of a Workspace.
- Without
--expected-revision,kiboreads the current revision first and then submits. If the revision changed by the time of submission, the command returns a conflict and does not retry automatically. - When a script needs to replay an update, pass
--command-idand--expected-revisiontogether.
Output of kibo
| Command | What it shows |
|---|---|
get | Two items, Labels and Annotations, with one entry per line. Empty items are omitted. Annotation values with non-printable characters are shown in quotes |
get --wide | Also both revisions, in the Revisions section |
list | No labels by default. --wide adds a LABELS column, and -L key shows one label as its own column, with - in rows without it |
--json | The fields labels, annotations, labels_revision, and annotations_revision. Empty maps are omitted |
For which list commands take --wide and -L, and how -L names its column, see Common command flags.
Keys and values
| Labels | Annotations | |
|---|---|---|
| key | [prefix/]name: the prefix is a lowercase DNS subdomain of at most 253 characters; the name is 1–63 characters, starts and ends with a letter or digit, and may contain -, _, and . in between | Same as labels |
| value | Empty, or at most 63 characters following the same character rules as the name | Any UTF-8 without U+0000 |
| Total limit (bytes of all keys and values) | 65536 | 262144 |
| Revision | labels_revision | annotations_revision |
- A request that breaks the character rules or a limit returns
invalid_argumentand names the field and key. - Prefixes of
kibotos.appand its subdomains are reserved for Kibotos's own components. ctrl does not reject requests that use them. For example, the E2B-compatible gateway usese2b.kibotos.app/.
With the API
| Operation | API |
|---|---|
| Set at creation | The labels and annotations of CreateWorkspace, CreateVolume, CreateEgress, and CreateResolver |
| Filter by label | The label_selector of ListWorkspaces, ListVolumes, ListEgresses, and ListResolvers. On the first two it combines with include_deleted |
| Update | Update…Labels and Update…Annotations on each resource, for example UpdateWorkspaceLabels. An empty map deletes everything |
- When paging, the
label_selectormust be the same as in the request that returned the cursor. - The capability names are
workspace.labels,workspace.annotations,volume.labels, andvolume.annotations. Older servers silently drop unknown fields, so confirm that the capability name exists before writing. When it is missing,kibofails with exit code14instead of creating a resource without the fields. - Egresses and Resolvers have no capability names of their own for labels and annotations. They come with
workspace.network_policy.egress.socks5andworkspace.network_policy.resolver, the capabilities of the resources themselves.
Next steps
- Creating and listing: other parameters of
createand list filters. - kibo CLI: command IDs and replaying a command safely.
- Egress and DNS and Resolvers: the other resources that carry labels.
Lifecycle
You stop, start, and delete a Workspace with the Go SDK, the E2B SDK, or kibo. In the Go examples, settleOptions resends a command while ctrl says it is still executing, as in examples/go/quickstart. This page also covers force stops, checking what a stop or deletion released, recovering a FAILED Workspace, and the cases where the server stops or restarts a Workspace on its own.
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.