Repository navigation
prototype: share a Databricks connection with Goose and Pi agents - #1036
Closed
salman1993 wants to merge 21 commits into
Closed
salman1993 wants to merge 21 commits into
salman1993 wants to merge 21 commits into
Conversation
A bundled `buzz.goose` plugin whose agents run as one `goose-acp` process each, with one ACP session per conversation. The Buzz tools reach goose over MCP-over-ACP (`mcp/message` on the same pipe), so the process holds no Buzz key. Uses the Claude plugin's Buzz prompt, appended with `_goose/unstable/session/system-prompt/set`; names sessions with `_meta.sessionTitle`; steers mid-turn messages with `_goose/unstable/session/steer`. Provider and model come from the owner's goose config unless the agent names its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Salman Mohammed <smohammed@squareup.com>
- New agent: the Goose type menu offers goose's own default provider and model, or a dialog to choose a provider, save its key into goose, pick a model, and test the connection. The card body keeps only instructions. - Settings: provider and model per agent, and Runtime diagnostics listing the agent's goose sessions with their transcripts, read through session/list and _goose/unstable/session/export. - A turn that writes text without calling send is posted as the agent's reply rather than reported as a failure. - A missing goose-acp says so; test connection deletes its session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Salman Mohammed <smohammed@squareup.com>
A bundled agent type for macOS and Linux whose agents run on Pi durable (@earendil-works/pi-durable), with any provider built into Pi. One Node host runs every Pi agent, each with its own SQLite storage; each Buzz thread or channel is one durable Pi conversation. - New agent offers Pi's default or a chosen provider and model, with keys saved to Pi's auth.json and a connection test. A provider that a Pi package adds, which Buzz does not load, is named as such. - Mentions steer a working run; a final buzz_send ends it; an answer that never used send is posted; failed turns are reported. Runs cut off by a stop continue from Pi's storage. - Watches and timers run as one-off conversations in their Interest's lane. The owner can pick a model and thinking level per turn. - Settings → Runtime diagnostics lists the agent's Pi conversations and shows each transcript, read from Pi's storage. - pi.sh installs Pi's packages once from a pinned lockfile with npm ci, on this computer's Node 22.19 or later. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Salman Mohammed <smohammed@squareup.com>
Follows #961: the Pi runtime takes each agent's AgentReads, as Claude's does, for owner attestation, Me chats, channels, the conversation before a turn, names and memory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Salman Mohammed <smohammed@squareup.com>
Pi still ships with Buzz, but like Todos and Bestie it starts off. Users turn it on in Settings → Plugins, and only then can they create Pi agents. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Salman Mohammed <smohammed@squareup.com>
pi-ai's credential stores treat a change that returns undefined as "leave the entry", and resolve with the entry after the change. Its OAuth refresh relies on that when another request or process refreshed first. Buzz's AuthFile deleted the entry instead, so two agents, or Buzz and the pi command, refreshing at once could sign the provider out of the auth.json they share. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Salman Mohammed <smohammed@squareup.com>
Signed-off-by: Salman Mohammed <smohammed@squareup.com>
… add Activity tab - A run that fails withdraws the requests queued to steer it, unanswered for the same reason, instead of leaving them for a later request. - A steer into a working run changes only the model or effort its owner picked, not the agent's configuration. - A request's answer is judged against the sends made after Pi placed it, not after its handover. - A turn whose retried attempt succeeded no longer shows the earlier error. - The provider dialog and Settings share one providers read with their fields, so Try again also updates what Use and Save allow. - Enter in the API key field saves the key, not the settings form. - A `!command` key that gave nothing runs again next time. - Pi's conversations move from Settings' Runtime diagnostics to an Activity tab, as for Claude Code and Codex. - Simplifications: useRead takes an abort signal and backs the transcript view; pi.sh has one entry point; effort labels and the once deadline come from Claude Code; unused props, fields, returns and exports are gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Salman Mohammed <smohammed@squareup.com>
main's New agent dialog (#966) replaced the type menu with one compact Model field per type, also shown on library cards. Pi's field lists its provider's models, starting on Pi's default, with a Provider… button that opens the existing provider dialog: provider, API key, model and Test connection. CreateModelChoices gains an optional trailing action for it. The menu, its open-state store and its trigger label are gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Salman Mohammed <smohammed@squareup.com>
…MCP (#1096) Signed-off-by: Salman Mohammed <smohammed@squareup.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…7284a' into claude/databricks-provider-goose-pi-a62d2a Signed-off-by: Salman Mohammed <smohammed@squareup.com> # Conflicts: # crates/plugin-manager/src/lib.rs # src/bundled/index.ts
Add a bundled Databricks provider plugin that owns browser sign-in, private credential storage, token refresh, and model discovery for Block's workspace. Goose agents choose "Databricks in Buzz" and an exact served GPT model; Buzz writes a Goose command-auth provider whose helper (the Buzz binary with --databricks-provider-token) prints fresh access tokens. Request formatting and streaming stay in Goose. The databricks-cli OAuth client accepts only http://localhost with an ephemeral port, so the shared loopback callback host gains an opt-in `localhost` callback host and bare-origin path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Salman Mohammed <smohammed@squareup.com>
The gateway's Chat Completions route rejects reasoning_effort when tools
are present ("Function tools with reasoning_effort are not supported for
gpt-6-luna"). A goose-wide GOOSE_THINKING_EFFORT in config.yaml reached
it, so tool-bearing turns and Test connection failed. Launch shared
Databricks agents with GOOSE_THINKING_EFFORT=none.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Salman Mohammed <smohammed@squareup.com>
Goose now reaches the shared Databricks connection through the gateway's Responses route instead of Chat Completions. The Chat route rejects reasoning effort alongside tools for GPT-6 models, and GPT-6.1 Sol always requires one, so the Responses route keeps the user's goose thinking effort and replaces the GOOSE_THINKING_EFFORT=none workaround. Replace the GPT-only filter with the endpoints verified with Goose's and Buzz's tools: GPT-6 and 6.1, Claude Opus/Sonnet/Haiku 5.5, GLM 5.3, and Grok 4.7. A provider file written for an earlier route is rewritten rather than reused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Salman Mohammed <smohammed@squareup.com>
main's #966 replaced CreateModelMenu and createModelLabel with a compact CreateModel field. goose now offers its provider's models there, with a Provider… button for its provider dialog, as Pi does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Salman Mohammed <smohammed@squareup.com>
The shared catalog now lists every AI Gateway API a model serves instead of one route Goose chose, and hands agents the token helper command so a host can fetch fresh access tokens itself. Goose keeps only models served on the MLflow Responses route it configures. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Salman Mohammed <smohammed@squareup.com>
Pi's provider list leads with Databricks in Buzz, signed in to with the Databricks plugin's connection rather than a key. The plugin maps each catalog model to its gateway route (Anthropic Messages for Claude, OpenAI Responses otherwise); the Pi host asks for that binding when it first needs the provider and registers it with pi-ai, borrowing limits and thinking levels from Pi's own models and running Buzz's token helper for each request's access token. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Salman Mohammed <smohammed@squareup.com>
Pi registers the shared provider in its host rather than loading the Databricks extension, since Buzz doesn't load Pi packages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Salman Mohammed <smohammed@squareup.com>
salman1993
force-pushed
the
codex/shared-databricks-provider
branch
from
October 14, 2026 21:20
4471d7a to
db09d64
Compare
Contributor
Author
|
this PR was a prototype to see if a provider plugin architecture made sense which could be shared among TLDR:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Goose and Pi can each use several inference providers, so today a user signs in to Databricks separately for each harness. provider-plugins-exploration.md proposes one shared provider plugin that owns sign-in and model discovery, while each agent plugin keeps its own inference code. This PR implements that doc's first two slices: one Databricks connection, used by both Goose and Pi agents.
What
buzz.databricksplugin adds Settings → Providers → Databricks. It signs in to Block's Databricks workspace in the browser, stores credentials privately, refreshes tokens, and lists models along with the gateway routes each one serves.localhostcallback host and a bare-origin path. Thedatabricks-cliOAuth client only acceptshttp://localhost:{port}.How
Shared plugin
auth.json. They live in Buzz's local data directory, atproviders/databricks/credential.json(folder0700, file0600). A file lock serializes token refresh across Buzz and every agent process.apis). Agent plugins filter those routes. The plugin also gives agents the token helper: the Buzz binary run with--databricks-provider-token, which prints a fresh access token and exits before the app starts. The helper refreshes a token 60 seconds before it expires.Goose
custom_providers/buzz_databricks.json) with command auth that runs the helper.ai-gateway/mlflow/v1/responses). The Chat route rejects reasoning effort alongside tools for GPT-6 models, and GPT-6.1 Sol always requires one. With Responses, the user's Goose thinking effort still applies.src/bundled/goose/shared-provider.ts, limited to models the catalog says serve the Responses route. Gemini fails on Goose'sstream_options, and Gemma rejectsminimumin a tool schema, so neither is offered.Pi
src/bundled/pi/shared-provider.ts). The host asks for it with a new host→pluginprovidercall: when the provider is first needed, and again each time it lists that provider's models, in case the user signed in or the catalog changed. Pi's own providers never need this call.Risk
Medium, for a prototype. This PR targets
sm/goose-agent-plugin(#1096) and merges in the Pi branch (#1103), so the diff includes #1103's commits until that PR lands. Pi stays off by default.The OAuth callback change is opt-in, so existing callers (hosted communities, builderlab) keep
127.0.0.1and their own paths. The Databricks plugin is enabled by default and points at Block's workspace, which needs a decision before this stops being a prototype.Testing
On this head (
db09d64e2)src/bundled,src/features/providers, andsrc/features/agents: 2,760 tests.helperop, and Goose rejecting a model without the Responses route.sharedBindingroutes each model, and returns nothing for Pi's own providers.providercall.host.live.test.ts, run locally withPI_DEPSpointing at Pi's installed packages): the real host and pi-ai 1.1.0 ran against a fake local gateway and a fake token command./ai-gateway/anthropic/v1/messages?beta=true, and o3 to/ai-gateway/openai/v1/responses. Both usedAuthorization: Bearer <token>with nox-api-key.From the Goose prototype commits (carried into this branch; not rerun on this head)
#[ignore]Rust test (since removed) ranauthorize, the callback host,connect, andmodelsagainst the real workspace. Databricks acceptedredirect_uri = http://localhost:62166, and discovery returned 57 models.--databricks-provider-tokenexited 0 and printed one token.goose runcalled a stubbed Buzzsendtool with all nine models, each loaded with Buzz's 12 tool schemas and the developer tools, withGOOSE_THINKING_EFFORT: medium. All nine passed.Not yet done
Bigger picture
OpenRouter can follow the same boundary. Known gaps:
🤖 Generated with Claude Code