ASM does not redefine the normalized provider runtime vocabulary. It wraps core runtime events in a run-scoped envelope and then reduces those envelopes into a final result.
Event Envelope
Backends usually emit CliSubprocessCore.Event values. ASM.Run.Server wraps
them as %ASM.Event{} with:
run_idsession_idproviderkindpayloadcore_eventsequenceprovider_session_idtimestampmetadata
The original normalized core event remains available in event.core_event.
Some promoted ASM-native lanes emit %ASM.Event{} directly through the same
backend envelope. The current native event set includes:
:host_tool_requested:host_tool_completed:host_tool_failed:host_tool_denied:session_checkpoint:session_resumed
The Codex app-server lane uses those host-tool events for dynamic tool request/response handling while continuing to emit normal core assistant and result events for text/result projection.
%ASM.Event{} remains the ergonomic public envelope. ASM.Schema.Event
validates and normalizes rebuilt event maps, while forward-compatible unknown
fields are preserved on event.extra instead of being silently dropped into
runtime assumptions.
Metadata Flow
Authoritative run metadata comes from lane/backend resolution and is merged with incoming event metadata through ASM's internal protected-metadata merge step.
Common projected keys include:
providerprovider_display_namerequested_lanepreferred_lanelanebackendexecution_modelane_reasonlane_fallback_reasonsdk_runtimesdk_available?capabilities
That keeps stream consumers and query consumers aligned on the same effective runtime path.
Final Result Projection
ASM.Stream.final_result/1 reduces the %ASM.Event{} stream through
ASM.Run.EventReducer.
The reducer is responsible for:
- accumulating assistant text and legacy message projections
- tracking provider session id and cost totals
- tracking pending approvals
- carrying the provider-returned structured object onto
%ASM.Result{}.object - marking terminal status on result, error, or interruption
- building
%ASM.Result{}
%ASM.Result.metadata therefore comes from the event stream itself instead of a
side channel.
%ASM.Result{}.object is the same fact: it is read from the terminal
:result payload's object field (CliSubprocessCore.Payload.Result.object)
and projected onto %ASM.Message.Result{}.object and %ASM.Result{}.object.
It is nil when the provider returned no structured object — the reducer never
reconstructs one from prose.
Terminal Semantics
:resultmarks the run completed successfully:errormarks the run failed and becomes%ASM.Error{}:run_completedis the ASM-local lifecycle completion signal:host_tool_*events are ASM-local host-tool lifecycle events and do not replace the terminal:result/:errorsemantics- approval and cost events continue to update run state before the final result
That deterministic reducer path is the source of truth for one-shot
ASM.query/3 result projection.