diff --git a/server/pkg/agent/models.go b/server/pkg/agent/models.go index bba0701fc..e47168e67 100644 --- a/server/pkg/agent/models.go +++ b/server/pkg/agent/models.go @@ -830,10 +830,14 @@ func discoverOpenclawAgents(ctx context.Context, executablePath string) ([]Model } // openclawAgentEntry is the shape parseOpenclawAgentsJSON expects -// from `openclaw agents list --json`. Both `name` and `id` are -// accepted as the identifier (different openclaw versions ship -// different field names); `model` is optional and only used to -// enrich the dropdown label. +// from `openclaw agents list --json`. `id` is the routing key +// passed to `openclaw agent --agent `; `name` is the human +// display label set via `openclaw agents set-identity --name` and +// is only used to enrich the dropdown label. The two are not +// interchangeable — see openclawEntriesToModels for the mapping. +// Older openclaw versions may emit only `name`; in that case we +// fall back to using it as the id for backward compatibility. +// `model` is optional and only used to enrich the dropdown label. type openclawAgentEntry struct { Name string `json:"name"` ID string `json:"id"` diff --git a/server/pkg/agent/openclaw.go b/server/pkg/agent/openclaw.go index b489681f2..7b341d1f9 100644 --- a/server/pkg/agent/openclaw.go +++ b/server/pkg/agent/openclaw.go @@ -178,10 +178,12 @@ func buildOpenclawArgs(prompt, sessionID string, opts ExecOptions, logger *slog. } // OpenClaw binds models to pre-registered agents at `openclaw agents // add/update --model` time; the daemon selects one at runtime by - // passing --agent . The model dropdown populates its list from - // `openclaw agents list`, so opts.Model here is an agent name. Only - // inject when the user hasn't already set --agent via custom_args — - // custom_args wins for backward compatibility with existing configs. + // passing --agent . The model dropdown populates its list from + // `openclaw agents list`, so opts.Model here is an agent id (see + // openclawEntriesToModels — the agent's display name lives in the + // dropdown label, not in opts.Model). Only inject when the user + // hasn't already set --agent via custom_args — custom_args wins for + // backward compatibility with existing configs. customArgs := filterCustomArgs(opts.CustomArgs, openclawBlockedArgs, logger) if opts.Model != "" && !customArgsContains(customArgs, "--agent") { args = append(args, "--agent", opts.Model)