feat(ai): let an admin pick which bot the AI assistant posts as (LC-693) #660

Merged
longjacksonle merged 1 commit from feat/LC-693-pick-assistant-bot into main 2026-08-09 19:05:14 +02:00

What

Adds an admin control to choose which bot the AI assistant posts as. Fixes LC-693.

Before: /ask answers (and catch-up summaries, post-call recaps, triage, weekly recap) always posted as the hard-coded assistant bot. Creating a second bot (standup-bot) on Admin > Bots had no effect on the assistant, and the page never said which bot the assistant uses.

How

  • New server setting assistant_bot_username. routes::assistant::assistant_bot() (the single resolver every assistant surface shares) reads it first: when it names an existing, active bot, the assistant posts as that bot; unset / renamed / disabled falls through to the built-in assistant (still lazily created), so a stale setting never breaks the assistant.
  • Read live from the settings KV per call - a change takes effect on the next /ask with no restart, same pattern as the llm_enabled kill switch.
  • Admin > Bots: an "AI assistant identity" card with a dropdown of the active bots (default "assistant (built-in)") that writes the setting via POST /admin/bots/assistant, plus an "AI assistant" pill on whichever bot row is currently selected. Selecting the default clears the setting; picking a bot validates it is a real, active bot first.

Bot API-token scopes are irrelevant here - the assistant posts internally via finalize_message_send, not through the bot's token - so any bot account can be the identity; only the displayed name/avatar changes.

Template stays comparison-free: the selected/active bot is resolved in the handler (BotRowView.is_assistant), matching the LC-683 pattern.

Scope

routes/assistant.rs (setting key + resolver), routes/admin.rs (read setting, POST handler, route), views/admin.rs (BotRowView.is_assistant, BotsPage.assistant_bot), templates/admin/bots.html (selector card + row pill), locales/en+es/admin.ftl (6 strings each). No schema change, no new CSS.

Verification

  • cargo check / cargo clippy --lib: clean.
  • cargo fmt --check: clean.
  • Full lib suite: 317 passed (incl. i18n en/es parity).

🤖 Generated with Claude Code

https://claude.ai/code/session_011M7CNRsGzgzc48KinZUAQ8

## What Adds an admin control to choose which bot the AI assistant posts as. Fixes LC-693. Before: `/ask` answers (and catch-up summaries, post-call recaps, triage, weekly recap) always posted as the hard-coded `assistant` bot. Creating a second bot (`standup-bot`) on Admin > Bots had no effect on the assistant, and the page never said which bot the assistant uses. ## How - New server setting `assistant_bot_username`. `routes::assistant::assistant_bot()` (the single resolver every assistant surface shares) reads it first: when it names an existing, active bot, the assistant posts as that bot; unset / renamed / disabled falls through to the built-in `assistant` (still lazily created), so a stale setting never breaks the assistant. - Read live from the settings KV per call - a change takes effect on the next `/ask` with no restart, same pattern as the `llm_enabled` kill switch. - Admin > Bots: an "AI assistant identity" card with a dropdown of the active bots (default "assistant (built-in)") that writes the setting via `POST /admin/bots/assistant`, plus an "AI assistant" pill on whichever bot row is currently selected. Selecting the default clears the setting; picking a bot validates it is a real, active bot first. Bot API-token scopes are irrelevant here - the assistant posts internally via `finalize_message_send`, not through the bot's token - so any bot account can be the identity; only the displayed name/avatar changes. Template stays comparison-free: the selected/active bot is resolved in the handler (`BotRowView.is_assistant`), matching the LC-683 pattern. ## Scope `routes/assistant.rs` (setting key + resolver), `routes/admin.rs` (read setting, POST handler, route), `views/admin.rs` (`BotRowView.is_assistant`, `BotsPage.assistant_bot`), `templates/admin/bots.html` (selector card + row pill), `locales/en+es/admin.ftl` (6 strings each). No schema change, no new CSS. ## Verification - `cargo check` / `cargo clippy --lib`: clean. - `cargo fmt --check`: clean. - Full lib suite: 317 passed (incl. i18n en/es parity). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_011M7CNRsGzgzc48KinZUAQ8
feat(ai): let an admin pick which bot the AI assistant posts as (LC-693)
All checks were successful
check-secrets / Kingfisher (push) Successful in 5s
check-secrets / TruffleHog (push) Successful in 4s
check-secrets / Nosey parker (push) Successful in 5s
check-secrets / Nosey parker (pull_request) Successful in 3s
Check / clippy + fmt + tests (pull_request) Successful in 7m50s
check-secrets / TruffleHog (pull_request) Successful in 5s
check-secrets / Kingfisher (pull_request) Successful in 6s
Create release / Create release from merged PR (pull_request) Has been skipped
5fc8bbe041
The AI assistant (/ask answers, catch-up summaries, post-call recaps, triage, weekly recap) always posted as the hard-coded `assistant` bot. `routes::assistant::assistant_bot()` resolved one fixed username and lazily created it; there was no way to make it post as another bot, and the admin Bots page never said which bot the assistant uses - so creating a second bot (`standup-bot`) had no effect on /ask.

Add a server setting `assistant_bot_username` and an admin control for it. The resolver now reads the setting first and, when it names an existing active (non-banned) bot, posts as that bot; an unset, renamed, or later-disabled choice falls through to the built-in `assistant`, so a stale setting never breaks the assistant. Because every assistant surface shares the resolver, the chosen identity applies everywhere at once. Read live from the settings KV per call, so a change takes effect on the next /ask with no restart (same pattern as the `llm_enabled` kill switch).

Admin > Bots gains an "AI assistant identity" card with a dropdown of the active bots (default "assistant (built-in)") that writes the setting, plus an "AI assistant" pill on whichever bot row is currently selected, so the page answers "which bot does the assistant use?" at a glance. Selecting the default clears the setting; picking a bot validates it is a real active bot first. Bot token scopes are irrelevant to this - the assistant posts internally, not through the bot's API token - so any bot account can serve as the identity.

No schema change (reuses the settings KV), no new CSS. i18n en/es both updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011M7CNRsGzgzc48KinZUAQ8
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-08-09 19:00:10 +02:00
longjacksonle deleted branch feat/LC-693-pick-assistant-bot 2026-08-09 19:05:14 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
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
psa-systems/lets-chat!660
No description provided.