Skip to content

[1/2] feat(agents): add a recommended agent setup (core) - #3344

Merged
tmellor-block merged 1 commit into
mainfrom
tmellor/recommended-agent-core
Nov 14, 2026
Merged

tmellor-block merged 1 commit into
mainfrom
tmellor/recommended-agent-core

Conversation

@tmellor-block

@tmellor-block tmellor-block commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Stack

  1. → [1/2] feat(agents): add a recommended agent setup (core) ([1/2] feat(agents): add a recommended agent setup (core) #3344) ← this PR
  2. [2/2] feat(agents): offer Automatic (Recommended) in Create agent and Identity ([2/2] feat(agents): offer Automatic (Recommended) in Create agent and Identity #3345)

What this adds

A way for a build to ship a recommended agent setup: which harness, model and thinking level a new agent should use. This PR is the non-UI part. It adds no screens. [2/2] adds the screens that use it.

If the setting is unset, as in every open-source build, nothing changes.

How it works

  • The candidate list. Packagers set BUZZ_RECOMMENDED_AGENT at build time. It is a JSON list of candidates, best first. Each one names a harness (goose, codex or claude-code), a model, a thinking level and a display label. goose candidates also name a provider. Vite checks the list and compiles it in. A bad value fails the build and names the field at fault without printing the value. A launch can also swap in its own list (setRuntimeCandidates).
  • Readiness checks. useRecommendedPick picks a setup for a new agent. It walks the list and asks each harness whether it is installed, signed in or set up, and whether it offers that model now. Each check has a time limit. A check that fails or runs out of time skips that candidate. It reports checking, none or found, plus which better candidates were skipped.
  • Following it at run time. An agent on the recommendation saves only a mark (preset: "recommended") and no model of its own. At run time, goose, Codex and Claude Code each use the first candidate for their own harness that they still offer. They check once per launch and look again a minute or more later, so a harness set up since then gets picked up. If none fits, the agent runs on the harness's own default instead of failing. Its harness never changes for it. A model or thinking pick that reaches a run for one of these agents is ignored, such as one saved in a Solo chat before the switch.
  • The synced mark. On a config channel the mark syncs next to the agent's settings, not inside them. Older versions ignore it and keep it when they edit. A synced revision that names a model, provider or thinking level takes the agent off the recommendation on every device.
  • Docs. docs/configuration.md documents the setting with placeholder values.

Testing

CI runs the suite. tsc --noEmit is clean locally.

🤖 Generated with Claude Code

@kazemek21 kazemek21 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Kyle reviewed the PR and the Nexus review-tracker notes and approved with the non-blocking comment below.

Posted by Codex (gpt-6.1-sol) on behalf of kylez

Comment thread src/bundled/codex/tabs.tsx Resolved
@tmellor-block
tmellor-block force-pushed the tmellor/recommended-agent-core branch 2 times, most recently from ed5523a to 466d7a7 Compare November 12, 2026 17:17

@atishpatel atishpatel left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 Review from atish's agent, against atish's guidance in the Buzz #buzz-onedotzero thread. I've numbered his points below, and the inline comments refer to them.

  1. Extendable presets. Ship "Automatic" now, but the data should already allow more named presets, e.g. [Automatic, Automatic (Remote), Manual].
  2. Recommended markers under Manual. Show which Remote and Local harness the company prefers, e.g. Remote → Builderlab (Recommended); Local → Goose (Recommended), Claude, Codex.
  3. Manual + "Default" model follows the company default. If someone picks a harness by hand but leaves the model on Default, we record that, so the agent moves when the default changes.
  4. Seamless updates for anyone on Automatic or Default.
  • Unset means unchanged: with no recommendation configured, the app behaves as it does today.
  • Easy-to-update config: an external YAML/JSON file, a LaunchDarkly flag or env vars, rather than only a build-time value.

Already good: unset means unchanged ✅. Saving only a mark and resolving at run time is the right base for point 4 ✅. Checks are time-limited and fall back to the harness default ✅.

Gaps in this PR (core):

  • The mark is one literal (preset: "recommended"), synced as recommended?: true. It can't name a second preset (point 1).
  • Candidates are limited to local harnesses (HARNESSES, !item.remote), so "Automatic (Remote)" can't be expressed (point 1).
  • The config has no field for a recommended harness per group, so the UI has nothing to mark (point 2).
  • The candidate list is compiled in at build time. setRuntimeCandidates has no caller, so every change needs a release.

Details are inline. None of this blocks shipping plain "Automatic" first. The ask is to get the schema and the mark into an extendable shape now, while nobody has saved data in this format yet.

Comment thread src/features/agents/recommended.ts Resolved
Comment thread src/features/agents/recommended.ts Resolved
Comment thread src/features/agents/recommended.ts Resolved
Comment thread src/features/agents/recommended.ts Resolved
Comment thread src/features/agents/agent-config.ts Resolved
@tmellor-block

Copy link
Copy Markdown
Contributor Author

🤖 Thanks for the review. We're keeping this stack tightly scoped to unblock shipping, while keeping these follow-ups possible:

  • MVP: the list is bundled at build time (this stack plus squareup/buzz-releases#132).
  • Next: fetch the list from a URL (the AI gateway) at launch, with the bundled value as the fallback.
  • Then: pick per person through the gateway.

On point 1, the saved and synced mark is already a string id (preset: "recommended"), so new presets need no format change. Points 2 and 3 and remote candidates are follow-up PRs. Details are in the inline replies.

@tmellor-block
tmellor-block force-pushed the tmellor/recommended-agent-core branch 3 times, most recently from 8195bf7 to 92f1fdc Compare November 13, 2026 18:27

@atishpatel atishpatel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 Re-reviewed at 92f1fdc: approving. No critical issues. With BUZZ_RECOMMENDED_AGENT unset, every path falls back to today's behaviour. The mark is saved as a string id beside settings, so older versions keep it and later presets need no migration. The ed5523a fix for the Codex negative cache looks right. The follow-ups agreed in the inline replies (named presets, Recommended labels, Manual "Default", a URL-backed config, writing down the harness-pinning decision) are fine as separate PRs.

@joahg joahg 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.

🤖 Not approving: this account does not approve UI-affecting changes, and this PR edits the bundled agent plugins under src/bundled/ (goose, Codex, Claude Code), including what an agent shows as its model. It needs a design or core-team reviewer. Two maintainers have already approved, so this is mostly a note on what I checked.

What I checked, against the "does this silently widen an agent" question:

  • Permissions/sandbox/tools: not touched. A candidate carries only harness, provider (goose), model, effort and label, and parseRecommended rejects any other field. The diff changes no permission, sandbox, approval or tool setting in any harness, so a recommended agent runs with the same defaults as a manual one.
  • Source: compiled in at build time from BUZZ_RECOMMENDED_AGENT, validated in vite.config.ts (a bad value fails the build). Unset (OSS builds) means recommendedCandidates() is empty and every new path falls back to current behavior. Nothing in this PR calls setRuntimeCandidates, so there is no remote source yet. Even then a candidate can only name a model that the harness itself lists (offers/recommends check the live catalog and the thinking level), and the harness set is a closed list of three.
  • Existing agents: unchanged. Only a config with preset: "recommended" and no model/provider/effort follows the recommendation, and only the new UI in [2/2] writes that mark. A synced revision without the mark takes the agent off it (resolveStart); one that names a model keeps it off.
  • Fallback: Create picks the first candidate whose harness is installed, ready and lists the model, else the next. At run time an agent keeps its own harness and, if none of that harness's candidates is offered, runs on the harness default instead of failing. Retries after 60s.

One note, inline: setRuntimeCandidates is the future trust boundary. Not blocking.

Not reviewed: the test files in detail, and goose sync() behavior when a marked agent's model changes mid-session once the recommendation is found.

Comment thread src/features/agents/recommended.ts Resolved
@tmellor-block
tmellor-block force-pushed the tmellor/recommended-agent-core branch from 92f1fdc to 0d550aa Compare November 13, 2026 21:09

@joahg joahg 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.

🤖 Not approving: this account does not approve UI-affecting changes, and this PR edits the bundled agent plugins under src/bundled/ (goose, Codex, Claude Code), including what an agent shows as its model. It still needs a design or core-team reviewer. Re-review of 0d550aa against my note on 92f1fdc; I read the delta and the head sources but did not run the app or tests.

Fixed

  • setRuntimeCandidates now runs a non-empty list through parseRecommended itself, so a runtime list gets the same closed harness set, field and unknown-field checks as the build's. An invalid list is ignored, the last good list is kept, and it returns false. undefined goes back to the build's list and [] still means "recommend nothing". The new test covers an out-of-set harness and an extra field, and the one service test that used a made-up echo harness through this path now uses a real id.

Still open

  • Nothing from my earlier note. No new findings in the delta (3 files: recommended.ts, recommended.test.ts, service.test.ts).
  • CI: Browser journeys (webkit, 4/18) and the aggregate CI required are failing on this head, and a few jobs are still pending. I could not read the failure log while the run is in progress; the same webkit shard also fails on #3345, so it may not be this change. Worth a rerun or a look before merge.
  • None of the edited files carries a FOUNDATION marker.

Packagers can set BUZZ_RECOMMENDED_AGENT, a JSON array of candidates
(harness, model, thinking level, label, and for goose a provider), best
first. Vite validates it and compiles it in; unset, as in every OSS build,
nothing changes.

- recommended.ts reads the list, marks an agent's config Recommended
  (preset: "recommended"), and finds what one harness's marked agents
  run on: the first candidate that harness offers here, once per launch.
  A remote execution target runs on its own default. Its header lists the
  interface the UI uses.
- useRecommendedPick(types) picks a setup for a new agent with a bounded
  check per harness (AgentType.recommends).
- goose, Codex and Claude Code follow the mark at run time, in summaries
  and in shared exports. onAutomatic(config, harness) says an agent is on
  Automatic; a model or effort pick that reaches a run for one, such as a
  Solo chat's saved before it switched, is ignored, so it runs on the
  recommendation.
- The mark syncs as a top-level preset beside settings in kind 45010; a
  synced model choice clears it.
- setRuntimeCandidates(list) lets a launch replace the compiled list.
- docs/configuration.md documents the setting.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Tim Mellor <[email protected]>
@tmellor-block
tmellor-block force-pushed the tmellor/recommended-agent-core branch from 0d550aa to ba229c2 Compare November 14, 2026 00:19
@tmellor-block

Copy link
Copy Markdown
Contributor Author

🤖 Small addition in ba229c2, so we can measure adoption: agent settings revisions (kind 45010) now carry a ["preset", "recommended"] tag when the agent is on Automatic, matching the preset already in the content.

  • The tag is set in artifactTemplate from the content itself, so both normal saves and History restores get it. A preset tag carried from an older head is always dropped, so the tag never disagrees with the content.
  • Only buzz.agent.settings revisions get it.
  • Why: the relay's Snowflake copy masks event content but not tags, so this lets us count Automatic agents over time without reading anyone's settings.
  • Tests: the template (on, off with a stale carried tag, other artifact types) and the real save path (fields → edited → template). docs/configuration.md mentions the tag.

@atishpatel atishpatel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 Re-reviewed the ba229c2ee delta. The preset tag is derived from each agent-settings snapshot, stale carried tags are replaced, and other artifact types do not gain one. Normal saves and History restores both go through artifactTemplate. Six affected config suites passed together locally at this head: 134 tests. Hosted CI is still running.

@joahg joahg 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.

🤖 Re-checked at ba229c2. The preset tag looks right. artifactTemplate derives it from the content, applies it only to buzz.agent.settings, and always drops a carried tag, so a normal save and a History restore can't disagree with the content. The tests cover on, off with a stale carried tag, and other artifact types. One P3: settingsPreset copies any non-empty string from content.preset into a plain-text tag. Today that can only be recommended. Consider an allowlist of known preset values, so a future or malformed preset can't put arbitrary text into tags that are readable without the content. The rest of the PR is unchanged since my last review, and the earlier points still hold. This needs a design or core-team reviewer for the UI.

@tmellor-block

Copy link
Copy Markdown
Contributor Author

🤖 Thanks. On the P3 allowlist: agreed it's a good guard. Today the app only ever writes recommended, so I'm leaving it out of this merge and will add it with the next change that adds a preset (named presets are already a planned follow-up). The remaining open threads were follow-ups the reviewer accepted as separate PRs, so I've resolved them.

@tmellor-block
tmellor-block merged commit 7b839bc into main Nov 14, 2026
64 checks passed
@tmellor-block
tmellor-block deleted the tmellor/recommended-agent-core branch November 14, 2026 01:03
wpfleger96 added a commit that referenced this pull request Nov 14, 2026
…y-unreads

* origin/main: (24 commits)
  [1/2] feat(agents): add a recommended agent setup (core) (#3344)
  test(browser): survive the live-stream restart a page-clock jump causes (#3442)
  chore(renovate): hold rusqlite below 0.41 for mesh-llm (#3438)
  test(browser): serve the diffs and CLI reload fixtures outside the navigation budget (#3445)
  test(browser): play the draft clip at rate 0 instead of looping it before the Play click (#3446)
  fix(status): reopen a status whose preset deadlines coincide as Today (#3449)
  fix(messages): tolerate a cancelled reaction-name chunk load (#3450)
  fix(pairing): tolerate /proc/net/tcp rows printed twice or missed (#3451)
  test(browser): wait on the signal each test asserts in local-agent-activity and message-navigation (#3444)
  Expose native channel headings to Solo sources (#3523)
  test(browser-host): run the 100,000-channel broker scale check alone in the measurements lane (#3447)
  fix(solo): keep every contributed destination action (#3516)
  fix(identity): report an issuer that keeps rate-limiting an agent as a limit (#2365)
  fix(identity): let a stuck at-launch sign-in copy its link (#2453)
  fix(profiles): open avatar previews on hover in compact density (#3510)
  feat(solo): smooth chat recency reordering (#3502)
  Reject self-mentions that cannot wake another session (#3513)
  feat(status): offer don't clear for every status (#3515)
  Let plugin panels name their tab with panels.useTabTitle (#3251)
  fix(agents): report a conversation wake that fails before its turn starts (#2192)
  ...

# Conflicts:
#	tests/browser/message-management.spec.mjs
tmellor-block added a commit that referenced this pull request Nov 14, 2026
… Identity (#3345)

## Stack

Depends on the recommended-agent core in
[#3344](#3344). This PR adds the
setup controls and agent-card presentation.

## What changes

Builds with a recommendation offer **Automatic** and **Custom** in
Create agent and the Identity settings for local agents. Builds without
a recommendation keep the existing controls.

- **Automatic** selects the recommended harness, model and thinking
level. The closed settings row shows **Set to [model] (recommended)**;
the model truncates on one line while the parenthetical remains visible.
- The Automatic option puts the recommender before the optional
description, with the active model details beneath it. Attribution and
description come from configuration; the shared default makes no promise
about cost or update frequency.
- The settings icon gently cycles between the AI icon and active harness
logo. Custom and reduced-motion settings use a static harness logo.
- When no recommended setup is usable, **Custom remains available**,
including hosted-agent creation. Automatic still requires a usable
recommendation.
- **Custom** reveals the existing Harness, Model and Thinking controls
in place. Its closed row omits the redundant model byline. Choosing
model, provider or thinking settings in Identity turns Automatic off.
- On the **Agents page**, Automatic agents show their model’s display
name followed by **(Automatic)** beside the cycling icon. This is a
read-only detail aligned with the other cards’ model rows and uses the
default text color.
- In chat, Automatic agents keep session controls while model and
thinking controls are hidden. Custom agents keep their existing
controls.

The recommendation setting accepts the existing candidates array or an
object containing `candidates`, optional `recommendedBy`, and optional
`description`. Attribution stays with the current recommendation rather
than being copied into saved agents. Hosted agent types retain their own
settings.

## Validation

Current head: `ee16e32f3885cdf374fb3508d7c58d9bc4462923`, rebased onto
the updated core. [Current-head
review](#3345 (review))
confirms the four UI commits are patch-identical to the previously
approved stack and reports **1,068 passed, one skipped** across eleven
affected component/config/service suites. [Hosted CI
passed](https://github.com/block/buzz-app/actions/runs/43534228146) on
this exact head, including `CI required`.

Local behavior evidence at `4d5014295583e185716ac3e49249e7b1e43f0645`:

- Related component/service checks: **1,033 passed, one existing skip**
across nine files, combining initial passes with final reruns of
affected files; this is not a single combined run. Includes Custom →
hosted harness → introduction → creation when no recommendation is
usable.
- Both TypeScript projects and mandatory pre-push related-unit/design
checks passed.
- Four Chromium/WebKit fixture checks passed, exercising narrow/wide
layout in both themes: model truncation, visible recommendation suffix,
and separation of description/model details. These establish browser
layout, not native acceptance.
- One browser geometry case was added because DOM-emulated tests cannot
prove wrapping/truncation. No browser cases were removed. Existing mode,
settings-retention and fallback assertions remain; stale label
assertions were updated for Custom and the new summary.
- Test-volume audit: changed files contain 841 → 848 named test
declarations (parameterized runtime cases counted separately). Tests
account for +1,558/−30 lines versus +1,221/−216 non-test lines in this
PR, so test changes exceed half the diff. The audit retained distinct
parser, metadata, host-wiring and recovery coverage.

At `fd3ee535098e7c411852ba847cce01911b29ba23`, the running macOS desktop
build was exercised through the Agents page and Automatic → Custom mode
switching in an unsaved Create draft. The draft was closed without
creating or changing an agent. This verifies the captured native
rendering and mode transition; broader native states are not covered by
these captures. The full Biome check and mandatory push hooks also
passed on that pre-rebase head.

## Screenshots

Actual macOS desktop captures at
`fd3ee535098e7c411852ba847cce01911b29ba23`; see the [native check
notes](#3345 (comment)).

| Agents page: aligned model details |
| --- |
| ![Agent cards showing the friendly model name and Automatic
status](https://github.com/user-attachments/assets/53a91878-ddc7-48de-b3ef-8e5c04b3869f)
|

| Automatic setup | Custom setup |
| --- | --- |
| ![Automatic setup with recommendation and model
details](https://github.com/user-attachments/assets/cf116d26-d7e2-4cf1-b919-57b3853ab8f4)
| ![Custom setup with Harness, Model and Thinking
controls](https://github.com/user-attachments/assets/2593215e-a1a4-4943-a542-e21433726fea)
|

---------

Signed-off-by: Tim Mellor <[email protected]>
Signed-off-by: Taylor Ho <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Taylor Ho <[email protected]>
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
wpfleger96 added a commit that referenced this pull request Nov 14, 2026
* origin/main: (27 commits)
  [2/2] feat(agents): offer Automatic (Recommended) in Create agent and Identity (#3345)
  fix(solo): preserve and resume unsent chat drafts (#3525)
  fix(builderlab): give refused app sign-ins and Identity links a route to Organization sign-in (#3078)
  fix(agents): say why Import an agent can't import here, and link Manage plugins (#3073)
  [1/2] feat(agents): add a recommended agent setup (core) (#3344)
  test(browser): survive the live-stream restart a page-clock jump causes (#3442)
  chore(renovate): hold rusqlite below 0.41 for mesh-llm (#3438)
  test(browser): serve the diffs and CLI reload fixtures outside the navigation budget (#3445)
  test(browser): play the draft clip at rate 0 instead of looping it before the Play click (#3446)
  fix(status): reopen a status whose preset deadlines coincide as Today (#3449)
  fix(messages): tolerate a cancelled reaction-name chunk load (#3450)
  fix(pairing): tolerate /proc/net/tcp rows printed twice or missed (#3451)
  test(browser): wait on the signal each test asserts in local-agent-activity and message-navigation (#3444)
  Expose native channel headings to Solo sources (#3523)
  test(browser-host): run the 100,000-channel broker scale check alone in the measurements lane (#3447)
  fix(solo): keep every contributed destination action (#3516)
  fix(identity): report an issuer that keeps rate-limiting an agent as a limit (#2365)
  fix(identity): let a stuck at-launch sign-in copy its link (#2453)
  fix(profiles): open avatar previews on hover in compact density (#3510)
  feat(solo): smooth chat recency reordering (#3502)
  ...

# Conflicts:
#	src-tauri/src/federated_identity/agent/tests.rs
#	src-tauri/src/federated_identity/mod.rs
#	src-tauri/src/federated_identity/protocol.rs
joahg added a commit to joahg/buzz-app that referenced this pull request Nov 14, 2026
* origin/main: (133 commits)
  Expose ordinary chats without workspace headings (block#3530)
  [2/2] feat(agents): offer Automatic (Recommended) in Create agent and Identity (block#3345)
  fix(solo): preserve and resume unsent chat drafts (block#3525)
  fix(builderlab): give refused app sign-ins and Identity links a route to Organization sign-in (block#3078)
  fix(agents): say why Import an agent can't import here, and link Manage plugins (block#3073)
  [1/2] feat(agents): add a recommended agent setup (core) (block#3344)
  test(browser): survive the live-stream restart a page-clock jump causes (block#3442)
  chore(renovate): hold rusqlite below 0.41 for mesh-llm (block#3438)
  test(browser): serve the diffs and CLI reload fixtures outside the navigation budget (block#3445)
  test(browser): play the draft clip at rate 0 instead of looping it before the Play click (block#3446)
  fix(status): reopen a status whose preset deadlines coincide as Today (block#3449)
  fix(messages): tolerate a cancelled reaction-name chunk load (block#3450)
  fix(pairing): tolerate /proc/net/tcp rows printed twice or missed (block#3451)
  test(browser): wait on the signal each test asserts in local-agent-activity and message-navigation (block#3444)
  Expose native channel headings to Solo sources (block#3523)
  test(browser-host): run the 100,000-channel broker scale check alone in the measurements lane (block#3447)
  fix(solo): keep every contributed destination action (block#3516)
  fix(identity): report an issuer that keeps rate-limiting an agent as a limit (block#2365)
  fix(identity): let a stuck at-launch sign-in copy its link (block#2453)
  fix(profiles): open avatar previews on hover in compact density (block#3510)
  ...

Signed-off-by: Joah Gerstenberg <[email protected]>

# Conflicts:
#	src/bundled/codex/prompt.test.ts
#	src/bundled/goose/runtime.ts
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.

4 participants