# Fen contracts

The non-function public surface: canonical types, extension
register kinds, event-bus shapes, and provider/auth/session
interfaces.

## Table of contents

- [Register kinds](#contract-section-register-kinds)
- [Events](#contract-section-events)
- [Canonical types](#contract-section-canonical-types)
- [Interfaces](#contract-section-interfaces)

## <a id="contract-section-register-kinds"></a>Register kinds

### <a id="contract-entry-register-kind-auth-backend"></a>`auth-backend`
Auth credential backend. Resolves an api-key or rotates an OAuth token for one or more providers.

- <a id="contract-field-register-kind-auth-backend-api-key"></a>`:api-key` `() -> string|nil` (required) — Return the current bearer/API key, refreshing or loading secrets as needed.
- <a id="contract-field-register-kind-auth-backend-login"></a>`:login!` `(opts) -> any` — Optional. Drives `fen --login <name>`.
- <a id="contract-field-register-kind-auth-backend-logout"></a>`:logout!` `() -> any` — Optional. Drives `fen --logout <name>`.
- <a id="contract-field-register-kind-auth-backend-name"></a>`:name` `keyword|string` (required) — Auth backend name selected by provider configuration or CLI login/logout flags.

### <a id="contract-entry-register-kind-command"></a>`command`
Slash command contribution. Looked up by name when the user submits `/<name> <args>` from a presenter.

- <a id="contract-field-register-kind-command-description"></a>`:description` `string` — Human-readable command help shown in command listings and docs.
- <a id="contract-field-register-kind-command-handler"></a>`:handler` `(args caller-state) -> any` (required) — Callback invoked with raw command arguments and the caller's runtime state.
- <a id="contract-field-register-kind-command-idle-only"></a>`:idle-only?` `boolean` — Refuse the command while the agent is busy.
- <a id="contract-field-register-kind-command-name"></a>`:name` `keyword|string` (required) — Command name without the leading slash.
- <a id="contract-field-register-kind-command-order"></a>`:order` `number` — Sort hint for `/help`.

### <a id="contract-entry-register-kind-control"></a>`control`
Keyboard/UI control surface for presenters that support typed input bindings.

- <a id="contract-field-register-kind-control-description"></a>`:description` `string` — Human-readable explanation of the control's UI effect.
- <a id="contract-field-register-kind-control-handler"></a>`:handler` `(ctx) -> any` (required) — Callback invoked by the presenter when the control is activated.
- <a id="contract-field-register-kind-control-name"></a>`:name` `keyword|string` (required) — Stable control name exposed to presenter help and docs.

### <a id="contract-entry-register-kind-hook"></a>`hook`
Lifecycle hook (currently `before-tool`). Inspects a tool call before it executes.

- <a id="contract-field-register-kind-hook-before-tool"></a>`:before-tool` `(tool-name args ctx) -> any` (required) — Return {:block true :reason string} to veto.

### <a id="contract-entry-register-kind-introspect"></a>`introspect`
Read-only extension state snapshot provider. Collected on demand for agent_state, /extensions, and runtime diagnostics.

- <a id="contract-field-register-kind-introspect-description"></a>`:description` `string` — Human-readable description shown by diagnostics and docs.
- <a id="contract-field-register-kind-introspect-name"></a>`:name` `keyword|string` (required) — Owner-scoped snapshot name. Multiple extensions may reuse the same name.
- <a id="contract-field-register-kind-introspect-snapshot"></a>`:snapshot` `(ctx) -> table` (required) — Cheap, side-effect-free thunk returning JSON-friendly data. It is pcall-isolated and should not expose secrets.

### <a id="contract-entry-register-kind-panel"></a>`panel`
Non-modal side panel contribution rendered by presenters that support panels.

- <a id="contract-field-register-kind-panel-enabled"></a>`:enabled?` `(ctx) -> boolean` — Optional predicate that hides the panel without unregistering it.
- <a id="contract-field-register-kind-panel-name"></a>`:name` `keyword|string` (required) — Stable panel name used for toggles, docs, and diagnostics.
- <a id="contract-field-register-kind-panel-render"></a>`:render` `(ctx) -> any` (required) — Callback returning rows or presenter-specific content for the panel body.
- <a id="contract-field-register-kind-panel-title"></a>`:title` `string` — Optional display title when the presenter renders panel chrome.

### <a id="contract-entry-register-kind-presenter"></a>`presenter`
UI driver. Owns the input/output loop. Exactly one is active per run; the loader picks based on flags and manifest hints.

- <a id="contract-field-register-kind-presenter-init"></a>`:init` `(ctx) -> nil` — Optional lifecycle callback run before the presenter loop starts.
- <a id="contract-field-register-kind-presenter-name"></a>`:name` `keyword|string` (required) — Presenter name selected by CLI flags or extension activation rules.
- <a id="contract-field-register-kind-presenter-run"></a>`:run` `(ctx) -> nil` (required) — Main input/output loop for the selected presenter.
- <a id="contract-field-register-kind-presenter-shutdown"></a>`:shutdown` `(ctx) -> nil` — Optional lifecycle callback used to release terminal, socket, or other UI resources.

### <a id="contract-entry-register-kind-provider"></a>`provider`
LLM provider contribution. See the :provider-interface contract for the required record.

- <a id="contract-field-register-kind-provider-api"></a>`:api` `keyword` (required) — Protocol family (:openai-completions, :anthropic-messages, ...). Many providers may share an :api.
- <a id="contract-field-register-kind-provider-build-body"></a>`:build-body` `(model ctx options) -> table` (required) — Build the provider request body from a model id, AgentContext, and call options.
- <a id="contract-field-register-kind-provider-complete"></a>`:complete` `(model ctx options ?on-event ?yield-fn) -> AssistantMessage` (required) — High-level provider entry point that runs one model turn and returns a canonical assistant message.
- <a id="contract-field-register-kind-provider-convert-messages"></a>`:convert-messages` `([Message]) -> [WireMessage]` (required) — Translate canonical conversation messages into this provider's wire message format.
- <a id="contract-field-register-kind-provider-convert-tools"></a>`:convert-tools` `([Tool]) -> [WireTool]` (required) — Translate canonical tool specs into this provider's wire tool schema.
- <a id="contract-field-register-kind-provider-map-stop-reason"></a>`:map-stop-reason` `(string) -> StopReason` (required) — Normalize provider stop reasons into fen's canonical StopReason enum.
- <a id="contract-field-register-kind-provider-name"></a>`:name` `keyword|string` (required) — Provider name selected by settings or CLI options.
- <a id="contract-field-register-kind-provider-parse-response"></a>`:parse-response` `(WireResponse) -> AssistantMessage` (required) — Convert a non-streaming provider response payload into an AssistantMessage.

### <a id="contract-entry-register-kind-session-backend"></a>`session-backend`
Persistence backend for canonical JSONL-style sessions. The `--session` flag selects one and `fen.core.extensions.register.session_backend.set-active!` activates it.

- <a id="contract-field-register-kind-session-backend-append"></a>`:append` `(session message) -> nil` (required) — Persist one canonical Message to the active session.
- <a id="contract-field-register-kind-session-backend-close"></a>`:close` `(session) -> nil` (required) — Flush and release backend resources for an open session.
- <a id="contract-field-register-kind-session-backend-find"></a>`:find` `(opts) -> [SessionInfo]` (required) — Search sessions using backend-specific filters.
- <a id="contract-field-register-kind-session-backend-latest"></a>`:latest` `(opts) -> SessionInfo|nil` (required) — Return the newest matching session, if any.
- <a id="contract-field-register-kind-session-backend-list"></a>`:list` `(opts) -> [SessionInfo]` (required) — List sessions visible to this backend in a stable display order.
- <a id="contract-field-register-kind-session-backend-load"></a>`:load` `(path opts) -> [Message]` (required) — Read canonical messages from a stored session path.
- <a id="contract-field-register-kind-session-backend-name"></a>`:name` `keyword|string` (required) — Session backend name selected by CLI flags or extension configuration.
- <a id="contract-field-register-kind-session-backend-open"></a>`:open` `(opts) -> session` (required) — Create or open the active session for a new run.
- <a id="contract-field-register-kind-session-backend-open-existing"></a>`:open-existing` `(path opts) -> session` (required) — Open an existing session file or directory for appending.

### <a id="contract-entry-register-kind-status"></a>`status`
Status-line contributor — produces a short string for the presenter's status row.

- <a id="contract-field-register-kind-status-name"></a>`:name` `keyword|string` (required) — Stable status item name used for sorting, diagnostics, and docs.
- <a id="contract-field-register-kind-status-order"></a>`:order` `number` — Sort hint within the status side; lower values render earlier.
- <a id="contract-field-register-kind-status-render"></a>`:render` `(ctx) -> string|nil` (required) — Callback returning the current status text, or nil/empty text to hide it.

### <a id="contract-entry-register-kind-tool"></a>`tool`
Agent tool contribution. Merged into the per-step `AgentContext.tools` and dispatched by name when the assistant emits a ToolCall.

- <a id="contract-field-register-kind-tool-description"></a>`:description` `string` (required) — Provider-facing guidance explaining when the model should call this tool.
- <a id="contract-field-register-kind-tool-execute"></a>`:execute` `(args ?yield-fn) -> AgentToolResult` (required) — Runtime callback that executes decoded arguments and returns canonical tool content.
- <a id="contract-field-register-kind-tool-label"></a>`:label` `string` — Optional short UI label shown by presenters while the tool runs.
- <a id="contract-field-register-kind-tool-name"></a>`:name` `string` (required) — Unique tool name exposed to providers and matched against ToolCall.name.
- <a id="contract-field-register-kind-tool-parameters"></a>`:parameters` `JSONSchema` (required) — JSON object schema describing the tool arguments providers may emit.

## <a id="contract-section-events"></a>Events

### <a id="contract-entry-event-agent-shutdown"></a>`agent-shutdown`
Emitted once per run during teardown. `:error` is present for crashed paths.

- <a id="contract-field-event-agent-shutdown-agent"></a>`:agent` `Agent` (required) — Agent instance associated with the event.
- <a id="contract-field-event-agent-shutdown-error"></a>`:error` `string` — Crash details when shutdown follows an error path.
- <a id="contract-field-event-agent-shutdown-reason"></a>`:reason` `keyword` (required) — :normal | :crashed
- <a id="contract-field-event-agent-shutdown-type"></a>`:type` `:agent-shutdown` (required) — Event discriminator for :agent-shutdown events.

### <a id="contract-entry-event-agent-started"></a>`agent-started`
Emitted once per run after setup and before the first new step.

- <a id="contract-field-event-agent-started-agent"></a>`:agent` `Agent` (required) — Agent instance associated with the event.
- <a id="contract-field-event-agent-started-cwd"></a>`:cwd` `string` (required) — Working directory for the active agent run.
- <a id="contract-field-event-agent-started-model"></a>`:model` `string` (required) — Model identifier selected for the active run.
- <a id="contract-field-event-agent-started-provider"></a>`:provider` `keyword|string` (required) — Provider name selected for the active run.
- <a id="contract-field-event-agent-started-type"></a>`:type` `:agent-started` (required) — Event discriminator for :agent-started events.

### <a id="contract-entry-event-agent-turn-complete"></a>`agent-turn-complete`
Emitted once per submitted user turn after the agent coroutine finishes and the presenter busy flag has been cleared.

- <a id="contract-field-event-agent-turn-complete-agent"></a>`:agent` `Agent` (required) — Agent instance associated with the completed turn.
- <a id="contract-field-event-agent-turn-complete-error"></a>`:error` `string` — Error summary when the turn ended with :status :error.
- <a id="contract-field-event-agent-turn-complete-message-count"></a>`:message-count` `number` (required) — Conversation message count after the turn finished.
- <a id="contract-field-event-agent-turn-complete-result"></a>`:result` `string` — Final visible assistant text for successful or cancelled turns, when available.
- <a id="contract-field-event-agent-turn-complete-status"></a>`:status` `keyword` (required) — :ok | :cancelled | :error
- <a id="contract-field-event-agent-turn-complete-type"></a>`:type` `:agent-turn-complete` (required) — Event discriminator for :agent-turn-complete events.

### <a id="contract-entry-event-assistant-stream-end"></a>`assistant-stream-end`
Stream finished. Emitted once after all per-block end events for a single AssistantMessage.

- <a id="contract-field-event-assistant-stream-end-type"></a>`:type` `:assistant-stream-end` (required) — Event discriminator for :assistant-stream-end events.

### <a id="contract-entry-event-assistant-text"></a>`assistant-text`
Final visible text emitted by the assistant. One per AssistantMessage with text blocks.

- <a id="contract-field-event-assistant-text-final"></a>`:final?` `boolean` — True when this is the final aggregate payload for the current block.
- <a id="contract-field-event-assistant-text-text"></a>`:text` `string` (required) — Complete assistant text payload for this event.
- <a id="contract-field-event-assistant-text-type"></a>`:type` `:assistant-text` (required) — Event discriminator for :assistant-text events.

### <a id="contract-entry-event-assistant-text-delta"></a>`assistant-text-delta`
Streaming text token. Aggregated by presenters during a stream.

- <a id="contract-field-event-assistant-text-delta-delta"></a>`:delta` `string` (required) — Incremental streamed text fragment for the open content block.
- <a id="contract-field-event-assistant-text-delta-type"></a>`:type` `:assistant-text-delta` (required) — Event discriminator for :assistant-text-delta events.

### <a id="contract-entry-event-assistant-thinking"></a>`assistant-thinking`
Final reasoning text from the assistant (for providers that surface reasoning content).

- <a id="contract-field-event-assistant-thinking-final"></a>`:final?` `boolean` — True when this is the final aggregate payload for the current block.
- <a id="contract-field-event-assistant-thinking-text"></a>`:text` `string` (required) — Complete assistant text payload for this event.
- <a id="contract-field-event-assistant-thinking-type"></a>`:type` `:assistant-thinking` (required) — Event discriminator for :assistant-thinking events.

### <a id="contract-entry-event-assistant-thinking-delta"></a>`assistant-thinking-delta`
Streaming reasoning token.

- <a id="contract-field-event-assistant-thinking-delta-delta"></a>`:delta` `string` (required) — Incremental streamed text fragment for the open content block.
- <a id="contract-field-event-assistant-thinking-delta-type"></a>`:type` `:assistant-thinking-delta` (required) — Event discriminator for :assistant-thinking-delta events.

### <a id="contract-entry-event-cancelled"></a>`cancelled`
Cooperative cancel observed; the current step appended an aborted assistant message.

- <a id="contract-field-event-cancelled-type"></a>`:type` `:cancelled` (required) — Event discriminator for :cancelled events.

### <a id="contract-entry-event-compaction-summary"></a>`compaction-summary`
Context compaction completed and produced a summary for older messages.

- <a id="contract-field-event-compaction-summary-guidance"></a>`:guidance` `string` — Optional user guidance supplied to /compact.
- <a id="contract-field-event-compaction-summary-messages-kept"></a>`:messages-kept` `number` — Number of recent messages kept verbatim.
- <a id="contract-field-event-compaction-summary-messages-summarized"></a>`:messages-summarized` `number` — Number of older messages summarized.
- <a id="contract-field-event-compaction-summary-summary"></a>`:summary` `string` (required) — Summary text installed into the compacted model context.
- <a id="contract-field-event-compaction-summary-tokens-after"></a>`:tokens-after` `number` — Approximate context tokens after compaction.
- <a id="contract-field-event-compaction-summary-tokens-before"></a>`:tokens-before` `number` — Approximate context tokens before compaction.
- <a id="contract-field-event-compaction-summary-trigger"></a>`:trigger` `keyword` — Why compaction ran, such as :manual.
- <a id="contract-field-event-compaction-summary-type"></a>`:type` `:compaction-summary` (required) — Event discriminator for :compaction-summary events.

### <a id="contract-entry-event-dismiss"></a>`dismiss`
Presenter signal that an open overlay/picker should close.

- <a id="contract-field-event-dismiss-type"></a>`:type` `:dismiss` (required) — Event discriminator for :dismiss events.

### <a id="contract-entry-event-done"></a>`done`
Provider stream: terminal event for a successful AssistantMessage.

- <a id="contract-field-event-done-message"></a>`:message` `AssistantMessage` (required) — Canonical assistant message produced by the provider stream.
- <a id="contract-field-event-done-type"></a>`:type` `:done` (required) — Event discriminator for :done events.

### <a id="contract-entry-event-error"></a>`error`
Generic surface error — typically command-dispatch or user-input failures.

- <a id="contract-field-event-error-error"></a>`:error` `string` (required) — Human-readable error message for presenters and logs.
- <a id="contract-field-event-error-type"></a>`:type` `:error` (required) — Event discriminator for :error events.

### <a id="contract-entry-event-extension-error"></a>`extension-error`
Emitted when an extension event handler raises. Suppressed for recursive extension-error events to prevent loops.

- <a id="contract-field-event-extension-error-error"></a>`:error` `string` (required) — Human-readable error message for presenters and logs.
- <a id="contract-field-event-extension-error-event"></a>`:event` `keyword|string` — Original event being handled when the extension error occurred.
- <a id="contract-field-event-extension-error-owner"></a>`:owner` `keyword|string` — Extension owner whose handler raised, when known.
- <a id="contract-field-event-extension-error-type"></a>`:type` `:extension-error` (required) — Event discriminator for :extension-error events.

### <a id="contract-entry-event-extension-loaded"></a>`extension-loaded`
Emitted by the loader for each successfully loaded extension manifest.

- <a id="contract-field-event-extension-loaded-first-party"></a>`:first-party?` `boolean` — True when the loaded extension came from fen's bundled extension set.
- <a id="contract-field-event-extension-loaded-name"></a>`:name` `string` (required) — Extension manifest name that was loaded.
- <a id="contract-field-event-extension-loaded-type"></a>`:type` `:extension-loaded` (required) — Event discriminator for :extension-loaded events.

### <a id="contract-entry-event-info"></a>`info`
Transient informational message intended for the presenter status row or panel.

- <a id="contract-field-event-info-info"></a>`:info` `string` — Human-readable informational message payload.
- <a id="contract-field-event-info-text"></a>`:text` `string` — Alternative human-readable informational text.
- <a id="contract-field-event-info-type"></a>`:type` `:info` (required) — Event discriminator for :info events.

### <a id="contract-entry-event-llm-end"></a>`llm-end`
Provider call completed (success or error). The :message field carries the canonical AssistantMessage.

- <a id="contract-field-event-llm-end-message"></a>`:message` `AssistantMessage` (required) — Canonical assistant message produced by the provider stream.
- <a id="contract-field-event-llm-end-type"></a>`:type` `:llm-end` (required) — Event discriminator for :llm-end events.

### <a id="contract-entry-event-llm-start"></a>`llm-start`
Provider call beginning.

- <a id="contract-field-event-llm-start-model"></a>`:model` `string` — Model identifier used for the provider request, when known.
- <a id="contract-field-event-llm-start-provider"></a>`:provider` `keyword` — Provider name for the outbound LLM call, when known.
- <a id="contract-field-event-llm-start-type"></a>`:type` `:llm-start` (required) — Event discriminator for :llm-start events.

### <a id="contract-entry-event-message-appended"></a>`message-appended`
Emitted by `fen.core.agent` immediately after `agent.messages` grows.

- <a id="contract-field-event-message-appended-agent"></a>`:agent` `Agent` (required) — Agent instance associated with the event.
- <a id="contract-field-event-message-appended-index"></a>`:index` `number` (required) — 1-based index of the appended message.
- <a id="contract-field-event-message-appended-message"></a>`:message` `Message` (required) — Canonical message that was appended to the conversation.
- <a id="contract-field-event-message-appended-type"></a>`:type` `:message-appended` (required) — Event discriminator for :message-appended events.

### <a id="contract-entry-event-queued"></a>`queued`
User-line queued while the agent is busy. Consumed by the agent on natural-stop.

- <a id="contract-field-event-queued-line"></a>`:line` `string` (required) — Raw user input line associated with the event.
- <a id="contract-field-event-queued-type"></a>`:type` `:queued` (required) — Event discriminator for :queued events.

### <a id="contract-entry-event-redraw"></a>`redraw`
Presenter hint that a registered panel needs to be repainted.

- <a id="contract-field-event-redraw-type"></a>`:type` `:redraw` (required) — Event discriminator for :redraw events.

### <a id="contract-entry-event-reinit-presenter"></a>`reinit-presenter`
Presenter signal that the UI should be torn down and re-initialized (used by /reload).

- <a id="contract-field-event-reinit-presenter-type"></a>`:type` `:reinit-presenter` (required) — Event discriminator for :reinit-presenter events.

### <a id="contract-entry-event-reset-conversation"></a>`reset-conversation`
Presenter signal that the active conversation should be cleared (used by /new).

- <a id="contract-field-event-reset-conversation-type"></a>`:type` `:reset-conversation` (required) — Event discriminator for :reset-conversation events.

### <a id="contract-entry-event-set-status-info"></a>`set-status-info`
Presenter-level status hint. Owners post a transient status line; nil clears.

- <a id="contract-field-event-set-status-info-info"></a>`:info` `string|nil` — Transient status text to show, or nil to clear it.
- <a id="contract-field-event-set-status-info-type"></a>`:type` `:set-status-info` (required) — Event discriminator for :set-status-info events.

### <a id="contract-entry-event-start"></a>`start`
Provider stream opened. Marker event emitted before any block events.

- <a id="contract-field-event-start-type"></a>`:type` `:start` (required) — Event discriminator for :start events.

### <a id="contract-entry-event-text-delta"></a>`text-delta`
Provider stream: incremental text token within the open block.

- <a id="contract-field-event-text-delta-content-index"></a>`:content-index` `number` (required) — Position within the assistant's content array.
- <a id="contract-field-event-text-delta-delta"></a>`:delta` `string` (required) — Incremental streamed text fragment for the open content block.
- <a id="contract-field-event-text-delta-type"></a>`:type` `:text-delta` (required) — Event discriminator for :text-delta events.

### <a id="contract-entry-event-text-end"></a>`text-end`
Provider stream: TextContent block closed; full text supplied.

- <a id="contract-field-event-text-end-content"></a>`:content` `string` (required) — Complete text or thinking content for the closed stream block.
- <a id="contract-field-event-text-end-content-index"></a>`:content-index` `number` (required) — Position within the assistant's content array.
- <a id="contract-field-event-text-end-type"></a>`:type` `:text-end` (required) — Event discriminator for :text-end events.

### <a id="contract-entry-event-text-start"></a>`text-start`
Provider stream: a TextContent block is starting.

- <a id="contract-field-event-text-start-content-index"></a>`:content-index` `number` (required) — Position within the assistant's content array.
- <a id="contract-field-event-text-start-type"></a>`:type` `:text-start` (required) — Event discriminator for :text-start events.

### <a id="contract-entry-event-thinking-delta"></a>`thinking-delta`
Provider stream: incremental reasoning token within the open block.

- <a id="contract-field-event-thinking-delta-content-index"></a>`:content-index` `number` (required) — Position within the assistant's content array.
- <a id="contract-field-event-thinking-delta-delta"></a>`:delta` `string` (required) — Incremental streamed text fragment for the open content block.
- <a id="contract-field-event-thinking-delta-type"></a>`:type` `:thinking-delta` (required) — Event discriminator for :thinking-delta events.

### <a id="contract-entry-event-thinking-end"></a>`thinking-end`
Provider stream: ThinkingContent block closed; full text supplied.

- <a id="contract-field-event-thinking-end-content"></a>`:content` `string` (required) — Complete text or thinking content for the closed stream block.
- <a id="contract-field-event-thinking-end-content-index"></a>`:content-index` `number` (required) — Position within the assistant's content array.
- <a id="contract-field-event-thinking-end-type"></a>`:type` `:thinking-end` (required) — Event discriminator for :thinking-end events.

### <a id="contract-entry-event-thinking-start"></a>`thinking-start`
Provider stream: a ThinkingContent block is starting.

- <a id="contract-field-event-thinking-start-content-index"></a>`:content-index` `number` (required) — Position within the assistant's content array.
- <a id="contract-field-event-thinking-start-type"></a>`:type` `:thinking-start` (required) — Event discriminator for :thinking-start events.

### <a id="contract-entry-event-tool-call"></a>`tool-call`
Tool call about to execute. Carries the canonical ToolCall block.

- <a id="contract-field-event-tool-call-tool-call"></a>`:tool-call` `ToolCall` (required) — Canonical tool-call block associated with this event.
- <a id="contract-field-event-tool-call-type"></a>`:type` `:tool-call` (required) — Event discriminator for :tool-call events.

### <a id="contract-entry-event-tool-call-delta"></a>`tool-call-delta`
Provider stream: incremental JSON-text fragment for the open ToolCall arguments. Some providers stream arguments token-by-token; consumers may concatenate.

- <a id="contract-field-event-tool-call-delta-content-index"></a>`:content-index` `number` (required) — Position within the assistant's content array.
- <a id="contract-field-event-tool-call-delta-delta"></a>`:delta` `string` (required) — Incremental streamed text fragment for the open content block.
- <a id="contract-field-event-tool-call-delta-type"></a>`:type` `:tool-call-delta` (required) — Event discriminator for :tool-call-delta events.

### <a id="contract-entry-event-tool-call-end"></a>`tool-call-end`
Provider stream: ToolCall block closed; complete canonical ToolCall block supplied.

- <a id="contract-field-event-tool-call-end-content-index"></a>`:content-index` `number` (required) — Position within the assistant's content array.
- <a id="contract-field-event-tool-call-end-tool-call"></a>`:tool-call` `ToolCall` (required) — Canonical tool-call block associated with this event.
- <a id="contract-field-event-tool-call-end-type"></a>`:type` `:tool-call-end` (required) — Event discriminator for :tool-call-end events.

### <a id="contract-entry-event-tool-call-start"></a>`tool-call-start`
Provider stream: a ToolCall block is starting; arguments not yet known.

- <a id="contract-field-event-tool-call-start-content-index"></a>`:content-index` `number` (required) — Position within the assistant's content array.
- <a id="contract-field-event-tool-call-start-type"></a>`:type` `:tool-call-start` (required) — Event discriminator for :tool-call-start events.

### <a id="contract-entry-event-tool-result"></a>`tool-result`
Tool execution finished. Carries the canonical ToolResultMessage.

- <a id="contract-field-event-tool-result-result"></a>`:result` `ToolResultMessage` (required) — Canonical tool-result message produced by the tool executor.
- <a id="contract-field-event-tool-result-type"></a>`:type` `:tool-result` (required) — Event discriminator for :tool-result events.

### <a id="contract-entry-event-user"></a>`user`
User-submitted line accepted by the presenter input layer. Distinct from :queued (which fires when the line is *queued* during a busy turn).

- <a id="contract-field-event-user-line"></a>`:line` `string` (required) — Raw user input line associated with the event.
- <a id="contract-field-event-user-type"></a>`:type` `:user` (required) — Event discriminator for :user events.

## <a id="contract-section-canonical-types"></a>Canonical types

### <a id="contract-entry-type-agentcontext"></a>`AgentContext`
Per-call payload handed to a provider's `:complete`.

- <a id="contract-field-type-agentcontext-max-tokens"></a>`:max-tokens` `number` (required) — Maximum output token budget requested for the provider call.
- <a id="contract-field-type-agentcontext-messages"></a>`:messages` `[Message]` (required) — Canonical conversation history to convert into provider wire format.
- <a id="contract-field-type-agentcontext-system-prompt"></a>`:system-prompt` `string|nil` — Fully rendered system prompt for the current step, or nil when omitted.
- <a id="contract-field-type-agentcontext-tools"></a>`:tools` `[Tool]` (required) — Provider-visible tool specs available for this step.

### <a id="contract-entry-type-agenttool"></a>`AgentTool`
Tool extended with execution metadata for the agent loop. Registered through `(api.register :tool ...)`.

- <a id="contract-field-type-agenttool-description"></a>`:description` `string` (required) — Provider-facing description included in the tool schema.
- <a id="contract-field-type-agenttool-execute"></a>`:execute` `(args ?yield-fn) -> AgentToolResult` (required) — Runtime callback that executes the tool with decoded arguments.
- <a id="contract-field-type-agenttool-label"></a>`:label` `string` — UI label.
- <a id="contract-field-type-agenttool-name"></a>`:name` `string` (required) — Registry name used to merge and dispatch the tool.
- <a id="contract-field-type-agenttool-parameters"></a>`:parameters` `JSONSchema` (required) — Provider-facing argument schema used for validation and prompting.

### <a id="contract-entry-type-agenttoolresult"></a>`AgentToolResult`
Outcome of a tool execution.

- <a id="contract-field-type-agenttoolresult-content"></a>`:content` `[TextContent]` (required) — Text content returned to the provider as the tool observation.
- <a id="contract-field-type-agenttoolresult-details"></a>`:details` `any` — Opaque presenter payload (UI-only).
- <a id="contract-field-type-agenttoolresult-is-error"></a>`:is-error?` `boolean` (required) — True when the tool observation represents a failed call.

### <a id="contract-entry-type-assistantmessage"></a>`AssistantMessage`
Single model response. Content is always an array, even when empty.

- <a id="contract-field-type-assistantmessage-api"></a>`:api` `keyword` — :openai-completions | :openai-responses | :anthropic-messages | :openai-codex
- <a id="contract-field-type-assistantmessage-content"></a>`:content` `[TextContent|ThinkingContent|ToolCall]` (required) — Ordered assistant output blocks, including visible text, reasoning, and tool calls.
- <a id="contract-field-type-assistantmessage-error-message"></a>`:error-message` `string` — Present only when stop-reason = :error.
- <a id="contract-field-type-assistantmessage-model"></a>`:model` `string` — Provider model identifier that produced this response.
- <a id="contract-field-type-assistantmessage-provider"></a>`:provider` `keyword` — Registered provider :name (e.g. :openai, :anthropic).
- <a id="contract-field-type-assistantmessage-role"></a>`:role` `:assistant` (required) — Message role discriminator for model-authored turns.
- <a id="contract-field-type-assistantmessage-stop-reason"></a>`:stop-reason` `StopReason` — Normalized reason the provider stopped generation.
- <a id="contract-field-type-assistantmessage-timestamp"></a>`:timestamp` `number` (required) — Milliseconds since epoch when the assistant message was recorded.
- <a id="contract-field-type-assistantmessage-usage"></a>`:usage` `Usage` — Optional token accounting returned by the provider for this response.

### <a id="contract-entry-type-message"></a>`Message`
Union of UserMessage, AssistantMessage, ToolResultMessage. Stored on `agent.messages` and passed to providers in `AgentContext.messages`.

- <a id="contract-member-type-message-variant-usermessage"></a>`UserMessage` `variant` — UserMessage is a Message union variant.
- <a id="contract-member-type-message-variant-assistantmessage"></a>`AssistantMessage` `variant` — AssistantMessage is a Message union variant.
- <a id="contract-member-type-message-variant-toolresultmessage"></a>`ToolResultMessage` `variant` — ToolResultMessage is a Message union variant.

### <a id="contract-entry-type-stopreason"></a>`StopReason`
Why the assistant stopped producing output.

- <a id="contract-member-type-stopreason-enum-stop"></a>`:stop` `enum` — :stop is a StopReason enum value.
- <a id="contract-member-type-stopreason-enum-length"></a>`:length` `enum` — :length is a StopReason enum value.
- <a id="contract-member-type-stopreason-enum-tool-use"></a>`:tool-use` `enum` — :tool-use is a StopReason enum value.
- <a id="contract-member-type-stopreason-enum-error"></a>`:error` `enum` — :error is a StopReason enum value.
- <a id="contract-member-type-stopreason-enum-aborted"></a>`:aborted` `enum` — :aborted is a StopReason enum value.

### <a id="contract-entry-type-textcontent"></a>`TextContent`
Plain visible text block.

- <a id="contract-field-type-textcontent-text"></a>`:text` `string` (required) — Visible UTF-8 text payload.
- <a id="contract-field-type-textcontent-type"></a>`:type` `:text` (required) — Content-block discriminator for visible text.

### <a id="contract-entry-type-thinkingcontent"></a>`ThinkingContent`
Reasoning/extended-thinking block. Surfaces both Anthropic extended thinking and OpenAI reasoning items.

- <a id="contract-field-type-thinkingcontent-redacted"></a>`:redacted?` `boolean` — True when the provider redacted visible text.
- <a id="contract-field-type-thinkingcontent-thinking"></a>`:thinking` `string` (required) — Reasoning or extended-thinking text emitted by the provider.
- <a id="contract-field-type-thinkingcontent-thinking-signature"></a>`:thinking-signature` `string` — Opaque echo signature; required for multi-turn extended thinking.
- <a id="contract-field-type-thinkingcontent-type"></a>`:type` `:thinking` (required) — Content-block discriminator for provider reasoning text.

### <a id="contract-entry-type-tool"></a>`Tool`
Provider-agnostic tool spec — what providers see in `AgentContext.tools`.

- <a id="contract-field-type-tool-description"></a>`:description` `string` (required) — Provider-visible explanation of when and how to call the tool.
- <a id="contract-field-type-tool-name"></a>`:name` `string` (required) — Provider-visible tool name used in tool-call blocks.
- <a id="contract-field-type-tool-parameters"></a>`:parameters` `JSONSchema` (required) — {:type :object :properties {...} :required [...]}

### <a id="contract-entry-type-toolcall"></a>`ToolCall`
Assistant request to invoke a tool. Arguments are a parsed Lua table — providers JSON-decode wire arguments before constructing this block.

- <a id="contract-field-type-toolcall-arguments"></a>`:arguments` `table` (required) — Decoded argument table validated by the target tool implementation.
- <a id="contract-field-type-toolcall-id"></a>`:id` `string` (required) — Provider- or agent-generated id used to match the eventual tool result.
- <a id="contract-field-type-toolcall-name"></a>`:name` `string` (required) — Registered tool name to execute.
- <a id="contract-field-type-toolcall-type"></a>`:type` `:tool-call` (required) — Content-block discriminator for tool invocation requests.

### <a id="contract-entry-type-toolresultmessage"></a>`ToolResultMessage`
Result of a single tool call, carried back to the provider on the next turn.

- <a id="contract-field-type-toolresultmessage-content"></a>`:content` `[TextContent]` (required) — Tool output blocks returned to the provider on the next turn.
- <a id="contract-field-type-toolresultmessage-details"></a>`:details` `any` — Opaque presenter payload (UI-only).
- <a id="contract-field-type-toolresultmessage-is-error"></a>`:is-error?` `boolean` (required) — True when the tool result should be treated as an error observation.
- <a id="contract-field-type-toolresultmessage-role"></a>`:role` `:tool-result` (required) — Message role discriminator for tool execution results.
- <a id="contract-field-type-toolresultmessage-timestamp"></a>`:timestamp` `number` (required) — Milliseconds since epoch when the tool result was recorded.
- <a id="contract-field-type-toolresultmessage-tool-call-id"></a>`:tool-call-id` `string` (required) — Matches the originating ToolCall.id.
- <a id="contract-field-type-toolresultmessage-tool-name"></a>`:tool-name` `string` (required) — Tool name that produced the result, copied from the originating call.

### <a id="contract-entry-type-usage"></a>`Usage`
Token usage counters returned by the provider (best-effort — providers fill what they can).

- <a id="contract-field-type-usage-cache-read"></a>`:cache-read` `number` — Provider cache-read tokens credited for the response.
- <a id="contract-field-type-usage-cache-write"></a>`:cache-write` `number` — Provider cache-write tokens billed or recorded for the response.
- <a id="contract-field-type-usage-input"></a>`:input` `number` — Input or prompt tokens counted for the response.
- <a id="contract-field-type-usage-output"></a>`:output` `number` — Generated output tokens counted for the response.
- <a id="contract-field-type-usage-total-tokens"></a>`:total-tokens` `number` — Provider-reported total tokens, or the best available aggregate.

### <a id="contract-entry-type-usermessage"></a>`UserMessage`
Single user turn. Content is either a plain string or an array of TextContent blocks.

- <a id="contract-field-type-usermessage-content"></a>`:content` `string|[TextContent]` (required) — Visible user input as plain text or canonical text content blocks.
- <a id="contract-field-type-usermessage-role"></a>`:role` `:user` (required) — Message role discriminator for user-authored turns.
- <a id="contract-field-type-usermessage-timestamp"></a>`:timestamp` `number` (required) — Milliseconds since epoch.

## <a id="contract-section-interfaces"></a>Interfaces

### <a id="contract-entry-interface-auth-backend"></a>`auth-backend`
Required record shape for `(api.register :auth-backend ...)`.

- <a id="contract-member-interface-auth-backend-method-api-key"></a>`:api-key` `method` — :api-key is a required auth-backend interface method.
- <a id="contract-member-interface-auth-backend-optional-method-login"></a>`:login!` `optional-method` — :login! is an optional auth-backend interface method.
- <a id="contract-member-interface-auth-backend-optional-method-logout"></a>`:logout!` `optional-method` — :logout! is an optional auth-backend interface method.

### <a id="contract-entry-interface-provider"></a>`provider`
Required record shape for `(api.register :provider ...)`. See the :provider register-kind for field details.

- <a id="contract-member-interface-provider-method-complete"></a>`:complete` `method` — :complete is a required provider interface method.
- <a id="contract-member-interface-provider-method-convert-messages"></a>`:convert-messages` `method` — :convert-messages is a required provider interface method.
- <a id="contract-member-interface-provider-method-convert-tools"></a>`:convert-tools` `method` — :convert-tools is a required provider interface method.
- <a id="contract-member-interface-provider-method-map-stop-reason"></a>`:map-stop-reason` `method` — :map-stop-reason is a required provider interface method.
- <a id="contract-member-interface-provider-method-parse-response"></a>`:parse-response` `method` — :parse-response is a required provider interface method.
- <a id="contract-member-interface-provider-method-build-body"></a>`:build-body` `method` — :build-body is a required provider interface method.

### <a id="contract-entry-interface-session-backend"></a>`session-backend`
Required record shape for `(api.register :session-backend ...)`.

- <a id="contract-member-interface-session-backend-method-open"></a>`:open` `method` — :open is a required session-backend interface method.
- <a id="contract-member-interface-session-backend-method-open-existing"></a>`:open-existing` `method` — :open-existing is a required session-backend interface method.
- <a id="contract-member-interface-session-backend-method-append"></a>`:append` `method` — :append is a required session-backend interface method.
- <a id="contract-member-interface-session-backend-method-close"></a>`:close` `method` — :close is a required session-backend interface method.
- <a id="contract-member-interface-session-backend-method-load"></a>`:load` `method` — :load is a required session-backend interface method.
- <a id="contract-member-interface-session-backend-method-find"></a>`:find` `method` — :find is a required session-backend interface method.
- <a id="contract-member-interface-session-backend-method-list"></a>`:list` `method` — :list is a required session-backend interface method.
- <a id="contract-member-interface-session-backend-method-latest"></a>`:latest` `method` — :latest is a required session-backend interface method.
