use serde::Serialize;
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
pub struct AgentFrameworkRecognizer {
pub name: &'static str,
pub prefixes: &'static [&'static str],
pub literal_keys: &'static [&'static str],
pub marker_keys: &'static [&'static str],
}
impl AgentFrameworkRecognizer {
pub fn matches_key(&self, key: &str) -> bool {
self.prefixes.iter().any(|p| key.starts_with(p)) || self.literal_keys.contains(&key)
}
pub fn is_present<'a, I: IntoIterator<Item = &'a str>>(&self, keys: I) -> bool {
let mut any_prefix = false;
for k in keys {
if self.marker_keys.contains(&k) {
return true;
}
if self.prefixes.iter().any(|p| k.starts_with(p)) {
any_prefix = true;
}
}
any_prefix
}
}
pub const AGENT_FRAMEWORKS: &[AgentFrameworkRecognizer] = &[
AgentFrameworkRecognizer {
name: "CrewAI",
prefixes: &["crew.", "task."],
literal_keys: &["agent.role", "agent.goal", "agent.backstory", "agent.id"],
marker_keys: &["crew.task", "crew.id", "agent.role", "agent.goal"],
},
AgentFrameworkRecognizer {
name: "AutoGen",
prefixes: &["autogen."],
literal_keys: &[],
marker_keys: &["autogen.agent_name", "autogen.role"],
},
AgentFrameworkRecognizer {
name: "LangGraph",
prefixes: &["graph.", "langgraph."],
literal_keys: &[],
marker_keys: &[
"graph.node",
"graph.state",
"langgraph.node",
"langgraph.step",
],
},
];
pub fn is_any_agent_framework_key(key: &str) -> bool {
AGENT_FRAMEWORKS.iter().any(|fw| fw.matches_key(key))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn crewai_matches_prefixes_and_literals() {
let crew = AGENT_FRAMEWORKS
.iter()
.find(|f| f.name == "CrewAI")
.unwrap();
assert!(crew.matches_key("crew.task"));
assert!(crew.matches_key("crew.id"));
assert!(crew.matches_key("task.name"));
assert!(crew.matches_key("agent.role"));
assert!(!crew.matches_key("autogen.x"));
assert!(!crew.matches_key("gen_ai.system"));
}
#[test]
fn is_present_requires_marker_or_prefix_match() {
let crew = AGENT_FRAMEWORKS
.iter()
.find(|f| f.name == "CrewAI")
.unwrap();
assert!(crew.is_present(["crew.task"].iter().copied()));
assert!(crew.is_present(["crew.custom_attr"].iter().copied()));
assert!(!crew.is_present(["gen_ai.system", "model"].iter().copied()));
}
#[test]
fn langgraph_marker_detection() {
let lg = AGENT_FRAMEWORKS
.iter()
.find(|f| f.name == "LangGraph")
.unwrap();
assert!(lg.is_present(["graph.node"].iter().copied()));
assert!(lg.is_present(["langgraph.step"].iter().copied()));
assert!(!lg.is_present(["gen_ai.system"].iter().copied()));
}
#[test]
fn is_any_agent_framework_key_covers_all_three() {
assert!(is_any_agent_framework_key("crew.task"));
assert!(is_any_agent_framework_key("autogen.agent_name"));
assert!(is_any_agent_framework_key("graph.state"));
assert!(is_any_agent_framework_key("agent.role"));
assert!(!is_any_agent_framework_key("gen_ai.system"));
assert!(!is_any_agent_framework_key("model"));
}
}