diff --git a/ui/src/ui/views/sessions.ts b/ui/src/ui/views/sessions.ts
index 6f0332f62..eea2fe5bd 100644
--- a/ui/src/ui/views/sessions.ts
+++ b/ui/src/ui/views/sessions.ts
@@ -4,6 +4,12 @@ import { pathForTab } from "../navigation.ts";
 import { formatSessionTokens } from "../presenter.ts";
 import type { GatewaySessionRow, SessionsListResult } from "../types.ts";
 
+export type AgentInfo = {
+  id: string;
+  name: string;
+  emoji?: string;
+};
+
 export type SessionsProps = {
   loading: boolean;
   result: SessionsListResult | null;
@@ -13,6 +19,9 @@ export type SessionsProps = {
   includeGlobal: boolean;
   includeUnknown: boolean;
   basePath: string;
+  agents?: AgentInfo[];
+  agentFilter?: string;
+  onAgentFilterChange?: (agentId: string) => void;
   onFiltersChange: (next: {
     activeMinutes: string;
     limit: string;
@@ -30,26 +39,17 @@ export type SessionsProps = {
     },
   ) => void;
   onDelete: (key: string) => void;
+  onViewHistory?: (key: string) => void;
 };
 
 const THINK_LEVELS = ["", "off", "minimal", "low", "medium", "high", "xhigh"] as const;
 const BINARY_THINK_LEVELS = ["", "off", "on"] as const;
-const VERBOSE_LEVELS = [
-  { value: "", label: "inherit" },
-  { value: "off", label: "off (explicit)" },
-  { value: "on", label: "on" },
-  { value: "full", label: "full" },
-] as const;
 const REASONING_LEVELS = ["", "off", "on", "stream"] as const;
 
 function normalizeProviderId(provider?: string | null): string {
-  if (!provider) {
-    return "";
-  }
+  if (!provider) return "";
   const normalized = provider.trim().toLowerCase();
-  if (normalized === "z.ai" || normalized === "z-ai") {
-    return "zai";
-  }
+  if (normalized === "z.ai" || normalized === "z-ai") return "zai";
   return normalized;
 }
 
@@ -62,59 +62,73 @@ function resolveThinkLevelOptions(provider?: string | null): readonly string[] {
 }
 
 function withCurrentOption(options: readonly string[], current: string): string[] {
-  if (!current) {
-    return [...options];
-  }
-  if (options.includes(current)) {
-    return [...options];
-  }
+  if (!current || options.includes(current)) return [...options];
   return [...options, current];
 }
 
-function withCurrentLabeledOption(
-  options: readonly { value: string; label: string }[],
-  current: string,
-): Array<{ value: string; label: string }> {
-  if (!current) {
-    return [...options];
-  }
-  if (options.some((option) => option.value === current)) {
-    return [...options];
-  }
-  return [...options, { value: current, label: `${current} (custom)` }];
-}
-
 function resolveThinkLevelDisplay(value: string, isBinary: boolean): string {
-  if (!isBinary) {
-    return value;
-  }
-  if (!value || value === "off") {
-    return value;
-  }
+  if (!isBinary) return value;
+  if (!value || value === "off") return value;
   return "on";
 }
 
 function resolveThinkLevelPatchValue(value: string, isBinary: boolean): string | null {
-  if (!value) {
-    return null;
-  }
-  if (!isBinary) {
-    return value;
-  }
-  if (value === "on") {
-    return "low";
-  }
+  if (!value) return null;
+  if (!isBinary) return value;
+  if (value === "on") return "low";
   return value;
 }
 
+// ── Session display name resolution ──────────────────────────────
+
+function resolveSessionFriendlyName(key: string, row: GatewaySessionRow): string {
+  const label = row.label?.trim();
+  if (label && label !== key) return label;
+  const dn = row.displayName?.trim();
+  if (dn && dn !== key) return dn;
+  if (key === "main" || key.endsWith(":main")) return "Main Session";
+  if (key.includes(":cron:") && key.includes(":run:")) return "Cron Run";
+  if (key.includes(":cron:")) return "Cron Job";
+  if (key.includes(":subagent:")) return "Subagent";
+  if (key.includes(":openai:")) return "OpenAI Session";
+  const directMatch = key.match(/:([^:]+):direct:(.+)$/);
+  if (directMatch) return `${capitalize(directMatch[1])} · ${directMatch[2]}`;
+  const groupMatch = key.match(/:([^:]+):group:(.+)$/);
+  if (groupMatch) return `${capitalize(groupMatch[1])} Group`;
+  return key;
+}
+
+function capitalize(s: string): string {
+  return s.charAt(0).toUpperCase() + s.slice(1);
+}
+
+function extractAgentId(key: string): string {
+  const match = key.match(/^agent:([^:]+):/);
+  return match ? match[1] : "unknown";
+}
+
+function resolveAgentLabel(agentId: string, agents?: AgentInfo[]): string {
+  if (!agents) return agentId;
+  const agent = agents.find((a) => a.id === agentId);
+  if (agent) return `${agent.emoji ?? "🤖"} ${agent.name}`;
+  return agentId;
+}
+
 export function renderSessions(props: SessionsProps) {
-  const rows = props.result?.sessions ?? [];
+  const allRows = props.result?.sessions ?? [];
+  const agents = props.agents ?? [];
+  const agentFilter = props.agentFilter ?? "";
+
+  const rows = agentFilter
+    ? allRows.filter((row) => extractAgentId(row.key) === agentFilter)
+    : allRows;
+
   return html`
     <section class="card">
       <div class="row" style="justify-content: space-between;">
         <div>
           <div class="card-title">Sessions</div>
-          <div class="card-sub">Active session keys and per-session overrides.</div>
+          <div class="card-sub">Inspect active sessions and adjust per-session defaults.</div>
         </div>
         <button class="btn" ?disabled=${props.loading} @click=${props.onRefresh}>
           ${props.loading ? "Loading…" : "Refresh"}
@@ -122,6 +136,25 @@ export function renderSessions(props: SessionsProps) {
       </div>
 
       <div class="filters" style="margin-top: 14px;">
+        ${agents.length > 0
+          ? html`
+              <label class="field">
+                <span>Agent</span>
+                <select
+                  @change=${(e: Event) =>
+                    props.onAgentFilterChange?.((e.target as HTMLSelectElement).value)}
+                >
+                  <option value="" ?selected=${!agentFilter}>All Agents</option>
+                  ${agents.map(
+                    (a) =>
+                      html`<option value=${a.id} ?selected=${agentFilter === a.id}>
+                        ${a.emoji ?? "🤖"} ${a.name}
+                      </option>`,
+                  )}
+                </select>
+              </label>
+            `
+          : nothing}
         <label class="field">
           <span>Active within (minutes)</span>
           <input
@@ -178,39 +211,86 @@ export function renderSessions(props: SessionsProps) {
         </label>
       </div>
 
-      ${
-        props.error
-          ? html`<div class="callout danger" style="margin-top: 12px;">${props.error}</div>`
-          : nothing
-      }
+      ${props.error
+        ? html`<div class="callout danger" style="margin-top: 12px;">${props.error}</div>`
+        : nothing}
 
       <div class="muted" style="margin-top: 12px;">
         ${props.result ? `Store: ${props.result.path}` : ""}
+        ${agentFilter && rows.length === 0
+          ? ` · No sessions for ${resolveAgentLabel(agentFilter, agents)}`
+          : ` · ${rows.length} session${rows.length !== 1 ? "s" : ""}`}
       </div>
 
-      <div class="table" style="margin-top: 16px;">
-        <div class="table-head">
-          <div>Key</div>
-          <div>Label</div>
+      <div class="sessions-grid" style="margin-top: 16px;">
+        <div class="sessions-grid__head">
+          <div>Session</div>
+          <div>Agent</div>
           <div>Kind</div>
           <div>Updated</div>
           <div>Tokens</div>
           <div>Thinking</div>
-          <div>Verbose</div>
           <div>Reasoning</div>
           <div>Actions</div>
         </div>
-        ${
-          rows.length === 0
-            ? html`
-                <div class="muted">No sessions found.</div>
-              `
-            : rows.map((row) =>
-                renderRow(row, props.basePath, props.onPatch, props.onDelete, props.loading),
-              )
-        }
+        ${rows.length === 0
+          ? html`
+              <div class="muted" style="padding: 16px; grid-column: 1 / -1;">
+                ${agentFilter
+                  ? `No sessions found for ${resolveAgentLabel(agentFilter, agents)}.`
+                  : "No sessions found."}
+              </div>
+            `
+          : rows.map((row) =>
+              renderRow(row, props.basePath, props.onPatch, props.onDelete, props.loading, props.onViewHistory, agents),
+            )}
       </div>
     </section>
+
+    <style>
+      .sessions-grid {
+        display: grid;
+        grid-template-columns: 2fr 1.2fr 0.6fr 0.8fr 1fr 0.8fr 0.8fr auto;
+        gap: 0;
+        font-size: 13px;
+      }
+      .sessions-grid__head {
+        display: contents;
+      }
+      .sessions-grid__head > div {
+        padding: 8px 10px;
+        font-weight: 600;
+        font-size: 12px;
+        text-transform: uppercase;
+        letter-spacing: 0.5px;
+        color: var(--text-muted, #888);
+        border-bottom: 1px solid var(--border, #333);
+      }
+      .sessions-grid__row {
+        display: contents;
+      }
+      .sessions-grid__row > div {
+        padding: 10px 10px;
+        border-bottom: 1px solid var(--border-subtle, rgba(255,255,255,0.06));
+        display: flex;
+        align-items: center;
+      }
+      .sessions-grid__row:hover > div {
+        background: rgba(255,255,255,0.02);
+      }
+      .sessions-grid__row .session-name-cell {
+        flex-direction: column;
+        align-items: flex-start;
+        justify-content: center;
+      }
+      .sessions-grid__row .session-actions {
+        gap: 6px;
+        justify-content: flex-end;
+      }
+      .sessions-grid select {
+        max-width: 100px;
+      }
+    </style>
   `;
 }
 
@@ -220,44 +300,37 @@ function renderRow(
   onPatch: SessionsProps["onPatch"],
   onDelete: SessionsProps["onDelete"],
   disabled: boolean,
+  onViewHistory?: SessionsProps["onViewHistory"],
+  agents?: AgentInfo[],
 ) {
   const updated = row.updatedAt ? formatRelativeTimestamp(row.updatedAt) : "n/a";
   const rawThinking = row.thinkingLevel ?? "";
   const isBinaryThinking = isBinaryThinkingProvider(row.modelProvider);
   const thinking = resolveThinkLevelDisplay(rawThinking, isBinaryThinking);
   const thinkLevels = withCurrentOption(resolveThinkLevelOptions(row.modelProvider), thinking);
-  const verbose = row.verboseLevel ?? "";
-  const verboseLevels = withCurrentLabeledOption(VERBOSE_LEVELS, verbose);
   const reasoning = row.reasoningLevel ?? "";
   const reasoningLevels = withCurrentOption(REASONING_LEVELS, reasoning);
-  const displayName =
-    typeof row.displayName === "string" && row.displayName.trim().length > 0
-      ? row.displayName.trim()
-      : null;
-  const label = typeof row.label === "string" ? row.label.trim() : "";
-  const showDisplayName = Boolean(displayName && displayName !== row.key && displayName !== label);
+
+  const friendlyName = resolveSessionFriendlyName(row.key, row);
+  const agentId = extractAgentId(row.key);
+  const agentLabel = resolveAgentLabel(agentId, agents);
+
   const canLink = row.kind !== "global";
   const chatUrl = canLink
     ? `${pathForTab("chat", basePath)}?session=${encodeURIComponent(row.key)}`
     : null;
 
   return html`
-    <div class="table-row">
-      <div class="mono session-key-cell">
-        ${canLink ? html`<a href=${chatUrl} class="session-link">${row.key}</a>` : row.key}
-        ${showDisplayName ? html`<span class="muted session-key-display-name">${displayName}</span>` : nothing}
-      </div>
-      <div>
-        <input
-          .value=${row.label ?? ""}
-          ?disabled=${disabled}
-          placeholder="(optional)"
-          @change=${(e: Event) => {
-            const value = (e.target as HTMLInputElement).value.trim();
-            onPatch(row.key, { label: value || null });
-          }}
-        />
+    <div class="sessions-grid__row">
+      <div class="session-name-cell">
+        ${canLink
+          ? html`<a href=${chatUrl} class="session-link" style="font-weight: 600; color: var(--accent, #6366f1);">${friendlyName}</a>`
+          : html`<span style="font-weight: 600;">${friendlyName}</span>`}
+        <span class="muted" style="font-size: 11px; opacity: 0.5; font-family: monospace; word-break: break-all;">
+          ${row.key}
+        </span>
       </div>
+      <div style="font-size: 13px;">${agentLabel}</div>
       <div>${row.kind}</div>
       <div>${updated}</div>
       <div>${formatSessionTokens(row)}</div>
@@ -266,32 +339,11 @@ function renderRow(
           ?disabled=${disabled}
           @change=${(e: Event) => {
             const value = (e.target as HTMLSelectElement).value;
-            onPatch(row.key, {
-              thinkingLevel: resolveThinkLevelPatchValue(value, isBinaryThinking),
-            });
+            onPatch(row.key, { thinkingLevel: resolveThinkLevelPatchValue(value, isBinaryThinking) });
           }}
         >
           ${thinkLevels.map(
-            (level) =>
-              html`<option value=${level} ?selected=${thinking === level}>
-                ${level || "inherit"}
-              </option>`,
-          )}
-        </select>
-      </div>
-      <div>
-        <select
-          ?disabled=${disabled}
-          @change=${(e: Event) => {
-            const value = (e.target as HTMLSelectElement).value;
-            onPatch(row.key, { verboseLevel: value || null });
-          }}
-        >
-          ${verboseLevels.map(
-            (level) =>
-              html`<option value=${level.value} ?selected=${verbose === level.value}>
-                ${level.label}
-              </option>`,
+            (level) => html`<option value=${level} ?selected=${thinking === level}>${level || "inherit"}</option>`,
           )}
         </select>
       </div>
@@ -304,17 +356,15 @@ function renderRow(
           }}
         >
           ${reasoningLevels.map(
-            (level) =>
-              html`<option value=${level} ?selected=${reasoning === level}>
-                ${level || "inherit"}
-              </option>`,
+            (level) => html`<option value=${level} ?selected=${reasoning === level}>${level || "inherit"}</option>`,
           )}
         </select>
       </div>
-      <div>
-        <button class="btn danger" ?disabled=${disabled} @click=${() => onDelete(row.key)}>
-          Delete
-        </button>
+      <div class="session-actions">
+        ${onViewHistory
+          ? html`<button class="btn" ?disabled=${disabled} @click=${() => onViewHistory(row.key)}>History</button>`
+          : nothing}
+        <button class="btn danger" ?disabled=${disabled} @click=${() => onDelete(row.key)}>Delete</button>
       </div>
     </div>
   `;
