Skip to main content

Project bundles

Experimental

A project bundle (spec.type: project) is the composite form of a bundle: instead of packaging a single resource, it packages an entire project together with everything it needs to run, in one document.

project here means the same project you already open from the UI — not a second, bundle-specific concept that happens to share the name. Installing a project bundle means creating a BasePeak.AI project.

What a project bundle carries​

The payload (spec.payload) is the project itself — the lead thread with Spec.Project = true — together with its tasks. Everything the project needs to run travels as a nested bundle under spec.includes:

Child typeCardinality
Agentexactly 1
Appat most 1
Knowledge set (knowledge)0 to any number
MCP connector (connector)0 to any number
Project (project)not allowed — a project bundle cannot nest another project

Install and uninstall order​

On install, children are created in this order:

connector → knowledge → agent → app → project → tasks.

On uninstall, the project's own thread is removed first, then its children come down app → agent → knowledge → connector. That order is not arbitrary — a knowledge set still attached to an agent cannot be removed. Removing the agent first frees the knowledge set it was using, so the knowledge child can then come down cleanly, followed by the connector nothing else in the tree depends on.

As part of installation, every installed knowledge set is attached to the installed agent — the same operation you would use to attach a standalone knowledge set to an existing agent by hand, just performed automatically as part of the install.

A failed install unwinds nothing​

If a child fails to install, nothing is rolled back. The parent installation is marked failed, the error names the child that failed, and every child that did land successfully stays on record. Cleaning up is a single call:

DELETE /api/bundles/installations/{id}

That removes the parent installation and every child that landed, in one step.

Updating is idempotent and resumable​

If a composite update stops partway through, re-running the same request finishes it: a child already at the target version is skipped rather than touched again. A partially applied update is not a dead end — the same request, sent again, catches the rest up.

One exception: if updating a child would trip that child's own eval gate, the entire update is refused before anything is written — not just for that one child, but for the whole composite. The error names the child. The way out is to update that child's own installation directly, where the gate runs normally, and then re-run the composite update — children already updated are skipped the second time around.

Orphaned tasks and children​

An update can drop a task or a child bundle that an earlier version created. Neither is deleted:

  • A task no longer declared by the update's payload keeps running as an ordinary task belonging to the project — it just loses the marker that identified it as this bundle's own. Nothing else about it changes.
  • A child bundle (an agent, a knowledge set, a connector) no longer declared in spec.includes is left completely alone, resource and installation record both, and is recorded as orphaned on the parent installation. Removing an agent or a knowledge set out from under a running project is not something an update is allowed to do on its own.

Either way, uninstalling the project then refuses while an orphaned task still exists on its thread: the project's own resource is the thread, and deleting the thread would delete every task still on it — including one this bundle no longer owns. The refusal names the task by its object name.

The way out is one of two choices:

  • Delete the task — an orphaned task is an ordinary task now, so DELETE /api/tasks/{id} removes it like any other. Once no orphaned task remains, uninstalling the project proceeds normally.
  • Keep the project — leave the installation in place. There is no deadline; the record survives a refused uninstall so it can be retried later, once you have decided what to do with the task.

An orphaned child bundle does not block an uninstall the way an orphaned task does — it is not a resource on the project's own thread. But the uninstall cascade does not touch it either: its resource and its own installation record are left standing exactly as the update that orphaned it left them. Removing one, if you want it gone, means uninstalling that child's own installation directly.

Export​

GET /api/assistants/{assistant_id}/projects/{project_id}/bundle

exports the agent, every standalone knowledge set attached to it, and every MCP connector the project or agent actually reference. An app child is included only when the caller names one, via ?app=<publicID>. That is deliberate, not an oversight: a project has no app association in the data model — there is no field the export could read one from — so the caller has to say which app is meant.

What is deliberately dropped​

A project bundle is meant for moving a working setup between instances, not for taking a copy of a live operation. The following is stripped on export (and, if it still shows up in a hand-written document, stripped again on install, with a warning):

DroppedWhy
Approver addresses (step.approval.approvers)a real caseworker's address does not belong on a stranger's instance
Env values (names travel)credentials; the name is the contract the target instance must satisfy
Project capabilities, task triggers webhook and emailthe webhook secret is plaintext in the spec, and two projects could otherwise answer the same inbound trigger
Task triggers poll, onSlackMessage, onDiscordMessageinstance-local trigger configuration
onTaskCompletenames a local workflow id; remapping it across instances is not yet supported
SharedTasksa list of local workflow names; this bundle installs its own tasks
Members, role grants, files, credentials, and anything under Statuslocal people, local state

What survives as a task trigger is only scheduled (schedule) and on demand (onDemand) — see Tasks.

Limits of this phase​

  • API only. There is no export or install dialog for project bundles in the UI yet.
  • Gating a composite update as a single unit (rather than per child) is not implemented.
  • onTaskComplete is dropped on export, not remapped across instances.