Docs
BlogHomeStart building

AI Agent

Prompt the agent that builds and changes your app, and follow it live.


The AI agent writes and changes the project's code from natural-language prompts. A run is asynchronous: Run AI Agent answers at once with status: "init", then you poll Get Agent Status every 10–15 seconds until status is "done". Every finished run that changed files is saved as a new version and deployed to the project's development preview — never to the published site, which only changes when you publish. The agent checks its work in its own browser and reads the app's logs (development and live); when a user says "it doesn't work", it reads the error logs first.

#Run AI Agent

POST/api/v1/vcaas/projects/:projectId/agent/startapi-keyMetered, at least 3 credits

Send one prompt to the agent (or a multi-prompt batch). One run at a time per project. Once the running prompt's change is in the preview and the run is only finishing, the next prompt is accepted and waits: it starts as soon as that run ends. One prompt can wait; Stop Agent cancels the waiting one first.

A prompt is priced by the work the agent does: at least 3 credits, usually 3 to 50. A question that changes nothing is answered in seconds for 3 credits and creates no version. A run that fails without producing anything is refunded. The agent works up to about 40 minutes on one prompt, then wraps up and saves what it built; most prompts take a few minutes.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Body parameters

FieldTypeRequiredDescription
promptstringYes¹The instruction, up to 40,000 characters
tierstringNo"auto" (default), "cheap", "normal" or "expensive" — see Agent tiers. model and modelTier are accepted as aliases
inputFilesobject[]NoUp to 10 files for this prompt. Say in the prompt what each one is for ("use this as the logo")
inputFiles[].namestringYesFile name
inputFiles[].imageDescriptionstringNoWhat the file shows
inputFiles[].urlstringYesPublic URL, or the url returned by Upload File
multiPromptobjectNoRun a batch of prompts one after another, unattended. Omit for normal use
multiPrompt.promptsstring[]No²1–50 prompts, run in order
multiPrompt.letTotalumDecidebooleanNo²true = Totalum plans the prompts from prompt (the goal)

¹ Not needed when multiPrompt.prompts is given. ² Exactly one of prompts or letTotalumDecide: true.

fastMode and effort are accepted for compatibility and ignored (an ignored option is listed in data.warnings; the run still starts).

#Agent tiers

TierUse it for
"auto"The default. Totalum picks the tier for each prompt from the prompt, the recent conversation and the project: cheap for small edits and questions, normal for builds and features, expensive only when a fix keeps failing or you ask for the best
"cheap"The lowest price for real work: landing pages, redesigns, small apps, edits
"normal"Full apps and features, with more thinking
"expensive"The most capable agent, for complex apps and hard bugs. Uses the most credits

With "auto", the run's final message carries autoMode: true and modelUsed: the tier that ran ("cheap", "normal" or "expensive"), charged as that tier.

Response fields

FieldTypeDescription
data.projectIdstringProject id
data.statusstringAlways "init"
data.messagestringHow to follow the run
data.expectedMinutesnumber | undefinedEstimated minutes — an estimate, never a deadline
data.expectedFinishAtstring | undefinedStart + expectedMinutes (ISO 8601)
data.warningsstring[] | undefinedOptions that were ignored
data.runIdstring | undefinedThe run's id (single prompt)
data.multiPrompt.totalPromptsnumber | undefinedBatches only: number of prompts (absent while Totalum plans them)

Example request

curl -X POST \
  -H "api-key: tlm_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"Add a contact form that emails me every message"}' \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/start
Success · 200 OK
json
{
  "errors": null,
  "data": {
    "projectId": "barber-bookings",
    "status": "init",
    "message": "Process started. Estimated time: about 6 minutes. This is only an approximation… Fetch GET /api/v1/vcaas/projects/barber-bookings/agent/status every 10-15 seconds to track progress; the status there is the only reliable signal that the run has finished.",
    "expectedMinutes": 6,
    "expectedFinishAt": "2026-10-08T11:16:00.000Z",
    "runId": "run_01k6xc4n7d"
  }
}

Error codes

