Skip to content

Agent run lifecycle

The server validates current Config, restored State and module references before external operations. It creates fresh native Capability/Toolset instances and runs Pydantic AI with a per-run Deps object. Current prompts and instructions are built from that run's config.

Native wrap_run scopes acquire operation resources and clean them in finally. Runtime acquires a lease; Shell bootstraps once and removes tracked jobs on exit; Config pulls mentioned assets on successful first initialization. Initialization flags are written only after successful setup, so failures can retry. The API's workflow terminal events own Workspace retirement and physical resource collection.

The runner saves captured conversation history in its outer finally, strips transient instructions and marks unexecuted trailing tool calls interrupted. If no messages were captured, restored history remains intact. Compaction rewrites are included. A terminal state snapshot is built after capability cleanup for success, failure and cancellation.

Snapshot v2 stores only JSON state:

{"schema_version": 2, "layers": {"history": {"messages": []}}}

Configurations, clients, lease handles, tokens, models and lifecycle enums are excluded. State is keyed by name, so instruction order does not constrain resume; known optional modules can be added or removed. The API resubmits current Config and retains session ownership through AgentWorkspaceBinding.session_snapshot. All snapshot readers use SessionSnapshot validation. Its migrate_snapshot validator dispatches v1 (including unversioned legacy lists) to the data-only migrate_snapshot_v1_to_v2 helper. V2 is validated directly; unknown explicit versions are rejected. Reading converts data in memory without updating stored JSON; the API saves the terminal v2 snapshot through its existing session owner. Known legacy names map to their meaningful State and removed AskHuman slots are discarded. Their unanswered tool calls are marked interrupted so native history repair closes them before the first new user turn. All runs use the native runner. Unknown legacy names and malformed state are rejected.