stackbone build
stackbone buildruns inside a project folder and targets no installation, so it takes no--agent. Its--jsonpayload uses the standard envelope and it exits with the shared exit codes.
Compile the project into the workspace bundle: the directory your container
image serves the agent from. The running image carries no TypeScript and no
bundler, so build compiles every agent and workflow here, ahead of time.
Use build instead of stackbone package when
you already own the image and the deployment and want only the workspace bundle.
stackbone build # writes dist/workspace-bundle
stackbone build --out-dir out/bundle # anywhere else (relative to the project)| Flag | Type | Description |
|---|---|---|
--out-dir |
string | Where to write the bundle. Relative paths resolve against the project. Default: dist/workspace-bundle. |
What lands in the output directory:
dist/workspace-bundle/
.well-known/workspace.json # the manifest the runtime reads first
.well-known/config/v1/config-schema.json # your config.schema.ts, as JSON Schema
.well-known/workflow/v1/step.mjs # your compiled workflow steps
.well-known/workflow/v1/workflow.vm.js # the workflow bundle the VM runs
.well-known/workflow/v1/manifest.json # workflow ids, schemas, schedules
.well-known/workflow/v1/workflow-schemas.mjs # the live validators `/start` checks input with
.well-known/migrations/v1/ # your database migrations, copied verbatim
deep-agents/<name>/index.mjs # one prebuilt module per deep agentworkflow-schemas.mjs makes the deployed container reject a bad
POST /api/workflows/:name/start the same way
stackbone dev does, instead of starting the run and
failing somewhere inside it. The build compiles it from your
inputSchema / outputSchema exports with the same zod your workflows use, and
inlines your dependencies into it, so the file loads wherever the image runs.
Only the packages the runtime image already carries stay outside it.
When the build cannot inline a dependency (a native addon, a dynamic
require), it warns and emits the older shape instead, which re-imports your
packages at boot. That file loads on your laptop and may not load in the image.
Name the package in
build.external,
or move the schemas into a <name>.contract.ts
sibling that imports only zod. A container that cannot load the sidecar says so
in its log and falls back to the shapes recorded in the manifest: /start still
refuses a wrong-shaped payload with a 400, but your defaults, coercions and
.transform() calls do not run. Grep for that warning after a deploy.
config-schema.json is your config.schema.ts, converted to JSON Schema at
build time. The container has no TypeScript, so it reads this file to render the
config form in the dashboard and to validate every save. Write no
config.schema.ts and the build ships no file: config stays free-form.
Write one the build cannot convert and it warns instead of failing,
ships without the file, and the dashboard falls back to a raw JSON field with no
validation on save. See stackbone.config.
The build bundles each deep agent with its own dependencies inlined, except for
the packages that must stay a single copy per process. If one of your dependencies
cannot survive bundling, keep it out with build.external. See
Keeping a package out of the bundle.
You install anything you list there into your image by hand, and the
build prints the list so you know what to add.
If your agent has a database, the build copies .stackbone/migrations/ into the
bundle and the container applies it on the first boot, straight off disk. There
is nothing to download, so a container with no outbound network still comes up
with your tables in place. Applying is idempotent: a restart adds nothing, and a
boot against an already-migrated database logs that it found nothing to do. See
stackbone.database. A workspace
with no schema file, or with a migrations folder you never generated into, ships
no migrations and the boot says so.
If the project is linked (see stackbone link), the
manifest also records the agent and organization it was built for, so the
deployed container needs fewer environment variables.
Two workflows always come along, the same two stackbone dev gives you:
rag-ingest (it turns an uploaded document into searchable chunks) and
mapping-suggest (the dashboard's Auto-map runs it). The build writes the
platform version of each into .stackbone/managed-workflows/ unless you wrote
your own at workflows/rag-ingest.workflow.ts or
workflows/mapping-suggest.workflow.ts, in which case yours wins. Leave them
out and a document upload fails in the container while it still works on your
laptop.
A workspace with only agents builds fine, and so does one with only workflows. Anything you did not write stays out of the manifest, and the runtime skips it.
A workflow that fails to compile does not fail the build. It ships in the manifest marked degraded, carrying its own compile error, so the deployed box lists it with the reason instead of serving a shorter catalog that explains nothing. The build names each degraded workflow in its summary. An agent that fails to compile still fails the whole build.
The build also reads your sources for calls to the prompt catalog and records,
per agent and per workflow, which prompt keys that code reads. The inventory
travels in the manifest, so the deployment can show which keys your code asks
for. Two cases stop the build, because a prompt belongs to one owner and the
build will not guess which: a
stackbone.prompts call in a file that belongs to
no agent and no workflow, and a workflow file that reads the catalog while
exporting more than one workflow. Each message names the file and the line. Move
the call into the agent or workflow that owns the prompt, or split the file so
it exports one workflow named after it. A project with no TypeScript installed
gets a warning and a bundle with no inventory, not a failed build.
Copy the directory into your image (the runtime reads it from
/app/workspace) and deploy. The variables that image boots on are listed at
What you set on the deployed container.
Requirements: your project must have esbuild installed (for agents) and
@workflow/builders (for workflows, which every bundle has because of the two
above). The build resolves both from your own node_modules, so it builds the
bundle with the exact versions your agent runs.
JSON payload
{
"schema_version": 1,
"outDir": "/abs/path/dist/workspace-bundle",
"deepAgents": ["support", "billing"],
"workflows": ["onboarding", "rag-ingest", "mapping-suggest"],
"degradedWorkflows": [], // shipped but not runnable; each entry carries { name, message }
"migrations": true, // false when the workspace ships no migrations
"external": ["sharp"], // what you must install into the image yourself
"manifestVersion": 2,
"minImageVersion": "0.3.0", // the oldest runtime image that can read this manifest
}Exit codes: 0 ok, 1 an agent compile failed (the message names the
agent at fault; a failed workflow ships degraded instead, see above), a prompt
call could not be attributed to an agent or a workflow, or the build could not
resolve esbuild or @workflow/builders from your project.