M26-2: agent-type wizard step 3 — provider chain editor #549

Closed
opened 2026-04-29 12:24:11 +00:00 by claude-desktop · 1 comment
Collaborator

As an operator, I want to configure an agent type's provider chain through the /agents page wizard instead of hand-editing config/agents.json, so that I can add or reorder providers without restarting the service or worrying about JSON syntax.

Background

M26-1 lands the provider_chain schema + per-instance failover. Today the only way to set it is to hand-edit config/agents.json and POST it to /config/agents. The existing wizard at /agents (Add type / Edit type) covers basics + container + plugins but has no provider section.

Acceptance criteria

Wizard step

  • New step "Provider chain" sits between "Container" and "Plugins" in the Add-type and Edit-type wizards.
  • Renders a row per tier (1–3) with: provider dropdown (anthropic / deepseek / ollama), model combobox (live from GET /agents/models?provider=<id>).
  • [ + Add tier ] button — disabled at 3 rows.
  • [ × ] per row — disabled when only 1 row exists.
  • [ ↑ ] [ ↓ ] reorder via dnd-kit. Reordering renumbers tier field on save (UI never persists tier gaps).
  • cooldown_min numeric input (1–1440), pause_if_all_fail checkbox, triggers checkbox group (4 entries: auth_error, quota_error, rate_limit, persistent_5xx — token_budget greyed out with tooltip "pending M26-4").
  • Inline status column per row (read-only): "⬤ ready" when env / API key is reachable, "⚠ DEEPSEEK_API_KEY missing" / "⚠ Ollama unreachable" otherwise — pulled from GET /agents/models?provider=<id> returning fallback flag.

Validation (client-side, before PUT)

  • Tier 1 must be anthropic if the type is host-mode (matches loader gate).
  • No two tiers may have the same provider (warn, not error — operator may legitimately want anthropic→anthropic with different models).
  • Model combobox value must be in the listing or operator-typed (free-text fallback).

Wire-up

  • /agents/models?provider=<id> already exists from M26-1 hookup — wizard hits it on focus, caches response per session.
  • PUT /config/agents round-trips the new shape; legacy single-provider types render as a 1-tier chain in the wizard.

Tests

  • Component test: 3 tiers render, reorder swaps rows, model combobox updates on provider change.
  • Component test: host-mode type with tier 1 = deepseek shows blocking validation error.
  • Component test: cooldown_min < 1 shows inline error, save button disabled.
  • E2E: open Edit on dev, add a deepseek tier 2, save, GET /config/agents returns the new chain.

Out of scope

  • Tier badge in agents list — M26-3.
  • Failover event log + provider history sparkline — M26-3.
  • Per-instance override of type-level chain (today provider_chain is type-level only).

