JobsService
Hand over work that is bigger than one call: analyze ten thousand rows, move forty thousand files, write to a hundred records. You submit a plan and read receipts; the rows themselves stay on our side and never travel back to you. A job outlives the request that started it, so it is submitted once and read back later.
Every call is a POST to https://api.atmon.ai/automaton.v1.JobsService/<Call> with a JSON body, and authenticates with Authorization: Bearer <your project key>. Field names in JSON are lowerCamelCase, so the field written tool_slug below is toolSlug on the wire. How to call the API has the whole convention.
Calls
| Call | Request | Response | Summary |
|---|---|---|---|
SubmitJob | SubmitJobRequest | SubmitJobResponse | |
GetJob | GetJobRequest | GetJobResponse | |
ListJobs | ListJobsRequest | ListJobsResponse | |
ListJobEvents | ListJobEventsRequest | ListJobEventsResponse | ListJobEvents reads one job's log in sequence order, each entry naming the chain that caused it. |
AnswerAsk | AnswerAskRequest | AnswerAskResponse | AnswerAsk is how a person answers a question a job addressed to them. |
ListAsks | ListAsksRequest | ListAsksResponse | ListAsks reads the questions a project has addressed to people: what is outstanding, who holds it, what was answered and by whom. |
GetAsk | GetAskRequest | GetAskResponse | GetAsk reads one of them. |
SubmitJob
Request SubmitJobRequest, response SubmitJobResponse.
POST /automaton.v1.JobsService/SubmitJob HTTP/1.1
Host: api.atmon.ai
Authorization: Bearer amk_your_project_key
Content-Type: application/json
{
"programJson": "{}",
"idempotencyKey": "...",
"mode": "...",
"simulateFirst": true
}
The response:
{
"job": {
"id": "...",
"status": "JOB_STATUS_PENDING_PLAN_APPROVAL",
"programJson": "{}",
"programHash": "...",
"estimate": { ... },
"planApprovalId": "...",
"park": { ... },
"stepReceipts": [{ ... }],
"receipt": { ... },
"lastError": "...",
"createdAt": "2026-01-31T09:15:00Z",
"updatedAt": "2026-01-31T09:15:00Z",
"finishedAt": "2026-01-31T09:15:00Z",
"pendingAsk": { ... },
"saga": { ... },
"mode": "...",
"simulatedFrom": "...",
"skillSlug": "..."
}
}
GetJob
Request GetJobRequest, response GetJobResponse.
POST /automaton.v1.JobsService/GetJob HTTP/1.1
Host: api.atmon.ai
Authorization: Bearer amk_your_project_key
Content-Type: application/json
{
"id": "..."
}
The response:
{
"job": {
"id": "...",
"status": "JOB_STATUS_PENDING_PLAN_APPROVAL",
"programJson": "{}",
"programHash": "...",
"estimate": { ... },
"planApprovalId": "...",
"park": { ... },
"stepReceipts": [{ ... }],
"receipt": { ... },
"lastError": "...",
"createdAt": "2026-01-31T09:15:00Z",
"updatedAt": "2026-01-31T09:15:00Z",
"finishedAt": "2026-01-31T09:15:00Z",
"pendingAsk": { ... },
"saga": { ... },
"mode": "...",
"simulatedFrom": "...",
"skillSlug": "..."
},
"simulation": {
"id": "...",
"status": "JOB_STATUS_PENDING_PLAN_APPROVAL",
"programJson": "{}",
"programHash": "...",
"estimate": { ... },
"planApprovalId": "...",
"park": { ... },
"stepReceipts": [{ ... }],
"receipt": { ... },
"lastError": "...",
"createdAt": "2026-01-31T09:15:00Z",
"updatedAt": "2026-01-31T09:15:00Z",
"finishedAt": "2026-01-31T09:15:00Z",
"pendingAsk": { ... },
"saga": { ... },
"mode": "...",
"simulatedFrom": "...",
"skillSlug": "..."
}
}
ListJobs
Request ListJobsRequest, response ListJobsResponse.
POST /automaton.v1.JobsService/ListJobs HTTP/1.1
Host: api.atmon.ai
Authorization: Bearer amk_your_project_key
Content-Type: application/json
{
"status": "JOB_STATUS_PENDING_PLAN_APPROVAL",
"pageSize": 0,
"pageToken": "...",
"mode": "...",
"skillSlug": "..."
}
The response:
{
"jobs": [{
"id": "...",
"status": "JOB_STATUS_PENDING_PLAN_APPROVAL",
"programJson": "{}",
"programHash": "...",
"estimate": { ... },
"planApprovalId": "...",
"park": { ... },
"stepReceipts": [{ ... }],
"receipt": { ... },
"lastError": "...",
"createdAt": "2026-01-31T09:15:00Z",
"updatedAt": "2026-01-31T09:15:00Z",
"finishedAt": "2026-01-31T09:15:00Z",
"pendingAsk": { ... },
"saga": { ... },
"mode": "...",
"simulatedFrom": "...",
"skillSlug": "..."
}],
"nextPageToken": "..."
}
ListJobEvents
ListJobEvents reads one job's log in sequence order, each entry naming the chain that caused it. It is the attribution surface over the engine, and a job of another project reads as missing.
Request ListJobEventsRequest, response ListJobEventsResponse.
POST /automaton.v1.JobsService/ListJobEvents HTTP/1.1
Host: api.atmon.ai
Authorization: Bearer amk_your_project_key
Content-Type: application/json
{
"jobId": "..."
}
The response:
{
"events": [{
"jobId": "...",
"seq": 0,
"type": "...",
"stepId": "...",
"at": "2026-01-31T09:15:00Z",
"payloadJson": "{}",
"principalChain": ["..."]
}]
}
AnswerAsk
AnswerAsk is how a person answers a question a job addressed to them.
Request AnswerAskRequest, response AnswerAskResponse.
POST /automaton.v1.JobsService/AnswerAsk HTTP/1.1
Host: api.atmon.ai
Authorization: Bearer amk_your_project_key
Content-Type: application/json
{
"jobId": "...",
"requestId": "...",
"principalId": "...",
"continuation": "...",
"overridesJson": "{}",
"note": "...",
"deliveryId": "..."
}
The response:
{
"job": {
"id": "...",
"status": "JOB_STATUS_PENDING_PLAN_APPROVAL",
"programJson": "{}",
"programHash": "...",
"estimate": { ... },
"planApprovalId": "...",
"park": { ... },
"stepReceipts": [{ ... }],
"receipt": { ... },
"lastError": "...",
"createdAt": "2026-01-31T09:15:00Z",
"updatedAt": "2026-01-31T09:15:00Z",
"finishedAt": "2026-01-31T09:15:00Z",
"pendingAsk": { ... },
"saga": { ... },
"mode": "...",
"simulatedFrom": "...",
"skillSlug": "..."
}
}
ListAsks
ListAsks reads the questions a project has addressed to people: what is outstanding, who holds it, what was answered and by whom. Until it existed an ask was visible only by listing jobs and reading pending_ask, so an answered one was visible only by reading a log.
Request ListAsksRequest, response ListAsksResponse.
POST /automaton.v1.JobsService/ListAsks HTTP/1.1
Host: api.atmon.ai
Authorization: Bearer amk_your_project_key
Content-Type: application/json
{
"state": "ASK_STATE_PENDING",
"principalId": "...",
"jobId": "...",
"standingProgramId": "...",
"pageSize": 0,
"pageToken": "..."
}
The response:
{
"asks": [{
"pointId": "...",
"principalId": "...",
"hopIndex": 0,
"deliveredPrincipals": ["..."],
"toolSlug": "...",
"entityId": "...",
"toolCallId": "...",
"deliveredAt": "2026-01-31T09:15:00Z",
"deadlineAt": "2026-01-31T09:15:00Z",
"approvalId": "...",
"exhausted": true,
"jobId": "...",
"requestId": "...",
"state": "ASK_STATE_PENDING",
"question": "...",
"answerSchemaJson": "{}",
"continuations": ["..."],
"escalation": [{ ... }],
"askedAt": "2026-01-31T09:15:00Z",
"decision": { ... },
"stepId": "...",
"delivery": "..."
}],
"nextPageToken": "..."
}
GetAsk
GetAsk reads one of them.
Request GetAskRequest, response GetAskResponse.
POST /automaton.v1.JobsService/GetAsk HTTP/1.1
Host: api.atmon.ai
Authorization: Bearer amk_your_project_key
Content-Type: application/json
{
"jobId": "...",
"requestId": "..."
}
The response:
{
"ask": {
"pointId": "...",
"principalId": "...",
"hopIndex": 0,
"deliveredPrincipals": ["..."],
"toolSlug": "...",
"entityId": "...",
"toolCallId": "...",
"deliveredAt": "2026-01-31T09:15:00Z",
"deadlineAt": "2026-01-31T09:15:00Z",
"approvalId": "...",
"exhausted": true,
"jobId": "...",
"requestId": "...",
"state": "ASK_STATE_PENDING",
"question": "...",
"answerSchemaJson": "{}",
"continuations": ["..."],
"escalation": [{ ... }],
"askedAt": "2026-01-31T09:15:00Z",
"decision": { ... },
"stepId": "...",
"delivery": "..."
}
}
Messages
AnswerAskRequest
AnswerAskRequest lands one principal's answer to an outstanding ask. The answer selects a continuation the program declared and nothing else, and the answering key comes from the authenticated request: an approval ask resolves its approval through policy, and policy refuses a key without the approver role and the very key whose plan parked there.
| Field | Type | # | Notes |
|---|---|---|---|
job_id | string | 1 | |
request_id | string | 2 | request_id is optional. Naming it refuses an answer to a question the job has already moved past. |
principal_id | string | 3 | principal_id is the contact answering. An answer from anyone the ask has not reached is refused. |
continuation | string | 4 | continuation is one of proceed, retry-with, skip, or abort, and it must be one the judgment point declared. |
overrides_json | string | 5 | overrides_json carries a retry-with answer's changes, in the shape the point's answer schema declares. |
note | string | 6 | |
delivery_id | string | 210 | delivery_id names the webhook delivery this answer came back on, taken from the X-Automaton-Delivery-Id header of the ask_raised delivery. It is recorded as the answer's surface and authorizes nothing: the answer is authorized by the presented key either way. Empty for an answer given directly, which records the surface as "api". Delivery is at-least-once and answering is at-most-once, so the same question can arrive twice. A second answer to an answered ask is refused, recorded on the job's log as an answer-refused entry, and moves nothing. |
AnswerAskResponse
| Field | Type | # | Notes |
|---|---|---|---|
job | Job | 1 |
Ask
Ask is one outstanding question addressed to a named principal: who holds it now, the channel call that carried it, and when the engine stops waiting. An ask is a judgment point whose handler is a principal, not a separate mechanism, so what releases the job is still an answer naming one of the continuations the program declared.
The question text is not repeated here. It is on the pending judgment this ask belongs to, and a job carries one of each.
| Field | Type | # | Notes |
|---|---|---|---|
point_id | string | 1 | point_id is the judgment point the program declared, or "approval" when the ask is an approval gate the engine addressed to a person. |
principal_id | string | 2 | principal_id is the contact who holds the question now, which is the last hop the escalation ladder reached. |
hop_index | int32 | 3 | |
delivered_principals | repeated string | 4 | delivered_principals lists every contact the ask has reached, in hop order. Only these may answer it. |
tool_slug | string | 5 | |
entity_id | string | 6 | |
tool_call_id | string | 7 | tool_call_id is the ledger row the delivery was recorded as. |
delivered_at | google.protobuf.Timestamp | 8 | |
deadline_at | google.protobuf.Timestamp | 9 | deadline_at is when this hop's timeout fires. Unset means the ask waits without a deadline, which is what an approval ask does: no clock approves. |
approval_id | string | 10 | approval_id is set when the ask is a policy approval gate. Answering it resolves that approval through policy, where separation of duty is enforced. |
exhausted | bool | 11 | exhausted reports an escalation ladder that ran out with no declared default: nothing more is delivered and a person owns the question. |
job_id | string | 200 | job_id and request_id are how an answer names this ask: AnswerAsk takes both, and request_id refuses an answer to a question the job has moved past. They and the fields below them are the read surface's (ListAsks, GetAsk); a job's pending_ask leaves them empty, because a job read carries the question on park.judgment beside it. |
request_id | string | 201 | |
state | AskState | 202 | |
question | string | 203 | question and answer_schema_json are the judgment point's own, repeated here because a reader of an ask list has no judgment beside it to read them from. A form is generated from the schema, so a program declaring a new question shape needs no client change. |
answer_schema_json | string | 204 | |
continuations | repeated string | 205 | continuations is what an answer may pick: proceed, retry-with, skip, abort, and only the ones the point declared. |
escalation | repeated AskHopSpec | 206 | escalation is the declared ladder, whether or not it has been climbed, so a reader sees who this question reaches next and when. |
asked_at | google.protobuf.Timestamp | 207 | |
decision | AskDecision | 208 | decision is set once the ask was settled, by a person or by the clock. |
step_id | string | 209 | |
delivery | string | 210 | delivery is what became of this ask's publication onto the registered ask endpoints: "delivered", "pending", or "dead-letter". Empty means nothing was published to an endpoint, which is what a project that registered none reads on every ask, and the channel call in tool_call_id is a separate surface either way. It is here so an ask that defaulted on its timeout with nobody reached reads differently from one a person did not answer. |
AskDecision
AskDecision is the recorded answer to an ask: which continuation it picked, who picked it, and where the answer arrived from. Every surface records the same entry, which is what keeps replay from a recorded answer a pure function.
| Field | Type | # | Notes |
|---|---|---|---|
continuation | string | 1 | continuation is one of proceed, retry-with, skip, or abort. |
principal_id | string | 2 | principal_id is the contact addressed that answered. Empty when the clock decided. |
key_id | string | 3 | key_id is the API key that presented the answer. A contact id is an address and authorizes nobody; the key is what was authorized, so an audit of "who decided" reads both. Empty when the clock decided, and on answers recorded before this field existed. |
surface | string | 4 | surface is where the answer arrived from: "api" for an answer presented on AnswerAsk, "timeout" for the declared default the clock applied. |
note | string | 5 | |
hop_index | int32 | 6 | hop_index is the rung that answered, so "who decided" answers with the hop as well as the principal. |
at | google.protobuf.Timestamp | 7 |
AskHopSpec
AskHopSpec is one rung of a declared escalation ladder: who it reaches and how long they hold the question. The arguments template is not on the wire, since it is the delivery's business and not the reader's.
| Field | Type | # | Notes |
|---|---|---|---|
principal_id | string | 1 | |
tool_slug | string | 2 | |
timeout_seconds | int32 | 3 |
CompensationReceipt
CompensationReceipt is one act step's unwind, told honestly: how many of its committed rows the saga tried to undo, how many it undid, and the ones it could not, named. A stranded row is an external resource with no owner until a human takes it, which is why the count is never rounded away.
| Field | Type | # | Notes |
|---|---|---|---|
attempted | int32 | 1 | |
compensated | int32 | 2 | |
stranded | int32 | 3 | |
stranded_row_keys | repeated string | 4 |
Cost
Cost is what a step or a job spent. Model spend is metered in micro-USD (one millionth of a dollar) because one row's map call costs less than a cent, and action_count is external effects, the unit an action budget is written in.
| Field | Type | # | Notes |
|---|---|---|---|
model_micro_usd | int64 | 1 | |
action_count | int32 | 2 | |
discarded_model_micro_usd | int64 | 3 | discarded_model_micro_usd is the part of model_micro_usd that prices work an attempt paid for and could not report: a step killed between checkpoints spends money nothing durable records, and the resumed attempt charges the rows it re-does twice rather than leaving that spend off the receipt. It is therefore a bound, not a measurement, and model_micro_usd is an upper bound of what the project paid whenever it is above zero. |
CostEstimate
CostEstimate is the projection a human approves.
| Field | Type | # | Notes |
|---|---|---|---|
rows | int32 | 1 | |
model_micro_usd | int64 | 2 | |
action_count | int32 | 3 | |
effects | repeated ProjectedEffect | 4 |
GetAskRequest
GetAskRequest reads one ask. request_id is optional: naming no request reads the ask the job is waiting on now.
| Field | Type | # | Notes |
|---|---|---|---|
job_id | string | 1 | |
request_id | string | 2 |
GetAskResponse
| Field | Type | # | Notes |
|---|---|---|---|
ask | Ask | 1 |
GetJobRequest
| Field | Type | # | Notes |
|---|---|---|---|
id | string | 1 |
GetJobResponse
| Field | Type | # | Notes |
|---|---|---|---|
job | Job | 1 | |
simulation | Job | 94 | simulation is the job named by job.simulated_from, receipts included, so an approver reads the measured diff beside the projected estimate in one call. Absent when the plan was not simulated first. |
Job
Job is the folded state of one job's event log.
| Field | Type | # | Notes |
|---|---|---|---|
id | string | 1 | |
status | JobStatus | 2 | |
program_json | string | 3 | the plan verbatim, as submitted |
program_hash | string | 4 | |
estimate | CostEstimate | 5 | |
plan_approval_id | string | 6 | set when the plan parked before step one |
park | Park | 7 | set while status is PARKED |
step_receipts | repeated StepReceipt | 8 | |
receipt | Receipt | 9 | the fold; complete is false until every step reported |
last_error | string | 10 | |
created_at | google.protobuf.Timestamp | 11 | |
updated_at | google.protobuf.Timestamp | 12 | |
finished_at | google.protobuf.Timestamp | 13 | |
pending_ask | Ask | 60 | pending_ask is the question this job owes an answer to, when it parked on one. It mirrors park.judgment's ask so a reader learns who was asked without walking into the park. |
saga | SagaState | 70 | saga is what became of the effects this job landed, set once an unwind has compensated anything. A job parked with stranded rows names them here. |
mode | string | 92 | mode is what this submission was allowed to touch: "run" (the default), "simulate" (act steps projected instead of called) or "shadow" (every external call answered from recorded state). Every receipt of a measuring run carries simulated, and a simulated receipt never folds into a real one. |
simulated_from | string | 93 | simulated_from names the simulation this plan was measured by, set when the submission asked to be simulated first. Its receipts are the diff an approver reads beside the estimate. |
skill_slug | string | 80 | skill_slug names the promoted skill whose call submitted this job, empty when a caller submitted the program directly. Everything else about the job is the same either way. |
JobEvent
JobEvent is one entry of a job's append-only log, which is the audit answer to "what did this job do". Rows never cross this surface: payload_json is the entry's own payload (a checkpoint, a receipt, a park reason), and the rows a step read or wrote live in collections.
| Field | Type | # | Notes |
|---|---|---|---|
job_id | string | 1 | |
seq | int64 | 2 | seq is dense and 1-based per job, so the order of the page is the order the job walked and a gap means a lost write. |
type | string | 3 | type is the log's closed vocabulary: submitted, plan-approved, step-started, checkpoint, step-completed, parked, judgment-requested, ask-delivered, judgment-recorded, answer-refused, compensation-applied, resumed, finished. |
step_id | string | 4 | |
at | google.protobuf.Timestamp | 5 | |
payload_json | string | 6 | |
principal_chain | repeated string | 140 | Who caused this entry, oldest cause first: "key:<id>", "skill:<slug>", "job:<id>". It is an audit record and never an authorization input. |
ListAsksRequest
ListAsksRequest pages one project's asks. Every filter narrows; an empty one does not. Asks of another project are absent rather than forbidden, which is the read rule every surface here follows.
| Field | Type | # | Notes |
|---|---|---|---|
state | AskState | 1 | state lists only asks in one state. Unspecified lists every state. |
principal_id | string | 2 | principal_id lists only the asks this contact has been reached by, which is the inbox read: a question delivered to somebody else is not theirs to answer and is not theirs to see in this list. |
job_id | string | 3 | |
standing_program_id | string | 4 | standing_program_id lists the asks raised by the jobs a standing program fired. |
page_size | int32 | 5 | |
page_token | string | 6 |
ListAsksResponse
| Field | Type | # | Notes |
|---|---|---|---|
asks | repeated Ask | 1 | asks, newest question first. |
next_page_token | string | 2 |
ListJobEventsRequest
| Field | Type | # | Notes |
|---|---|---|---|
job_id | string | 1 |
ListJobEventsResponse
| Field | Type | # | Notes |
|---|---|---|---|
events | repeated JobEvent | 1 | The whole log in sequence order. A job's log is bounded by its own steps and checkpoints, so the page is the log rather than a window on it. |
ListJobsRequest
| Field | Type | # | Notes |
|---|---|---|---|
status | JobStatus | 1 | unspecified lists every status |
page_size | int32 | 2 | |
page_token | string | 3 | |
mode | string | 95 | mode narrows the page to one submission mode. Empty lists every mode. |
skill_slug | string | 80 | skill_slug lists only the jobs one skill submitted, which is how "what has this skill done" is answered from the log. Empty lists every job. |
ListJobsResponse
| Field | Type | # | Notes |
|---|---|---|---|
jobs | repeated Job | 1 | |
next_page_token | string | 2 |
Park
Park is why a running job stopped. approval_id names an approval in the policy queue, judgment the question a job waits on; both are set when the approval was delivered as an ask.
| Field | Type | # | Notes |
|---|---|---|---|
step_id | string | 1 | |
reason | string | 2 | |
approval_id | string | 3 | |
judgment | PendingJudgment | 4 | |
at | google.protobuf.Timestamp | 5 |
PendingJudgment
PendingJudgment is a declared pause waiting on an answer. It carries the question and the continuations the program declared, never rows: a decision sees counts and reasons.
| Field | Type | # | Notes |
|---|---|---|---|
id | string | 1 | |
step_id | string | 2 | |
handler | string | 3 | model, human, or principal |
question | string | 4 | |
answer_schema_json | string | 5 | |
continuations | repeated string | 6 | proceed, retry-with, skip, or abort |
breaches | repeated string | 7 | the declared bounds this step exceeded, if any |
asked_at | google.protobuf.Timestamp | 8 |
ProjectedEffect
ProjectedEffect is one line of what a plan would do to the world, derived statically from the program before anything executes. access_class is the catalog's blast-radius class, and a destructive one is what makes a plan park for approval.
| Field | Type | # | Notes |
|---|---|---|---|
step_id | string | 1 | |
tool_slug | string | 2 | |
access_class | string | 3 | |
count | int32 | 4 | |
compensation | bool | 70 | compensation marks an effect that only happens on an unwind: the inverse the step declared. An approver reads the forward effects as what the plan intends and these as what undoing it would do. |
Receipt
Receipt is the failure-honesty contract: how many rows went in, how many came out, what was dropped and why, whether the producer saw everything it was supposed to, and what it cost. A job receipt is the fold of its step receipts, so it cannot claim more than the steps proved.
| Field | Type | # | Notes |
|---|---|---|---|
rows_in | int32 | 1 | rows_in and rows_out are the plan's "in" and "out". They are spelled out here because "in" is a keyword in some generated languages. |
rows_out | int32 | 2 | |
dropped | map<string, int32> | 3 | dropped counts rows by reason. Nothing disappears without a reason. |
complete | bool | 4 | complete is false when any producer declared a shortfall, and it is the AND over folded receipts. |
cost | Cost | 5 | |
simulated | bool | 6 | simulated marks a receipt produced without touching the world. A simulated receipt is never folded into a real one. |
SagaState
SagaState is the same account for the whole job: what its act steps landed and still stands, what was undone, and what is stranded. It is derived from the act steps' outcome collections and the log's compensation entries, and it is unset for a job that never unwound anything.
| Field | Type | # | Notes |
|---|---|---|---|
committed | int32 | 1 | committed is how many landed rows still stand, including the rows of act steps that declared no inverse. |
compensated | int32 | 2 | |
stranded | int32 | 3 | |
stranded_row_keys | repeated string | 4 |
StepReceipt
StepReceipt is one step's receipt plus what it produced.
| Field | Type | # | Notes |
|---|---|---|---|
step_id | string | 1 | |
primitive | string | 2 | collect, map, reduce, act, or files |
receipt | Receipt | 3 | |
output_handle | string | 4 | the collection this step produced, if any |
reused | bool | 5 | reused reports that the step did not run: an identical fingerprint already had an output collection, so the content address was served instead. |
attempt | int32 | 6 | |
started_at | google.protobuf.Timestamp | 7 | |
finished_at | google.protobuf.Timestamp | 8 | |
compensation | CompensationReceipt | 70 | compensation is the saga's account of this step's unwind, unset when nothing was unwound. It sits beside the receipt rather than inside it: rows in and rows out count what the step did, and undoing an effect does not touch a row twice. |
SubmitJobRequest
| Field | Type | # | Notes |
|---|---|---|---|
program_json | string | 1 | program_json is the job program. JSON is the surface syntax: SDKs generate it, and any sugar compiles to it. An unknown field is a refusal, so a typo fails at submit time instead of being ignored at hour three. |
idempotency_key | string | 2 | idempotency_key makes a repeated submission return the original job instead of starting a second run of the same plan. |
mode | string | 90 | mode is what this submission may touch: "run" (default), "simulate" or "shadow". It rides on the request rather than in the program because the same program has to be runnable both ways: the plan a human approves and the plan that then runs are the same bytes. |
simulate_first | bool | 91 | simulate_first submits two jobs: a simulation that runs now, and this plan, which parks for approval naming it. Two jobs, because a simulated receipt and a real one must never share a fold. |
SubmitJobResponse
| Field | Type | # | Notes |
|---|---|---|---|
job | Job | 1 | job carries the status the submission reached: running, or pending plan approval with the estimate the approver decides on. |
Enums
JobStatus
| Value | # | Meaning |
|---|---|---|
JOB_STATUS_UNSPECIFIED | 0 | |
JOB_STATUS_PENDING_PLAN_APPROVAL | 1 | The plan needs a human decision before step one runs. plan_approval_id names the approval and estimate carries the numbers it was granted on. |
JOB_STATUS_RUNNING | 2 | |
JOB_STATUS_PARKED | 3 | Stopped on an approval or a judgment point. park says which, so a parked job is a visible state with an owner rather than a stall. |
JOB_STATUS_SUCCEEDED | 4 | |
JOB_STATUS_FAILED | 5 | |
JOB_STATUS_CANCELED | 6 |
AskState
AskState is what an ask is doing now. exhausted is not a state: an ask whose ladder ran out is still pending or escalated, because it still owes a person's answer, and the exhausted flag says nothing more will be delivered.
| Value | # | Meaning |
|---|---|---|
ASK_STATE_UNSPECIFIED | 0 | |
ASK_STATE_PENDING | 1 | Outstanding, at the first hop. |
ASK_STATE_ESCALATED | 2 | Outstanding, and the ladder has climbed at least one rung. |
ASK_STATE_ANSWERED | 3 | A principal answered it. |
ASK_STATE_TIMED_OUT | 4 | Nobody answered and the declared default applied. No approval ask reaches this state: an approval carries no default, because no clock approves. |