Skip to main content

agent_evaluate_contract/
objective.rs

1//! Objective metrics derived deterministically from one authoritative Trace partition.
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6/// Identifies one Trace partition and gives the resulting metric set a stable id.
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8#[serde(rename_all = "camelCase", deny_unknown_fields)]
9pub struct TraceObjectiveMetricsRequest {
10    pub trace_id: String,
11    pub conversation_id: String,
12    pub run_id: String,
13    #[serde(default, skip_serializing_if = "Option::is_none")]
14    pub expected_turns: Option<u64>,
15    #[serde(default, skip_serializing_if = "Option::is_none")]
16    pub expected_tool_calls: Option<u64>,
17}
18
19/// Transport-neutral event projection consumed by Evaluate's pure calculator.
20#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
21#[serde(rename_all = "camelCase", deny_unknown_fields)]
22pub struct ObjectiveTraceEvent {
23    pub id: String,
24    pub event_type: String,
25    #[serde(default)]
26    pub payload: Value,
27    #[serde(default)]
28    pub sequence: i64,
29    #[serde(default)]
30    pub created_at_ms: i64,
31}
32
33/// One raw, reproducible observation. No weighted or model-judged score is produced.
34#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
35#[serde(rename_all = "camelCase", deny_unknown_fields)]
36pub struct ObjectiveMetricObservation {
37    pub metric: String,
38    pub value: f64,
39    pub unit: String,
40    #[serde(default, skip_serializing_if = "Option::is_none")]
41    pub numerator: Option<u64>,
42    #[serde(default, skip_serializing_if = "Option::is_none")]
43    pub denominator: Option<u64>,
44}
45
46/// Complete bounded metric view derivable without an LLM judge or repository code.
47#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
48#[serde(rename_all = "camelCase", deny_unknown_fields)]
49pub struct TraceObjectiveMetrics {
50    pub trace_id: String,
51    pub conversation_id: String,
52    pub run_id: String,
53    #[serde(default, skip_serializing_if = "Option::is_none")]
54    pub expected_turns: Option<u64>,
55    #[serde(default, skip_serializing_if = "Option::is_none")]
56    pub expected_tool_calls: Option<u64>,
57    pub event_count: u64,
58    pub recognized_event_count: u64,
59    pub unknown_event_count: u64,
60    #[serde(default, skip_serializing_if = "Option::is_none")]
61    pub started_at_ms: Option<i64>,
62    #[serde(default, skip_serializing_if = "Option::is_none")]
63    pub completed_at_ms: Option<i64>,
64    pub wall_duration_ms: u64,
65    pub model_duration_ms: u64,
66    pub max_model_duration_ms: u64,
67    pub tool_duration_ms: u64,
68    pub max_tool_duration_ms: u64,
69    pub run_started_count: u64,
70    pub run_completed_count: u64,
71    pub run_failed_count: u64,
72    pub model_started_count: u64,
73    pub model_completed_count: u64,
74    pub model_failed_count: u64,
75    pub tool_started_count: u64,
76    pub tool_completed_count: u64,
77    pub tool_failed_count: u64,
78    pub retry_count: u64,
79    pub context_compaction_count: u64,
80    pub input_tokens: u64,
81    pub input_cached_tokens: u64,
82    pub input_cache_write_tokens: u64,
83    pub output_tokens: u64,
84    pub total_tokens: u64,
85    pub cost_micros: u64,
86    pub error_count: u64,
87    pub timestamp_regression_count: u64,
88    pub sequence_regression_count: u64,
89    #[serde(default, skip_serializing_if = "Option::is_none")]
90    pub recognized_event_rate: Option<f64>,
91    #[serde(default, skip_serializing_if = "Option::is_none")]
92    pub run_success_rate: Option<f64>,
93    #[serde(default, skip_serializing_if = "Option::is_none")]
94    pub model_success_rate: Option<f64>,
95    #[serde(default, skip_serializing_if = "Option::is_none")]
96    pub tool_success_rate: Option<f64>,
97    #[serde(default, skip_serializing_if = "Option::is_none")]
98    pub turn_completion_rate: Option<f64>,
99    #[serde(default, skip_serializing_if = "Option::is_none")]
100    pub expected_tool_completion_rate: Option<f64>,
101    #[serde(default, skip_serializing_if = "Option::is_none")]
102    pub average_model_duration_ms: Option<f64>,
103    #[serde(default, skip_serializing_if = "Option::is_none")]
104    pub average_tool_duration_ms: Option<f64>,
105    #[serde(default, skip_serializing_if = "Option::is_none")]
106    pub output_tokens_per_second: Option<f64>,
107    #[serde(default, skip_serializing_if = "Option::is_none")]
108    pub input_cache_hit_rate: Option<f64>,
109    pub complete: bool,
110    #[serde(default)]
111    pub missing_signals: Vec<String>,
112    #[serde(default)]
113    pub observations: Vec<ObjectiveMetricObservation>,
114}