🤖 feat: advisors-as-code (configuration via .mux/advisors/<name>/ADVISOR.md)#3361
🤖 feat: advisors-as-code (configuration via .mux/advisors/<name>/ADVISOR.md)#3361ammar-agent wants to merge 2 commits into
Conversation
…SOR.md) Graduate the advisor tool from experimental to GA. Configuration shifts from Settings UI + cfg fields to per-advisor markdown files, mirroring the skills loader pattern. Multiple advisors can coexist; the model picks one per call via advisor_name. Opt-in by construction: the tool only appears when at least one ADVISOR.md is loaded. --- _Generated with `mux` • Model: `anthropic:claude-opus-4-7` • Thinking: `max` • Cost: `$10.51`_ <!-- mux-attribution: model=anthropic:claude-opus-4-7 thinking=max costs=10.51 -->
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0df6592532
ℹ️ 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".
Codex review caught that 'model: " "' parsed at load time but blew up at execute time, breaking the 'invalid files surface in diagnostics' invariant. Tighten the schema with a refine() so whitespace-only models fail at discovery (where they're collected into invalidAdvisors) instead of crashing the advisor turn.
|
@codex review Tightened |
|
Codex Review: Didn't find any major issues. Keep them coming! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
Summary
Graduate the advisor tool from experimental to GA. Configuration moves from a Settings UI + global cfg fields to per-advisor markdown files at
.mux/advisors/<name>/ADVISOR.md(mirroring the skills loader). Multiple advisors can coexist; the model selects one per call via a new requiredadvisor_nameparameter. Opt-in by construction: the tool only appears when at least one ADVISOR.md is loaded — no experiment toggle to remember, no settings page to discover.Background
The pre-GA advisor was one global model toggled via
Settings → Experiments → Advisor Tool, with per-agent enable switches under Tasks. The framing answered "should the advisor be on?" — which was the wrong question. The right question is "which specialist do I hand this to?", and that's what advisors-as-code captures.Key wins:
ml-fellowadvisor onopus + highfor theorem work coexists with acode-reviewadvisor onhaikufor PR review without either starving the other..mux/skills/. Same scope rules (project wins over global), same loader, same hot-reload (no caching, takes effect next turn), same diagnostics envelope (bad YAML doesn't crash the catalog).Implementation
File layout
Frontmatter schema
descriptionmodelprovider:modelform.thinkingoff.max_uses_per_turnnull= unlimited, positive int = cap. Defaults to 3.max_output_tokensagentsBody (after the closing
---) appends to the base advisor system prompt for per-advisor persona/voice/focus.Tool wiring
ToolConfiguration.advisorRuntimenow carriesadvisors: readonly AdvisorPackage[](already filtered by effective agent) anddefaultMaxUsesPerTurn. Per-advisor budgets read directly from frontmatter at execute time.AdvisorToolInputSchemaadds a requiredadvisor_name. Tool description is rebuilt per-stream with the live catalog, so the model discovers advisors there (not the system prompt — the prior<advisor-guidance>section is removed).advisor_name→ self-correctable error result that lists the live catalog, so the model can retry in the same turn instead of crashing it.ml-fellowrunning out of budget can't starvecode-review.Slash commands
/advisor/advisor init <name>.mux/advisors/<name>/ADVISOR.mdfrom a working template.ORPC:
advisors.list(diagnostics-flavored) +advisors.scaffold(returns the source path).Tool display
The advisor name becomes the lead identity pill in
AdvisorToolCall— e.g.,advisor [ml-fellow] · done · 3.2s— so the user sees which advisor handled the turn before drilling in for the underlying model.Gating refactor
resolveAgentForStreamtakesadvisorAvailable: boolean(wasisAdvisorExperimentEnabled) and opens the regex when any advisor is loaded; per-agent filtering via theagents:frontmatter field happens at runtime bundle assembly.EXPERIMENT_IDS.ADVISOR_TOOLgate,AdvisorToolExperimentConfig.tsx, the per-agentadvisorEnabledcfg field, and thecfg.advisor{ModelString,ThinkingLevel,MaxUsesPerTurn,MaxOutputTokens}keys are all gone. Old keys in user configs are silently ignored.aiService.tsis gone too — advisor guidance now lives in the tool description, so one build is always correct.Validation
aiService.test.tsharness to seed advisors via.mux/advisors/default/ADVISOR.mdfiles instead of cfg writes.make static-checkgreen;bun testshows 7957 pass / 1 pre-existing flake (GeneralSection > persists the collapsed bash summaries display mode— passes in isolation, fails in the full sweep due to happy-dom global isolation; unrelated to this change).Risks
AdvisorToolInputSchema(adds requiredadvisor_name). The pre-GA tool was experiment-gated and effectively unreleased to most users; transcripts pinned to the old shape become unreplayable, but the failure mode is bounded to advisor tool calls. Acceptable because the GA flip is atomic with the schema change.advisorModelString,advisorThinkingLevel,advisorMaxUsesPerTurn,advisorMaxOutputTokens,agentAiDefaults.<id>.advisorEnabled) are silently dropped via Zod's.passthrough(). Migration path:/advisor init defaultthen edit the file.experiments.advisorToolfield from the send-options chain andExperimentsSchema. Old clients sending it will have it stripped; backend behavior is unchanged.Pains
The pre-GA wiring threaded the experiment flag through 7+ files (
aiService.ts,agentResolution.ts,resolveToolPolicy.ts,streamContextBuilder.ts, send-options chain, Settings UI). Untangling those into the simpler "is any advisor loaded?" gate took most of the diff. The biggest cleanup win: the pre-policy/post-policy system prompt rebuild dance inaiService.tsis gone, because guidance now lives in the dynamic tool description instead of the system prompt.Generated with
mux• Model:anthropic:claude-opus-4-7• Thinking:max• Cost:$10.51