References

  • M26-1 (#TBD) — server schema this consumes.
  • Existing wizard: apps/web/src/routes/agents.tsx (Add type / Edit type drawers).
  • Live model listing: GET /agents/models?provider=<id> (handler at apps/server/src/main.ts::handleAgentsModels).
  • Reorder pattern: apps/web/src/features/flows/FlowCanvas already uses dnd-kit — reuse the same primitives.
As an **operator**, I want to configure an agent type's provider chain through the `/agents` page wizard instead of hand-editing `config/agents.json`, so that I can add or reorder providers without restarting the service or worrying about JSON syntax. ### Background M26-1 lands the `provider_chain` schema + per-instance failover. Today the only way to set it is to hand-edit `config/agents.json` and POST it to `/config/agents`. The existing wizard at `/agents` (Add type / Edit type) covers basics + container + plugins but has no provider section. ### Acceptance criteria #### Wizard step - [ ] New step "Provider chain" sits between "Container" and "Plugins" in the Add-type and Edit-type wizards. - [ ] Renders a row per tier (1–3) with: provider dropdown (anthropic / deepseek / ollama), model combobox (live from `GET /agents/models?provider=<id>`). - [ ] `[ + Add tier ]` button — disabled at 3 rows. - [ ] `[ × ]` per row — disabled when only 1 row exists. - [ ] `[ ↑ ] [ ↓ ]` reorder via dnd-kit. Reordering renumbers `tier` field on save (UI never persists tier gaps). - [ ] `cooldown_min` numeric input (1–1440), `pause_if_all_fail` checkbox, `triggers` checkbox group (4 entries: auth_error, quota_error, rate_limit, persistent_5xx — token_budget greyed out with tooltip "pending M26-4"). - [ ] Inline status column per row (read-only): "⬤ ready" when env / API key is reachable, "⚠ DEEPSEEK_API_KEY missing" / "⚠ Ollama unreachable" otherwise — pulled from `GET /agents/models?provider=<id>` returning fallback flag. #### Validation (client-side, before PUT) - [ ] Tier 1 must be `anthropic` if the type is host-mode (matches loader gate). - [ ] No two tiers may have the same provider (warn, not error — operator may legitimately want anthropic→anthropic with different models). - [ ] Model combobox value must be in the listing or operator-typed (free-text fallback). #### Wire-up - [ ] `/agents/models?provider=<id>` already exists from M26-1 hookup — wizard hits it on focus, caches response per session. - [ ] PUT `/config/agents` round-trips the new shape; legacy single-`provider` types render as a 1-tier chain in the wizard. #### Tests - [ ] Component test: 3 tiers render, reorder swaps rows, model combobox updates on provider change. - [ ] Component test: host-mode type with tier 1 = deepseek shows blocking validation error. - [ ] Component test: cooldown_min < 1 shows inline error, save button disabled. - [ ] E2E: open Edit on `dev`, add a deepseek tier 2, save, GET `/config/agents` returns the new chain. ### Out of scope - Tier badge in agents list — **M26-3**. - Failover event log + provider history sparkline — **M26-3**. - Per-instance override of type-level chain (today `provider_chain` is type-level only). ### References - M26-1 (#TBD) — server schema this consumes. - Existing wizard: `apps/web/src/routes/agents.tsx` (Add type / Edit type drawers). - Live model listing: `GET /agents/models?provider=<id>` (handler at `apps/server/src/main.ts::handleAgentsModels`). - Reorder pattern: `apps/web/src/features/flows/FlowCanvas` already uses dnd-kit — reuse the same primitives.
Author
Collaborator

Shipped via PR #552 + #553 + #554. Final shape:

  • Provider section tab in the type editor (now an accordion <details> block per #554's redesign), shows up alongside Identity / Prompt / Routing / Skills / Thresholds / Container.
  • 1–3 tier rows with provider dropdown + model combobox. Datalist-backed combobox autocompletes from GET /agents/models?provider=<id> (live in #553) with free-text fallback.
  • + Add tier (max 3), × remove (min 1), ↑/↓ reorder. Tiers renumber to contiguous 1..N on save.
  • Failover block (only when chain ≥ 2): cooldown_min, pause_if_all_fail, trigger checkboxes (4 enabled + token_budget enabled per M26-5 follow-up).
  • M26-5 token budget input row appears under the failover block when the trigger is checked; binds usage_threshold_tokens.
  • Validation banner: host-mode + non-anthropic tier 1 (red, blocking), missing models (red), duplicate providers (warning).

Deviations from original spec:

  • Reorder via ↑/↓ buttons rather than dnd-kit (simpler, equivalent UX for max 3 rows).
  • Inline status column ("⬤ ready" / "⚠ env missing") not implemented — combobox falls through to free-text on missing key, banner covers misconfigurations.

Tests: 10 ProviderSection cases (legacy 1-tier render, add/remove/reorder, failover gate on chain length, validation banner, token_budget visibility, combobox list wiring).

Shipped via PR #552 + #553 + #554. Final shape: - `Provider` section tab in the type editor (now an accordion `<details>` block per #554's redesign), shows up alongside Identity / Prompt / Routing / Skills / Thresholds / Container. - 1–3 tier rows with provider dropdown + model combobox. Datalist-backed combobox autocompletes from `GET /agents/models?provider=<id>` (live in #553) with free-text fallback. - `+ Add tier` (max 3), `×` remove (min 1), `↑/↓` reorder. Tiers renumber to contiguous 1..N on save. - Failover block (only when chain ≥ 2): `cooldown_min`, `pause_if_all_fail`, trigger checkboxes (4 enabled + `token_budget` enabled per M26-5 follow-up). - M26-5 token budget input row appears under the failover block when the trigger is checked; binds `usage_threshold_tokens`. - Validation banner: host-mode + non-anthropic tier 1 (red, blocking), missing models (red), duplicate providers (warning). Deviations from original spec: - Reorder via `↑/↓` buttons rather than dnd-kit (simpler, equivalent UX for max 3 rows). - Inline status column ("⬤ ready" / "⚠ env missing") not implemented — combobox falls through to free-text on missing key, banner covers misconfigurations. Tests: 10 ProviderSection cases (legacy 1-tier render, add/remove/reorder, failover gate on chain length, validation banner, token_budget visibility, combobox `list` wiring).
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#549
No description provided.