6b938b61cb
Co-authored-by: Carlos Florencio <carlosmflorencio@gmail.com>
106 lines
5.0 KiB
Markdown
106 lines
5.0 KiB
Markdown
---
|
|
status: draft
|
|
created: 2026-08-01
|
|
owner: kandev
|
|
---
|
|
|
|
# Disable an Agent Profile
|
|
|
|
## Why
|
|
|
|
A profile sometimes needs to be taken out of rotation — a model is being
|
|
retired, an agent CLI is misbehaving, or a workspace is migrating. Today the
|
|
only way to stop a profile being picked for new work is to delete it, which
|
|
blocks on active sessions and destroys its configuration. Users need a
|
|
reversible "off switch" that hides the profile from new-task selection while
|
|
leaving existing sessions untouched.
|
|
|
|
## What
|
|
|
|
- An agent profile has an `enabled` state, defaulting to enabled.
|
|
- The profile settings page (`/settings/agents/<agent>/profiles/<id>`) shows an
|
|
**Enabled** toggle in the page header. Toggling it is part of the normal
|
|
profile save flow (dirty state, save button, same persistence as other
|
|
profile fields).
|
|
- The agent profiles list on `/settings/agents` (under "Manage existing
|
|
profiles by agent") shows the same toggle per profile row. Toggling it
|
|
saves immediately and updates the row without navigating.
|
|
- A disabled profile is not offered as a choice when creating a new task, a
|
|
new subtask, a new session on an existing task, a handoff session from an
|
|
existing session, or a quick chat.
|
|
- A disabled profile is still listed in settings (with its toggle visible),
|
|
still editable, and still shown as the label of any existing session that
|
|
uses it. Existing sessions (running or not) are unaffected: they keep their
|
|
profile and can still be resumed.
|
|
- Disabling a profile is always allowed — unlike deleting, it never conflicts
|
|
on active sessions, watchers, or routing tiers.
|
|
- Pre-selection defaults (last-used profile, workspace default, workflow
|
|
default, first compatible profile) never resolve to a disabled profile when
|
|
a new task/session dialog opens; the dialog falls back to an enabled
|
|
candidate. A workflow that locks a disabled profile shows no compatible
|
|
agent until the profile is re-enabled or the workflow is changed.
|
|
|
|
## Data model
|
|
|
|
`agent_profiles` table (SQLite, `apps/backend/internal/agent/settings/store`):
|
|
|
|
```sql
|
|
enabled INTEGER NOT NULL DEFAULT 1 -- 1 = selectable for new work, 0 = hidden from selection
|
|
```
|
|
|
|
Existing rows backfill to `1` via the column default. The column is
|
|
independent of `deleted_at` (soft delete) and of the office `status` column
|
|
(`idle`/`working`/...) — disabling is a kanban-flavour selection flag, not a
|
|
lifecycle state.
|
|
|
|
## API surface
|
|
|
|
`PATCH /api/v1/agent-profiles/:id` accepts an optional `enabled` boolean in
|
|
the request body and returns the updated profile including `enabled`. All
|
|
profile listing responses (`GET /api/v1/agents`, `GET
|
|
/api/v1/agent-profiles/:id`) include `enabled` on each profile, `true` when
|
|
unset for backward compatibility. Disabled profiles remain present in every
|
|
listing endpoint — filtering happens only where profiles are offered as
|
|
selection choices.
|
|
|
|
## Scenarios
|
|
|
|
- **GIVEN** an enabled profile, **WHEN** the user turns off the Enabled toggle
|
|
in the profile settings header and saves, **THEN** the profile's `enabled`
|
|
is `false`, the header shows the toggle off, and the save persists across
|
|
reload.
|
|
- **GIVEN** a profile with `enabled: false`, **WHEN** the user opens the new
|
|
task dialog, **THEN** the agent profile selector does not list it.
|
|
- **GIVEN** a profile with `enabled: false`, **WHEN** the user opens the new
|
|
session / new subtask / handoff / quick-chat selectors, **THEN** the
|
|
selector does not list it.
|
|
- **GIVEN** a profile with `enabled: false`, **WHEN** the user opens
|
|
`/settings/agents`, **THEN** the profile still appears under "Manage
|
|
existing profiles by agent" with its Enabled toggle off, and toggling it on
|
|
makes it selectable again without a page reload.
|
|
- **GIVEN** a profile with `enabled: false`, **WHEN** an existing session that
|
|
uses the profile resumes, **THEN** the session starts with that profile and
|
|
its label still renders.
|
|
- **GIVEN** a profile with `enabled: false` that is the workspace default,
|
|
**WHEN** the new task dialog autopicks a profile, **THEN** the dialog
|
|
selects an enabled profile instead.
|
|
- **GIVEN** a profile with `enabled: false` that is locked by a workflow,
|
|
**WHEN** the new task dialog opens for that workflow, **THEN** the selector
|
|
does not pre-select it and task creation is gated on choosing an enabled
|
|
profile.
|
|
- **GIVEN** a profile with `enabled: false` and active sessions, **WHEN** the
|
|
user toggles it back on, **THEN** it becomes selectable immediately with no
|
|
session-side effects.
|
|
|
|
## Out of scope
|
|
|
|
- Office workspace agents (`/office` routes, `office.agentProfiles` slice).
|
|
Office rows are separate workspace-scoped profiles with their own
|
|
`status`/pause semantics; this toggle applies to the
|
|
`/settings/agents` profile flavor.
|
|
- Enforcing `enabled` on the backend task/session start endpoints: an API
|
|
caller that explicitly passes a disabled profile ID can still start a
|
|
session. Only selection surfaces hide it.
|
|
- Renaming, reordering, or styling changes to profile pickers beyond hiding
|
|
disabled entries.
|