Expand description
The public exit-code contract: a stable, machine-actionable API (e.g. for a
Kubernetes podFailurePolicy). Schedulers branch on these numbers, so treat
any change to a code’s meaning as breaking.
| Code | Meaning | Scheduler hint |
|---|---|---|
| 0 | success (one-shot completed / clean SIGTERM drain) | Complete |
| 1 | generic/unspecified failure | retriable |
| 2 | config / usage error (validation) | non-retriable |
| 3 | partial result | policy |
| 4 | intelligence unreachable / auth after retries | retriable |
| 5 | semantic — task cannot be done / refused | non-retriable |
| 6 | required MCP server failed to connect/handshake/die | retriable |
| 7 | budget exceeded (steps/tokens/deadline/tree) | policy |
| 124 | hard wall-clock deadline (mnemonic to timeout(1)) | — |
| 137 | killed by SIGKILL (128+9, OS-set) — often OOM | raise memory |
| 143 | killed by SIGTERM (128+15, OS-set) — ungraceful | — |
A clean SIGTERM drain returns 0, not 143: draining on request is a
success, not a kill. 137/143 only ever appear because the OS sets them when
the kernel kills the process; agentd never calls exit(137) itself.
Around the table this module freezes two things a control plane depends on:
a contract version (EXIT_CODES, surfaced at surfaces.exit_codes) and a
per-code podFailurePolicy intent (pod_failure_intent) that agentctl
compiles into onExitCodes rules. agentd emits codes and intents only; the
policy decision itself belongs to agentctl.
Constants§
- BUDGET
- DEADLINE
- EXIT_
CODES - The exit-code contract version (major.minor), surfaced in the manifest at
surfaces.exit_codes. It freezes the code->meaning table plus thepod_failure_intentmapping as a versioned public API that a control plane authorspodFailurePolicyrules against. New codes may be added within a major; any change to an existing code’s meaning or intent is breaking and bumps the major, because a reader compiled against the old major would otherwise silently author the wrong policy. agentctl refuses to compile rules for anexit_codesmajor it does not understand. - GENERIC
- INTEL_
UNAVAILABLE - MCP_
REQUIRED_ DOWN - PARTIAL
- REFUSED
- SIGKILL_
EXIT - The OS-set codes (
128 + signo). agentd never returns these itself (once_exittops out atDEADLINE= 124); the kernel sets them when it kills the process. They are named here sopod_failure_intentcan classify the kernel-set code a reader actually observes. - SIGTERM_
EXIT - SUCCESS
- USAGE
Functions§
- apply_
budget_ remap - Apply the operator’s
--budget-exit-coderemap. ONLY the two operator-tunablepolicy-intent budget codes are remappable —EXIT_PARTIAL(3) andEXIT_BUDGET(7); every other code (a clean0, a terminal refusal5, thepolicydeadline124, a kernel137) is returned UNCHANGED. With no remap configured (None) the canonical table applies verbatim. - once_
exit - Map a one-shot root subagent’s outcome to an exit code.
partialis the result-body property, not a status: aCompletedrun that only partially satisfied the objective exits3. A budget-bounded run that nonetheless produced usable output is still reported under its budget code (7) with the partial flag carried in the result JSON. - pod_
failure_ intent - The
podFailurePolicyintent a control plane compiles each exit code into. agentd emits the code; agentctl owns the actualFailJob/Ignore/Countchoice and any operator override — this is the frozen hint it branches on, not a policy.