Skip to content

feat(cli): add docker agent setup wizard, offered when no model is usable (phase 3 of #3442)#3499

Merged
Sayt-0 merged 3 commits into
mainfrom
feat/3442-setup-wizard
Jul 7, 2026
Merged

feat(cli): add docker agent setup wizard, offered when no model is usable (phase 3 of #3442)#3499
Sayt-0 merged 3 commits into
mainfrom
feat/3442-setup-wizard

Conversation

@Sayt-0

@Sayt-0 Sayt-0 commented Jul 7, 2026

Copy link
Copy Markdown
Member

Phase 3 of #3442: a guided path from "no API key" to a working model. Complements Phase 1 (#3452, actionable errors) and Phase 2 (#3489, docker agent doctor). Phase 4 (docs tutorial) stays a follow-up.

What it does

docker agent setup
  |- Cloud provider   -> pick provider -> paste key (hidden) -> store it
  |                      (macOS Keychain | pass | ~/.config/cagent/.env)
  `- Local model      -> check Docker Model Runner -> pull a model if none pulled
        -> ends with a ready-to-copy `docker agent run` line

docker agent run / bare docker agent   (interactive, no usable model)
  -> failure printed -> "Run the interactive setup now?" -> wizard -> retry once
     (decline -> one-line error, exit 1; non-TTY / --exec unchanged)

Issue expectations vs implementation

Phase 3 expectation Status
interactive wizard: pick provider, paste key yes; the 18 providers of the auto-selection table, priority order, hidden input via term.ReadPassword
choose where to store it (env file, keychain, pass) yes; stores are the write-side counterparts of the read-side providers, offered when usable on the machine
local path: check DMR, pick and pull a model yes; reuses dmr.ListModels (doctor) and a new dmr.Pull (run-path pull minus the second confirmation)
ends with a ready-to-copy docker agent run line yes, plus the --model provider/model variant and a doctor pointer
offered automatically when bare docker agent or an interactive run finds no usable model (TTY only, decline-able) yes; classifies AutoModelFallbackError, dmr.ErrNotInstalled, RequiredEnvError with missing model credentials, and the first_available variant; retries the run once after a successful setup
complements the first-run tour (#3426) the offer only appears on failure, so it never competes with the tour

Open questions from the issue, resolved here

Question Choice made
where setup stores keys by default (keychain on macOS, pass on Linux, fallback ~/.config/cagent/.env?) store list is OS-ordered: Keychain first on macOS, pass when installed, env file always last (plain text, labeled as such). For the env file to be useful it becomes a default secret source (config-env-file, between run-secrets and credential-helper): read on every run, reported by doctor. Missing file skipped; malformed file logs a warning instead of blocking the chain (an implicit file must not lock every command out, unlike an explicit --env-from-file, which stays fatal per Phase 1)
offer setup on first run before the tour, or only on failure? only on failure, matching the flow diagram in the issue

Sample session

$ docker agent setup
Let's set up a model for docker agent.

How do you want to run models?
  1. Cloud provider (needs an API key)
  2. Local model via Docker Model Runner (no API key)
Choice [1]: 1

Pick a provider:
   1. anthropic       (ANTHROPIC_API_KEY)
   2. openai          (OPENAI_API_KEY)
   ...
Choice [1]: 1

Paste your anthropic API key (ANTHROPIC_API_KEY, input hidden):

Where should ANTHROPIC_API_KEY be stored?
  1. macOS Keychain
  2. docker agent env file (~/.config/cagent/.env, plain text)
Choice [1]: 1

Stored ANTHROPIC_API_KEY in the macOS Keychain.

You're all set. Start chatting with:

  docker agent run

Or pin the model explicitly: docker agent run --model anthropic/claude-sonnet-4-6
Check your setup anytime with `docker agent doctor`.

Implementation notes

  • pkg/environment/store.go: SecretStore interface + Keychain (security -i, command over stdin so the value never reaches argv, -U updates the item on re-runs), pass (insert -e -f, value over stdin), env file (0600, atomic write, upsert preserving comments and unrelated lines). Store names match the source names so the wizard and the doctor never diverge (asserted by a test).
  • cmd/root/setup.go: the command and the wizard behind test seams (scripted answers, fake stores, fake DMR); a failed store re-offers the locations without re-asking the key; EOF/Ctrl+C cancel cleanly.
  • Offer path: after a successful cloud setup the stored key is exported into the process env for the retry, because the run's provider chain was built before the key existed (keychain/pass lookups are live either way; a just-created env file is not).
  • Declining returns a one-line error (the full failure was printed just above the offer), keeping Phase 1's single-print guarantee.
  • "No usable model" errors (AutoModelFallbackError, RequiredEnvError, first_available variant, doctor issue line) now name docker agent setup, so non-TTY failures point at the same fix as the interactive offer.
  • Docs: CLI reference section for setup; secrets guide gains the config-env-file source (table, section, precedence).

Validation

Check Result
go build ./... ok
go test on cmd/..., pkg/environment, pkg/config, pkg/model/provider/dmr, pkg/cli ok (TestURLSource_Read_RejectsLocalAddresses and TestLoadExamples fail on main too in this sandboxed network)
golangci-lint run on touched packages 0 issues
go run ./lint . no offenses
end-to-end against a built binary (expect/PTY) cloud path to env file and to Keychain (round-trip read, doctor reports the source), local path (pull prompt, clean Ctrl+D cancel), offer on bare docker agent and run (decline: concise error, exit 1; accept: wizard, retry, TUI starts), DOCKER_AGENT_NO_SETUP=1 suppression, non-TTY setup errors with exit 1

Sayt-0 added 3 commits July 7, 2026 11:37
…urce

Write-side counterparts of the read-side secret providers, for the setup
wizard: macOS Keychain (security -i, value over stdin, never in argv),
pass (insert -e -f, value over stdin), and an env file at
~/.config/cagent/.env (0600, atomic write, upsert preserving other lines).

The config env file becomes a default secret source (config-env-file,
between run-secrets and credential-helper) so stored keys resolve on every
run without flags and show up in docker agent doctor. A missing file is
skipped; a malformed one logs a warning instead of blocking the chain,
unlike an explicit --env-from-file which stays fatal.
Same pull as the run path (skip when the model exists locally, recover
once from a corrupted partial download) but without the interactive
confirmation, for callers that already obtained consent such as the
setup wizard.
…able

Phase 3 of #3442.

docker agent setup walks either path interactively: pick a cloud provider,
paste its API key (hidden input) and choose where to store it (Keychain,
pass, or the docker agent env file), or check Docker Model Runner and pull
a local model. Ends with a ready-to-copy docker agent run line.

When an interactive run finds no usable model (auto selection fell
through, DMR not installed, or missing model credentials), the failure is
printed and the wizard offered, decline-able; on success the run is
retried once. Non-TTY and --exec runs are unchanged, and
DOCKER_AGENT_NO_SETUP=1 / CAGENT_NO_SETUP=1 suppress the offer for
scripted terminals. Declining returns a one-line error instead of
repeating the full failure text.

The no-usable-model errors (AutoModelFallbackError, RequiredEnvError,
the first_available variant, doctor's issue line) now name docker agent
setup so non-interactive failures point at the same fix.
@Sayt-0 Sayt-0 requested a review from a team as a code owner July 7, 2026 09:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants