agent: Add telemetry events for subagents (#50849)

Katie Geer created

Adds five telemetry events to track subagent lifecycle and user
interactions:

- **Subagent Started** — fires on creation or resumption, includes
parent session, subagent session, depth, and whether it was resumed
- **Subagent Completed** — fires when `SpawnAgentTool` finishes,
includes subagent session and status (completed/error)
- **Subagent Toggled** — fires when the user expands or collapses a
subagent card
- **Subagent Stopped** — fires when the user clicks Stop on a running
subagent
- **Subagent Maximized** — fires when the user clicks Maximize to
navigate into a subagent
 
Release Notes:
 - N/A

Change summary

crates/agent/src/agent.rs                          | 22 ++++++++++++++++
crates/agent/src/tools/spawn_agent_tool.rs         | 11 ++++++++
crates/agent_ui/src/connection_view/thread_view.rs |  5 +++
3 files changed, 38 insertions(+)

Detailed changes

crates/agent/src/agent.rs 🔗

@@ -1629,6 +1629,16 @@ impl NativeThreadEnvironment {
             agent.register_session(subagent_thread.clone(), cx)
         })?;
 
+        let depth = current_depth + 1;
+
+        telemetry::event!(
+            "Subagent Started",
+            session = parent_thread_entity.read(cx).id().to_string(),
+            subagent_session = session_id.to_string(),
+            depth,
+            is_resumed = false,
+        );
+
         self.prompt_subagent(session_id, subagent_thread, acp_thread)
     }
 
@@ -1645,6 +1655,18 @@ impl NativeThreadEnvironment {
             anyhow::Ok((session.thread.clone(), session.acp_thread.clone()))
         })??;
 
+        let depth = subagent_thread.read(cx).depth();
+
+        if let Some(parent_thread_entity) = self.thread.upgrade() {
+            telemetry::event!(
+                "Subagent Started",
+                session = parent_thread_entity.read(cx).id().to_string(),
+                subagent_session = session_id.to_string(),
+                depth,
+                is_resumed = true,
+            );
+        }
+
         self.prompt_subagent(session_id, subagent_thread, acp_thread)
     }
 

crates/agent/src/tools/spawn_agent_tool.rs 🔗

@@ -163,6 +163,17 @@ impl AgentTool for SpawnAgentTool {
 
             let send_result = subagent.send(input.message, cx).await;
 
+            let status = if send_result.is_ok() {
+                "completed"
+            } else {
+                "error"
+            };
+            telemetry::event!(
+                "Subagent Completed",
+                subagent_session = session_info.session_id.to_string(),
+                status,
+            );
+
             session_info.message_end_index =
                 cx.update(|cx| Some(subagent.num_entries(cx).saturating_sub(1)));
 

crates/agent_ui/src/connection_view/thread_view.rs 🔗

@@ -6756,6 +6756,9 @@ impl ThreadView {
                                                 this.expanded_tool_calls
                                                     .insert(tool_call_id.clone());
                                             }
+                                            let expanded =
+                                                this.expanded_tool_calls.contains(&tool_call_id);
+                                            telemetry::event!("Subagent Toggled", expanded);
                                             cx.notify();
                                         }
                                     }))
@@ -6774,6 +6777,7 @@ impl ThreadView {
                                     |this, thread| {
                                         this.on_click(cx.listener(
                                             move |_this, _event, _window, cx| {
+                                                telemetry::event!("Subagent Stopped");
                                                 thread.update(cx, |thread, cx| {
                                                     thread.cancel(cx).detach();
                                                 });
@@ -6809,6 +6813,7 @@ impl ThreadView {
                     )
                     .tooltip(Tooltip::text("Make Subagent Full Screen"))
                     .on_click(cx.listener(move |this, _event, window, cx| {
+                        telemetry::event!("Subagent Maximized");
                         this.server_view
                             .update(cx, |this, cx| {
                                 this.navigate_to_session(session_id.clone(), window, cx);