ExAthena.Loop.Terminations (ExAthena v0.15.1)

Copy Markdown View Source

Typed termination subtypes for agent-loop runs.

Every run ends with exactly one termination. Normal completions use :stop; everything else is an error subtype carrying enough context (usage, cost, duration) to drive retries and observability.

Inspired by the Claude Agent SDK's typed termination subtypes — they keep accounting uniform across happy and sad paths.

Subtypes

  • :stop — model returned text with no tool calls.
  • :submitted — model explicitly called the finish tool to declare completion. The Result.deliverable field carries the payload.
  • :error_max_turns — iteration cap reached.
  • :error_max_budget_usd — cost ceiling tripped.
  • :error_during_execution — unrecoverable tool / provider error.
  • :error_max_structured_output_retries — repair budget exhausted.
  • :error_consecutive_mistakes — mistake counter threshold hit.
  • :error_halted — hook or tool returned :halt.
  • :error_compaction_failed — context compaction failed.
  • :error_prompt_too_long — provider rejected the request because the assembled prompt exceeded the model's context window. Modes signal this to the kernel so the compaction pipeline can attempt reactive recovery before the run terminates.
  • :error_no_progress — consecutive-iteration productivity threshold exceeded; the last N iterations produced identical tool calls with no new text. The Result.no_progress_snapshot field carries the stuck message pairs for remediation reprompts.
  • :error_schema_validation — model output could not be parsed as valid structured output or tool calls. Category :retryable; caller may retry with a reformat prompt hint. Result.error_diagnostic carries the structured failure payload.
  • :error_provider_auth — provider returned HTTP 401 or 403. Category :fatal; blind retry will not help — operator must fix credentials.

Summary

Functions

All known termination subtypes.

Categorise a termination for retry classification. Returns one of: :retryable, :capacity, :fatal.

Is this an error termination?

Is this a successful termination?

Types

subtype()

@type subtype() ::
  :stop
  | :submitted
  | :error_max_turns
  | :error_max_budget_usd
  | :error_during_execution
  | :error_max_structured_output_retries
  | :error_consecutive_mistakes
  | :error_halted
  | :error_compaction_failed
  | :error_prompt_too_long
  | :error_no_progress
  | :error_schema_validation
  | :error_provider_auth

Functions

all()

@spec all() :: [subtype()]

All known termination subtypes.

category(atom)

@spec category(subtype()) :: :success | :retryable | :capacity | :fatal

Categorise a termination for retry classification. Returns one of: :retryable, :capacity, :fatal.

  • :retryable — transient; caller may retry on a new run.
  • :capacity — the run hit a configured limit; caller should increase the limit or reduce scope.
  • :fatal — don't retry without operator action.

error?(arg1)

@spec error?(subtype()) :: boolean()

Is this an error termination?

success?(arg1)

@spec success?(subtype()) :: boolean()

Is this a successful termination?