kortecxdocs
Context

Context bundles

Keep the brief, the spec and the brand guide in a named folder the runtime can read, and hand it to a run by name instead of pasting it every time.

A context bundle is a named folder of background reading. You put the documents in once — the brief, the spec, the brand guide, last quarter's notes — give the folder a name, and then hand that name to any run. The runtime reads the documents and gives them to the model before it starts work.

The point is that you stop pasting. The same grounding, the same wording, every time, for every person on the team who uses the name.

A bundle has two parts:

  • a handle — a three-part name like team/ctx/spec, in the shape namespace/collection/name
  • one or more items — each item is a file, with a short label you choose (design, brand, notes)

Every command on this page talks to a running runtime, so start one first — see Serving.

Make a bundle

Put a file in and name the folder

--file <label>=<path> uploads the file and attaches it under that label, in one command.

kx context add team/ctx/spec --file design=./design.md --description "the design doc"

Add more files by repeating the flag:

kx context add team/ctx/spec \
  --file design=./design.md \
  --file brand=./brand-guide.md \
  --description "design doc + brand guide"

add is an upsert — running it again at the same handle replaces what was there. It refuses to run with no items at all.

Hand it to a run

Pass the handle with --context. The flag is repeatable, so a run can carry several bundles.

kx invoke kx/recipes/react \
  --args '{"instruction":"summarize the design"}' \
  --context team/ctx/spec --wait

The runtime resolves the handle to its files, fetches each one, and puts it in front of the prompt as a labelled block. If one of the files cannot be fetched, the run fails rather than running on half the folder — the model never silently gets partial grounding.

This example needs a served model

kx/recipes/react is an agent loop, so it only exists once the runtime is serving a model, which needs a build with the inference feature turned on — it is not in the default build. See Local inference and Serving. --context itself is not gated: any app handle your runtime can run accepts it.

Attaching a folder that is already uploaded

If the bytes are already in the content store you can attach them by reference instead of re-uploading. kx content put prints the reference; --item <label>=<ref> binds it. The reference is the 64-character value after ref= — pass that value alone, without the ref= prefix.

kx content put ./notes.txt
ref=9f2c…  size=1284 deduplicated=false
kx context add team/ctx/notes --item notes=9f2c…

Look at what you have

kx context list
kx context get team/ctx/spec

list shows every bundle you authored. get shows one bundle's manifest — its items, their labels and their references.

Bundles are scoped to whoever made them. You see yours; you cannot see, or test for the existence of, anyone else's.

Export the contents to a folder on disk

--output writes every item's full body into a directory, plus a manifest.json listing the labels, filenames, references and byte sizes.

kx context get team/ctx/spec --output ./out

Filenames come from the item labels, cleaned up so they are safe to write (no path separators, no ..), with duplicates numbered name-2, name-3.

Change one item

Every per-item command needs to know which item you mean. Select it by its label with --item <label>, or by its position with --index <n> counting from 0. Pass one or the other, not both. If two items share a label the name is ambiguous and you have to use the index.

# Replace one item's body from a file:
kx context edit team/ctx/spec --item design --file ./design-v2.md

# Replace it and rename it at the same time:
kx context edit team/ctx/spec --index 0 --file ./design-v2.md --name design.md

# Drop one item:
kx context remove-item team/ctx/spec --item old-notes

# Re-set the description (the items are untouched):
kx context describe team/ctx/spec --description "the design doc, v2"

remove-item refuses to remove the last item — a bundle with nothing in it is not a thing. To get rid of the whole folder, unbind the handle:

kx context remove team/ctx/notes

Removing a bundle unbinds the name. The uploaded files themselves stay in the content store.

Two properties worth understanding

These two are the reason bundles behave predictably, and they are worth reading even if you never touch the internals.

Attaching a bundle changes the identity of the run

A run is identified by what went into it. The attached context is part of that. So the same prompt with different grounding is a different run — it gets its own identity and its own cache entry, and it will really execute rather than returning the earlier answer.

The other direction holds too. The same prompt with the same bundle re-derives the same identity, so re-invoking it is idempotent: you get the recorded run back instead of paying for the work twice.

In practice: swap team/ctx/spec for team/ctx/spec-v2 and you get a genuinely fresh answer, with no cache-busting trick needed.

Editing an item cannot rewrite history

The content store is immutable. A file's reference is derived from its bytes, so a reference never changes meaning — it will always point at exactly the bytes it pointed at when it was made.

That is why kx context edit does not modify anything in place. It uploads the new bytes, which produces a new reference, and re-points the item at it. The old reference is still perfectly valid.

The consequence you care about: a run that already captured the old grounding replays unchanged. Editing a bundle only affects future attachments. You can improve the spec on Tuesday without altering what Monday's run was actually given, or what it would produce if you replayed it.

The bundle index is a convenience, not a record

Bundle manifests live in a small sidecar file beside the runtime, deliberately off the record-keeping path. If that file is lost you lose the index of names and have to author the bundles again. It cannot corrupt or move any run's recorded identity.

Where to go next