agent_runtime_kernel_api/
lib.rs1use std::{collections::BTreeSet, sync::Arc};
4
5use async_trait::async_trait;
6use runtime_extension_api::AgentPackage;
7use runtime_ports::{
8 CommitDisposition, ExecutionSessions, OperationContext, ResolvedExecutionContext, TokenUsage,
9};
10use runtime_types::{ConversationId, ExecutionId};
11use thiserror::Error;
12
13#[derive(Debug, Clone)]
14pub struct KernelLimits {
15 pub max_model_turns: usize,
16 pub max_tool_calls: usize,
17 pub context: ContextLimits,
18 pub max_tool_output_bytes: usize,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
24pub struct ContextLimits {
25 pub max_messages: usize,
26 pub max_input_tokens: u64,
27 pub reserved_output_tokens: u32,
28 pub protocol_overhead_tokens: u64,
29 pub auto_compact: bool,
30 pub compaction: ContextCompactionLimits,
31}
32
33impl Default for ContextLimits {
34 fn default() -> Self {
35 Self {
36 max_messages: 128,
37 max_input_tokens: 128 * 1024,
38 reserved_output_tokens: 8 * 1024,
39 protocol_overhead_tokens: 256,
40 auto_compact: true,
41 compaction: ContextCompactionLimits::default(),
42 }
43 }
44}
45
46#[derive(Debug, Clone, PartialEq, Eq)]
47pub struct ContextCompactionLimits {
48 pub trigger_percent: u8,
49 pub target_percent: u8,
50 pub emergency_percent: u8,
51 pub min_reclaim_percent: u8,
52 pub min_turns_between: usize,
53 pub checkpoint_max_chars: usize,
54}
55
56impl Default for ContextCompactionLimits {
57 fn default() -> Self {
58 Self {
59 trigger_percent: 82,
60 target_percent: 60,
61 emergency_percent: 95,
62 min_reclaim_percent: 10,
63 min_turns_between: 4,
64 checkpoint_max_chars: 8_000,
65 }
66 }
67}
68
69#[derive(Clone)]
70pub struct KernelSpec {
71 pub execution_id: ExecutionId,
72 pub conversation_id: Option<ConversationId>,
73 pub user_prompt: String,
74 pub model: String,
75 pub package: Arc<AgentPackage>,
76 pub granted_capabilities: BTreeSet<String>,
77 pub limits: KernelLimits,
78}
79
80#[derive(Debug, Clone)]
81pub enum KernelEvent {
82 Started,
83 ModelStarted {
84 turn: usize,
85 },
86 ModelCompleted {
87 turn: usize,
88 },
89 ToolStarted {
90 call_id: String,
91 name: String,
92 },
93 ToolCompleted {
94 call_id: String,
95 name: String,
96 failed: bool,
97 },
98 Warning {
99 code: String,
100 message: String,
101 },
102}
103
104#[async_trait]
105pub trait KernelEventSink: Send + Sync {
106 async fn emit(&self, event: KernelEvent) -> Result<(), KernelFailure>;
107}
108
109#[derive(Debug, Clone)]
110pub struct KernelOutcome {
111 pub answer: String,
112 pub model_turns: usize,
113 pub tool_calls: usize,
114 pub usage: TokenUsage,
115}
116
117#[derive(Debug, Error, Clone)]
118#[error("{code}: {message}")]
119pub struct KernelFailure {
120 pub code: String,
121 pub message: String,
122 pub retryable: bool,
123 pub commit: CommitDisposition,
124}
125
126impl KernelFailure {
127 pub fn new(code: impl Into<String>, message: impl Into<String>) -> Self {
128 Self {
129 code: code.into(),
130 message: message.into(),
131 retryable: false,
132 commit: CommitDisposition::NotCommitted,
133 }
134 }
135}
136
137#[async_trait]
138pub trait RuntimeKernel: Send + Sync {
139 async fn execute(
140 &self,
141 operation: OperationContext,
142 spec: KernelSpec,
143 sessions: ExecutionSessions,
144 events: Arc<dyn KernelEventSink>,
145 ) -> Result<KernelOutcome, KernelFailure>;
146}
147
148#[async_trait]
149pub trait AgentPackageResolver: Send + Sync {
150 async fn resolve(
151 &self,
152 operation: &OperationContext,
153 resolved: &ResolvedExecutionContext,
154 ) -> Result<Arc<AgentPackage>, KernelFailure>;
155}