Skip to main content

Deploys

A Deploy brings up a project's main sandbox, the one behind its Preview. The deploy agent reads the repository, writes the project settings and boots the sandbox. Start one with POST /api/projects/{projectId}/settings/agentic-deploy, answer the agent on the same route with userResponse, and follow it with GET /api/projects/{projectId}/deploy-messages.

MethodPathDescription
GET/api/projects/{projectId}/deploy-messagesRead the deploy conversation and the current deploy status.
GET/api/projects/{projectId}/deploys?page=&pageSize=List the project's Deploys, newest first: whether a member (user) or the platform (system) started each, its status, error and timestamps, with the total in meta.pagination.
POST/api/projects/{projectId}/settings/agentic-deployStart a deploy (empty JSON body) or continue the current one with userResponse. While the deploy agent works, the message waits Up next; while the sandbox builds, it joins the agent's first turn as instructions. Attachments ride along as multipart, where the message is called content.
POST/api/projects/{projectId}/settings/agentic-deploy/cancelStop the running deploy. Steers its agent had not taken go back to the top of Up next, which pauses; instructions sent while its sandbox built are discarded and listed.
PUT/api/projects/{projectId}/settings/agentic-deploy/modelPick the model the deploy agent runs on, as an encoded id such as anthropic:sonnet__medium. Refused while a deploy runs or waits for an answer.
GET/api/projects/{projectId}/settings/agentic-deploy/queueList the messages waiting Up next in the Deploy Chat, in the order they will be sent, and whether Up next is paused.
PATCH/api/projects/{projectId}/settings/agentic-deploy/queue/{queuedMessageId}Save an edit to your own queued Deploy Chat message, keeping its place in Up next. New files ride along as multipart.
DELETE/api/projects/{projectId}/settings/agentic-deploy/queue/{queuedMessageId}Delete a queued Deploy Chat message: your own, or any as a workspace owner or admin.
POST/api/projects/{projectId}/settings/agentic-deploy/queue/{queuedMessageId}/moveMove your own queued Deploy Chat message to another place in Up next.
POST/api/projects/{projectId}/settings/agentic-deploy/queue/{queuedMessageId}/sendSend your own queued Deploy Chat message now, ahead of the rest of Up next. Only while the deploy agent is idle; it resumes a paused Up next.
POST/api/projects/{projectId}/settings/agentic-deploy/queue/{queuedMessageId}/steerSend your own queued Deploy Chat message into the running deploy agent Turn as a steer. Claude deploys only; the message stays queued when nothing can take it.
POST/api/projects/{projectId}/settings/agentic-deploy/queue/resumeResume the Deploy Chat's paused Up next. Its top message is sent as soon as the deploy is idle.

Any member of the workspace can call these routes. A Deploy runs on the workspace's Credentials, and the deploy agent needs Anthropic or OpenAI ones. What a Deploy does in the web app, and what to do when one fails, is on Deploy your project.

Start a Deploy​

Send the request with an empty body. It starts a new Deploy and stops any Deploy already running. The web app's Redeploy sends the same request, but only when nothing runs or the agent is waiting on a Clarification.

curl -s -X POST https://app.kosuke.ai/api/projects/$PROJECT_ID/settings/agentic-deploy \
-H "Authorization: Bearer $KOSUKE_API_KEY"
{
"data": {
"delivery": "job",
"status": "creating_sandbox",
"deployJobId": "c7e2a9d4-5b1f-4e8a-9c3d-2f6b0a1e4d87"
}
}

To give a project's first Deploy instructions, send them with freshDeploy. This starts a new Deploy only on a project that has never deployed.

Body fieldMeaning
userResponseYour message to the deploy agent.
freshDeploytrue starts the first Deploy with userResponse as its instructions.
runningDeployJobIdThe deployJobId you saw running. See Answer the deploy agent.
curl -s https://app.kosuke.ai/api/projects/$PROJECT_ID/settings/agentic-deploy \
-H "Authorization: Bearer $KOSUKE_API_KEY" \
--json '{ "userResponse": "The API lives in apps/api and needs Redis.", "freshDeploy": true }'

