From 153a66b579fe07e20ff46387e2e29294427c0a0e Mon Sep 17 00:00:00 2001
From: Ethan <39577870+ethanndickson@users.noreply.github.com>
Date: Wed, 1 Apr 2026 15:34:21 +1100
Subject: [PATCH] fix(site/src/pages/AgentsPage): confirm active agent archive
(#23887)
Add a confirmation dialog before archiving an agent that is actively
running from the Agents UI.
This PR came about as feedback on PR 23758:
https://github.com/coder/coder/pull/23758#issuecomment-4160424938.
Active agents now require confirmation before archive interrupts the
current run, while inactive agents keep the existing one-click archive
behavior.
---
site/src/pages/AgentsPage/AgentsPage.tsx | 38 ++++++++++++++++++++++--
1 file changed, 36 insertions(+), 2 deletions(-)
diff --git a/site/src/pages/AgentsPage/AgentsPage.tsx b/site/src/pages/AgentsPage/AgentsPage.tsx
index 0277cb8379..8214b5de33 100644
--- a/site/src/pages/AgentsPage/AgentsPage.tsx
+++ b/site/src/pages/AgentsPage/AgentsPage.tsx
@@ -29,6 +29,7 @@ import {
} from "#/api/queries/chats";
import { workspaceById } from "#/api/queries/workspaces";
import type * as TypesGen from "#/api/typesGenerated";
+import { ConfirmDialog } from "#/components/Dialogs/ConfirmDialog/ConfirmDialog";
import { DeleteDialog } from "#/components/Dialogs/DeleteDialog/DeleteDialog";
import { useAuthenticated } from "#/hooks/useAuthenticated";
import { useDashboard } from "#/modules/dashboard/useDashboard";
@@ -187,6 +188,9 @@ const AgentsPage: FC = () => {
toast.error(getErrorMessage(error, "Failed to archive agent."));
},
});
+ const [pendingArchiveChatId, setPendingArchiveChatId] = useState<
+ string | null
+ >(null);
const [pendingArchiveAndDelete, setPendingArchiveAndDelete] = useState<{
chatId: string;
workspaceId: string;
@@ -282,10 +286,30 @@ const AgentsPage: FC = () => {
(archiveAndDeleteMutation.isPending
? archiveAndDeleteMutation.variables?.chatId
: undefined);
+ const isActiveChat = (chat: TypesGen.Chat | undefined) =>
+ chat?.status === "pending" || chat?.status === "running";
const requestArchiveAgent = (chatId: string) => {
- if (!isArchiving) {
- archiveAgentMutation.mutate(chatId);
+ if (isArchiving) {
+ return;
}
+ const chat =
+ queryClient.getQueryData(chatKey(chatId)) ??
+ chatList.find((candidate) => candidate.id === chatId);
+ if (chat === undefined || isActiveChat(chat)) {
+ setPendingArchiveChatId(chatId);
+ return;
+ }
+ archiveAgentMutation.mutate(chatId);
+ };
+ const handleConfirmArchiveAgent = () => {
+ if (!pendingArchiveChatId || isArchiving) {
+ return;
+ }
+ archiveAgentMutation.mutate(pendingArchiveChatId, {
+ onSettled: () => {
+ setPendingArchiveChatId(null);
+ },
+ });
};
const requestArchiveAndDeleteWorkspace = async (
chatId: string,
@@ -699,6 +723,16 @@ const AgentsPage: FC = () => {
archivedFilter={archivedFilter}
onArchivedFilterChange={setArchivedFilter}
/>
+ setPendingArchiveChatId(null)}
+ onConfirm={handleConfirmArchiveAgent}
+ type="delete"
+ confirmText="Archive"
+ confirmLoading={archiveAgentMutation.isPending}
+ title="Archive agent?"
+ description="This agent is currently running. Archiving it will interrupt the current run."
+ />