-
Notifications
You must be signed in to change notification settings - Fork 572
Description
Defining any custom command line flags with the flag package causes the default launchers shipped by ADK to fail to parse their flags.
For example, in my demo agent, I want to use command-line flags to control the setup and configuration of the agent [1].
I include a flag:
var (
stateBucket = flag.String("state-bucket", "", "The GCS bucket to store the agent's persistent state")
)
And this cases the call to Execute() to fail:
flag provided but not defined: -state-bucket
Usage of console:
-otel_to_cloud
Enables/disables OpenTelemetry export to GCP: telemetry.googleapis.com. See adk-go/telemetry package for details about supported options, credentials and environment variables.
-shutdown-timeout duration
Console shutdown timeout (i.e. '10s', '2m' - see time.ParseDuration for details) - for waiting for active requests to finish during shutdown (default 2s)
-streaming_mode string
defines streaming mode (none|sse) (default "sse")
To work around this, I have to hackily filter out my flags from os.Args before I pass them to Execute()
// ADK's built-in launchers explode if they are handed arg lists with flags
// they don't understand. This is a problem if you want to have additional
// flags in your own main.
filteredArgs := os.Args[1:]
filteredArgs = slices.DeleteFunc(filteredArgs, func(x string) bool {
return strings.HasPrefix(x, "-state-bucket") || strings.HasPrefix(x, "--state-bucket")
})
The core problem here is that the flag package deliberately does not provide a way to parse a command-line while ignoring flags that are unrecognized. The Go team (correctly, IMO) believes that it is not possible to provide this feature safely, because it is not possible to know whether the sequence -foo -bar is an unknown flag foo with value -bar, or one unknown boolean flag -foo followed by a known boolean flag -bar.
According to the Google Go style guide [3], programs should only define flags in package main, and all other program configuration should be done by passing down Go objects or variables. I propose adopting this approach for the ADK launchers, perhaps supplementing with some utility functions to help the program author declare the flags each launcher is likely to need.
[1] https://github.com/ahmedtd/hermes/blob/73353fd23dfd246c6910f46cbeb8851e2a5b756f/cmd/hermes/hermes.go
[2] golang/go#58839
[3] https://google.github.io/styleguide/go/decisions#flags