To attach files, send the request as multipart/form-data. The message goes in a content field next to the files. A multipart request always needs content.

When the workspace has no usable Anthropic or OpenAI Credentials, the Deploy starts and then fails, and its error says so.

In the CLI, run kosuke deploy run <projectId>. Add --user-response "..." --fresh-deploy for instructions. To attach files, pass the message as --content "..." and add --attach <path> for each file.

Follow a Deploy​

Read the Deploy Chat and the current state.

curl -s https://app.kosuke.ai/api/projects/$PROJECT_ID/deploy-messages \
-H "Authorization: Bearer $KOSUKE_API_KEY"
{
"data": {
"status": "running_agent",
"deployJobId": "c7e2a9d4-5b1f-4e8a-9c3d-2f6b0a1e4d87",
"activeStreamId": "d9f1b3c5-7e2a-4d6b-8a0c-1e3f5a7b9c2d",
"lastStreamId": "d9f1b3c5-7e2a-4d6b-8a0c-1e3f5a7b9c2d",
"error": null,
"deploySandboxId": "i8k2m4p6r9t1v3x5z7b0d",
"deployModel": "anthropic:opus__xhigh",
"credentialOwners": {
"anthropic": { "kind": "organization", "needsReauth": false, "authMethod": "api_key" },
"openai": null,
"zai": null,
"moonshot": null
},
"messages": [
{
"id": "0e4c8a2f-6b1d-4f3e-9a5c-7d2b1e0f8a36",
"deployJobId": "c7e2a9d4-5b1f-4e8a-9c3d-2f6b0a1e4d87",
"role": "user",
"content": "deploy my project",
"attachments": [],
"author": {
"userId": "u8Rk2mQ4xT7vB1nP9sL3cW6yD0fH5jZa",
"name": "Sam Rivera",
"email": "sam@acme.com",
"imageUrl": null
},
"createdAt": "2026-09-30T10:02:11.000Z"
}
]
}
}

messages starts at the project's most recent Deploy a member started, and includes the Recovery Deploys Kosuke started after it. role is user, assistant or system.

statusMeaning
idleThe project has no Deploy yet.
creating_sandboxKosuke is creating a fresh sandbox.
starting_servicesThe services are starting, and Kosuke waits for them to be healthy.
running_agentThe deploy agent is setting up and checking the project.
updatingThe deploy agent is working on the live project.
awaiting_userThe deploy agent asked a Clarification. Answer it with userResponse.
warmingKosuke loads pages so the sandbox starts with a warm cache.
promotingKosuke runs final checks and makes the new sandbox live.
warming_poolKosuke prepares spare sandboxes so new sessions start fast.
deployedThe project is live.
failedThe Deploy failed. error says why.
cancelledThe Deploy was stopped: by a member, by a newer Deploy that replaced it, or by Kosuke when it could not run. When Kosuke stopped it, error says why.

To stream the running turn instead of polling, pass activeStreamId to the CLI. The session id argument is not read for a Deploy, so any value works there:

kosuke sessions watch <projectId> _ <activeStreamId> --type deploy

How to poll well is on Follow a turn. In the CLI, the read above is kosuke deploy messages <projectId>.

Answer the deploy agent​

When status is awaiting_user, the agent is waiting for you. Send your answer as userResponse.

curl -s https://app.kosuke.ai/api/projects/$PROJECT_ID/settings/agentic-deploy \
-H "Authorization: Bearer $KOSUKE_API_KEY" \
--json '{
"userResponse": "Use a Stripe test key. I added STRIPE_SECRET_KEY as a secret.",
"runningDeployJobId": "c7e2a9d4-5b1f-4e8a-9c3d-2f6b0a1e4d87"
}'
warning

