Skip to content

fix(desktop): let Goose agents use OpenAI-compatible provider URLs - #2905

Open
BradGroux wants to merge 1 commit into
block:mainfrom
BradGroux:agent/goose-custom-provider
Open

fix(desktop): let Goose agents use OpenAI-compatible provider URLs#2905
BradGroux wants to merge 1 commit into
block:mainfrom
BradGroux:agent/goose-custom-provider

Conversation

@BradGroux

@BradGroux BradGroux commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Addresses the Buzz-to-Goose runtime boundary in #2749. The structured base-URL UI remains in #3798.

What was happening

Goose already supports OpenAI-compatible providers when they are configured in Goose itself. The broken path is narrower: Buzz-managed Goose configuration can launch goose acp with a legacy endpoint URL in GOOSE_PROVIDER, or keep Buzz's canonical OPENAI_COMPAT_* values separate from the runtime variables Goose reads. That makes otherwise valid Buzz settings fail before or during model discovery.

What changes

  • Keep this PR focused on the Buzz-to-Goose runtime boundary; it no longer changes Buzz Agent configuration or provider UI.
  • Map openai-compat and valid legacy HTTP(S) provider values to GOOSE_PROVIDER=openai.
  • Mirror the canonical key and base URL into current Goose variables (GOOSE_PROVIDER__API_KEY and GOOSE_PROVIDER__HOST) and the supported OpenAI aliases (OPENAI_API_KEY, OPENAI_HOST, and OPENAI_BASE_URL).
  • Normalize aliases inside each configuration layer before merging, so global, persona, and agent precedence stays consistent regardless of which spelling is used.
  • Apply the same effective mapping to readiness, saved and unsaved model discovery, spawn, and spawn hashing.
  • Reject credential-bearing, query-bearing, fragment-bearing, or invalid HTTP(S) endpoint values before persistence.

#3798 remains the owner of structured OpenAI-compatible Base URL UI. This PR does not duplicate that work.

Verification

Verified on exact head bbf31271ea22cddebcead0bde60457818b13a580, rebased onto current main at b1b283cd4c7f926e12eeee8ae1f38c7471922b16:

  • Desktop static checks, formatting, and file-size ratchet passed.
  • Full Desktop JavaScript suite passed: 3,885 tests, 0 failures.
  • Desktop production build passed.
  • Tauri cargo check passed.
  • Full Tauri suite passed: 2,063 library tests and 3 mixer diagnostics, 0 failures, 14 ignored keychain/relay tests.
  • Strict Tauri Clippy passed with warnings denied.

No third-party credential or live remote endpoint was used. The regression coverage verifies the effective environment and discovery inputs Buzz produces for Goose; it does not claim packaged-GUI or Windows validation.

Scope

This changes only OpenAI-compatible provider translation for Goose. It does not change Buzz Agent provider behavior, add a dependency, or add overlapping configuration UI.

@BradGroux
BradGroux requested a review from a team as a code owner July 25, 2026 22:38
@BradGroux
BradGroux force-pushed the agent/goose-custom-provider branch from 788ff48 to 6ab056e Compare July 28, 2026 16:40
@BradGroux

Copy link
Copy Markdown
Contributor Author

I rebuilt this branch on current main rather than force-merging the old implementation through four overlapping runtime refactors.

The issue is still real: Buzz's canonical OpenAI-compatible settings and the environment Goose expects can diverge across readiness, model discovery, and spawn. However, #1968, #2773, #2974, and #3093 changed the correct integration seam. The refreshed implementation uses runtime metadata plus the current effective descriptor so every consumer gets the same provider alias and environment mapping.

Head 484f7e4518202434e6e91c76deb5bdd6fa555ec8 keeps openai-compat as the stored provider identity, supplies Goose's openai backend and runtime-native key/base-URL variables, preserves alias-aware global/persona/agent precedence, and remains compatible with legacy records that stored the endpoint in provider. The UI now separates the provider from its base URL and rejects credential-bearing, query-bearing, fragment-bearing, or non-HTTP(S) endpoints before save.

Verification includes all 3,725 Desktop JavaScript tests, Desktop typecheck, targeted Biome checks, native managed-agent tests, and strict native Clippy. No live third-party endpoint or credential was used, so the proof is the effective environment/discovery contract rather than a remote-provider smoke test.

@yashrajd

Copy link
Copy Markdown

