diff --git a/packages/views/issues/components/backlog-agent-hint-dialog.tsx b/packages/views/issues/components/backlog-agent-hint-dialog.tsx
new file mode 100644
index 000000000..13cb67fef
--- /dev/null
+++ b/packages/views/issues/components/backlog-agent-hint-dialog.tsx
@@ -0,0 +1,124 @@
+"use client";
+
+import { useState } from "react";
+import { Archive, ArrowRight, Bot, CheckCircle2 } from "lucide-react";
+import {
+ AlertDialog,
+ AlertDialogContent,
+} from "@multica/ui/components/ui/alert-dialog";
+import { Button } from "@multica/ui/components/ui/button";
+import { Checkbox } from "@multica/ui/components/ui/checkbox";
+
+interface BacklogAgentHintDialogProps {
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+ onDismissPermanently: () => void;
+ onMoveToTodo: () => void;
+}
+
+export function BacklogAgentHintDialog({
+ open,
+ onOpenChange,
+ onDismissPermanently,
+ onMoveToTodo,
+}: BacklogAgentHintDialogProps) {
+ return (
+
+
+ onOpenChange(false)}
+ onDismissPermanently={onDismissPermanently}
+ onMoveToTodo={onMoveToTodo}
+ />
+
+
+ );
+}
+
+interface BacklogAgentHintContentProps {
+ onKeepInBacklog: () => void;
+ onDismissPermanently: () => void;
+ onMoveToTodo: () => void;
+}
+
+export function BacklogAgentHintContent({
+ onKeepInBacklog,
+ onDismissPermanently,
+ onMoveToTodo,
+}: BacklogAgentHintContentProps) {
+ const [dontShowAgain, setDontShowAgain] = useState(false);
+
+ const handleKeepInBacklog = () => {
+ if (dontShowAgain) onDismissPermanently();
+ onKeepInBacklog();
+ };
+
+ const handleMoveToTodo = () => {
+ if (dontShowAgain) onDismissPermanently();
+ onMoveToTodo();
+ };
+
+ return (
+ <>
+
+
+
+
+
+
+
+ Agent is paused in Backlog
+
+
+ This issue is parked, so the assigned agent will wait. Move it to
+ Todo when you want the agent to start.
+
+
+
+
+
+
+
+
Backlog
+
keeps the agent paused
+
+
+
+
Todo
+
starts the agent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/packages/views/issues/components/issue-detail.tsx b/packages/views/issues/components/issue-detail.tsx
index 01e49c81e..20a73b18a 100644
--- a/packages/views/issues/components/issue-detail.tsx
+++ b/packages/views/issues/components/issue-detail.tsx
@@ -64,6 +64,7 @@ import { ProjectPicker } from "../../projects/components/project-picker";
import { CommentCard } from "./comment-card";
import { CommentInput } from "./comment-input";
import { AgentLiveCard, TaskRunHistory } from "./agent-live-card";
+import { BacklogAgentHintDialog } from "./backlog-agent-hint-dialog";
import { useQuery } from "@tanstack/react-query";
import { useAuthStore } from "@multica/core/auth";
import { useWorkspaceStore } from "@multica/core/workspace";
@@ -344,6 +345,7 @@ export function IssueDetail({ issueId, onDelete, defaultSidebarOpen = true, layo
const [sidebarOpen, setSidebarOpen] = useState(defaultSidebarOpen);
const [deleting, setDeleting] = useState(false);
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
+ const [backlogHintOpen, setBacklogHintOpen] = useState(false);
const [propertiesOpen, setPropertiesOpen] = useState(true);
const [detailsOpen, setDetailsOpen] = useState(true);
const scrollContainerRef = useRef(null);
@@ -444,6 +446,16 @@ export function IssueDetail({ issueId, onDelete, defaultSidebarOpen = true, layo
{ id, ...updates },
{ onError: () => toast.error("Failed to update issue") },
);
+ // Hint: assigning an agent to a backlog issue won't trigger execution
+ // until the issue is moved to an active status.
+ if (
+ updates.assignee_type === "agent" &&
+ updates.assignee_id &&
+ issue.status === "backlog" &&
+ localStorage.getItem("multica:backlog-agent-hint-dismissed") !== "true"
+ ) {
+ setBacklogHintOpen(true);
+ }
},
[issue, id, updateIssueMutation],
);
@@ -862,6 +874,21 @@ export function IssueDetail({ issueId, onDelete, defaultSidebarOpen = true, layo
+ {
+ localStorage.setItem("multica:backlog-agent-hint-dismissed", "true");
+ }}
+ onMoveToTodo={() => {
+ updateIssueMutation.mutate(
+ { id, status: "todo" },
+ { onError: () => toast.error("Failed to update status") },
+ );
+ setBacklogHintOpen(false);
+ }}
+ />
+
{/* Set parent issue picker */}
({
vi.mock("@multica/core/issues/mutations", () => ({
useCreateIssue: () => ({ mutateAsync: mockCreateIssue }),
+ useUpdateIssue: () => ({ mutate: vi.fn() }),
}));
vi.mock("@multica/core/hooks/use-file-upload", () => ({
diff --git a/packages/views/modals/create-issue.tsx b/packages/views/modals/create-issue.tsx
index b558fe2af..a1bb687bb 100644
--- a/packages/views/modals/create-issue.tsx
+++ b/packages/views/modals/create-issue.tsx
@@ -15,10 +15,11 @@ import { Tooltip, TooltipTrigger, TooltipContent } from "@multica/ui/components/
import { Button } from "@multica/ui/components/ui/button";
import { ContentEditor, type ContentEditorRef, TitleEditor, useFileDropZone, FileDropOverlay } from "../editor";
import { StatusIcon, StatusPicker, PriorityPicker, AssigneePicker, DueDatePicker } from "../issues/components";
+import { BacklogAgentHintContent } from "../issues/components/backlog-agent-hint-dialog";
import { ProjectPicker } from "../projects/components/project-picker";
import { useWorkspaceStore } from "@multica/core/workspace";
import { useIssueDraftStore } from "@multica/core/issues/stores/draft-store";
-import { useCreateIssue } from "@multica/core/issues/mutations";
+import { useCreateIssue, useUpdateIssue } from "@multica/core/issues/mutations";
import { useFileUpload } from "@multica/core/hooks/use-file-upload";
import { api } from "@multica/core/api";
import { FileUploadButton } from "@multica/ui/components/common/file-upload-button";
@@ -74,6 +75,7 @@ export function CreateIssueModal({ onClose, data }: { onClose: () => void; data?
(data?.project_id as string) || undefined,
);
const [isExpanded, setIsExpanded] = useState(false);
+ const [backlogHintIssueId, setBacklogHintIssueId] = useState(null);
// File upload — collect attachment IDs so we can link them after issue creation.
const [attachmentIds, setAttachmentIds] = useState([]);
@@ -97,6 +99,7 @@ export function CreateIssueModal({ onClose, data }: { onClose: () => void; data?
const updateDueDate = (v: string | null) => { setDueDate(v); setDraft({ dueDate: v }); };
const createIssueMutation = useCreateIssue();
+ const updateIssueMutation = useUpdateIssue();
const handleSubmit = async () => {
if (!title.trim() || submitting) return;
setSubmitting(true);
@@ -114,31 +117,42 @@ export function CreateIssueModal({ onClose, data }: { onClose: () => void; data?
project_id: projectId,
});
clearDraft();
- onClose();
- toast.custom((t) => (
-
-
-
-
+ const shouldShowBacklogHint =
+ status === "backlog" && assigneeType === "agent" && assigneeId &&
+ localStorage.getItem("multica:backlog-agent-hint-dismissed") !== "true";
+
+ if (shouldShowBacklogHint) {
+ setBacklogHintIssueId(issue.id);
+ } else {
+ onClose();
+ }
+
+ if (!shouldShowBacklogHint) {
+ toast.custom((t) => (
+
+
-
Issue created
+
+
+ {issue.identifier} – {issue.title}
+
+
-
-
- {issue.identifier} – {issue.title}
-
-
-
- ), { duration: 5000 });
+ ), { duration: 5000 });
+ }
} catch {
toast.error("Failed to create issue");
} finally {
@@ -147,145 +161,179 @@ export function CreateIssueModal({ onClose, data }: { onClose: () => void; data?
};
return (
-