Always send the message as userResponse. A JSON body without userResponse starts a new Deploy and stops the running one. That includes a body that carries the message in content, which only multipart requests read.

Pass the deployJobId you saw as runningDeployJobId. If someone stopped that Deploy before your message arrived, the call answers 409 JOB_STOPPED instead of starting over.

The same route takes any message for the deploy agent. What happens depends on where the Deploy is:

When you sendWhat happensAnswer
The agent is working (running_agent or updating)The message waits Up next and starts the next turn.201, delivery: "queued" with a queuedMessageId
The sandbox is still building (creating_sandbox, starting_services, warming or promoting)The message joins the agent's first turn as instructions.delivery: "steer"
The agent asked a Clarification (awaiting_user)Your answer continues the Deploy. It may carry files.delivery: "job"
The project is deployed and nothing runsThe agent starts a new turn on the live project.delivery: "job", status: "updating"
You stopped the project's first DeployThe Deploy resumes where it stopped.delivery: "job"
The project has no main sandbox (it never deployed, or its main sandbox was reclaimed) and nothing runsRefused with 409 NOT_DEPLOYED. Start a Deploy first.

In the CLI, run kosuke deploy run <projectId> --user-response "..." --running-deploy-job-id <deployJobId>.

Stop a Deploy​

Stop the running Deploy.

curl -s -X POST https://app.kosuke.ai/api/projects/$PROJECT_ID/settings/agentic-deploy/cancel \
-H "Authorization: Bearer $KOSUKE_API_KEY"
{ "data": { "cancelled": 1, "discardedInstructionIds": [], "discardedInstructions": [] } }

After a stop, messages you steered that the agent had not taken go back to the top of Up next, and Up next pauses. Instructions sent while the sandbox was building are dropped and returned in discardedInstructions. A stopped first Deploy keeps its sandbox, so your next message resumes it. With nothing running, cancelled is 0.

In the CLI, run kosuke deploy cancel <projectId>.

Pick the deploy model​

Choose the model the deploy agent runs on. Take a value from Models.

Body fieldMeaning
modelAn Anthropic or OpenAI model, such as openai:gpt-6.1-sol__high. The workspace needs Credentials for that provider.
curl -s -X PUT https://app.kosuke.ai/api/projects/$PROJECT_ID/settings/agentic-deploy/model \
-H "Authorization: Bearer $KOSUKE_API_KEY" \
--json '{ "model": "openai:gpt-6.1-sol__high" }'
{ "data": { "deployModel": "openai:gpt-6.1-sol__high" } }

Change the model between Deploys. While a Deploy runs or waits for an answer, the route answers 400. Switching to another provider starts the agent's next turn fresh, with the conversation so far handed over as text. When no model is saved, the deploy agent runs on anthropic:opus__xhigh, or on openai:gpt-6-astra__high when the workspace has only OpenAI Credentials. deployModel in the Deploy Chat response shows the current one. If the workspace loses the Credentials for the saved model's provider, pick another model before the next Deploy.

In the CLI, run kosuke deploy set-model <projectId> --model openai:gpt-6.1-sol__high.

Up next​

A message sent while the deploy agent works waits Up next, as in a chat session. Up next holds at most 20 messages. It pauses when a Deploy fails, is stopped, or ends on a Clarification.

curl -s https://app.kosuke.ai/api/projects/$PROJECT_ID/settings/agentic-deploy/queue \
-H "Authorization: Bearer $KOSUKE_API_KEY"
{
"data": {
"messages": [
{
"id": "4b7d1f3a-9e2c-4a5b-8d6f-0c1e2a3b4c5d",
"content": "Also seed the database with the demo fixtures.",
"position": 0,
"author": {
"userId": "u8Rk2mQ4xT7vB1nP9sL3cW6yD0fH5jZa",
"name": "Sam Rivera",
"email": "sam@acme.com",
"imageUrl": null
},
"attachments": [],
"context": {},
"editingBy": null,
"can": { "edit": true, "move": true, "steer": true, "delete": true },
"createdAt": "2026-09-30T10:06:40.000Z"
}
],
"paused": null
}
}

