Skip to content

Add Goose agent support via Databricks AI Gateway#61

Open
bkvarda wants to merge 4 commits into
databricks:mainfrom
bkvarda:add-goose-agent
Open

Add Goose agent support via Databricks AI Gateway#61
bkvarda wants to merge 4 commits into
databricks:mainfrom
bkvarda:add-goose-agent

Conversation

@bkvarda
Copy link
Copy Markdown

@bkvarda bkvarda commented May 21, 2026

Summary

  • Adds Goose as a fully supported ucode agent alongside codex, claude, gemini, opencode, copilot, and pi
  • Databricks provider: merges three managed keys (DATABRICKS_HOST, GOOSE_PROVIDER, GOOSE_MODEL) into ~/.config/goose/config.yaml while preserving user-defined extensions and preferences
  • Multi-model support: default_model prefers Claude (sonnet → opus → haiku) and falls back to Databricks-hosted Gemini models; check_gateway_endpoint and CLI discovery consumers updated accordingly
  • MCP: goose is a full MCP client; write_mcp_server_config/remove_mcp_server_config use goose's streamable_http extension format; OAUTH_TOKEN is injected at runtime and referenced via env_keys for extension header auth
  • Skills: the goose skills platform extension (type: platform) is enabled in the managed overlay so .goose/skills and .claude/skills tool directories are active by default
  • DATABRICKS_TOKEN is injected as an env variable at launch and refreshed every 30 minutes via a background thread — never written to the config file; OAUTH_TOKEN is set alongside it for MCP auth
  • Goose ships as a native Rust binary (not an npm package), so install_tool_binary now short-circuits with an actionable install message for tools with an empty package
  • Adds read_yaml_safe and write_yaml_file helpers to config_io.py, with pyyaml>=6.0 as a new runtime dependency
  • 52 focused unit tests (up from 34 in the initial draft); updated test_mcp.py and test_agents_init.py

Note: validated end-to-end against a real workspace including MCP discovery. The --profile fix required to make MCP discovery work with Databricks CLI v1.0.0 is tracked separately in #62 and should be merged first.

Test plan

  • Merge Pass --profile to databricks CLI listing commands (fixes MCP discovery with CLI v1.0.0) #62 first (fixes MCP discovery with CLI v1.0.0)
  • uv run pytest — all 566 tests pass
  • uv run ruff check . — no lint errors
  • Manual: ucode configure --agent goose merges config without overwriting user extensions; skills extension is enabled
  • Manual: ucode goose launches a Goose session with auto-refreshed token
  • Manual: ucode configure mcp discovers and saves external MCP connections to ~/.config/goose/config.yaml as streamable_http extensions

This pull request and its description were written by Isaac.

Goose (https://github.com/aaif-goose/goose) is a native Rust binary with a
built-in Databricks provider. This wires it into ucode alongside codex, claude,
gemini, opencode, copilot, and pi.

Key design decisions:
- Config is merged (not overwritten) into ~/.config/goose/config.yaml so that
  user-defined extensions and preferences survive reconfiguration.
- Only DATABRICKS_HOST, GOOSE_PROVIDER, and GOOSE_MODEL are managed; the token
  is injected as DATABRICKS_TOKEN at launch and refreshed every 30 minutes.
- Goose ships as a native binary (not an npm package), so install_tool_binary
  now short-circuits with a helpful message for tools with an empty `package`.
- Adds pyyaml as a runtime dependency for YAML config read/write.
- Adds read_yaml_safe and write_yaml_file helpers to config_io.py.
- 34 focused unit tests cover the full agent surface (spec, model selection,
  overlay rendering, runtime env, config write/merge, validate_cmd, validate_env).

MCP support (config.yaml extensions block) is a follow-up, consistent with Pi.

Co-authored-by: Isaac
@bkvarda bkvarda closed this May 21, 2026
- MCP: wire goose into MCP_CLIENTS; add write_mcp_server_config and
  remove_mcp_server_config using goose's streamable_http extension format;
  OAUTH_TOKEN is forwarded via env_keys and injected at runtime
- Skills: enable the goose skills platform extension in the managed overlay
  so .goose/skills and .claude/skills directories are loaded by default
- Gemini model support: default_model now falls back to gemini_models from the
  Databricks gateway; check_gateway_endpoint and _TOOL_DISCOVERY_SOURCES
  updated accordingly; cli discovery consumers include goose in both
  claude and gemini lookups
- build_runtime_env now sets OAUTH_TOKEN alongside DATABRICKS_TOKEN
- 52 goose unit tests (up from 34); updated test_mcp.py and test_agents_init.py

Co-authored-by: Isaac
@bkvarda bkvarda reopened this May 21, 2026
@bkvarda bkvarda force-pushed the add-goose-agent branch from 1729461 to 7655507 Compare May 21, 2026 22:36
Brandon Kvarda added 2 commits May 21, 2026 15:44
Goose resolves ${OAUTH_TOKEN} in streamable_http extension headers from
its config file, not the process environment. Without OAUTH_TOKEN as a
top-level key in config.yaml, goose fails to start any MCP extension
with: "Failed to fetch secret 'OAUTH_TOKEN' from config: Configuration
value not found: OAUTH_TOKEN".

write_tool_config now writes OAUTH_TOKEN alongside DATABRICKS_HOST so
goose can substitute it into the Authorization header of each registered
MCP extension. It is refreshed every 30 minutes by the background token
refresh thread alongside the rest of the managed config.

Co-authored-by: Isaac
Goose resolves env_keys from the system keyring (service="goose",
username="secrets"), not from config.yaml top-level keys. The token
written to OAUTH_TOKEN: in config.yaml was never found during
extension startup, causing "Configuration value not found: OAUTH_TOKEN".

The fix: store the token in the extension's envs dict instead.
Goose merges envs with env_keys before header substitution, so
${OAUTH_TOKEN} in the Authorization header resolves from envs.

write_tool_config now also refreshes envs.OAUTH_TOKEN for all
streamable_http extensions on every token refresh (every 30 min),
keeping long-running sessions authenticated. configure_client_mcp_server
fetches a fresh token when writing a new goose MCP extension.

Co-authored-by: Isaac
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.

1 participant