Skip to main content

ainl_runtime/
lib.rs

1//! AINL Runtime - graph-based agent programming runtime
2//!
3//! This crate provides the execution runtime for AINL (AI Native Language),
4//! integrating with the ainl-memory graph substrate for persistent memory.
5
6use ainl_memory::{AinlMemoryNode, GraphStore};
7use serde::{Deserialize, Serialize};
8
9/// Trait that memory backends must implement for AINL runtime integration
10pub trait MemoryProvider {
11    /// Write an agent turn as an episode node
12    fn record_episode(&self, node: AinlMemoryNode) -> Result<(), String>;
13
14    /// Query recent episodes for context retrieval
15    fn get_recent_context(
16        &self,
17        agent_id: &str,
18        limit: usize,
19    ) -> Result<Vec<AinlMemoryNode>, String>;
20}
21
22/// Configuration for the AINL runtime
23#[derive(Serialize, Deserialize, Debug, Clone)]
24pub struct RuntimeConfig {
25    /// Maximum depth for delegation chains
26    pub max_delegation_depth: u32,
27
28    /// Enable graph-based memory persistence
29    pub enable_graph_memory: bool,
30}
31
32impl Default for RuntimeConfig {
33    fn default() -> Self {
34        Self {
35            max_delegation_depth: 10,
36            enable_graph_memory: true,
37        }
38    }
39}
40
41/// AINL runtime context for execution
42pub struct RuntimeContext<S: GraphStore> {
43    _config: RuntimeConfig,
44    memory: Option<S>,
45}
46
47impl<S: GraphStore> RuntimeContext<S> {
48    /// Create a new runtime context with the given memory backend
49    pub fn new(config: RuntimeConfig, memory: Option<S>) -> Self {
50        Self {
51            _config: config,
52            memory,
53        }
54    }
55
56    /// Record an agent delegation as an episode node
57    pub fn record_delegation(
58        &self,
59        agent_id: String,
60        delegated_to: String,
61        trace_id: String,
62        depth: u32,
63    ) -> Result<(), String> {
64        if let Some(store) = &self.memory {
65            let node = AinlMemoryNode::new_delegation_episode(
66                agent_id,
67                delegated_to,
68                trace_id,
69                depth,
70            );
71            store.write_node(&node)?;
72        }
73        Ok(())
74    }
75
76    /// Record a tool execution as an episode node
77    pub fn record_tool_execution(
78        &self,
79        agent_id: String,
80        tool_name: String,
81    ) -> Result<(), String> {
82        if let Some(store) = &self.memory {
83            let node = AinlMemoryNode::new_tool_episode(agent_id, tool_name);
84            store.write_node(&node)?;
85        }
86        Ok(())
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    #[test]
95    fn test_runtime_config_default() {
96        let config = RuntimeConfig::default();
97        assert_eq!(config.max_delegation_depth, 10);
98        assert!(config.enable_graph_memory);
99    }
100}