AFAICT you can already configure and use openAI-compatible providers in Goose. And Goose is wired up with Buzz already when you install (at least i didn't manually configure anything for it). So if your openai-compat provider is setup with Goose it will already work in Buzz (screenshot below)

goose-with-openai-compat

#2827 is about enabling the openai-compatible provider in Buzz harness (not Goose or any other), just some wiring and UI stuff – this AFAICT is still missing.

@BradGroux BradGroux changed the title Let Goose agents use OpenAI-compatible provider URLs fix(desktop): let Goose agents use OpenAI-compatible provider URLs Jul 29, 2026
@BradGroux
BradGroux force-pushed the agent/goose-custom-provider branch from 6ab056e to 3662994 Compare July 30, 2026 02:26
@BradGroux

Copy link
Copy Markdown
Contributor Author

Thanks for the correction. You're right that Goose itself already supports OpenAI-compatible providers, and #2827 is the right place for Buzz Agent/onboarding Base URL UI.

The remaining bug in #2749 is narrower: when the provider is configured through Buzz, especially for legacy records that stored the endpoint URL as the provider, Buzz can launch Goose with that URL in GOOSE_PROVIDER and without translating OPENAI_COMPAT_* settings into the variables Goose reads.

I've rebased and narrowed this PR to that Buzz-to-Goose boundary. The overlapping Buzz Agent/UI changes are gone. Head 36629940a53ebd4c2568623103e1e9de999b857e maps the Buzz configuration to GOOSE_PROVIDER=openai, current GOOSE_PROVIDER__HOST/GOOSE_PROVIDER__API_KEY, and the supported OpenAI aliases while preserving legacy records.

The full Tauri suite now passes with 1,889 library tests plus 3 mixer diagnostics, strict Clippy is clean, and the Desktop checks/build and 3,781-test JavaScript suite pass.

@BradGroux
BradGroux force-pushed the agent/goose-custom-provider branch from 3662994 to e640378 Compare July 30, 2026 14:37
@BradGroux

Copy link
Copy Markdown
Contributor Author

Rebased this branch onto current block/buzz main at c55e421a0.

Head moved from 36629940a to e64037835. The only manual integration was in the agent configuration contributor rules: the newly landed shared-agent access rule remains rule 11, and this PR's provider-translation rule is retained as rule 12. The runtime translation implementation itself is unchanged.

Verification:

  • Tauri compile check passed.
  • Tauri tests passed: 1,889 library tests plus 3 mixer diagnostics; 14 keychain/relay-dependent tests remained explicitly ignored.
  • Strict Tauri Clippy passed with all targets and warnings denied.
  • git diff --check, DCO trailer checks, and the direct merge-base audit passed.

GitHub checks are rerunning on the new head.

@BradGroux
BradGroux force-pushed the agent/goose-custom-provider branch from e640378 to bbf3127 Compare August 1, 2026 00:51
@BradGroux

Copy link
Copy Markdown
Contributor Author

Rebased onto current main at b1b283cd4c7f926e12eeee8ae1f38c7471922b16 and re-audited this against #2749 and the current competing PR landscape.

The remaining change is still needed, but its boundary is narrower than the original issue: #3798 owns the structured base-URL UI, while this PR fixes the Buzz-to-Goose runtime translation for Buzz-managed and legacy settings. #3398 only aliases the API key and does not cover endpoint translation or the runtime paths here.

The rebase also tightened the implementation after a clean-context review:

  • Ordinary openai configuration no longer inherits a stale compatibility host.
  • Provider values and custom endpoint URLs are normalized before precedence is applied.
  • Legacy records no longer block unrelated saves; validation happens at the create/update and publication boundaries instead.
  • Custom harness aliases remain available without being rejected by generic OpenAI-compatible validation.

Exact-head verification on bbf31271ea22cddebcead0bde60457818b13a580:

  • Desktop static checks, typecheck, formatting, and file-size ratchet passed.
  • Full Desktop JavaScript suite: 3,885 passed, 0 failed.
  • Desktop production build passed.
  • Tauri cargo check passed.
  • Full Tauri suite: 2,063 library tests plus 3 mixer diagnostics passed, 0 failed, 14 ignored.
  • Strict Tauri Clippy passed with warnings denied.

No packaged-GUI or Windows validation was performed; the regression coverage verifies the effective environment and discovery inputs Buzz produces for Goose.

@BradGroux
BradGroux force-pushed the agent/goose-custom-provider branch from bbf3127 to 4c58859 Compare August 4, 2026 20:24
@BradGroux

Copy link
Copy Markdown
Contributor Author

Rebased onto block/buzz main at ce3cf3cd2591f132f286fbc0a42a9e6699d0b08d and rechecked the original report, the external feedback, the current runtime configuration path, and the overlapping provider work.

The feedback that Goose itself already supports OpenAI-compatible providers is correct, but it does not remove this PR's remaining Buzz-side bug. Current Buzz main still does not translate its canonical OPENAI_COMPAT_* settings into the GOOSE_PROVIDER__HOST and GOOSE_PROVIDER__API_KEY values Goose consumes across readiness, model discovery, and spawn. #3798 and #3398 cover UI and API-key slices; neither supplies the complete endpoint translation and precedence behavior implemented here. The PR therefore remains valid and was not closed.

The rebase required manual integration around the newer effective-config tiers, model-tuning fields, configuration-diff work, and spawn-snapshot layout. Those behaviors are preserved. I also corrected one integration defect exposed by the current file-size ratchet: provider mapping was moved out of the already-large discovery module into managed_agents/runtime/provider_env.rs, keyed by runtime ID, so discovery stays within its enforced size limit without changing the runtime contract.

Exact-head verification on 4c5885964fed7ef4fcd3913382b91cb4261e25ca:

  • Desktop policy/static checks passed, including formatting and the file-size ratchet.
  • Full Desktop JavaScript suite passed: 4,212 tests, 0 failures.
  • Desktop typecheck and production build passed.
  • Tauri formatting and cargo check passed.
  • Full Tauri suite passed: 2,220 library tests plus 3 mixer diagnostics, 0 failures; 13 library tests and the native latency gate remained explicitly ignored.
  • Strict Tauri Clippy passed with all targets and warnings denied.
  • git diff --check, conflict-marker scan, merge-base audit, and required DCO trailers passed.

No live third-party provider or credential was used. The proof remains the effective environment, precedence, discovery, readiness, and spawn contracts Buzz produces for Goose; packaged-GUI and Windows validation remain outside this branch's verified surface.

@BradGroux
BradGroux force-pushed the agent/goose-custom-provider branch from 4c58859 to 1265d0b Compare August 5, 2026 22:27
@BradGroux

Copy link
Copy Markdown
Contributor Author

Review and rebase summary

Reviewed the PR for accuracy against current block/buzz main at d42d60d64 and rebased the branch onto that commit.

What this PR does

Maps Buzz's canonical OpenAI-compatible provider settings into Goose's native provider environment variables. When a user selects openai-compat (or any HTTP base URL provider), the discovery and spawn paths now translate OPENAI_COMPAT_API_KEY/OPENAI_COMPAT_BASE_URL into GOOSE_PROVIDER=openai, GOOSE_PROVIDER__API_KEY, GOOSE_PROVIDER__HOST, and OPENAI_HOST. The is_openai_compatible_provider check is broadened to recognize any HTTP base URL, not just the two named aliases. Provider validation (validate_provider_value) is added at every write path: agent creation, agent update, persona create, persona update, and agent event building.

Accuracy review

  • The merge_runtime_provider_env_layers function correctly applies scope precedence: user env overrides definition env, and both override derived env. The test draft_agent_model_discovery_applies_aliases_with_scope_precedence verifies this.
  • The validate_provider_env_urls check rejects credential-bearing base URLs (https://user:secret@example.com/v1) without echoing the secret in the error message — the test confirms the error contains "cannot include credentials" but not "secret".
  • The apply_model_provider_prompt_update function now returns Result<(), String> so invalid provider values fail loudly instead of silently persisting. The linked-instance guard (persona_id check) still returns Ok(()) early.
  • The saved_agent_model_discovery_uses_descriptor_provider_mapping test verifies the full round-trip from a saved agent record through discovery env construction.
  • The external feedback from @yashrajd is addressed: Goose already supports OpenAI-compatible providers natively, and this PR fixes the remaining env-var mapping gap rather than duplicating Goose's own provider UI.
  • No unwrap() or expect() in production paths. No new dependencies.

Rebase result

Head moved from 4c5885964 to 1265d0b9e. No conflicts. git range-diff shows the patch is unchanged.

CI

DCO passes. Semgrep OSS and zizmor were pending at the time of this comment.

Co-authored-by: Brad Groux <bradgroux@hotmail.com>
Signed-off-by: Brad Groux <bradgroux@hotmail.com>
@BradGroux
BradGroux force-pushed the agent/goose-custom-provider branch from 1265d0b to 48b1207 Compare August 7, 2026 21:03
@BradGroux

Copy link
Copy Markdown
Contributor Author

Rebase and accuracy review (2026-08-07)

Rebased onto current main (2b873cf20). Conflict resolved — 52 commits applied, 1 file conflicted.

Branch state: 48b1207c7 (was 1265d0b9e) Mergeable: ✅ MERGEABLE · BLOCKED (branch protection — awaiting maintainer review)

Conflict resolution

desktop/src/features/agents/AGENTS.md — main added the owner-only-access build capability paragraph (extending item 11), while the branch added a new item 12 for provider translation metadata. Resolution: kept both — main's extended item 11 text followed by the branch's new item 12. No content lost.

Accuracy review

The PR adds provider-environment translation for Goose agents: when Buzz's canonical provider ID or env names differ from what the Goose harness reads, the mapping is declared on KnownAcpRuntime and applied after effective config precedence is resolved. The provider_env.rs module centralizes the translation logic with 231 lines of tests.

The implementation is clean: provider_env/tests.rs covers the OpenAI-compatible URL mapping, env-var precedence, and error cases. No unwrap()/expect() in production paths. No new dependencies — uses existing hex and serde crates.

The AGENTS.md documentation correctly states that provider translation belongs in runtime metadata, not duplicated across UI components or individual call sites.

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