Long-running jobs, start, poll, finish
Writing takes minutes, not seconds. Every slow tool returns an id at once; here's how to wait well.
Nothing in the API blocks. A tool that starts real work returns immediately with an id and status: "running"; you poll a matching status tool until it says done (or failed / error). This is true on every surface: an agent does it for you, the CLI has a status command per job, and over HTTP you call the status tool yourself.
The pairs
| Start | Poll | Typical time |
|---|---|---|
run_kernel with article_id | get_kernel_run_status (by kernel_job_id) | 1 to 4 min short piece, 15 to 20 min long-form |
run_kernel without article_id | get_kernel_endpoint_run (by run_id) | the same, for a run not bound to a post |
run_arena | get_arena_run | 3 to 10 min; pauses at awaiting_direction when the direction gate is on |
run_shred (async by default) | get_shred_job | seconds to minutes, by document length |
run_seer (async: true) | get_seer_run | 1 to 5 min; a news scan is a live web search |
run_enhance_pass | get_enhance_run | returns when the pass is done; get_enhance_run reads its record later |
run_collection | get_collection_run | 20 to 60 min (research, write, Enhance passes, publish, rebuild) |
plan_phantom (accept) | get_phantom_launch_status | ~10 min to a live site; first posts continue after |
create_phantom | get_phantom | 2 to 5 min to live; its configuration job continues after |
How to poll
Every 10 seconds is plenty; status calls are free and every poll also nudges the job forward if it's waiting on a slow step. A loop in any language:
let job;
do {
await new Promise((r) => setTimeout(r, 10_000));
job = await call("get_kernel_run_status", { kernel_job_id });
} while (job.status === "running");
Every run also comes back with two blocks worth reading: constraints (what it actually ran with) and, once it settles, verification (a short list of checks read back against those constraints). See KB-407.
get_kernel_run_status has one extra behavior worth knowing: when the run has just finished, the poll is what writes the article into your draft (applied: true). So poll at least once after it's done, or the draft won't have the text yet.
Locks
- One kernel run per post at a time, and one arena run per post at a time; starting a second of either returns
409. A hosted arena run is also refused while Auto-Pen owns the post. Different posts run in parallel, and a standalone arena run (noarticle_id) takes no lock at all. - Auto-Pen locks the post for its whole sequence; the editor shows "Auto-Pen is orchestrating this post."
- A run that finishes unlocks; a cancelled run unlocks; a failed run unlocks.
When a job never finishes
Jobs are durable: background sweeps advance running jobs every few minutes, so a one-shot finishes even if you stop polling. An onboarding or configuration job (phantom, collection, domain or mailer onboarding, phantom configuration) that makes no progress for six hours is closed as failed with a message saying so; anything it had already written (a draft, a site) is left in place. Start a new job to continue.
Rate limits on starting
Starting AI work (kernel, arena, collection and seer runs, shreds, Enhance passes, image generation) is limited to 5 per minute per key; onboarding a domain or collection, sitemap imports and site audits to 5 per hour. A refused start comes back as an error and nothing was started; wait and try again. Every call, polls included, also counts toward the key's own per-minute limit (1000 by default), which answers 429 with Retry-After. Details in KB-404.