Skip to content

refactor(agent): share model endpoint resolution - #7942

Open
shellz-n-stuff wants to merge 1 commit into
mainfrom
codex/launcher-endpoints
Open

shellz-n-stuff wants to merge 1 commit into
mainfrom
codex/launcher-endpoints

Conversation

@shellz-n-stuff

@shellz-n-stuff shellz-n-stuff commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Centralize model endpoint selection so external launchers can resolve the same destination as the agent without reading credentials or making network requests. Existing provider defaults and overrides are unchanged.

This has an explicit use-case for network sandboxing as it ensures you can't accidentally prevent your agent from talking to a required provider endpoint.

Stack 1/3: base main; next: TLS trust snapshots.

Validation: endpoint regression test passes; commit hooks pass. No plugin dependency.

Review / merge order: #7942 → #7943 → #7944. Related: #5286. Replaces #7940.

Required push checks passed for this branch. Hosted CI is tracked on the PR.

@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

🔐 Codex Security Review

Status: review required for the current range.

The current range is 12670bd0f037c66a682272bb81c46c3f254fad74...68c005869b8d4faf627a76253f5dddeb37c495ce.
A new review must complete for this exact range. When manual authorization
is required, a Block organization member must comment exactly
@buzz-security-review 68c005869b8d4faf627a76253f5dddeb37c495ce to authorize a new review.
Any previous review applies only to its recorded range.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1bb547c2d7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

//! Endpoint resolution shared by agent startup and desktop security suggestions.
use super::Provider;