can says what you may do with each message. paused is null, or holds the reason and pausedAt.

RouteWhat it doesWho
PATCH /api/projects/{projectId}/settings/agentic-deploy/queue/{queuedMessageId}Saves new content and keeps its place. List the files to keep in retainedAttachmentIds. Answers 204.Its author
DELETE /api/projects/{projectId}/settings/agentic-deploy/queue/{queuedMessageId}Deletes the message. Answers 204.Its author, or a workspace owner or admin
POST /api/projects/{projectId}/settings/agentic-deploy/queue/{queuedMessageId}/moveMoves it to toIndex, counted from the top. Answers 204.Its author
POST /api/projects/{projectId}/settings/agentic-deploy/queue/{queuedMessageId}/steerSends it into the running turn as a steer. Works only when the deploy model is a Claude model.Its author
POST /api/projects/{projectId}/settings/agentic-deploy/queue/resumeResumes a paused Up next. Its top message goes as soon as no Deploy is running, or at once as the answer when the agent is waiting on a Clarification. Answers 204.Any member

A steer the running turn cannot take answers 409 STEER_UNAVAILABLE, and the message stays Up next.

In the CLI, the commands are kosuke deploy queue list, update, delete, move, send, steer and resume.

Read past Deploys​

List the project's Deploys, newest first.

Query parameterMeaning
pagePage number, from 1. Default 1.
pageSizeDeploys per page. Default 25. Values above 100 are read as 100.
curl -s "https://app.kosuke.ai/api/projects/$PROJECT_ID/deploys?pageSize=10" \
-H "Authorization: Bearer $KOSUKE_API_KEY"
{
"data": [
{
"id": "c7e2a9d4-5b1f-4e8a-9c3d-2f6b0a1e4d87",
"trigger": "user",
"status": "deployed",
"error": null,
"createdAt": "2026-09-30T10:02:10.000Z",
"startedAt": "2026-09-30T10:02:12.000Z",
"completedAt": "2026-09-30T10:09:51.000Z"
}
],
"meta": { "pagination": { "page": 1, "totalPages": 3, "pageSize": 10, "total": 24, "hasMore": true } }
}

trigger is user for a Deploy a member started and system for a Recovery Deploy. status takes the values in Follow a Deploy.

In the CLI, run kosuke deploy list <projectId> --page-size 10.

Errors​

StatusCodeWhen
400BAD_REQUESTThe message is empty, a file is refused, or the model is refused. A model change while a Deploy runs is refused too.
402CREDIT_LIMIT_REACHEDThe workspace is blocked on billing.
403FORBIDDENYou changed a queued message you did not write.
404NOT_FOUNDNo such project or queued message.
409DEPLOY_ACTIVEA Deploy is already running, or still stopping.
409JOB_STOPPEDThe Deploy you named in runningDeployJobId was stopped.
409NOT_DEPLOYEDThe project has no main sandbox, because it never deployed or its main sandbox was reclaimed. Start a Deploy.
409DEPLOY_RESUME_UNAVAILABLEThe stopped Deploy cannot resume. Start a new one.
409QUEUE_FULLUp next already holds 20 messages.
409STEER_UNAVAILABLENo turn can take the steer right now. The message stays Up next.
409JOB_STOPPED_TEXT_RETURNEDThe turn you steered into was stopped before it took the message. The message stays Up next.
409QUEUED_MESSAGE_CHANGEDThe message changed or was sent while you edited it. Read Up next again before you save.
409QUEUED_MESSAGE_GONEThe message already left Up next. It was sent or deleted.

The full list is in Responses and errors.

Next steps​