CodeHTTPMeaning
MISSING_PROMPT400prompt is missing
INVALID_MULTI_PROMPT400multiPrompt needs exactly one of prompts or letTotalumDecide: true
TOO_MANY_PROMPTS400More than 50 prompts
INVALID_PROMPT_ITEM400A prompt in prompts is empty
VALIDATION_ERROR400The prompt is over 40,000 characters, or a field has the wrong type
INSUFFICIENT_CREDITS402Your balance is below 1 credit
PROJECT_CREDIT_LIMIT_REACHED403The project's monthly development cap is reached — raise it with Update Credit Limits
AGENT_RUNNING409A prompt is already running and its change is not in the preview yet, or a prompt is already waiting (a batch answers 400 AGENT_ALREADY_RUNNING)
PROJECT_PAUSED_BY_USER409The project is paused — resume it first
OPERATION_IN_PROGRESS409A restore, import or other long operation holds the project
PROJECT_NOT_FOUND404No such project in your account
RATE_LIMITED429Your account sent more prompts this minute than its plan allows, or has the most prompts running at once (all projects together, see Limits) — retry after Retry-After seconds
A run that runs out of credits

If your balance reaches 0 during a run, the run stops: what it built is saved as a version, it ends with INSUFFICIENT_CREDITS, and you are charged only what it used. A run that crosses the project's development cap stops the same way with PROJECT_CREDIT_LIMIT_REACHED.

#Get Agent Status

GET/api/v1/vcaas/projects/:projectId/agent/statusapi-keyFree

Whether a prompt is running, and the messages of the current (or last) run. Poll every 10–15 seconds. When status becomes "done", read the preview URL again from Get Project.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Response fields