pub fn provider_base_url(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Document the public endpoint resolver

provider_base_url is newly exposed through the public config::endpoint module but has no Rustdoc describing its lookup contract, provider defaults, or the required Databricks host. Add a doc comment, or restrict its visibility if it is not intended for external launchers, to satisfy the repository requirement that every new public API be documented.

AGENTS.md reference: AGENTS.md:L193-L196

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems overkill for a lookup?

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-28T15:23:00.268833Z 1bb547c Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Signed-off-by: Alex Rosenzweig <arosenzweig@squareup.com>
@shellz-n-stuff
shellz-n-stuff force-pushed the codex/launcher-endpoints branch from 1bb547c to 68c0058 Compare September 28, 2026 23:14

@wpfleger96 wpfleger96 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 hey @shellz-n-stuff, thanks for splitting the stack up like this, it made it easy to review.

The from_env refactor looks right to me. As far as I can tell the defaults, the DATABRICKS_HOST required error, and the order errors come out in are all unchanged, and the existing integration tests already push every base-URL env var through from_env. So I don't have concerns about how the agent behaves at startup. My comments are all about configured_endpoint, what it promises, and its test.

One small thing on the description: I'd scope "ensures you can't accidentally prevent your agent from talking to a required provider endpoint" down to buzz-agent model traffic. goose, Claude Code, and Codex each work out their own endpoints, and MCP servers, the relay, and the databricks CLI auth path aren't covered either. So a launcher that only allows this URL would still block things the agent needs.

The red Desktop Smoke E2E (4) shard looks unrelated. This PR only touches crates/buzz-agent, and shard 4 has also been red on main today on other specs (video-attachment, workflows), so I think a rerun should clear it.

Comment on lines +19 to +20
/// Resolve without fetching credentials, signing in, or making network requests.
pub fn configured_endpoint(lookup: impl Fn(&str) -> Option<String>) -> Option<String> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 I think this one needs a sentence or two of contract. My guess is that's why the bot keeps flagging it, though I agree full Rustdoc on provider_base_url would be overkill. Nothing in the repo calls configured_endpoint, and nothing in #7943 or #7944 does either. The module comment says desktop uses it, but I couldn't find a caller there. If the plan is for Sandpit to depend on buzz-agent as a crate, I'd say that here: it's for launchers, it returns the configured base URL (not a validated host or a full allowlist), overrides are returned as-is, and None means the provider is missing or unsupported, or it's Databricks with no host. The caller also has to pass the child's actual effective env.

Related: for an allowlist use case, OPENAI_COMPAT_BASE_URL="" coming back as Some("") is probably not what a launcher wants. I'd treat empty or whitespace-only values as unset here and leave from_env alone, since it already behaves that way on main.

Comment on lines +21 to +26
let provider = super::resolve_provider(
lookup("BUZZ_AGENT_PROVIDER").as_deref(),
Some("configured"),
Some("configured"),
Some("configured"),
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 The "configured" placeholders work because they happen to satisfy the three key-presence checks in resolve_provider, but that ties this function to resolve_provider's current parameters. If a provider later requires a different key, this would silently lie about it. I think it'd be cleaner to pull the name → Provider match out of resolve_provider into a small pure fn and have both call it.

Comment on lines +57 to +63
assert_eq!(
provider_base_url(&Provider::OpenAi, |_| Some(
"http://localhost:1234/v1".into()
))
.unwrap(),
"http://localhost:1234/v1"
);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 This lookup returns the custom URL for any key, so if OpenAI's override key accidentally became ANTHROPIC_BASE_URL this would still pass. Could this use a key-sensitive lookup, ideally with a different override set for each provider at once, and assert that only the selected provider's value wins? A table-driven test would also make it easy to add a couple of cases that aren't checked today: Databricks with no DATABRICKS_HOST (should be None), and a blank or unsupported BUZZ_AGENT_PROVIDER.

shellz-n-stuff added a commit that referenced this pull request Sep 30, 2026
## Summary

Replacing `BUZZ_ACP_AGENT_COMMAND` with a sandbox launcher hides the
real adapter from Buzz: for example, Goose loses its default `acp`
argument. Add optional `BUZZ_ACP_LAUNCH_PREFIX`, a JSON argument array
applied at the shared subprocess boundary, after normal worker
configuration.

On Unix, every spawn runs `prefix... worker args...` without shell
interpolation. Worker identity, environment setup, stdio and existing
process cleanup are preserved. Invalid or unavailable prefixes fail
launch without falling back to the worker; unset keeps direct launch on
every platform. Configured prefixes fail closed on non-Unix because
per-worker process-tree cleanup is unavailable. Desktop reserves the key
against saved user-environment overrides, and spawn failures name the
executable.

### Related issue

Prerequisite for [Buzz-App
#415](block/buzz-app#415). One commit directly
on `main`, independent of #7942–#7944. No duplicate launch-prefix PR
found. Policy enforcement, verified launcher staging, protected paths
and the supporting runtime pin remain Buzz-App/plugin work.

### Testing

- Original head `9ae9d82f8`: complete ACP suite (990 passed, three
existing ignored), shipped local-task test, real-Goose probe, and full
repository-wide `just ci` passed.
- Review fixes: five launch tests and 44 Desktop environment-filter
tests pass locally, covering the real production platform gate, save
rejection, both merge layers, case variants, and executable error
context.
- Subprocess tests cover direct/wrapped argument defaults, Pi skills,
Hermes/Codex environment, adapter identity, repeated spawns and
invalid/missing prefix refusal.
- Shipped `buzz-acp run` entrypoint completes a task through the wrapper
and deterministic ACP peer.
- Real Goose 1.52.0: direct and wrapped `auth-methods` return identical
results; the wrapper receives `goose acp` with initially empty worker
args.
- Independent agent review: no blocking findings.
- Required push checks passed on the updated head. The existing native
Windows CI job now explicitly runs the platform-contract tests. Its
result is pending; the non-Unix refusal branch was not exercised on this
macOS host.

Repeated-spawn coverage is not a full lazy-pool wake/crash test.
Protected Goose in the Buzz-App UI and human acceptance remain pending.

To try the hook after building `buzz-acp`, use an installed Goose path:

```sh
BUZZ_ACP_LAUNCH_PREFIX='["/usr/bin/env"]' target/debug/buzz-acp auth-methods \
  --agent-command /absolute/path/to/goose --agent-args '' --json
```

Expect the same authentication methods as without the prefix. Changing
the prefix to `["/missing-launcher"]` must fail. Draft pending human
testing.

Signed-off-by: Alex Rosenzweig <arosenzweig@squareup.com>

This branch has not been deployed

No deployments
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