Workspace Runs
Run an uploaded workspace archive in a curated CrowNest environment, stream events, and read durable evidence.
Workspace Runs are CrowNest's archive-based execution surface for agent and repo workflows. Create a run, upload a gzipped tar archive, start execution, stream events, then read the Evidence Bundle after the sandbox is gone.
Use Workspace Runs when you want CrowNest to execute a checked-out project, test suite, build, or agent-produced archive without keeping a sandbox open manually.
The API key needs workspace_run:create, workspace_run:read, and
workspace_run:cancel for the run lifecycle. Runs that export artifacts also
need artifact:create and file:read.
Archive input
Upload an existing .tar.gz or .tgz archive. The public API does not pack a local
directory for you. For dirty checkout sync, use a client such as Crabbox or build the
archive before calling CrowNest.
The Workspace Run object
| Field | Type | Description |
|---|---|---|
id | string | Workspace Run ID, prefixed wsr_. |
projectId | string | Project that owns the run. |
status | string | awaiting_archive, archive_uploaded, starting, extracting, running, collecting, succeeded, failed, or canceled. |
command | string | Shell command executed after archive extraction. |
templateSlug | string | CrowNest template slug, such as python-node. |
templateVersionId | string | Frozen CrowNest template version used for placement. |
archive | object | Uploaded archive checksum, size, and upload timestamp. |
artifactIds | array | Artifacts collected from explicit artifact requests. |
artifactErrors | array | Per-path artifact collection errors. |
cleanupStatus | string | succeeded, failed, pending, or not_requested. |
evidenceAvailable | boolean | True only when the durable Evidence Bundle has been persisted and GET /evidence can read it. |
exitCode | integer | Command exit code after completion. |
failureClass | string | user_input, user_command, platform, or canceled when failed. |
failureReason | string | Stable failure reason, such as command_exit, timeout, or extraction_failed. |
sandboxId | string | Internal CrowNest sandbox ID when available. Provider IDs are never exposed. |
Create a run
POST /v1/workspace-runs — requires workspace_run:create. Accepts an
Idempotency-Key header.
| Field | Type | Required | Description |
|---|---|---|---|
command | string | Yes | Shell command to run after archive extraction. |
projectId | string | No | Project to create the run in. Defaults to the key's project context. |
template | string | No | CrowNest template slug. python-node is the launch template and default. |
templateVersionId | string | No | Specific CrowNest template version. |
sandboxId | string | No | Warm sandbox to reuse. Its template must match the run template. |
keepSandbox | boolean | No | Keep the sandbox after the run instead of cleaning it up. |
timeoutMs | integer | No | Command timeout in milliseconds. |
metadata | object | No | Small string labels for listing and evidence. |
sourceMetadata | object | No | Caller-supplied source labels, such as repo or commit. |
artifacts | array | No | Explicit relative paths to collect after the command finishes. |
Artifact collection also requires artifact:create and file:read.
curl -X POST https://api.crownest.dev/v1/workspace-runs \
-H "Authorization: Bearer $CROWNEST_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: repo-test-01" \
-d '{
"template": "python-node",
"command": "pnpm test",
"timeoutMs": 120000,
"artifacts": [{ "path": "coverage/lcov.info", "name": "coverage" }],
"sourceMetadata": { "repo": "acme/app", "commit": "abc123" }
}'Returns 201 with { "workspaceRun": { ... } } and status
awaiting_archive.
Upload an archive
For small archives, upload raw gzipped tar bytes directly:
PUT /v1/workspace-runs/{workspaceRunId}/archive — requires
workspace_run:create.
SHA=$(shasum -a 256 repo.tgz | awk '{print $1}')
SIZE=$(wc -c < repo.tgz | tr -d ' ')
curl -X PUT "https://api.crownest.dev/v1/workspace-runs/wsr_abc123/archive" \
-H "Authorization: Bearer $CROWNEST_API_KEY" \
-H "Content-Type: application/gzip" \
-H "x-crownest-archive-sha256: $SHA" \
-H "x-crownest-archive-size: $SIZE" \
--data-binary @repo.tgzReturns { "archive": { ... }, "workspaceRun": { ... } } with status
archive_uploaded.
Archive size
Direct uploads are capped at 8 MiB. Use staged archive transfer for repo archives up
to the returned transfer.maxSizeBytes.
Staged archive transfer
Use staged transfer for normal repo archives. CrowNest returns an upload target
with an explicit uploadId, maxSizeBytes, headers, and finalize step.
-
Create a transfer:
Terminal curl -X POST "https://api.crownest.dev/v1/workspace-runs/wsr_abc123/archive-transfer" \ -H "Authorization: Bearer $CROWNEST_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"sha256\": \"$SHA\", \"sizeBytes\": $SIZE }" -
Upload the archive to
transfer.uploadUrlwithtransfer.methodand the returnedtransfer.headers. Production transfer URLs may point directly at storage; do not attach the CrowNest bearer token to external upload URLs. -
Finalize:
Terminal curl -X POST "https://api.crownest.dev/v1/workspace-runs/wsr_abc123/archive/finalize" \ -H "Authorization: Bearer $CROWNEST_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"uploadId\": \"upl_abc123\", \"sha256\": \"$SHA\", \"sizeBytes\": $SIZE }"
Start execution
POST /v1/workspace-runs/{workspaceRunId}/start — requires
workspace_run:create. Accepts an Idempotency-Key header.
The run must already have an uploaded archive. Start transitions through
starting, extracting, and running, then finishes as succeeded,
failed, or canceled.
curl -X POST "https://api.crownest.dev/v1/workspace-runs/wsr_abc123/start" \
-H "Authorization: Bearer $CROWNEST_API_KEY"Read and stream events
GET /v1/workspace-runs/{workspaceRunId}/events — requires
workspace_run:read.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
afterSeq | integer | Return events after this sequence. |
limit | integer | Maximum events to return. |
stream | boolean | Set true for server-sent events. |
Stored event reads return { "data": [...], "hasMore": false, "nextSeq": 12 }. Streaming uses SSE and accepts afterSeq or the
standard Last-Event-ID header.
Event types are status, archive_progress, stdout, stderr,
artifact_collected, artifact_error, heartbeat, terminal, and
error.
curl -N "https://api.crownest.dev/v1/workspace-runs/wsr_abc123/events?stream=true" \
-H "Authorization: Bearer $CROWNEST_API_KEY"Status, list, cancel, and evidence
GET /v1/workspace-runs/{workspaceRunId} — requires
workspace_run:read.
GET /v1/workspace-runs — requires workspace_run:read.
POST /v1/workspace-runs/{workspaceRunId}/cancel — requires
workspace_run:cancel. Cancel is idempotent by state.
GET /v1/workspace-runs/{workspaceRunId}/evidence — requires
workspace_run:read.
The Evidence Bundle is durable run proof: command, template fields, archive checksum, timing, exit code, artifact IDs and errors, failure classification, cleanup status, metadata, and source metadata. It is available only after the run reaches a terminal state and evidence persistence succeeds.
Dashboard inspection
The signed-in dashboard includes a Workspace Runs inspection surface at
/workspace-runs. Use it after a run is created through the API, CLI, SDK, or
Crabbox to list runs, open a detail page, inspect Evidence Bundle fields, copy
Artifact IDs, and cancel active runs.
Next steps
- TypeScript SDK Workspace Runs — use the typed client and staged upload helper.
- CLI Workspace Runs — run an existing archive from the terminal.
- Capability matrix — compare supported surfaces.