google / google/adk-go

Using any custom flags in application's main file causes launchers to fail to parse their flags

Open
#606 1 comment 0 reactions 0 assignees View on GitHub
bug
Dominant language
Go
Stars
8.8k
Forks
1k
Avg merge
3d 18h
Merged PRs (30d)
88

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] https://github.com/golang/go/issues/58839
[3] https://google.github.io/styleguide/go/decisions#flags

Contributor guide

Open the contributing guide

Research direction

Start by inspecting the ADK default launchers and the Execute() entry point, then compare their flag parsing with Go's flag package behavior. Trace how os.Args reaches the launchers and determine how application-defined flags can coexist with launcher flags. Done means a main package can define custom flags without the shipped launchers failing to parse their arguments.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.