| 1 | package event |
| 2 | |
| 3 | import "reasonix/internal/nilutil" |
| 4 | |
| 5 | // SubagentLifecycleInfo is content-free host telemetry for one child |
| 6 | // transition. It intentionally excludes prompts, reasoning, tool output, and |
| 7 | // paths so it can be forwarded to diagnostics without leaking transcript data. |
| 8 | type SubagentLifecycleInfo struct { |
| 9 | Phase string // child_created | child_running | child_completed | child_partial | child_failed | child_cancelled | child_resume |
| 10 | Ref string |
| 11 | ParentToolCallID string |
| 12 | Skill string |
| 13 | Model string |
| 14 | Effort string |
| 15 | Status string |
| 16 | ErrorCode string |
| 17 | Retryable bool |
| 18 | OutputBytes int |
| 19 | StartUnixMs int64 |
| 20 | EndUnixMs int64 |
| 21 | ValidatorMode string |
| 22 | ValidatorOutcome string |
| 23 | ValidatorAttempt int |
| 24 | ProviderRequestID string |
| 25 | } |
| 26 | |
| 27 | // SubagentLifecycleAuditSink receives host-only child lifecycle telemetry. |
| 28 | type SubagentLifecycleAuditSink interface { |
| 29 | RecordSubagentLifecycle(SubagentLifecycleInfo) |
| 30 | } |
| 31 | |
| 32 | // RecordSubagentLifecycle forwards content-free child lifecycle telemetry to |
| 33 | // sinks that explicitly opt in. |
| 34 | func RecordSubagentLifecycle(s Sink, info SubagentLifecycleInfo) { |
| 35 | if nilutil.IsNil(s) { |
| 36 | return |
| 37 | } |
| 38 | if ls, ok := s.(SubagentLifecycleAuditSink); ok { |
| 39 | ls.RecordSubagentLifecycle(info) |
| 40 | } |
| 41 | } |
| 42 |