@@ -245,16 +266,20 @@ export default function AgentDetailPage() {
Live status is unavailable — this agent isn't currently
active. Spawn it to see live state.
-
-
- Spawn Agent
-
- }
- />
+
+
+
+
+ Spawn Agent
+
+ }
+ />
+
+
) : agent ? (
@@ -287,9 +312,11 @@ export default function AgentDetailPage() {
-
- {agent.error_count} error(s)
-
+
+
+ {agent.error_count} error(s)
+
+
)}
diff --git a/panel/src/app/(dashboard)/agents/page.tsx b/panel/src/app/(dashboard)/agents/page.tsx
index ee40b32a..816aeca9 100644
--- a/panel/src/app/(dashboard)/agents/page.tsx
+++ b/panel/src/app/(dashboard)/agents/page.tsx
@@ -108,6 +108,7 @@ export default function AgentsPage() {
one Leadership band so a lone Main PM card never wastes a full row. */}
0 && (
{entry.sentiment && (
- {entry.sentiment}
+
+ {entry.sentiment}
+
)}
{subtitle && (
@@ -305,18 +314,21 @@ function PerformanceTabContent() {
value={completedToday}
subtitle="Tasks finished"
icon={}
+ tip="Tasks whose completed_at timestamp falls on today's calendar date"
/>
}
+ tip="Tasks completed in the trailing 7 days from now"
/>
}
+ tip="Every task that has ever reached the completed status"
/>
}
+ tip="Completed tasks divided by every task in the table, all-time"
/>
@@ -390,24 +403,28 @@ function PerformanceTabContent() {
value={runningAgents}
subtitle="Active agents"
icon={}
+ tip="Agents currently spawned and actively working a task"
/>
}
+ tip="Agents with no container running — free to be spawned for new work"
/>
}
+ tip="Agents stuck waiting unusually long, possibly needing human attention"
/>
}
+ tip="Agents whose last spawn exited in an error state"
/>
@@ -624,12 +641,14 @@ interface ProjectionCardProps {
function ProjectionCard({ projection, isLoading }: ProjectionCardProps) {
return (
-
-
-
- Monthly Projection
-
-
+
+
+
+
+ Monthly Projection
+
+
+
{isLoading ? (
@@ -699,12 +718,14 @@ interface RoleUsageTableProps {
function RoleUsageTable({ data, isLoading }: RoleUsageTableProps) {
return (
-
-
-
- Cost & Cache by Role
-
-
+
+
+
+
+ Cost & Cache by Role
+
+
+
{isLoading ? (
@@ -869,6 +890,13 @@ const VALID_METRICS_TABS: MetricsTab[] = [
"scorecards",
];
+const METRICS_TAB_HINTS: Record = {
+ performance: "Task velocity, status counts, agent load, and team health",
+ "token-usage": "Token spend, cost projections, cache efficiency, and per-session detail",
+ delivery: "Cycle time, bottlenecks, and rework rate reconstructed from the audit log",
+ scorecards: "Per-agent and per-team delivery scorecards",
+};
+
function isValidMetricsTab(value: string | null): value is MetricsTab {
return VALID_METRICS_TABS.includes(value as MetricsTab);
}
@@ -905,10 +933,29 @@ function MetricsPageContent() {
- Performance
- Token Usage
- Delivery
- Scorecards
+ {VALID_METRICS_TABS.map((tab) => (
+
+
+ {/* TooltipTrigger's asChild Slot merge overwrites the
+ data-state Radix Tabs sets on this trigger, so the
+ data-[state=active] style never fires unless it's
+ re-asserted explicitly after the merge. */}
+
+ {tab === "performance"
+ ? "Performance"
+ : tab === "token-usage"
+ ? "Token Usage"
+ : tab === "delivery"
+ ? "Delivery"
+ : "Scorecards"}
+
+
+ {METRICS_TAB_HINTS[tab]}
+
+ ))}
diff --git a/panel/src/components/a2a/a2a-connection-badge.tsx b/panel/src/components/a2a/a2a-connection-badge.tsx
index 0c9a9e16..522dc613 100644
--- a/panel/src/components/a2a/a2a-connection-badge.tsx
+++ b/panel/src/components/a2a/a2a-connection-badge.tsx
@@ -12,20 +12,22 @@ import { connectionDotClasses, connectionStateLabel } from "./a2a-utils";
* conversation must read differently from a stream that is the problem. */
export function A2AConnectionBadge({ state }: { state: ConnectionState }) {
return (
-