From c84d87bd4d27f3c8a885b0515b4dbe36018d047a Mon Sep 17 00:00:00 2001 From: Tom O'Rourke Date: Sat, 18 Apr 2026 15:32:58 +0100 Subject: [PATCH 1/2] cli: add --provider flag to kagent install The install command previously only read the provider from the undocumented KAGENT_DEFAULT_MODEL_PROVIDER env var, defaulting silently to OpenAI. Users trying to install with Anthropic, Ollama or Azure OpenAI would see a confusing "OPENAI_API_KEY is not set" error with no indication that other providers were supported or how to select them. - Add --provider flag to kagent install (openAI, anthropic, azureOpenAI, ollama) - Flag overrides KAGENT_DEFAULT_MODEL_PROVIDER when set - Add shell completion for --provider values - Fix misleading error comments ("If model provider is openai") to be provider-agnostic - Add a hint in the error output pointing to --provider and KAGENT_DEFAULT_MODEL_PROVIDER when no provider flag was explicitly set --- go/core/cli/cmd/kagent/main.go | 4 ++++ go/core/cli/internal/cli/agent/const.go | 23 ++++++++++++++++++++++ go/core/cli/internal/cli/agent/install.go | 24 +++++++++++++++++++---- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/go/core/cli/cmd/kagent/main.go b/go/core/cli/cmd/kagent/main.go index 8792835b0..aa294a6ab 100644 --- a/go/core/cli/cmd/kagent/main.go +++ b/go/core/cli/cmd/kagent/main.go @@ -64,6 +64,10 @@ func main() { _ = installCmd.RegisterFlagCompletionFunc("profile", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return profiles.Profiles, cobra.ShellCompDirectiveNoFileComp }) + installCmd.Flags().StringVar(&installCfg.Provider, "provider", "", "LLM provider to use (openAI, anthropic, azureOpenAI, ollama). Overrides KAGENT_DEFAULT_MODEL_PROVIDER.") + _ = installCmd.RegisterFlagCompletionFunc("provider", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return cli.ValidProviders(), cobra.ShellCompDirectiveNoFileComp + }) uninstallCmd := &cobra.Command{ Use: "uninstall", diff --git a/go/core/cli/internal/cli/agent/const.go b/go/core/cli/internal/cli/agent/const.go index 885f44c5d..798c366b2 100644 --- a/go/core/cli/internal/cli/agent/const.go +++ b/go/core/cli/internal/cli/agent/const.go @@ -1,6 +1,7 @@ package cli import ( + "fmt" "os" "strings" @@ -63,3 +64,25 @@ func GetEnvVarWithDefault(envVar, defaultValue string) string { } return defaultValue } + +// ValidProviders returns the accepted --provider flag values (helm key format). +func ValidProviders() []string { + return []string{ + GetModelProviderHelmValuesKey(v1alpha2.ModelProviderOpenAI), + GetModelProviderHelmValuesKey(v1alpha2.ModelProviderAnthropic), + GetModelProviderHelmValuesKey(v1alpha2.ModelProviderAzureOpenAI), + GetModelProviderHelmValuesKey(v1alpha2.ModelProviderOllama), + } +} + +// applyProviderFlag validates the --provider value and sets KAGENT_DEFAULT_MODEL_PROVIDER so +// that GetModelProvider() picks it up. This lets users avoid setting the env var manually. +func applyProviderFlag(provider string) error { + valid := ValidProviders() + for _, v := range valid { + if provider == v { + return os.Setenv(env.KagentDefaultModelProvider.Name(), provider) + } + } + return fmt.Errorf("unknown provider %q — valid values: %s", provider, strings.Join(valid, ", ")) +} diff --git a/go/core/cli/internal/cli/agent/install.go b/go/core/cli/internal/cli/agent/install.go index 27f5577c9..e11501f09 100644 --- a/go/core/cli/internal/cli/agent/install.go +++ b/go/core/cli/internal/cli/agent/install.go @@ -20,8 +20,9 @@ import ( ) type InstallCfg struct { - Config *config.Config - Profile string + Config *config.Config + Profile string + Provider string } // installChart installs or upgrades a Helm chart with the given parameters @@ -76,16 +77,28 @@ func InstallCmd(ctx context.Context, cfg *InstallCfg) *PortForward { return nil } + // --provider flag takes precedence over KAGENT_DEFAULT_MODEL_PROVIDER env var + if cfg.Provider != "" { + if err := applyProviderFlag(cfg.Provider); err != nil { + fmt.Fprintln(os.Stderr, err) + return nil + } + } + // get model provider from KAGENT_DEFAULT_MODEL_PROVIDER environment variable or use DefaultModelProvider modelProvider := GetModelProvider() - // If model provider is openai, check if the API key is set + // Check if the required API key is set for this provider apiKeyName := GetProviderAPIKey(modelProvider) apiKeyValue := os.Getenv(apiKeyName) if apiKeyName != "" && apiKeyValue == "" { fmt.Fprintf(os.Stderr, "%s is not set\n", apiKeyName) fmt.Fprintf(os.Stderr, "Please set the %s environment variable\n", apiKeyName) + if cfg.Provider == "" { + fmt.Fprintf(os.Stderr, "Tip: use --provider to select a different LLM provider (e.g. --provider anthropic)\n") + fmt.Fprintf(os.Stderr, " or set %s=%s before running install\n", env.KagentDefaultModelProvider.Name(), GetModelProviderHelmValuesKey(v1alpha2.ModelProviderAnthropic)) + } return nil } @@ -120,13 +133,16 @@ func InteractiveInstallCmd(ctx context.Context, c *ishell.Context) *PortForward // get model provider from KAGENT_DEFAULT_MODEL_PROVIDER environment variable or use DefaultModelProvider modelProvider := GetModelProvider() - // if model provider is openai, check if the api key is set + // Check if the required API key is set for this provider apiKeyName := GetProviderAPIKey(modelProvider) apiKeyValue := os.Getenv(apiKeyName) if apiKeyName != "" && apiKeyValue == "" { fmt.Fprintf(os.Stderr, "%s is not set\n", apiKeyName) fmt.Fprintf(os.Stderr, "Please set the %s environment variable\n", apiKeyName) + fmt.Fprintf(os.Stderr, "Tip: set %s to select a different provider (e.g. %s=%s)\n", + env.KagentDefaultModelProvider.Name(), env.KagentDefaultModelProvider.Name(), + GetModelProviderHelmValuesKey(v1alpha2.ModelProviderAnthropic)) return nil } From 0c9b512c28c0cedfdf534c0666539350755db0c7 Mon Sep 17 00:00:00 2001 From: Tom O'Rourke Date: Sat, 18 Apr 2026 15:46:06 +0100 Subject: [PATCH 2/2] Address Copilot review: sync help text, ASCII punctuation, gate provider tip - Generate --provider help string from ValidProviders() instead of hard-coding the list (keeps docs, completion, and validation in sync) - Replace Unicode em dash with ASCII colon in error message - Only show --provider tip when the error is for the default OpenAI selection, not when a user explicitly chose a non-OpenAI provider Co-Authored-By: Claude Opus 4.6 (1M context) --- go/core/cli/cmd/kagent/main.go | 3 ++- go/core/cli/internal/cli/agent/const.go | 2 +- go/core/cli/internal/cli/agent/install.go | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/go/core/cli/cmd/kagent/main.go b/go/core/cli/cmd/kagent/main.go index aa294a6ab..bfec18610 100644 --- a/go/core/cli/cmd/kagent/main.go +++ b/go/core/cli/cmd/kagent/main.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "strings" "os/signal" "syscall" "time" @@ -64,7 +65,7 @@ func main() { _ = installCmd.RegisterFlagCompletionFunc("profile", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return profiles.Profiles, cobra.ShellCompDirectiveNoFileComp }) - installCmd.Flags().StringVar(&installCfg.Provider, "provider", "", "LLM provider to use (openAI, anthropic, azureOpenAI, ollama). Overrides KAGENT_DEFAULT_MODEL_PROVIDER.") + installCmd.Flags().StringVar(&installCfg.Provider, "provider", "", fmt.Sprintf("LLM provider to use (%s). Overrides KAGENT_DEFAULT_MODEL_PROVIDER.", strings.Join(cli.ValidProviders(), ", "))) _ = installCmd.RegisterFlagCompletionFunc("provider", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return cli.ValidProviders(), cobra.ShellCompDirectiveNoFileComp }) diff --git a/go/core/cli/internal/cli/agent/const.go b/go/core/cli/internal/cli/agent/const.go index 798c366b2..2592379cb 100644 --- a/go/core/cli/internal/cli/agent/const.go +++ b/go/core/cli/internal/cli/agent/const.go @@ -84,5 +84,5 @@ func applyProviderFlag(provider string) error { return os.Setenv(env.KagentDefaultModelProvider.Name(), provider) } } - return fmt.Errorf("unknown provider %q — valid values: %s", provider, strings.Join(valid, ", ")) + return fmt.Errorf("unknown provider %q: valid values: %s", provider, strings.Join(valid, ", ")) } diff --git a/go/core/cli/internal/cli/agent/install.go b/go/core/cli/internal/cli/agent/install.go index e11501f09..7f6959d6e 100644 --- a/go/core/cli/internal/cli/agent/install.go +++ b/go/core/cli/internal/cli/agent/install.go @@ -95,7 +95,7 @@ func InstallCmd(ctx context.Context, cfg *InstallCfg) *PortForward { if apiKeyName != "" && apiKeyValue == "" { fmt.Fprintf(os.Stderr, "%s is not set\n", apiKeyName) fmt.Fprintf(os.Stderr, "Please set the %s environment variable\n", apiKeyName) - if cfg.Provider == "" { + if cfg.Provider == "" && modelProvider == DefaultModelProvider && apiKeyName == env.OpenAIAPIKey.Name() { fmt.Fprintf(os.Stderr, "Tip: use --provider to select a different LLM provider (e.g. --provider anthropic)\n") fmt.Fprintf(os.Stderr, " or set %s=%s before running install\n", env.KagentDefaultModelProvider.Name(), GetModelProviderHelmValuesKey(v1alpha2.ModelProviderAnthropic)) }