diff --git a/ui/litellm-dashboard/src/app/(dashboard)/lens/_components/LensOverview.tsx b/ui/litellm-dashboard/src/app/(dashboard)/lens/_components/LensOverview.tsx index 414f9eb41fd..2e2a0318d85 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/lens/_components/LensOverview.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/lens/_components/LensOverview.tsx @@ -75,62 +75,50 @@ export function InvestigationExample({ onClose }: { onClose: () => void }) { if (!open) onClose(); }} > - -
- - Example investigation - Does the support agent recover when a tool fails? - -
-
-
- + + + Example investigation + +
+
+ + 3 of 20 conversations
-

- Failed lookups leave customers without an answer +

+ Failed lookups leave customers without answers

-

- The agent repeats the same failed order lookup, then ends the conversation without an answer or a handoff. -

-
+ + The agent retries the same failed order lookup, then ends the conversation without an answer or a handoff. + +
+
+

After three failed lookups, the agent replies:

-
“I will check that for you.”
-
- - See the trace - -
    -
  1. - Customer · Where is my order? -
  2. -
  3. - Order lookup · Service unavailable -
  4. -
  5. - Two retries · Same error, no new information -
  6. -
  7. - Agent · I will check that for you. Conversation - ends. -
  8. -
-
+
“I will check that for you.”
-
-

What to change

-

- After repeated failures, explain the problem and offer a handoff instead of retrying. -

-
-
-
-

Illustrative data, not your agent’s results

- +
+ + See the trace + +
    +
  1. + Customer · Where is my order? +
  2. +
  3. + Order lookup · Service unavailable +
  4. +
  5. + Two retries · Same error, no new information +
  6. +
  7. + Agent · I will check that for you. Conversation + ends. +
  8. +
+
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/lens/_components/LensView.integration.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/lens/_components/LensView.integration.test.tsx index 2e4f1dcc1bc..a3ec7877223 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/lens/_components/LensView.integration.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/lens/_components/LensView.integration.test.tsx @@ -231,6 +231,42 @@ it("runs saved settings immediately without opening setup", async () => { expect(screen.queryByRole("dialog")).not.toBeInTheDocument(); }); +it("lets a new user inspect example evidence and return to setup without starting an investigation", async () => { + window.history.replaceState({}, "", "/lens/"); + testQueryClient.clear(); + vi.mocked(apiClient.get).mockImplementation(async (path) => { + if (path === "/lens") return { lenses: [], workers: [], tracing_enabled: false }; + return { traces: false, requests: false }; + }); + const user = userEvent.setup(); + renderWithProviders(); + + await user.click(await screen.findByRole("button", { name: "View an example" })); + const example = within(screen.getByRole("dialog", { name: "Example investigation" })); + expect(example.getByRole("heading", { name: "Failed lookups leave customers without answers" })).toBeVisible(); + const evidence = example.getByText(/Where is my order\?/); + expect(evidence).not.toBeVisible(); + await user.click(example.getByText("See the trace")); + expect(evidence).toBeVisible(); + expect(example.getByText(/Service unavailable/)).toBeVisible(); + await user.click(example.getByText("See the trace")); + expect(evidence).not.toBeVisible(); + + await user.click(example.getByRole("button", { name: "Close" })); + await waitFor(() => expect(screen.queryByRole("dialog")).not.toBeInTheDocument()); + expect(screen.getByRole("link", { name: "Set up traces" })).toBeVisible(); + expect(screen.getByRole("button", { name: "Connect worker" })).toBeDisabled(); + expect(screen.getByRole("button", { name: "New investigation" })).toBeDisabled(); + + await user.click(screen.getByRole("button", { name: "View an example" })); + expect(screen.getByRole("dialog", { name: "Example investigation" })).toBeVisible(); + expect(screen.getByText(/Where is my order\?/)).not.toBeVisible(); + await user.keyboard("{Escape}"); + await waitFor(() => expect(screen.queryByRole("dialog")).not.toBeInTheDocument()); + expect(screen.getByRole("button", { name: "View an example" })).toBeVisible(); + expect(apiClient.post).not.toHaveBeenCalled(); +}); + it("guides a first-time administrator into worker connection and lens setup", async () => { window.history.replaceState({}, "", "/lens/"); testQueryClient.clear();