FieldTypeDescription
data.projectIdstringProject id
data.statusstring"init" (running), "done" (the last run finished) or "idle" (never prompted)
data.startedAtstring | nullStart of the current or last run
data.runIdstring | undefinedThe current or last run
data.realtimeConversationobject[]The run's messages, oldest first (the user's prompt is in Get Full Conversation)
data.realtimeConversation[].authorstring"user" or "agent"
data.realtimeConversation[].messagestringText
data.realtimeConversation[].messageTypestring"regular", "starting", "building" (a status note), "finished" (the run's summary), "error", "limit-reached" or "individual" (a one-off notice)
data.realtimeConversation[].createdAtstringISO 8601
data.realtimeConversation[].versionIdstring | undefinedThe version this message created
data.realtimeConversation[].secretKeysNeededobject | undefinedSecrets the app needs: { NAME: { isProvided, description } }. Add them with Create Secret
data.realtimeConversation[].filesobject[] | undefinedFiles attached to the message
data.realtimeConversation[].autoModeboolean | undefinedtrue on the final message of an auto run
data.realtimeConversation[].modelUsedstring | undefinedThe tier an auto run used
data.creditsSpentnumber | undefinedWhat the last run cost, once "done"
data.expectedMinutesnumber | nullEstimate of the running prompt
data.expectedFinishAtstring | nullStart + estimate
data.multiPromptobject | nullThe batch, when one exists: { status, totalPrompts, currentPromptIndex, prompts[{ order, prompt, status }], startedAt, updatedAt }. status: "executing", "paused", "done", "cancelled"

Example request

curl -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/status
Success · 200 OK
json
{
  "errors": null,
  "data": {
    "projectId": "barber-bookings",
    "status": "done",
    "startedAt": "2026-10-08T11:10:00.000Z",
    "realtimeConversation": [
      {
        "author": "agent",
        "message": "Added a contact form on /contact. Every message is saved and e-mailed to you. I sent a test message: saved, 200.",
        "messageType": "finished",
        "versionId": "ver_01k6xd2m8q",
        "createdAt": "2026-10-08T11:15:40.000Z",
        "autoMode": true,
        "modelUsed": "normal"
      }
    ],
    "creditsSpent": 7.4,
    "expectedMinutes": null,
    "expectedFinishAt": null,
    "multiPrompt": null,
    "runId": "run_01k6xc4n7d"
  }
}
Right after "done"

For a few seconds after a run ends, the preview may answer 503 with the header x-totalum-preview: updating while the new version goes live. Retry after the retry-after header; the preview never serves the previous version in that window.

#Get Agent Progress

GET/api/v1/vcaas/projects/:projectId/agent/progressapi-keyFree

A step-by-step view of the current run (or the last one): its stage, the files it changed, the builds and checks it ran. Use it to show a live "building" timeline. data is null before the first run.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Response fields

FieldTypeDescription
data.runIdstringThe run
data.statestring"queued", "provisioning", "running", "finishing", "done", "failed", "cancelled" or "incomplete"
data.stagestringWhere the run is: "queued", "sandbox", "starting", "thinking", "working", "build", "deploy", "fixing", "wrapping-up", "entry-page", "done", "failed", "cancelled", "incomplete"
data.startedAtstringStart time
data.finishedAtstring | undefinedEnd time
data.turnsnumberAgent turns so far
data.stepsobject[]Up to the 40 latest steps: { at, kind, file?, task?, ok?, added?, removed? }. kind: read, search, create, edit, delete, command, web, browser, integration, helper, plan, waiting; task (commands): build, test, install, database, check, save, other
data.totalStepsnumberAll steps of the run
data.filesobject[]Files changed: { path, change: "create" | "edit" | "delete", added, removed }
data.countsobject{ reads, searches, edits, commands, failedCommands }
data.buildobject | undefined{ ok } of the last build
data.testsobject | undefined{ runs, failed, failedFlows? }: the checks the agent ran on the pages it changed
data.versionIdstring | undefinedThe version the run saved
data.failurestring | undefinedWhy it failed: INSUFFICIENT_CREDITS, PROJECT_CREDIT_LIMIT_REACHED, DEPLOY_FAILED, RUN_TIMED_OUT, RUN_INTERRUPTED, CONTENT_BLOCKED, … or OTHER
data.creditsSpentnumber | undefinedWhat the run cost, once it ended
data.previewAtstring | undefinedWhen the preview last started serving this run's new build (reload your preview frame when it changes)

Example request

curl -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/progress
Success · 200 OK
json
{
  "errors": null,
  "data": {
    "runId": "run_01k6xc4n7d",
    "state": "running",
    "stage": "working",
    "startedAt": "2026-10-08T11:10:00.000Z",
    "turns": 12,
    "steps": [
      { "at": "2026-10-08T11:12:01.000Z", "kind": "edit", "file": "src/app/contact/page.tsx", "added": 64, "removed": 0 },
      { "at": "2026-10-08T11:12:30.000Z", "kind": "command", "task": "database", "ok": true }
    ],
    "totalSteps": 18,
    "files": [{ "path": "src/app/contact/page.tsx", "change": "create", "added": 64, "removed": 0 }],
    "counts": { "reads": 6, "searches": 2, "edits": 4, "commands": 3, "failedCommands": 0 }
  }
}

#Get Full Conversation

GET/api/v1/vcaas/projects/:projectId/agent/full-conversationapi-keyFree

The project's whole chat: every prompt and every agent message, oldest first (the latest 1,000).

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Response fields

FieldTypeDescription
data.projectIdstringProject id
data.conversationobject[]Messages with the fields of realtimeConversation[] in Get Agent Status

Example request

curl -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/full-conversation
Success · 200 OK
json
{
  "errors": null,
  "data": {
    "projectId": "barber-bookings",
    "conversation": [
      { "author": "user", "message": "Add a contact form that emails me every message", "messageType": "regular", "createdAt": "2026-10-08T11:10:00.000Z" },
      { "author": "agent", "message": "Added a contact form on /contact…", "messageType": "finished", "versionId": "ver_01k6xd2m8q", "createdAt": "2026-10-08T11:15:40.000Z" }
    ]
  }
}
End of Get Full ConversationNext endpointPOSTStop Agent

#Stop Agent

POST/api/v1/vcaas/projects/:projectId/agent/stopapi-keyFree

Stop the running prompt (and the rest of a multi-prompt batch). What the run built so far is kept; you pay only for what it used.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Response fields

FieldTypeDescription
data.messagestring"Agent process cancelled successfully"
data.pausedbooleanfalse

Example request

curl -X POST -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/stop
Success · 200 OK
json
{ "errors": null, "data": { "message": "Agent process cancelled successfully", "paused": false } }

Error codes

CodeHTTPMeaning
NO_PROCESS_RUNNING400No prompt is running

#Resume Multi-Prompt Batch

POST/api/v1/vcaas/projects/:projectId/agent/multi-prompt/resumeapi-keyThe prompts it runs

When a prompt of a batch fails, the batch pauses there (multiPrompt.status: "paused") because the next prompts build on it. This runs the failed prompt again, then the rest. Stop Agent cancels the batch instead.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Response fields

FieldTypeDescription
data.projectIdstringProject id
data.statusstring"init"
data.messagestringWhich prompt the batch continues from
data.multiPrompt.totalPromptsnumberPrompts in the batch

Example request

curl -X POST -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/multi-prompt/resume
Success · 200 OK
json
{ "errors": null, "data": { "projectId": "barber-bookings", "status": "init", "message": "Multi-prompt run continued from prompt 2.", "multiPrompt": { "totalPrompts": 3 } } }

Error codes

CodeHTTPMeaning
INVALID_AUTO_STATUS400No batch is paused
AGENT_RUNNING400A prompt is running
End of Resume Multi-Prompt BatchNext endpointPOSTClear Agent Context

#Clear Agent Context

POST/api/v1/vcaas/projects/:projectId/agent/clear-contextapi-keyFree

The next prompt starts with a fresh agent memory: it works from the project's current code and its change history, plus the messages sent after the clear. Restate anything from before that still matters.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Response fields

FieldTypeDescription
data.messagestring"Agent context cleared"
data.contextClearPendingbooleantrue until the next prompt starts

Example request

curl -X POST -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/clear-context
Success · 200 OK
json
{ "errors": null, "data": { "message": "Agent context cleared", "contextClearPending": true } }

Error codes

CodeHTTPMeaning
AGENT_RUNNING400A prompt is running
End of Clear Agent ContextNext endpointGETGet System Prompt

#Get System Prompt

GET/api/v1/vcaas/projects/:projectId/agent/system-promptapi-keyFree

The project's own instructions for the agent, added to every prompt (house style, rules, context).

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Response fields

FieldTypeDescription
data.systemPromptstring | nullThe instructions, or null
data.updatedAtstring | nullWhen they were last set

Example request

curl -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/system-prompt
Success · 200 OK
json
{ "errors": null, "data": { "systemPrompt": "Write every page in Spanish. Use our brand blue #1d4ed8.", "updatedAt": "2026-10-08T09:00:00.000Z" } }
End of Get System PromptNext endpointPUTSet System Prompt

#Set System Prompt

PUT/api/v1/vcaas/projects/:projectId/agent/system-promptapi-keyFree

Set or clear the project's instructions for the agent.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Body parameters

FieldTypeRequiredDescription
systemPromptstring | nullYesUp to 20,000 characters; null or "" clears it
systemPromptBase64stringNoThe same text as base64 (UTF-8), instead of systemPrompt

Response fields

FieldTypeDescription
data.systemPromptstring | nullThe saved instructions
data.updatedAtstringWhen they were saved

Example request

curl -X PUT \
  -H "api-key: tlm_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"systemPrompt":"Write every page in Spanish. Use our brand blue #1d4ed8."}' \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/system-prompt
Success · 200 OK
json
{ "errors": null, "data": { "systemPrompt": "Write every page in Spanish. Use our brand blue #1d4ed8.", "updatedAt": "2026-10-08T09:00:00.000Z" } }

Error codes

CodeHTTPMeaning
VALIDATION_ERROR400Not text, or over 20,000 characters
End of Set System PromptNext endpointGETList MCP Servers

#List MCP Servers

GET/api/v1/vcaas/projects/:projectId/agent/mcp-serversapi-keyFree

The MCP servers you added for the agent to use while it builds (header values are never returned).

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Response fields

FieldTypeDescription
data.serversobject[]The servers
data.servers[].idstringServer id
data.servers[].namestringName
data.servers[].transportstring"http" or "sse"
data.servers[].urlstringServer URL
data.servers[].headerNamesstring[]Names of the headers sent (values are write-only)
data.servers[].enabledbooleanWhether the agent uses it
data.servers[].verifiedAtstringWhen it last answered the handshake
data.servers[].toolsstring[]Its tools
data.servers[].createdAtstringWhen it was added

Example request

curl -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/mcp-servers
Success · 200 OK
json
{ "errors": null, "data": { "servers": [{ "id": "mcp_01k6xe", "name": "crm", "transport": "http", "url": "https://mcp.example.com/mcp", "headerNames": ["Authorization"], "enabled": true, "verifiedAt": "2026-10-08T09:00:00.000Z", "tools": ["find_customer"], "createdAt": "2026-10-08T09:00:00.000Z" }] } }

#Verify MCP Server

POST/api/v1/vcaas/projects/:projectId/agent/mcp-servers/verifyapi-keyFree

Check that a server answers the MCP handshake and lists at least one tool, without saving it.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Body parameters

FieldTypeRequiredDescription
mcpobjectYesThe server
mcp.namestringYes2–41 characters: lowercase letters, digits, _, -. Not totalum, playwright, figma, github or context7
mcp.transportstringYes"http" (streamable HTTP) or "sse"
mcp.urlstringYesA public https URL
mcp.headersobjectNoUp to 20 headers, e.g. { "Authorization": "Bearer …" }

Response fields

FieldTypeDescription
data.okbooleantrue
data.serverInfoobject{ name, version }
data.protocolVersionstringMCP protocol version
data.toolsobject[]{ name, description? }

Example request

curl -X POST \
  -H "api-key: tlm_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"mcp":{"name":"crm","transport":"http","url":"https://mcp.example.com/mcp","headers":{"Authorization":"Bearer abc"}}}' \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/mcp-servers/verify
Success · 200 OK
json
{ "errors": null, "data": { "ok": true, "serverInfo": { "name": "crm", "version": "1.0.0" }, "protocolVersion": "2025-06-18", "tools": [{ "name": "find_customer" }] } }

Error codes

CodeHTTPMeaning
MCP_VERIFY_FAILED400The handshake failed. errorDetails: { stage: "connect" | "initialize" | "tools_list" | "auth", message, authHint? }
VALIDATION_ERROR400A field is invalid or the name is reserved
End of Verify MCP ServerNext endpointPOSTAdd MCP Server

#Add MCP Server

POST/api/v1/vcaas/projects/:projectId/agent/mcp-serversapi-keyFree

Verify and add an MCP server for the agent (at most 10 per project). Same body as Verify MCP Server.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Body parameters

FieldTypeRequiredDescription
mcpobjectYes{ name, transport, url, headers? } as in Verify MCP Server

Response fields

FieldTypeDescription
data.serverobjectThe stored server, with the fields of servers[] in List MCP Servers

Example request

curl -X POST \
  -H "api-key: tlm_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"mcp":{"name":"crm","transport":"http","url":"https://mcp.example.com/mcp"}}' \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/mcp-servers
Success · 201 Created
json
{ "errors": null, "data": { "server": { "id": "mcp_01k6xe", "name": "crm", "transport": "http", "url": "https://mcp.example.com/mcp", "headerNames": [], "enabled": true, "verifiedAt": "2026-10-08T09:00:00.000Z", "tools": ["find_customer"], "createdAt": "2026-10-08T09:00:00.000Z" } } }

Error codes

CodeHTTPMeaning
MCP_LIMIT_REACHED400The project already has 10 servers
MCP_VERIFY_FAILED400The server did not pass the handshake
VALIDATION_ERROR400A field is invalid or the name is taken or reserved

#Update MCP Server

PATCH/api/v1/vcaas/projects/:projectId/agent/mcp-servers/:mcpIdapi-keyFree

Turn a server on or off, or change it (a changed configuration is verified again).

Path parameters

ParameterTypeDescription
projectIdstringThe project id
mcpIdstringThe server id

Body parameters

FieldTypeRequiredDescription
enabledbooleanNoUse it or not
mcpobjectNoA new { name, transport, url, headers? }

Response fields

FieldTypeDescription
data.serverobjectThe server after the change

Example request

curl -X PATCH \
  -H "api-key: tlm_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"enabled":false}' \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/mcp-servers/mcp_01k6xe
Success · 200 OK
json
{ "errors": null, "data": { "server": { "id": "mcp_01k6xe", "name": "crm", "transport": "http", "url": "https://mcp.example.com/mcp", "headerNames": [], "enabled": false, "verifiedAt": "2026-10-08T09:00:00.000Z", "tools": ["find_customer"], "createdAt": "2026-10-08T09:00:00.000Z" } } }

Error codes

CodeHTTPMeaning
MCP_SERVER_NOT_FOUND404No such server
MCP_VERIFY_FAILED400The new configuration did not pass the handshake

#Delete MCP Server

DELETE/api/v1/vcaas/projects/:projectId/agent/mcp-servers/:mcpIdapi-keyFree

Remove an MCP server.

Path parameters

ParameterTypeDescription
projectIdstringThe project id
mcpIdstringThe server id

Response fields

FieldTypeDescription
data.deletedbooleantrue

Example request

curl -X DELETE -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/mcp-servers/mcp_01k6xe
Success · 200 OK
json
{ "errors": null, "data": { "deleted": true } }

Error codes

CodeHTTPMeaning
MCP_SERVER_NOT_FOUND404No such server
End of Delete MCP Server Back to top