Summary
POST /v1/runs accepts an optional agentId that is documented as the requested Agent Runtime adapter. When that agentId is unknown or not registered, the executor silently keeps using its default adapter instead of failing the run. That makes an explicit runtime selection unreliable.
Evidence
api/openapi.yaml:1812-1814 documents agentId as the adapter ID (claude-code, codex, opencode, orchestrator) and says only an omitted value defaults to the server default.
edge-server/internal/api/handlers.go:460-472 parses agentId, and edge-server/internal/api/handlers.go:534-546 passes it into RunProcessContext without validating it against AdapterRegistry before creating and accepting the run.
edge-server/internal/adapters/registry.go:76-90 correctly returns an error when a non-empty agentID is not registered.
edge-server/internal/lifecycle/process_executor.go:248-254 discards that error: it initializes adapter := e.adapter, calls Resolve(runCtx.AgentID), and only replaces the adapter if err == nil. On error, execution proceeds with the default adapter.
Impact
A caller can request a specific runtime and get a successful 202 Accepted, but the process may run under a different runtime. Examples:
- Requesting
codex on an Edge configured only with claude-code can run Claude Code instead of failing.
- A typo or stale
agentId silently changes model/tool/permission behavior.
- Product UI and Hub dispatch cannot reliably interpret the run as the adapter the user selected.
This is especially important because adapters have different permission flags, sandbox behavior, session-resume semantics, streaming formats, and model resolution.
Suggested fix
- Validate non-empty
agentId before creating the run, or make ProcessExecutor.Start return the registry resolution error before launching a process.
- Return a clear 400/404-style error such as
agent_adapter_not_found for an unknown explicit adapter.
- Keep default adapter fallback only for omitted
agentId.
- Add tests for explicit known adapter, omitted adapter defaulting, and explicit unknown adapter rejection.
Acceptance criteria
- Unknown non-empty
agentId cannot launch any process under the default adapter.
- The API response distinguishes omitted default selection from invalid explicit selection.
- Tests cover
POST /v1/runs and executor-level adapter resolution behavior.
Summary
POST /v1/runsaccepts an optionalagentIdthat is documented as the requested Agent Runtime adapter. When thatagentIdis unknown or not registered, the executor silently keeps using its default adapter instead of failing the run. That makes an explicit runtime selection unreliable.Evidence
api/openapi.yaml:1812-1814documentsagentIdas the adapter ID (claude-code,codex,opencode,orchestrator) and says only an omitted value defaults to the server default.edge-server/internal/api/handlers.go:460-472parsesagentId, andedge-server/internal/api/handlers.go:534-546passes it intoRunProcessContextwithout validating it againstAdapterRegistrybefore creating and accepting the run.edge-server/internal/adapters/registry.go:76-90correctly returns an error when a non-emptyagentIDis not registered.edge-server/internal/lifecycle/process_executor.go:248-254discards that error: it initializesadapter := e.adapter, callsResolve(runCtx.AgentID), and only replaces the adapter iferr == nil. On error, execution proceeds with the default adapter.Impact
A caller can request a specific runtime and get a successful
202 Accepted, but the process may run under a different runtime. Examples:codexon an Edge configured only withclaude-codecan run Claude Code instead of failing.agentIdsilently changes model/tool/permission behavior.This is especially important because adapters have different permission flags, sandbox behavior, session-resume semantics, streaming formats, and model resolution.
Suggested fix
agentIdbefore creating the run, or makeProcessExecutor.Startreturn the registry resolution error before launching a process.agent_adapter_not_foundfor an unknown explicit adapter.agentId.Acceptance criteria
agentIdcannot launch any process under the default adapter.POST /v1/runsand executor-level adapter resolution behavior.