Skip to Content
ProjectsOverview

Projects

A project is a named container for your code and runtime. You push a code tarball. Computalot stages and builds it durably. After the revision is published, jobs trigger runtime preparation.

Lifecycle

POST /api/v1/projects → create POST /api/v1/projects/:name/push → upload code tarball POST /api/v1/jobs → submit work POST /api/v1/projects/:name/init → optional: prepare currently available workers GET /api/v1/projects/:name/status → inspect published vs warm state

GET /api/v1/projects/:name/status is the top-level truth for the active revision. After a push publishes the current content hash, you can submit jobs with "project": "my-project" immediately. ready_for_jobs: true means that the active revision is already warm.

Example

# 1. Create curl -sS "$BASE_URL/api/v1/projects" \ -X POST -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "my-project", "remote_dir": "/root/my-project"}' # 2. Upload (raw binary, NOT multipart) tar czf code.tar.gz Dockerfile computalot.project.json script.py curl -sS "$BASE_URL/api/v1/projects/my-project/push" \ -X POST -H "Authorization: Bearer $TOKEN" --data-binary @code.tar.gz # 3. Submit work immediately if you want curl -sS "$BASE_URL/api/v1/jobs" \ -X POST -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"type": "structured_runner", "runner_command": ["python3", "script.py"], "payload": {"test": true}, "project": "my-project", "timeout_s": 120}' # 4. Optional: prepare currently available workers ahead of time curl -sS "$BASE_URL/api/v1/projects/my-project/init" \ -X POST -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" -d '{}'

How it works

Projects run as sandboxed OCI containers. Push a tarball with your code, a Dockerfile, and a computalot.project.json manifest. Computalot builds a container image and runs tasks in a sandboxed environment.

User-upload projects must use OCI with gVisor. Install dependencies and build assets in the Dockerfile. The API rejects host-style init commands, runtime services, and manifest validation commands. Declarative executable and file checks stay available in the manifest.

See Project Manifest for the manifest schema and Setup for the init flow.

If your project runs long ML or evaluation jobs: declare immutable model and dataset inputs in data_sources. Declare writable package and model caches in cache_mounts. Enable resumable checkpoints on the jobs themselves. Do not assume that runner-side downloads are reused automatically across tasks.

Updating code

Push a new tarball. The new revision is published immediately. Jobs on that revision can cold-start once while runtime preparation catches up. Use invalidate only to discard old prepared runtimes. Use init only to prepare currently available workers before a burst:

tar czf code.tar.gz . curl -sS "$BASE_URL/api/v1/projects/my-project/push" \ -X POST -H "Authorization: Bearer $TOKEN" --data-binary @code.tar.gz curl -sS "$BASE_URL/api/v1/projects/my-project/invalidate" \ -X POST -H "Authorization: Bearer $TOKEN" curl -sS "$BASE_URL/api/v1/projects/my-project/init" \ -X POST -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" -d '{}'

Use PUT /api/v1/projects/:name for metadata-only changes. Code always goes through /push. A controller-side OCI build returns 202 with a push_ref and status_url after the tarball and build record are durable. Poll that URL (or GET /api/v1/projects/:name/push) until the status is published or failed. The previous published revision stays active in the meantime. Push status includes bounded build diagnostics, and it can include a tarball_diff (added_files, removed_files, changed_files). A 409 includes the active push when another build or initialization is already in flight.

Readiness

  • can_accept_new_jobs: true means that the latest project revision is published. You can submit jobs now
  • ready_for_jobs: true means that the active revision is warm enough to admit work without a wait for runtime preparation
  • It does not prove that your application-level imports or credentials work. Use manifest validation checks for that
  • After a successful push, expect can_accept_new_jobs: true and often ready_for_jobs: false while the first job or an optional /init prepares the runtime
  • When status_message is not enough, use GET /api/v1/projects/:name/status/details. It adds sanitized diagnostics, log tails, and recovery guidance
  • After setup changes, run one small smoke job before you submit a large batch

Recovery

If setup fails or the runtime state becomes stale:

  1. Read GET /api/v1/projects/:name/status to see whether the active revision is ready
  2. Read GET /api/v1/projects/:name/status/details for sanitized diagnostics plus the recommended next step
  3. Correct your project. If necessary, push a new tarball. Then POST /api/v1/projects/:name/invalidate
  4. Submit a small job normally, or call POST /api/v1/projects/:name/init to prepare currently available workers

Endpoints

MethodPathDescription
POST/api/v1/projectsCreate a project
GET/api/v1/projectsList your projects
GET/api/v1/projects/:nameProject configuration + readiness
PUT/api/v1/projects/:nameUpdate project metadata (not code)
DELETE/api/v1/projects/:nameDelete project (blocked while jobs are active)
POST/api/v1/projects/:name/pushUpload code tarball
POST/api/v1/projects/:name/initPrepare currently available workers
PUT/api/v1/projects/:name/cancel-queuedCancel queued/planning jobs
POST/api/v1/projects/:name/invalidateMark for re-init
GET/api/v1/projects/:name/statusRead readiness
GET/api/v1/projects/:name/status/detailsDiagnostics for setup errors
PUT/api/v1/projects/:name/kv/:keyWrite project-scoped shared state
GET/api/v1/projects/:name/kv/:keyRead project-scoped shared state
DELETE/api/v1/projects/:name/kv/:keyDelete project-scoped shared state
GET/api/v1/projects/:name/streamSSE stream for all jobs in a project
Last updated on