API reference
Activities
Standalone Activities are User-owned, possibly reusable units of work. They
can be created directly or generated when an inline definition is supplied
while creating or updating a Pipeline. The current supported types are approval,
quiz, direct_loop, refinement_loop, and roundtable_loop. Approval
activities represent human approval, and quiz activities collect human quiz
responses. Direct, refinement, and roundtable loop activities can create
persisted runs. Refinement runs add reviewer approval and retry checkpoints
after local application. Approval and quiz execution are reserved for future
pipeline orchestration. Standalone Activity routes use X-User-ID and ignore
X-Project-ID. Pipeline creation creates internal Activity definitions with
the owning User. Nested Activity-run routes remain
Project-selected because execution occurs in a concrete Project.
Resource endpoints
| Method | Path | Purpose |
|---|---|---|
GET |
/api/v1/activities |
List activities. |
POST |
/api/v1/activities |
Create an activity. |
GET |
/api/v1/activities/{activity_id} |
Describe an activity. |
PATCH |
/api/v1/activities/{activity_id} |
Update an activity. |
DELETE |
/api/v1/activities/{activity_id} |
Delete an activity. |
GET |
/api/v1/activities/{activity_id}/changelog |
List activity history. |
Activity creation specifies the sole type discriminator. config does not
include a type field; its required shape is selected by the top-level type.
The activity type is immutable after creation, and PATCH validates replacement
configurations against the persisted activity type.
Activities also accept nullable top-level model_id and harness overrides.
Loop agents accept nullable model_id values. null clears an Activity
override. PipelineRun creation resolves an Activity model ID before Pipeline
and User candidates, and resolves an Activity Harness before Pipeline and User
candidates. The resolved values are frozen into the child ActivityRun
snapshot. An agent model ID takes precedence over the resolved Activity model
ID. For louie, run creation requires an effective model ID; Personas provide
instructions only.
Every Activity response includes top-level model_id and harness keys,
with null for an unset override. The type-specific response examples below
omit those repeated null fields unless an override is relevant.
Activity Definition Schema
POST /api/v1/activities accepts the following JSON properties. PATCH
accepts the mutable properties marked as optional; it rejects an empty request.
| Property | JSON type | Create | Update | Restrictions |
|---|---|---|---|---|
name |
String | Required | Optional | Contains 1 to 140 characters. Starts with a Unicode letter, number, or _. May contain spaces but not line breaks, tabs, ., +, ?, /, <, >, *, %, &, or :. |
description |
String | Required | Optional | May be empty. |
type |
String | Required | Not allowed | One of approval, quiz, direct_loop, refinement_loop, or roundtable_loop. Immutable after creation. |
config |
Object | Required | Optional | Shape is selected by type. Does not contain a nested type property. |
model_id |
String or null | Optional | Optional | A logical catalog model ID. null clears the override. |
harness |
Object or null | Optional | Optional | An empty louie v1 or codex_cli v1 configuration. null clears the override. |
status |
String | Not allowed | Optional | One of active, disabled, or archived. |
The following table describes the required config shape for every Activity
type.
| Activity type | Required config properties |
Restrictions |
|---|---|---|
approval |
None | config must be an empty object. |
quiz |
quiz |
quiz is an object containing the quiz definition. |
direct_loop |
stop_conditions, agents, output_contract |
Exactly one generator; no reviewer or aggregator. |
refinement_loop |
stop_conditions, agents, output_contract |
Exactly one generator, at least one reviewer, and no aggregator. |
roundtable_loop |
stop_conditions, agents, output_contract |
At least two generators, exactly one aggregator, and no reviewer. |
Every loop agent requires a persona_id and role. Its model_id is nullable.
Activity definition validation permits an absent model ID. For louie, run
creation rejects an agent when no effective model ID is available after
inheritance.
For codex_cli, the same inheritance order is frozen as requested_model in
the child run; API Linked Services are not selected for local Codex execution.
Activity runs
Pipeline scheduling creates persisted ActivityRuns for dependency-ready steps.
/api/v1/activities/{activity_id}/runs exposes those Pipeline-owned runs for
display and execution continuation; it cannot create standalone executions.
Each run response identifies its owning definition with activity_id; it does
not expose a legacy loop identifier.
List activities
GET /api/v1/activities returns ten activities after the optional
non-negative offset.
GET /api/v1/activities?offset=0
Example response (200 OK):
{
"items": [
{
"id": "activity-implementation",
"name": "ImplementRequestedChange",
"description": "Make and validate a focused code change.",
"status": "active",
"type": "direct_loop",
"config": {
"stop_conditions": {
"max_iterations": 3,
"max_tokens": 12000
},
"agents": [
{
"model_id": "gpt-5",
"persona_id": "software-engineer",
"role": "generator"
}
],
"output_contract": {
"type": "text",
"description": "A concise implementation summary and validation result."
}
},
"created_at": "2026-08-13T10:00:00Z",
"created_by": "user-123",
"updated_at": "2026-08-13T10:00:00Z",
"updated_by": "user-123"
}
],
"total": 1
}
Describe an activity
GET /api/v1/activities/{activity_id} returns the complete Activity,
including its type-specific configuration.
GET /api/v1/activities/activity-implementation
Example response (200 OK):
{
"id": "activity-implementation",
"name": "ImplementRequestedChange",
"description": "Make and validate a focused code change.",
"status": "active",
"type": "direct_loop",
"config": {
"stop_conditions": {
"max_iterations": 3,
"max_tokens": 12000
},
"agents": [
{
"model_id": "gpt-5",
"persona_id": "software-engineer",
"role": "generator"
}
],
"output_contract": {
"type": "text",
"description": "A concise implementation summary and validation result."
}
},
"created_at": "2026-08-13T10:00:00Z",
"created_by": "user-123",
"updated_at": "2026-08-13T10:00:00Z",
"updated_by": "user-123"
}
Create an activity
POST /api/v1/activities creates an active Activity for X-User-ID. Every
request needs a non-empty name, a description, a supported type, and a
configuration matching that type.
Direct loop
Use a direct loop for an executable single-agent task. max_iterations,
max_tokens, and timeout_seconds are optional individually, but at least one
stop condition and exactly one generator agent are required. Direct loops do
not allow reviewer or aggregator agents.
POST /api/v1/activities
Content-Type: application/json
{
"name": "ImplementRequestedChange",
"description": "Make and validate a focused code change.",
"type": "direct_loop",
"config": {
"stop_conditions": {
"max_iterations": 3,
"max_tokens": 12000
},
"agents": [
{
"model_id": "gpt-5",
"persona_id": "software-engineer",
"role": "generator"
}
],
"output_contract": {
"type": "text",
"description": "A concise implementation summary and validation result."
}
}
}
Example response (201 Created):
{
"id": "activity-implementation",
"name": "ImplementRequestedChange",
"description": "Make and validate a focused code change.",
"status": "active",
"type": "direct_loop",
"config": {
"stop_conditions": {
"max_iterations": 3,
"max_tokens": 12000
},
"agents": [
{
"model_id": "gpt-5",
"persona_id": "software-engineer",
"role": "generator"
}
],
"output_contract": {
"type": "text",
"description": "A concise implementation summary and validation result."
}
},
"created_at": "2026-08-13T10:00:00Z",
"created_by": "user-123",
"updated_at": "2026-08-13T10:00:00Z",
"updated_by": "user-123"
}
Roundtable loop
Use a roundtable loop for an executable discussion between specialised agents.
It requires at least two generator agents and exactly one aggregator agent.
Roundtable loops do not allow reviewer agents.
{
"name": "ReviewReleasePlan",
"description": "Reach a shared decision about release readiness.",
"type": "roundtable_loop",
"config": {
"stop_conditions": {
"max_iterations": 2
},
"agents": [
{
"model_id": "gpt-5",
"persona_id": "release-manager",
"role": "generator"
},
{
"model_id": "gpt-5",
"persona_id": "quality-engineer",
"role": "generator"
},
{
"model_id": "gpt-5",
"persona_id": "technical-lead",
"role": "aggregator"
}
],
"output_contract": {
"type": "json",
"description": "The release decision and its rationale.",
"schema": {
"type": "object",
"required": [
"decision",
"rationale"
],
"properties": {
"decision": {
"type": "string"
},
"rationale": {
"type": "string"
}
}
}
}
}
}
Example response (201 Created):
{
"id": "activity-release-review",
"name": "ReviewReleasePlan",
"description": "Reach a shared decision about release readiness.",
"status": "active",
"type": "roundtable_loop",
"config": {
"stop_conditions": {
"max_iterations": 2
},
"agents": [
{
"model_id": "gpt-5",
"persona_id": "release-manager",
"role": "generator"
},
{
"model_id": "gpt-5",
"persona_id": "quality-engineer",
"role": "generator"
},
{
"model_id": "gpt-5",
"persona_id": "technical-lead",
"role": "aggregator"
}
],
"output_contract": {
"type": "json",
"description": "The release decision and its rationale.",
"schema": {
"type": "object",
"required": [
"decision",
"rationale"
],
"properties": {
"decision": {
"type": "string"
},
"rationale": {
"type": "string"
}
}
}
}
},
"created_at": "2026-08-13T10:00:00Z",
"created_by": "user-123",
"updated_at": "2026-08-13T10:00:00Z",
"updated_by": "user-123"
}
Refinement loop
Use a refinement loop for an iterative improvement task. It requires exactly
one generator, at least one reviewer, and no aggregator. After applying a
generated plan, reviewers approve the changed files or request a new iteration
within the configured max_iterations limit.
{
"name": "RefineDocumentationDraft",
"description": "Improve a draft through review iterations.",
"type": "refinement_loop",
"config": {
"stop_conditions": {
"timeout_seconds": 900
},
"agents": [
{
"model_id": "gpt-5",
"persona_id": "technical-writer",
"role": "generator"
},
{
"model_id": "gpt-5",
"persona_id": "documentation-reviewer",
"role": "reviewer"
}
],
"output_contract": {
"type": "files",
"description": "An updated API guide.",
"files": [
"doc/public-api/overview.md"
]
}
}
}
Example response (201 Created):
{
"id": "activity-documentation-refinement",
"name": "RefineDocumentationDraft",
"description": "Improve a draft through review iterations.",
"status": "active",
"type": "refinement_loop",
"config": {
"stop_conditions": {
"timeout_seconds": 900
},
"agents": [
{
"model_id": "gpt-5",
"persona_id": "technical-writer",
"role": "generator"
},
{
"model_id": "gpt-5",
"persona_id": "documentation-reviewer",
"role": "reviewer"
}
],
"output_contract": {
"type": "files",
"description": "An updated API guide.",
"files": [
"doc/public-api/overview.md"
]
}
},
"created_at": "2026-08-13T10:00:00Z",
"created_by": "user-123",
"updated_at": "2026-08-13T10:00:00Z",
"updated_by": "user-123"
}
Approval
Use an approval activity for a human decision. Its configuration has no additional fields.
{
"name": "ApproveProductionRelease",
"description": "A release manager must approve deployment to production.",
"type": "approval",
"config": {
}
}
Example response (201 Created):
{
"id": "activity-production-approval",
"name": "ApproveProductionRelease",
"description": "A release manager must approve deployment to production.",
"status": "active",
"type": "approval",
"config": {
},
"created_at": "2026-08-13T10:00:00Z",
"created_by": "user-123",
"updated_at": "2026-08-13T10:00:00Z",
"updated_by": "user-123"
}
Quiz
Use a quiz activity to collect structured human answers. The quiz object is
application-defined and stored as supplied.
{
"name": "DeploymentReadinessQuiz",
"description": "Confirm operational readiness before deployment.",
"type": "quiz",
"config": {
"quiz": {
"questions": [
{
"id": "rollback-tested",
"prompt": "Has the rollback procedure been tested?",
"required": true
}
]
}
}
}
Example response (201 Created):
{
"id": "activity-deployment-quiz",
"name": "DeploymentReadinessQuiz",
"description": "Confirm operational readiness before deployment.",
"status": "active",
"type": "quiz",
"config": {
"quiz": {
"questions": [
{
"id": "rollback-tested",
"prompt": "Has the rollback procedure been tested?",
"required": true
}
]
}
},
"created_at": "2026-08-13T10:00:00Z",
"created_by": "user-123",
"updated_at": "2026-08-13T10:00:00Z",
"updated_by": "user-123"
}
Update an activity
PATCH /api/v1/activities/{activity_id} accepts one or more of name,
description, status, config, model_id, and harness. status must
be active, disabled, or archived. A replacement config must match the
persisted immutable Activity type and must not include type. Setting
model_id or harness to null clears that override.
PATCH /api/v1/activities/activity-implementation
Content-Type: application/json
{
"status": "disabled"
}
Example response (200 OK):
{
"id": "activity-implementation",
"name": "ImplementRequestedChange",
"description": "Make and validate a focused code change.",
"status": "disabled",
"type": "direct_loop",
"config": {
"stop_conditions": {
"max_iterations": 3,
"max_tokens": 12000
},
"agents": [
{
"model_id": "gpt-5",
"persona_id": "software-engineer",
"role": "generator"
}
],
"output_contract": {
"type": "text",
"description": "A concise implementation summary and validation result."
}
},
"created_at": "2026-08-13T10:00:00Z",
"created_by": "user-123",
"updated_at": "2026-08-13T10:15:00Z",
"updated_by": "user-123"
}
Delete an activity
DELETE /api/v1/activities/{activity_id} removes an Activity definition while
preserving its changelog entries.
DELETE /api/v1/activities/activity-implementation
Example response (200 OK):
{
"deleted": true
}
The endpoint returns 404 activity_not_found when the Activity does not exist
for the current User.
Loop activity runs
Only active activities with type: "direct_loop", type: "refinement_loop",
or type: "roundtable_loop" can run. Their config is captured when a run is
created, so later definition changes do not alter an in-progress run.
| Method | Path | Purpose |
|---|---|---|
GET |
/api/v1/activities/{activity_id}/runs |
List runs for a loop activity. |
GET |
/api/v1/activities/{activity_id}/runs/{run_id} |
Describe a run. |
POST |
/api/v1/activities/{activity_id}/runs/{run_id}/continue |
Submit one runtime or human checkpoint result. |
GET /api/v1/activities/{activity_id}/runs returns ten runs after the
optional non-negative offset.
GET /api/v1/activities/activity-implementation/runs?offset=0
X-Project-ID: project-acme
Example response (200 OK):
{
"items": [
{
"id": "run-implementation-001",
"activity_id": "activity-implementation",
"input": "Implement the requested change.",
"status": "in_progress",
"state": "awaiting_snapshot",
"next_action": "collect_snapshot",
"iteration": 1,
"token_revision": 1,
"continuation_token": "continuation-token",
"created_at": "2026-08-13T10:05:00Z",
"created_by": "user-123",
"updated_at": "2026-08-13T10:05:00Z",
"payload": {
}
}
],
"total": 1
}
Describe an activity run
GET /api/v1/activities/{activity_id}/runs/{run_id} returns one complete run
owned by the selected Activity.
GET /api/v1/activities/activity-implementation/runs/run-implementation-001
X-Project-ID: project-acme
Example response (200 OK):
{
"id": "run-implementation-001",
"activity_id": "activity-implementation",
"input": "Implement the requested change.",
"status": "in_progress",
"state": "awaiting_snapshot",
"next_action": "collect_snapshot",
"iteration": 1,
"token_revision": 1,
"continuation_token": "continuation-token",
"created_at": "2026-08-13T10:05:00Z",
"created_by": "user-123",
"updated_at": "2026-08-13T10:05:00Z",
"payload": {
}
}
Run creation accepts the existing request body:
{
"input": "Implement the requested change."
}
Example response (201 Created):
{
"id": "run-implementation-001",
"activity_id": "activity-implementation",
"input": "Implement the requested change.",
"status": "in_progress",
"state": "awaiting_snapshot",
"next_action": "collect_snapshot",
"iteration": 1,
"token_revision": 1,
"continuation_token": "continuation-token",
"created_at": "2026-08-13T10:05:00Z",
"created_by": "user-123",
"updated_at": "2026-08-13T10:05:00Z",
"payload": {
}
}
Continue an activity run
POST /api/v1/activities/{activity_id}/runs/{run_id}/continue submits one
idempotent CLI checkpoint result. Every request requires the current
continuation_token, a unique idempotency_key, and a result object whose
action matches the run’s next_action.
POST /api/v1/activities/activity-implementation/runs/run-implementation-001/continue
X-Project-ID: project-acme
Content-Type: application/json
{
"continuation_token": "continuation-token",
"idempotency_key": "checkpoint-001",
"result": {
"action": "collect_snapshot",
"repo_context": "Repository context for generation.",
"checkout_metadata": {
"checkout_path": "/workspace/project",
"source_commit_sha": "a1b2c3d4"
},
"constitution": "Repository contribution rules.",
"project_profile": {
"source_file_count": 24,
"approximate_source_chars": 12000,
"extension_counts": {
".py": 24
},
"top_level_entries": [
"src",
"tests"
],
"markers": {
"nuxt": false,
"package_json": false,
"fastapi": true,
"docker": false,
"tests": true
}
}
}
}
The endpoint returns the updated Activity run (200 OK). A run selected by a
Pipeline additionally requires its pipeline_run_id and active Pipeline
lease_token. The API rejects a missing, expired, or mismatched lease with
409 activity_run_invalid_transition before persisting a checkpoint result.
For run_harness, a successful commit-enabled Codex result must include a
non-empty commit_message. The API preserves it and returns it later as the
payload of commit_if_allowed; commit_mode=forbid does not require it. Every
successful Codex result must also include requested_model and actual_model.
The requested value must equal the model frozen in the Activity snapshot; both
values are persisted as runtime artifacts. The normalized success or failure
observation is subsequently returned in the ActivityRun payload, including:
schema_versionand the frozenharnesskind, version, and configuration;started_at,completed_at, andduration_ms;requested_model,actual_model, and nullablereasoning_effort;session_reference,usage,exit_code, anddiagnostics;materialized_skills, each with ID, normalized name, and version;source_commit_sha,final_commit_sha,final_diff, andchanged_files;final_response,completed, and nullableerror.
If the later commit checkpoint succeeds, final_commit_sha is updated to the
authorized commit SHA. Failed Harness turns retain any observations emitted
before failure rather than returning an empty payload.
These fields form the v1 common Harness observation envelope. Consumers should
discriminate variants through harness.kind; materialized_skills is currently
specific to the codex_cli variant. Older runtimes may omit the two
discriminants when submitting a checkpoint, but the API always derives and
publishes them from the frozen Activity snapshot.
Requests for inactive or non-executable activities return
409 activity_run_unavailable. An invalid or stale continuation token returns
409 activity_run_token_conflict.
Standalone Activity runs continue with their checkpoint token and idempotency
key. A child run selected by a Pipeline additionally requires its
pipeline_run_id and active Pipeline lease_token. The API rejects a missing,
expired, or mismatched lease with 409 activity_run_invalid_transition before it
persists the checkpoint result.
List activity changelog entries
GET /api/v1/activities/{activity_id}/changelog returns ten newest entries
after the optional non-negative offset.
GET /api/v1/activities/activity-implementation/changelog?offset=0
Example response (200 OK):
{
"items": [
{
"id": "activity-change-002",
"activity_id": "activity-implementation",
"change_type": "disabled",
"actor_id": "user-123",
"changed_at": "2026-08-13T10:15:00Z",
"diff": {
"status": {
"from": "active",
"to": "disabled"
}
},
"content": null
}
],
"total": 2
}
