Modulify

Long-running work

Methods that answer before the work is done, and how to follow each one to the end.

On this page

Building a site, publishing it, taking a backup and restoring files take longer than one request should wait. The methods that start them answer as soon as the work is under way, and a second method reports how it is going. Your code calls the second one every few seconds until the work reaches an end.

Work Started by Followed with Finished when
A generation by the site agent send_message, create_site get_job state is succeeded, failed or cancelled
A publish publish_site, trigger_deploy_hook get_publish_status running is false
A storage archive create_storage_backup list_storage_backups The row reads ready or failed
A database archive create_database_backup list_database_backups The row reads ready or failed
A storage restore restore_storage_backup get_storage_restore_status active is false and Status is completed or failed

Wait a few seconds between calls. Each one spends from the token's per-minute budget, and asking more often does not make the work go faster. See Rate limits.

Generations

send_message hands a prompt to the site agent. When the site is free it starts at once and answers with queued: false and a jobId. When the agent is busy, the message joins the site's queue and the answer carries queued: true instead. create_site creates a site and starts its first build in one call, and answers with the new site and a jobId.

Follow a generation with get_job:

curl -X POST https://api.modulify.ai/v1/get_job \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{"projectId":"SITE_ID","jobId":"JOB_ID","cursor":0}'

The answer carries the state and the events the run has produced, such as text, file changes and tool calls. Send the cursor from each answer back on the next call and you receive only the events that are new. count is the number of events in this answer, and limit asks for up to 500 at a time.

state What it means What to do
running The agent is working Call again in a few seconds
stalled No heartbeat for over a minute Keep calling. It is not over: Modulify resumes or closes a run that has produced nothing for 15 minutes
succeeded The run ended normally Read the result. Check incomplete too
failed The run ended with an error error and errorCode say why
cancelled Somebody stopped it Nothing more will happen

Four details matter:

  • incomplete: true on a succeeded run means the agent stopped part way through the turn. incompleteReason says how. The run was billed and what it changed was kept, so send a follow-up asking it to continue rather than starting over.
  • Error code SC-6001 on a failed run means the workspace ran out of AI credits part way through. What it changed was kept and only what the balance covered was charged.
  • reset: true means the run was retried from the start. Throw away the events you collected and carry on from the new cursor.
  • Leaving out jobId reads the most recent generation of the site, which is how you find a run your code did not start.

cancel_job stops a running generation and keeps whatever the agent had already written. See Building with prompts for the whole conversation, including questions the agent asks and plans waiting for approval.

Publishes

publish_site starts a publish and answers once it has started. If a publish is already running, the answer carries pending: true and the deploymentId of that run instead of starting a second one, so treat it as success and follow that one.

Call get_publish_status until running is false, then read status:

status What it means
ready The new version is live
failed The publish failed. error has the reason, and get_publish_logs has the build output
cancelled The publish was stopped
null The site has never been published

Any other value, such as provisioning or deploying, is a step still in progress. get_publish_timeline shows each step with how long it took, and stop_publish abandons a publish that has not yet switched over. A publish started by trigger_deploy_hook is followed the same way.

Backups

create_storage_backup and create_database_backup answer as soon as the archive is reserved, with a row that reads pending. The archive itself is built later. Read list_storage_backups or list_database_backups until the row reads ready, or failed with the reason. Do not delete or move the files or rows it should hold until it is ready: anything removed before the archive reads it is left out.

create_backup and restore_backup work on the site's pages and components and answer when they are done.

Storage restores

restore_storage_backup is a two-step method, so nothing is overwritten by mistake. The first call, without confirm, changes nothing. It answers with a plan: how many files come back, how many are overwritten or deleted, and a confirm value. The second call sends the same arguments plus that confirm value and starts the restore.

The restore then runs in the background. Call get_storage_restore_status until active is false. Status reads pending, running, completed or failed, and counts such as FilesWritten and FilesFailed show progress. Only completed means the files are back. While a restore runs, the methods that change storage are refused and the ones that read it keep working.

Work that finishes in one call

Exports answer with everything at once. export_collection, export_site_analytics, export_site_crons, export_site_webhooks and export_deploy_hooks return their data in data, with nothing to follow.

Next