Skip to content

Commit 4e910bf

Browse files
authored
adding parent_thread_id in guardian (openai#17249)
## Summary This PR adds the parent conversation/session id to the subagent-start analytics event for Guardian subagents. Previously, Guardian sessions were emitted as subagent thread-initialized events, but their `parent_thread_id` was serialized as `null`. After this change, the `codex_thread_initialized` analytics event for a Guardian child session includes the parent user conversation id.
1 parent 26a28af commit 4e910bf

7 files changed

Lines changed: 39 additions & 1 deletion

File tree

codex-rs/analytics/src/analytics_client_tests.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ fn subagent_thread_started_review_serializes_expected_shape() {
454454
let event = TrackEventRequest::ThreadInitialized(subagent_thread_started_event_request(
455455
SubAgentThreadStartedInput {
456456
thread_id: "thread-review".to_string(),
457+
parent_thread_id: None,
457458
product_client_id: "codex-tui".to_string(),
458459
client_name: "codex-tui".to_string(),
459460
client_version: "1.0.0".to_string(),
@@ -496,6 +497,7 @@ fn subagent_thread_started_thread_spawn_serializes_parent_thread_id() {
496497
let event = TrackEventRequest::ThreadInitialized(subagent_thread_started_event_request(
497498
SubAgentThreadStartedInput {
498499
thread_id: "thread-spawn".to_string(),
500+
parent_thread_id: None,
499501
product_client_id: "codex-tui".to_string(),
500502
client_name: "codex-tui".to_string(),
501503
client_version: "1.0.0".to_string(),
@@ -526,6 +528,7 @@ fn subagent_thread_started_memory_consolidation_serializes_expected_shape() {
526528
let event = TrackEventRequest::ThreadInitialized(subagent_thread_started_event_request(
527529
SubAgentThreadStartedInput {
528530
thread_id: "thread-memory".to_string(),
531+
parent_thread_id: None,
529532
product_client_id: "codex-tui".to_string(),
530533
client_name: "codex-tui".to_string(),
531534
client_version: "1.0.0".to_string(),
@@ -550,6 +553,7 @@ fn subagent_thread_started_other_serializes_expected_shape() {
550553
let event = TrackEventRequest::ThreadInitialized(subagent_thread_started_event_request(
551554
SubAgentThreadStartedInput {
552555
thread_id: "thread-guardian".to_string(),
556+
parent_thread_id: None,
553557
product_client_id: "codex-tui".to_string(),
554558
client_name: "codex-tui".to_string(),
555559
client_version: "1.0.0".to_string(),
@@ -562,6 +566,31 @@ fn subagent_thread_started_other_serializes_expected_shape() {
562566

563567
let payload = serde_json::to_value(&event).expect("serialize other subagent event");
564568
assert_eq!(payload["event_params"]["subagent_source"], "guardian");
569+
assert_eq!(payload["event_params"]["parent_thread_id"], json!(null));
570+
}
571+
572+
#[test]
573+
fn subagent_thread_started_other_serializes_explicit_parent_thread_id() {
574+
let event = TrackEventRequest::ThreadInitialized(subagent_thread_started_event_request(
575+
SubAgentThreadStartedInput {
576+
thread_id: "thread-guardian".to_string(),
577+
parent_thread_id: Some("parent-thread-guardian".to_string()),
578+
product_client_id: "codex-tui".to_string(),
579+
client_name: "codex-tui".to_string(),
580+
client_version: "1.0.0".to_string(),
581+
model: "gpt-5".to_string(),
582+
ephemeral: false,
583+
subagent_source: SubAgentSource::Other("guardian".to_string()),
584+
created_at: 126,
585+
},
586+
));
587+
588+
let payload = serde_json::to_value(&event).expect("serialize guardian subagent event");
589+
assert_eq!(payload["event_params"]["subagent_source"], "guardian");
590+
assert_eq!(
591+
payload["event_params"]["parent_thread_id"],
592+
"parent-thread-guardian"
593+
);
565594
}
566595

567596
#[tokio::test]
@@ -574,6 +603,7 @@ async fn subagent_thread_started_publishes_without_initialize() {
574603
AnalyticsFact::Custom(CustomAnalyticsFact::SubAgentThreadStarted(
575604
SubAgentThreadStartedInput {
576605
thread_id: "thread-review".to_string(),
606+
parent_thread_id: None,
577607
product_client_id: "codex-tui".to_string(),
578608
client_name: "codex-tui".to_string(),
579609
client_version: "1.0.0".to_string(),

codex-rs/analytics/src/events.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,9 @@ pub(crate) fn subagent_thread_started_event_request(
249249
thread_source: Some("subagent"),
250250
initialization_mode: ThreadInitializationMode::New,
251251
subagent_source: Some(subagent_source_name(&input.subagent_source)),
252-
parent_thread_id: subagent_parent_thread_id(&input.subagent_source),
252+
parent_thread_id: input
253+
.parent_thread_id
254+
.or_else(|| subagent_parent_thread_id(&input.subagent_source)),
253255
created_at: input.created_at,
254256
};
255257
ThreadInitializedEvent {

codex-rs/analytics/src/facts.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pub struct AppInvocation {
5454
#[derive(Clone)]
5555
pub struct SubAgentThreadStartedInput {
5656
pub thread_id: String,
57+
pub parent_thread_id: Option<String>,
5758
pub product_client_id: String,
5859
pub client_name: String,
5960
pub client_version: String,

codex-rs/core/src/agent/control.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ impl AgentControl {
283283
.analytics_events_client,
284284
client_metadata,
285285
new_thread.thread_id,
286+
/*parent_thread_id*/ None,
286287
thread_config,
287288
subagent_source.clone(),
288289
);

codex-rs/core/src/codex.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4582,6 +4582,7 @@ pub(crate) fn emit_subagent_session_started(
45824582
analytics_events_client: &AnalyticsEventsClient,
45834583
client_metadata: AppServerClientMetadata,
45844584
thread_id: ThreadId,
4585+
parent_thread_id: Option<ThreadId>,
45854586
thread_config: ThreadConfigSnapshot,
45864587
subagent_source: SubAgentSource,
45874588
) {
@@ -4599,6 +4600,7 @@ pub(crate) fn emit_subagent_session_started(
45994600
.as_secs();
46004601
analytics_events_client.track_subagent_thread_started(SubAgentThreadStartedInput {
46014602
thread_id: thread_id.to_string(),
4603+
parent_thread_id: parent_thread_id.map(|thread_id| thread_id.to_string()),
46024604
product_client_id: client_name.clone(),
46034605
client_name,
46044606
client_version,

codex-rs/core/src/codex_delegate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ pub(crate) async fn run_codex_thread_interactive(
104104
&parent_session.services.analytics_events_client,
105105
client_metadata,
106106
codex.session.conversation_id,
107+
Some(parent_session.conversation_id),
107108
thread_config,
108109
subagent_source,
109110
);

codex-rs/core/src/memories/phase2.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ pub(super) async fn run(session: &Arc<Session>, config: Arc<Config>) {
156156
&session.services.analytics_events_client,
157157
client_metadata,
158158
thread_id,
159+
/*parent_thread_id*/ None,
159160
thread_config,
160161
SubAgentSource::MemoryConsolidation,
161162
);

0 commit comments

Comments
 (0)