fix(graph): reject agents that ship both config.yaml and graph.yaml at load

Agent::init refuses that layout, so any agent node pointing at such a
directory failed at run time while validation passed it as graph-capable.
This commit is contained in:
Dark-Alex-17 committed 2026-09-11 10:56:28 -06:00
1 parent 778aa6449c
commit 02e2227aa0
1 file changed
+30
+30
View File
@@ -477,6 +477,15 @@ impl GraphValidator {
a.agent a.agent
), ),
)); ));
} else if has_config && has_graph {
result.error(ValidationError::with_node(
node_id,
format!(
"Agent '{}' has both config.yaml and graph.yaml; a graph agent is \
defined by graph.yaml alone — remove one of the two files",
a.agent
),
));
} }
if let Some(inputs) = &a.inputs { if let Some(inputs) = &a.inputs {
if has_config && !has_graph { if has_config && !has_graph {
@@ -4046,6 +4055,27 @@ mod tests {
assert!(!inputs_requires_graph_agent_error(&result, "a")); assert!(!inputs_requires_graph_agent_error(&result, "a"));
} }
#[test]
#[serial]
fn agent_with_both_config_and_graph_errors() {
let _guard = TestConfigDirGuard::new();
materialize_config_only_agent("mixed-agent");
materialize_graph_agent("mixed-agent");
let node = agent_node_with_inputs("a", "mixed-agent", &[("x", "{{k}}")]);
let graph = graph_with(vec![("a", node), ("end", end_node("end"))], "a");
let result = validator().validate(&graph);
assert!(
result.errors.iter().any(|e| e
.message
.starts_with("Agent 'mixed-agent' has both config.yaml and graph.yaml")
&& e.node_id.as_deref() == Some("a")),
"{:?}",
result.errors
);
}
#[test] #[test]
#[serial] #[serial]
fn agent_inputs_missing_agent_dir_gets_only_the_not_found_error() { fn agent_inputs_missing_agent_dir_gets_only_the_not_found_error() {