ASM separates lane discovery from execution mode. Provider resolution decides
which backend lane is preferred, and only then does execution mode decide
whether that lane can actually run.
The Three Lane Values
requested_lane: what the caller asked for (:auto | :core | :sdk)preferred_lane: what provider/runtime discovery selected before execution-mode checkslane: the backend lane that actually executed
This distinction matters most when execution_mode: :remote_node is involved.
Lane Policies
:corealways resolves toASM.ProviderBackend.Coreand does not probe or load optional provider SDK runtime modules:sdkresolves toASM.ProviderBackend.SDKonly when the provider runtime kit is installed locally:autoprefers:sdkwhen that runtime kit is available locally, otherwise it uses:core
An explicit lane: :sdk without a loadable SDK runtime fails as a config error
whose cause is %ASM.ProviderBackend.SdkUnavailableError{}. It never falls
back to the core backend. lane: :auto is the only lane that may fall back to
core for SDK absence.
Use ASM.ProviderRegistry.provider_info/1 when you want provider-level facts,
lane_info/2 when you want discovery without execution-mode compatibility, and
resolve/2 when you need the effective backend choice for a real run.
lane_info(provider, lane: :core) intentionally does not check SDK
availability. Use provider_info/1 when you explicitly need provider SDK
availability discovery.
Local Versus Remote Execution
Lane selection remains discovery-driven in both modes:
- local runs can execute either
:coreor:sdk - local
:coreand local:sdkpreserve the same normalizedexecution_surfacecontract - remote runs execute only the core lane in the landed Phase 3 boundary
lane: :sdkwithexecution_mode: :remote_nodeis a configuration errorlane: :automay still reportpreferred_lane: :sdkbut execute withlane: :core
Typical remote auto-lane resolution:
{:ok, resolution} =
ASM.ProviderRegistry.resolve(:codex,
lane: :auto,
execution_mode: :remote_node
)
resolution.observability
# %{
# requested_lane: :auto,
# preferred_lane: :sdk,
# lane: :core,
# backend: ASM.ProviderBackend.Core,
# execution_mode: :remote_node,
# lane_fallback_reason: :sdk_remote_unsupported,
# ...
# }Observability Fields
Lane resolution is projected into both streamed %ASM.Event{} metadata and the
final %ASM.Result.metadata map.
Common fields:
requested_lanepreferred_lanelanebackendexecution_modelane_reasonlane_fallback_reasonsdk_runtimesdk_available?capabilities
That shared metadata keeps stream consumers and one-shot query consumers in sync about which runtime path actually executed.