diff --git a/backend/src/core/agent/crewai/template_loader.py b/backend/src/core/agent/crewai/template_loader.py
index 89a230d..d91f552 100644
--- a/backend/src/core/agent/crewai/template_loader.py
+++ b/backend/src/core/agent/crewai/template_loader.py
@@ -12,12 +12,11 @@ class CrewAITemplate:
agents: dict[str, Any]
tasks: dict[str, Any]
workflow: dict[str, Any]
- prompts: dict[str, str]
tools_whitelist: set[str]
def _default_static_root() -> Path:
- return Path(__file__).resolve().parents[3] / "config" / "static" / "agent"
+ return Path(__file__).resolve().parents[3] / "config" / "static" / "crewai"
def _read_yaml(file_path: Path) -> dict[str, Any]:
@@ -30,12 +29,6 @@ def _read_yaml(file_path: Path) -> dict[str, Any]:
return loaded
-def _read_prompt(file_path: Path) -> str:
- if not file_path.is_file():
- raise FileNotFoundError(f"Required prompt file not found: {file_path}")
- return file_path.read_text(encoding="utf-8").strip()
-
-
def validate_workflow_stages(stages: list[str]) -> None:
expected = ["intent", "execution", "organization"]
if stages != expected:
@@ -56,27 +49,19 @@ def load_tools_whitelist(static_root: Path | None = None) -> set[str]:
def load_crewai_template(static_root: Path | None = None) -> CrewAITemplate:
root = static_root or _default_static_root()
- crewai_root = root / "crewai"
- agents = _read_yaml(crewai_root / "agents.yaml")
- tasks = _read_yaml(crewai_root / "tasks.yaml")
- workflow = _read_yaml(crewai_root / "workflow.yaml")
+ agents = _read_yaml(root / "agents.yaml")
+ tasks = _read_yaml(root / "tasks.yaml")
+ workflow = _read_yaml(root / "workflow.yaml")
stages = workflow.get("stages")
if not isinstance(stages, list):
raise ValueError("workflow.yaml field 'stages' must be a list")
validate_workflow_stages([str(stage) for stage in stages])
- prompts = {
- "intent": _read_prompt(crewai_root / "prompts" / "intent.md"),
- "execution": _read_prompt(crewai_root / "prompts" / "execution.md"),
- "organization": _read_prompt(crewai_root / "prompts" / "organization.md"),
- }
-
return CrewAITemplate(
agents=agents,
tasks=tasks,
workflow=workflow,
- prompts=prompts,
tools_whitelist=load_tools_whitelist(root),
)
diff --git a/backend/src/core/initialization/init_data.py b/backend/src/core/config/initial/init_data.py
similarity index 95%
rename from backend/src/core/initialization/init_data.py
rename to backend/src/core/config/initial/init_data.py
index c066f96..bc87829 100644
--- a/backend/src/core/initialization/init_data.py
+++ b/backend/src/core/config/initial/init_data.py
@@ -14,7 +14,7 @@ from core.logging import get_logger
from models.llm import Llm
from models.llm_factory import LlmFactory
-logger = get_logger("core.initialization.init_data")
+logger = get_logger("core.config.initial.init_data")
class LlmFactorySeed(BaseModel):
@@ -35,11 +35,7 @@ class LlmCatalogSeed(BaseModel):
def _default_catalog_path() -> Path:
return (
- Path(__file__).resolve().parents[1]
- / "config"
- / "static"
- / "agent"
- / "llm_catalog.yaml"
+ Path(__file__).resolve().parents[1] / "static" / "database" / "llm_catalog.yaml"
)
diff --git a/backend/src/core/config/static/agent/crewai/agents.yaml b/backend/src/core/config/static/agent/crewai/agents.yaml
deleted file mode 100644
index 74f611f..0000000
--- a/backend/src/core/config/static/agent/crewai/agents.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-intent:
- role: Intent Agent
- goal: Classify user intent and decide execution strategy
-execution:
- role: Execution Agent
- goal: Execute tasks with available tools
-organization:
- role: Organization Agent
- goal: Organize output for user-friendly response
diff --git a/backend/src/core/config/static/agent/crewai/prompts/execution.md b/backend/src/core/config/static/agent/crewai/prompts/execution.md
deleted file mode 100644
index ed0546b..0000000
--- a/backend/src/core/config/static/agent/crewai/prompts/execution.md
+++ /dev/null
@@ -1,2 +0,0 @@
-你是任务执行代理。
-基于输入意图与上下文调用可用工具,并生成可验证执行结果。
diff --git a/backend/src/core/config/static/agent/crewai/prompts/intent.md b/backend/src/core/config/static/agent/crewai/prompts/intent.md
deleted file mode 100644
index 5e7dd3b..0000000
--- a/backend/src/core/config/static/agent/crewai/prompts/intent.md
+++ /dev/null
@@ -1,2 +0,0 @@
-你是意图识别代理。
-你的任务是识别用户输入的意图类型,并返回结构化意图标签。
diff --git a/backend/src/core/config/static/agent/crewai/prompts/organization.md b/backend/src/core/config/static/agent/crewai/prompts/organization.md
deleted file mode 100644
index 4e0268f..0000000
--- a/backend/src/core/config/static/agent/crewai/prompts/organization.md
+++ /dev/null
@@ -1,2 +0,0 @@
-你是结果整理代理。
-将执行结果组织为面向用户的清晰回复,保留关键信息与必要引用。
diff --git a/backend/src/core/config/static/agent/crewai/tasks.yaml b/backend/src/core/config/static/agent/crewai/tasks.yaml
deleted file mode 100644
index 43a1f9f..0000000
--- a/backend/src/core/config/static/agent/crewai/tasks.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-intent:
- description: Identify user intent and required capabilities
-execution:
- description: Execute intent with tools and model calls
-organization:
- description: Format final response and references
diff --git a/backend/src/core/config/static/crewai/agents.yaml b/backend/src/core/config/static/crewai/agents.yaml
new file mode 100644
index 0000000..3076346
--- /dev/null
+++ b/backend/src/core/config/static/crewai/agents.yaml
@@ -0,0 +1,22 @@
+intent:
+ role: Intent Agent
+ goal: Classify user intent and decide execution strategy
+ backstory: >
+ You are an expert intent classifier with deep understanding
+ of user query patterns and dialogue acts. Your role is to
+ analyze user input and determine the appropriate action.
+
+execution:
+ role: Execution Agent
+ goal: Execute tasks with available tools
+ backstory: >
+ You are a skilled task executor with expertise in tool calling,
+ API interactions, and result verification. You work systematically
+ to complete user requests.
+
+organization:
+ role: Organization Agent
+ goal: Organize output for user-friendly response
+ backstory: >
+ You specialize in presenting results in a clear, user-friendly manner.
+ You ensure responses are well-structured and actionable.
diff --git a/backend/src/core/config/static/crewai/tasks.yaml b/backend/src/core/config/static/crewai/tasks.yaml
new file mode 100644
index 0000000..bc652dd
--- /dev/null
+++ b/backend/src/core/config/static/crewai/tasks.yaml
@@ -0,0 +1,16 @@
+intent:
+ description: Identify user intent and required capabilities
+ expected_output: >
+ Structured intent classification with intent type, confidence score,
+ and recommended action plan
+
+execution:
+ description: Execute intent with tools and model calls
+ expected_output: >
+ Verified execution results with tool outputs, status, and any errors
+
+organization:
+ description: Format final response and references
+ expected_output: >
+ User-friendly response with structured output, citations, and
+ clear next steps if applicable
diff --git a/backend/src/core/config/static/agent/tools.yaml b/backend/src/core/config/static/crewai/tools.yaml
similarity index 100%
rename from backend/src/core/config/static/agent/tools.yaml
rename to backend/src/core/config/static/crewai/tools.yaml
diff --git a/backend/src/core/config/static/agent/crewai/workflow.yaml b/backend/src/core/config/static/crewai/workflow.yaml
similarity index 100%
rename from backend/src/core/config/static/agent/crewai/workflow.yaml
rename to backend/src/core/config/static/crewai/workflow.yaml
diff --git a/backend/src/core/config/static/agent/llm_catalog.yaml b/backend/src/core/config/static/database/llm_catalog.yaml
similarity index 100%
rename from backend/src/core/config/static/agent/llm_catalog.yaml
rename to backend/src/core/config/static/database/llm_catalog.yaml
diff --git a/backend/src/core/config/static/database/user_agent_catalog.yaml b/backend/src/core/config/static/database/user_agent_catalog.yaml
new file mode 100644
index 0000000..8428f80
--- /dev/null
+++ b/backend/src/core/config/static/database/user_agent_catalog.yaml
@@ -0,0 +1 @@
+agents: []
diff --git a/backend/src/core/runtime/cli.py b/backend/src/core/runtime/cli.py
index e8cfcc4..d12e039 100644
--- a/backend/src/core/runtime/cli.py
+++ b/backend/src/core/runtime/cli.py
@@ -5,7 +5,7 @@ import subprocess
import sys
from pathlib import Path
-from core.initialization.init_data import initialize_data
+from core.config.initial.init_data import initialize_data
from core.logging import get_logger
logger = get_logger("core.runtime.cli")
diff --git a/backend/tests/unit/core/config/test_crewai_template_loader.py b/backend/tests/unit/core/config/test_crewai_template_loader.py
index 6287a1b..88c4870 100644
--- a/backend/tests/unit/core/config/test_crewai_template_loader.py
+++ b/backend/tests/unit/core/config/test_crewai_template_loader.py
@@ -18,7 +18,7 @@ def _write(path: Path, content: str) -> None:
def _prepare_static_root(root: Path) -> Path:
_write(
- root / "crewai" / "agents.yaml",
+ root / "agents.yaml",
"""
intent:
role: Intent Agent
@@ -29,7 +29,7 @@ organization:
""".strip(),
)
_write(
- root / "crewai" / "tasks.yaml",
+ root / "tasks.yaml",
"""
intent:
description: classify
@@ -40,7 +40,7 @@ organization:
""".strip(),
)
_write(
- root / "crewai" / "workflow.yaml",
+ root / "workflow.yaml",
"""
stages:
- intent
@@ -48,9 +48,6 @@ stages:
- organization
""".strip(),
)
- _write(root / "crewai" / "prompts" / "intent.md", "intent prompt")
- _write(root / "crewai" / "prompts" / "execution.md", "execution prompt")
- _write(root / "crewai" / "prompts" / "organization.md", "organization prompt")
_write(
root / "tools.yaml",
"""
@@ -63,24 +60,21 @@ tools:
def test_load_crewai_template_success_when_all_files_valid(tmp_path: Path) -> None:
- static_root = _prepare_static_root(tmp_path / "agent")
+ static_root = _prepare_static_root(tmp_path)
template = load_crewai_template(static_root)
assert set(template.agents.keys()) == {"intent", "execution", "organization"}
assert set(template.tasks.keys()) == {"intent", "execution", "organization"}
assert template.workflow["stages"] == ["intent", "execution", "organization"]
- assert template.prompts["intent"] == "intent prompt"
- assert template.prompts["execution"] == "execution prompt"
- assert template.prompts["organization"] == "organization prompt"
assert template.tools_whitelist == {"asr_fun_asr", "doc_extract"}
def test_load_crewai_template_raises_file_not_found_when_required_file_missing(
tmp_path: Path,
) -> None:
- static_root = _prepare_static_root(tmp_path / "agent")
- (static_root / "crewai" / "tasks.yaml").unlink()
+ static_root = _prepare_static_root(tmp_path)
+ (static_root / "tasks.yaml").unlink()
with pytest.raises(FileNotFoundError):
load_crewai_template(static_root)
@@ -89,9 +83,9 @@ def test_load_crewai_template_raises_file_not_found_when_required_file_missing(
def test_load_crewai_template_raises_value_error_when_workflow_stages_invalid(
tmp_path: Path,
) -> None:
- static_root = _prepare_static_root(tmp_path / "agent")
+ static_root = _prepare_static_root(tmp_path)
_write(
- static_root / "crewai" / "workflow.yaml",
+ static_root / "workflow.yaml",
"""
stages:
- execution
@@ -105,7 +99,7 @@ stages:
def test_load_tools_whitelist_from_tools_yaml(tmp_path: Path) -> None:
- static_root = _prepare_static_root(tmp_path / "agent")
+ static_root = _prepare_static_root(tmp_path)
whitelist = load_tools_whitelist(static_root)
@@ -124,7 +118,7 @@ def test_validate_workflow_stages_rejects_extra_or_missing_stage() -> None:
def test_load_tools_whitelist_rejects_non_string_item(tmp_path: Path) -> None:
- static_root = _prepare_static_root(tmp_path / "agent")
+ static_root = _prepare_static_root(tmp_path)
_write(
static_root / "tools.yaml",
"""
diff --git a/backend/tests/unit/core/test_agent_init_data.py b/backend/tests/unit/core/test_agent_init_data.py
index 9d85e95..cbd1359 100644
--- a/backend/tests/unit/core/test_agent_init_data.py
+++ b/backend/tests/unit/core/test_agent_init_data.py
@@ -7,7 +7,7 @@ from sqlalchemy import Column, String, Table, func, select
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from core.db.base import Base
-from core.initialization import init_data
+from core.config.initial import init_data
from models.llm import Llm
from models.llm_factory import LlmFactory
@@ -19,7 +19,7 @@ def test_llm_catalog_file_exists_and_has_required_fields() -> None:
/ "core"
/ "config"
/ "static"
- / "agent"
+ / "database"
/ "llm_catalog.yaml"
)
diff --git a/docs/plans/2026-03-02-config-restructuring-plan.md b/docs/plans/2026-03-02-config-restructuring-plan.md
new file mode 100644
index 0000000..0eefbe4
--- /dev/null
+++ b/docs/plans/2026-03-02-config-restructuring-plan.md
@@ -0,0 +1,184 @@
+# Config 目录重构计划
+
+**日期**: 2026-03-02
+**目标**: 重新整理 backend/src/core/config 下的配置文件,按领域分类
+
+---
+
+## 1. 需求背景
+
+当前 `backend/src/core/config` 结构存在以下问题:
+
+1. **职责不清**: `initialization` 模块放在 `core/` 根目录,但实际是配置初始化,应归属 `config/`
+2. **分类粗放**: `static/agent/` 混入了不同领域的配置(LLM 目录、工具白名单、Agent 模板)
+3. **配置不符规范**: CrewAI 模板缺少必要字段(backstory、expected_output),且 prompts 目录是冗余的
+
+---
+
+## 2. 目标结构
+
+```
+backend/src/core/
+├── config/
+│ ├── settings.py # 运行时配置(不变)
+│ ├── initial/
+│ │ └── init_data.py # 种子数据初始化(移动)
+│ └── static/
+│ ├── database/
+│ │ ├── llm_catalog.yaml # LLM 目录(移动)
+│ │ └── user_agent_catalog.yaml # 用户 Agent 种子(新增,置空)
+│ └── crewai/
+│ ├── agents.yaml # Agent 定义(移动 + 补充字段)
+│ ├── tasks.yaml # Task 定义(移动 + 补充 expected_output)
+│ ├── workflow.yaml # 工作流(移动)
+│ └── tools.yaml # 工具白名单(移动)
+└── agent/ # 代码实现(不变)
+ └── crewai/
+ └── template_loader.py # 需更新路径引用
+```
+
+---
+
+## 3. 涉及代码清单
+
+### 3.1 需要移动/删除的文件
+
+| 操作 | 源路径 | 目标路径 |
+|------|--------|----------|
+| 移动 | `core/initialization/init_data.py` | `core/config/initial/init_data.py` |
+| 移动 | `core/config/static/agent/llm_catalog.yaml` | `core/config/static/database/llm_catalog.yaml` |
+| 新建 | - | `core/config/static/database/user_agent_catalog.yaml` |
+| 移动 | `core/config/static/agent/crewai/agents.yaml` | `core/config/static/crewai/agents.yaml` |
+| 移动 | `core/config/static/agent/crewai/tasks.yaml` | `core/config/static/crewai/tasks.yaml` |
+| 移动 | `core/config/static/agent/crewai/workflow.yaml` | `core/config/static/crewai/workflow.yaml` |
+| 移动 | `core/config/static/agent/tools.yaml` | `core/config/static/crewai/tools.yaml` |
+| 删除 | `core/config/static/agent/crewai/prompts/` | - |
+
+### 3.2 需要修改的代码文件
+
+| 文件 | 修改内容 |
+|------|----------|
+| `core/config/initial/init_data.py` | 更新 `_default_catalog_path()` 指向 `static/database/` |
+| `core/agent/crewai/template_loader.py` | 1. 更新 `_default_static_root()` 指向 `static/crewai/`
2. 移除 `CrewAITemplate.prompts` 字段
3. 移除 `_read_prompt()` 和 prompts 加载逻辑 |
+| `core/runtime/cli.py` | 更新 import 路径 |
+| `tests/unit/core/test_agent_init_data.py` | 更新 import 路径和路径断言 |
+| `tests/unit/core/config/test_crewai_template_loader.py` | 1. 更新路径构造
2. 移除 prompts 目录创建
3. 移除 prompts 相关断言 |
+
+### 3.3 需要更新的配置文件内容
+
+#### agents.yaml - 补充 backstory
+
+```yaml
+intent:
+ role: Intent Agent
+ goal: Classify user intent and decide execution strategy
+ backstory: >
+ You are an expert intent classifier with deep understanding
+ of user query patterns and dialogue acts. Your role is to
+ analyze user input and determine the appropriate action.
+
+execution:
+ role: Execution Agent
+ goal: Execute tasks with available tools
+ backstory: >
+ You are a skilled task executor with expertise in tool calling,
+ API interactions, and result verification. You work systematically
+ to complete user requests.
+
+organization:
+ role: Organization Agent
+ goal: Format final response and references
+ backstory: >
+ You specialize in presenting results in a clear, user-friendly manner.
+ You ensure responses are well-structured and actionable.
+```
+
+#### tasks.yaml - 补充 expected_output
+
+```yaml
+intent:
+ description: Identify user intent and required capabilities
+ expected_output: >
+ Structured intent classification with intent type, confidence score,
+ and recommended action plan
+
+execution:
+ description: Execute intent with tools and model calls
+ expected_output: >
+ Verified execution results with tool outputs, status, and any errors
+
+organization:
+ description: Format final response and references
+ expected_output: >
+ User-friendly response with structured output, citations, and
+ clear next steps if applicable
+```
+
+#### user_agent_catalog.yaml - 置空
+
+```yaml
+agents: []
+```
+
+---
+
+## 4. 实施步骤
+
+### Phase 1: 移动配置文件
+
+1. 创建 `core/config/static/database/` 目录
+2. 创建 `core/config/static/crewai/` 目录
+3. 移动并合并 LLM 目录配置
+4. 创建空的 user_agent_catalog.yaml
+
+### Phase 2: 更新代码引用
+
+1. 移动 `initialization/init_data.py` → `config/initial/init_data.py`
+2. 更新 `init_data.py` 中的路径函数 `_default_catalog_path()` → `static/database/`
+3. 更新 `template_loader.py`:
+ - 路径函数 `_default_static_root()` → `static/crewai/`
+ - 移除 `_read_prompt()` 函数
+ - 移除 `CrewAITemplate.prompts` 字段
+ - 移除 prompts 加载逻辑
+4. 更新 `cli.py` 的 import 路径
+5. 删除旧的 `core/initialization/` 目录(如为空)
+
+### Phase 4: 更新测试
+
+1. 更新 `test_agent_init_data.py`:
+ - import 路径: `core.initialization` → `core.config.initial`
+ - 路径断言: `static/agent/` → `static/database/`
+2. 更新 `test_crewai_template_loader.py`:
+ - 路径构造: `agent/` → `crewai/`
+ - 移除 prompts 目录创建代码
+ - 移除 `template.prompts` 相关断言
+3. 运行测试验证
+
+---
+
+## 5. 风险与回滚
+
+### 风险
+
+- 路径变更可能导致运行时找不到配置文件
+- 测试路径断言需要同步更新
+
+### 回滚方案
+
+- 保留 git 分支,验证通过后再合并
+- 如有问题,可通过 git revert 快速回滚
+
+---
+
+## 6. 验证方式
+
+```bash
+# 1. 运行单元测试
+cd backend && uv run pytest tests/unit/core/test_agent_init_data.py tests/unit/core/config/test_crewai_template_loader.py -v
+
+# 2. 运行 lint
+cd backend && uv run ruff check src/core/config/ src/core/agent/crewai/ src/core/runtime/cli.py
+
+# 3. 运行 typecheck
+cd backend && uv run basedpyright src/core/config/ src/core/agent/crewai/ src/core/runtime/cli.py
+```