This is an automated email from the ASF dual-hosted git repository.

wenjin272 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/flink-agents.git


The following commit(s) were added to refs/heads/main by this push:
     new 0c8da869 [fix] Make agents block optional so infra-only YAML files 
load (#775) (#809)
0c8da869 is described below

commit 0c8da869605112de7549393d5ebeb1393e0bbe1f
Author: Wenjin Xie <[email protected]>
AuthorDate: Mon Jun 8 17:12:11 2026 +0800

    [fix] Make agents block optional so infra-only YAML files load (#775) (#809)
    
    Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
---
 .../apache/flink/agents/api/yaml/spec/YamlAgentsDocument.java  |  4 ++--
 .../flink/agents/api/yaml/spec/YamlAgentsDocumentTest.java     | 10 ++++++++++
 docs/content/docs/development/yaml.md                          |  2 +-
 docs/yaml-schema.json                                          |  5 +----
 python/flink_agents/api/yaml/specs.py                          |  9 ++++++---
 python/flink_agents/api/yaml/tests/test_specs.py               |  9 ++++++---
 6 files changed, 26 insertions(+), 13 deletions(-)

diff --git 
a/api/src/main/java/org/apache/flink/agents/api/yaml/spec/YamlAgentsDocument.java
 
b/api/src/main/java/org/apache/flink/agents/api/yaml/spec/YamlAgentsDocument.java
index cc0874d0..1b0fbfa9 100644
--- 
a/api/src/main/java/org/apache/flink/agents/api/yaml/spec/YamlAgentsDocument.java
+++ 
b/api/src/main/java/org/apache/flink/agents/api/yaml/spec/YamlAgentsDocument.java
@@ -42,7 +42,7 @@ public final class YamlAgentsDocument {
 
     @JsonCreator
     public YamlAgentsDocument(
-            @JsonProperty(value = "agents", required = true) List<AgentSpec> 
agents,
+            @JsonProperty("agents") List<AgentSpec> agents,
             @JsonProperty("prompts") List<PromptSpec> prompts,
             @JsonProperty("tools") List<ToolSpec> tools,
             @JsonProperty("skills") List<SkillsSpec> skills,
@@ -54,7 +54,7 @@ public final class YamlAgentsDocument {
             @JsonProperty("embedding_model_setups") List<DescriptorSpec> 
embeddingModelSetups,
             @JsonProperty("vector_stores") List<DescriptorSpec> vectorStores,
             @JsonProperty("mcp_servers") List<DescriptorSpec> mcpServers) {
-        this.agents = agents;
+        this.agents = orEmpty(agents);
         this.prompts = orEmpty(prompts);
         this.tools = orEmpty(tools);
         this.skills = orEmpty(skills);
diff --git 
a/api/src/test/java/org/apache/flink/agents/api/yaml/spec/YamlAgentsDocumentTest.java
 
b/api/src/test/java/org/apache/flink/agents/api/yaml/spec/YamlAgentsDocumentTest.java
index e5326826..d7e7604e 100644
--- 
a/api/src/test/java/org/apache/flink/agents/api/yaml/spec/YamlAgentsDocumentTest.java
+++ 
b/api/src/test/java/org/apache/flink/agents/api/yaml/spec/YamlAgentsDocumentTest.java
@@ -46,4 +46,14 @@ class YamlAgentsDocumentTest {
         assertThat(doc.getActions()).hasSize(1);
         assertThat(doc.getActions().get(0).getName()).isEqualTo("shared_a");
     }
+
+    @Test
+    void infraOnlyFile() throws Exception {
+        YamlAgentsDocument doc =
+                M.readValue(
+                        "chat_model_connections:\n  - name: x\n    clazz: 
ollama\n",
+                        YamlAgentsDocument.class);
+        assertThat(doc.getAgents()).isEmpty();
+        assertThat(doc.getChatModelConnections()).hasSize(1);
+    }
 }
diff --git a/docs/content/docs/development/yaml.md 
b/docs/content/docs/development/yaml.md
index 30760d80..a6054fa3 100644
--- a/docs/content/docs/development/yaml.md
+++ b/docs/content/docs/development/yaml.md
@@ -382,7 +382,7 @@ agentsEnv.loadYaml(Paths.get("./shared.yaml"));
 
 {{< /tabs >}}
 
-A common pattern is to split a topology file (the agents themselves) from an 
infrastructure file (chat-model connections, vector stores, ...). The 
infrastructure file can be swapped per environment (dev / staging / prod) 
without touching the agent definitions.
+A common pattern is to split a topology file (the agents themselves) from an 
infrastructure file (chat-model connections, vector stores, ...). The 
infrastructure file can be swapped per environment (dev / staging / prod) 
without touching the agent definitions. The `agents:` block is optional, so an 
infrastructure-only file (no `agents:` block) is loaded as shared resources.
 
 For an end-to-end runnable walkthrough that loads a YAML-declared agent and 
runs it on Flink, see [YAML Agent Quickstart]({{< ref 
"docs/get-started/quickstart/yaml_agent" >}}).
 
diff --git a/docs/yaml-schema.json b/docs/yaml-schema.json
index 015fdebd..2b21d71d 100644
--- a/docs/yaml-schema.json
+++ b/docs/yaml-schema.json
@@ -400,7 +400,7 @@
     }
   },
   "additionalProperties": false,
-  "description": "Top-level YAML document.\n\nAlways wraps one or more agents 
under ``agents:``. Resources and\nactions declared at the same level as 
``agents:`` are shared:\nresources are registered on the environment; actions 
can be\nreferenced from any agent by name string.",
+  "description": "Top-level YAML document.\n\nAgents are declared under 
``agents:``. The block is optional, so a\nfile may carry only shared 
infrastructure (chat-model connections,\nvector stores, ...) \u2014 useful for 
splitting a topology file from an\ninfrastructure file that can be swapped per 
environment. Resources\nand actions declared at the same level as ``agents:`` 
are shared:\nresources are registered on the environment; actions can 
be\nreferenced from any agent by name string.",
   "properties": {
     "actions": {
       "items": {
@@ -480,9 +480,6 @@
       "type": "array"
     }
   },
-  "required": [
-    "agents"
-  ],
   "title": "YamlAgentsDocument",
   "type": "object"
 }
diff --git a/python/flink_agents/api/yaml/specs.py 
b/python/flink_agents/api/yaml/specs.py
index b7b7cf71..cf99c66b 100644
--- a/python/flink_agents/api/yaml/specs.py
+++ b/python/flink_agents/api/yaml/specs.py
@@ -220,15 +220,18 @@ class AgentSpec(BaseModel):
 class YamlAgentsDocument(BaseModel):
     """Top-level YAML document.
 
-    Always wraps one or more agents under ``agents:``. Resources and
-    actions declared at the same level as ``agents:`` are shared:
+    Agents are declared under ``agents:``. The block is optional, so a
+    file may carry only shared infrastructure (chat-model connections,
+    vector stores, ...) — useful for splitting a topology file from an
+    infrastructure file that can be swapped per environment. Resources
+    and actions declared at the same level as ``agents:`` are shared:
     resources are registered on the environment; actions can be
     referenced from any agent by name string.
     """
 
     model_config = ConfigDict(extra="forbid")
 
-    agents: List[AgentSpec]
+    agents: List[AgentSpec] = Field(default_factory=list)
 
     prompts: List[PromptSpec] = Field(default_factory=list)
     tools: List[ToolSpec] = Field(default_factory=list)
diff --git a/python/flink_agents/api/yaml/tests/test_specs.py 
b/python/flink_agents/api/yaml/tests/test_specs.py
index e7028588..1c849f0f 100644
--- a/python/flink_agents/api/yaml/tests/test_specs.py
+++ b/python/flink_agents/api/yaml/tests/test_specs.py
@@ -224,9 +224,12 @@ def test_agent_spec_action_can_be_string_reference() -> 
None:
     assert isinstance(spec.actions[1], ActionSpec)
 
 
-def test_yaml_document_requires_agents() -> None:
-    with pytest.raises(ValidationError):
-        YamlAgentsDocument.model_validate({})
+def test_yaml_document_allows_infra_only_file() -> None:
+    doc = YamlAgentsDocument.model_validate(
+        {"chat_model_connections": [{"name": "x", "clazz": "ollama"}]}
+    )
+    assert doc.agents == []
+    assert doc.chat_model_connections[0].name == "x"
 
 
 def test_yaml_document_minimal() -> None:

Reply via email to