AI jobs and progress
Start a job and follow its progress. Generation, review, document import and diagrams share an asynchronous job system.
POST/ai/start
Start a job and return its identifier.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| type | string | required | generateSop | generateChart | reviewSop | applySuggestions | importDocument | generateFlow |
| params | object | required | Job-specific fields; see the table below. |
Example response
{ "jobId": "JOB_UUID" }Types and parameters
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| generateSop | { orgNodeId, prompt } | optional | Create a draft SOP owned by the selected organization node. |
| generateChart | { prompt } | optional | Generate organization-chart structure. |
| reviewSop | { sopId } | optional | Review an accessible version and return its source version and content identity. |
| applySuggestions | { sopId, review } | optional | Send the returned review object, including sourceVersionId and sourceContentHash. A stale review cannot authorize edits. |
| importDocument | { orgNodeId, documentBase64, mimeType } | optional | application/pdf | text/plain | text/markdown; base64 ≤ 50 MB. |
| generateFlow | { flowId, prompt } | optional | Append generated diagram content to an editable draft flow. |
Identifiers are UUIDs. Prompts accept 5–5,000 characters. The review object includes summary, improvements and optionally missingSteps, together with the reviewed content identity.
GET/ai/progress/:jobId
SSE progress for a job owned by your session. Messages contain a status field, not job.done event names.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| status | running | done | error | optional | Close the stream on completion or failure. |
| result | object | optional | Job-specific completion result. |
| error | string | optional | Failure message when the job fails. |
Example response
data: {"status":"running","stage":"generating","message":"Writing steps…","progress":40}
data: {"status":"done","stage":"done","message":"Done","progress":100,"result":{}}GET/ai/status/:jobId
Check status with the same session after a stream interruption. An expired job result may no longer be available.
Example response
{ "id":"JOB_UUID", "status":"running", "stage":"generating", "message":"Writing steps…", "progress":40 }Review example
// Run on the SOPFlow application origin with a signed-in session.
const response = await fetch("/ai/start", {
method: "POST", credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ type: "reviewSop", params: { sopId: "SOP_UUID" } }),
});
if (!response.ok) throw new Error(await response.text());
const { jobId } = await response.json();
const stream = new EventSource("/ai/progress/" + jobId, { withCredentials: true });
stream.onmessage = event => {
const job = JSON.parse(event.data);
console.log(job.stage, job.message, job.progress);
if (job.status === "done") { console.log(job.result); stream.close(); }
if (job.status === "error") { console.error(job.error); stream.close(); }
};
stream.onerror = () => {
stream.close();
// Check /ai/status/:jobId with the same session before offering a retry.
};