Projects

The projects namespace wraps the Projects REST resource — pipeline-driven workflows expanded from a versioned template into phases (tasks), steps (subtasks), and per-execution attempts, with versioned artifacts per phase.

For the object shapes, error codes, and the endpoints the SDK doesn't wrap yet (gate resolution, phase retrigger, artifact revert, edit sessions — all REST-only), see the wire-level reference. For the model, see Concepts → Project.

Auth. Every route in this namespace requires the control plane's x-catentio-session header, which this SDK never sends. Neither apiKey mode nor Bearer-session mode authenticates here. See SDKs → Auth: what actually works.

Namespace

catentio.projects — the surface, grouped by intent:

// Basics
catentio.projects.list()
catentio.projects.get(id)
catentio.projects.create(input)

// Attachments
catentio.projects.listAttachments(id)
catentio.projects.addAttachment(id, input)

// Drill-down
catentio.projects.listTasks(id)
catentio.projects.getTask(id, taskId)
catentio.projects.listSubtasks(id, taskId)
catentio.projects.getSubtask(id, taskId, subtaskId)
catentio.projects.listAttempts(id, subtaskId)
catentio.projects.listArtifacts(id)
catentio.projects.listEvents(id)

// Cost
catentio.projects.cost(id)

// Lifecycle
catentio.projects.pause(id)
catentio.projects.resume(id)
catentio.projects.abandon(id)
catentio.projects.runStep(id, input?)
catentio.projects.retrySubtask(id, subtaskId)

Method names are camelCase, but the payloads are the raw wire shapes with snake_case keys — list calls return { data: [...], meta: {...} }, single-object calls return the bare object.

Core methods

projects.list / projects.get

const page = await catentio.projects.list();
for (const p of page.data) {
  console.log(p.id, p.status, p.cost_total_usd);
}

const p = await catentio.projects.get('sustainable-urban-farming-explainer-3f9a1c2b');

Project ids are <title-slug>-<8 hex chars> — the title lowercased with non-alphanumerics collapsed to dashes (truncated to 48 chars), plus a random 8-character hex suffix (app/runtime/api.py, POST /v1/projects). status is one of planning, active, paused, completed, abandoned.

projects.create

Signature. catentio.projects.create(input, token?): Promise<Project>

Spawns a project and expands its template atomically — the response is a fully planned project.

const project = await catentio.projects.create({
  title: 'Sustainable urban farming explainer',
  workflow_slug: 'content',
  brief: 'A practical explainer on sustainable urban farming. Tone: hands-on.',
  cost_budget_usd: '5.00',        // optional, USD
  // workflow_version: 2,         // optional; omitted = latest active
});

title, workflow_slug, and brief (a plain string — not an object) are required. Ownership is forced from your credential server-side. An archived template or an unresolvable step binding fails with 400 before any row is created.

Drill-down

Project → tasks (phases) → subtasks (steps) → attempts:

const tasks = (await catentio.projects.listTasks(project.id)).data;
const research = tasks.find((t) => t.phase_slug === 'research');

const subtasks = (await catentio.projects.listSubtasks(project.id, research.id)).data;
const attempts = (await catentio.projects.listAttempts(project.id, subtasks[0].id)).data;

Task and subtask ids are UUIDs. Each attempt carries attempt_number, attempt_reason, status (pending / running / succeeded / failed), output, cost_usd, duration_ms, and — for agent steps — the child_run_id of the run it spawned.

Artifacts and events

const artifacts = (await catentio.projects.listArtifacts(project.id)).data;
const events = (await catentio.projects.listEvents(project.id)).data;

listArtifacts returns each phase's current pipeline-artifact version (the wire default current_only=true; the SDK doesn't expose the full-history flag — use the REST endpoint with ?current_only=false). Events are the project's full pipeline timeline.

Cost

const breakdown = await catentio.projects.cost(project.id);
console.log(breakdown.total_usd, breakdown.budget_usd, breakdown.budget_burn);

Amounts are USD decimal strings. See Cost & budgets.

Lifecycle

await catentio.projects.pause(pid);     // park at status=paused; autodrive skips it
await catentio.projects.resume(pid);    // crash-recover + back to active
await catentio.projects.abandon(pid);   // terminal
await catentio.projects.runStep(pid);   // advance exactly one eligible step
await catentio.projects.retrySubtask(pid, subtaskId); // queue a manual_retry attempt

retrySubtask rejects with a 409 when an attempt is already queued for the subtask. The SDK method doesn't take an addendum brief — pass ?addendum_brief= on the REST endpoint if you need one.

Not in the SDK (REST-only)

  • PATCH /v1/projects/{id} — edit title / cost_budget_usd.
  • POST …/subtasks/{sid}/resolve-gategate approval.
  • POST …/phases/{slug}/retrigger, POST …/phases/{slug}/revert-artifact, POST …/edit-sessions (+ /approve) — the backtrack surface.

Errors

FastAPI-shaped errors ({ detail: … }) surface with the HTTP status: 400 validation (missing fields, unknown/archived template, bad bindings), 404 unknown ids, 409 conflicts (queued retry, in-flight phase), 502 runtime unreachable.

Next

  • API → Projects — full wire-level reference including the REST-only actions.
  • Workflows — what projects expand from.
  • Runs — the sessions agent steps spawn.