27 KiB
27 KiB
Steering Agent 规划文档
✅ 状态: 实施完成 📅 完成时间: 2026-02-24
1. 项目概述
1.1 定位
Steering Agent 是一个项目约束管理Agent,用于:
- 从代码库自动提取项目知识(技术栈、规范、模式)
- 管理用户定义的项目规则
- 在代码生成前提供上下文约束
- 在代码生成后进行合规性检查
1.2 核心价值
| 价值 | 说明 |
|---|---|
| 持久的项目知识 | 自动提取并维护项目的技术栈、规范、模式等信息 |
| 一致的代码生成 | 确保 AI 生成的代码符合项目既有风格和规范 |
| 减少重复解释 | 一次定义规则,所有代码生成自动遵循 |
1.3 工作流程
flowchart TB
subgraph Extract["知识提取"]
A[代码库] --> B[自动分析]
B --> C[技术栈信息]
B --> D[命名规范]
B --> E[目录结构]
B --> F[代码模式]
end
subgraph Define["规则定义"]
G[用户输入] --> H[业务规则]
G --> I[技术规则]
G --> J[安全规则]
G --> K[架构规则]
end
subgraph Merge["知识合并"]
C --> L[项目上下文]
D --> L
E --> L
F --> L
H --> L
I --> L
J --> L
K --> L
end
subgraph Use["使用场景"]
L --> M[生成前: 提供上下文]
L --> N[生成后: 合规检查]
end
M --> O[specs_agent]
M --> P[code_agent]
N --> Q[format_police_agent]
2. 功能设计
2.1 知识提取(自动)
从代码库自动提取以下信息:
| 类别 | 提取内容 | 来源 |
|---|---|---|
| 技术栈 | 语言、框架、版本 | requirements.txt, package.json, Dockerfile |
| 目录结构 | 项目布局、模块划分 | 文件系统扫描 |
| 命名规范 | 文件命名、变量命名、函数命名 | 代码文件分析 |
| 代码模式 | 常用模式、设计模式 | 代码文件分析 |
| 依赖关系 | 内部依赖、外部依赖 | import 语句分析 |
| 配置规范 | 环境变量、配置文件格式 | 配置文件分析 |
2.1.1 技术栈提取详细设计
提取来源与方法:
# tech_stack.py - 技术栈提取器
class TechStackExtractor:
"""技术栈信息提取器"""
def extract(self, project_path: str) -> dict:
return {
"language": self._detect_language(project_path),
"framework": self._detect_frameworks(project_path),
"dependencies": self._extract_dependencies(project_path),
"runtime": self._detect_runtime(project_path)
}
| 检测项 | 检测方法 | 检测文件 |
|---|---|---|
| Python 版本 | 解析 Dockerfile 的 FROM 语句 | Dockerfile |
| Python 依赖 | 解析 requirements.txt | requirements.txt |
| 框架检测 | 检查依赖中的框架关键词 | requirements.txt |
| Node.js 版本 | 解析 package.json 的 engines | package.json |
| Node.js 依赖 | 解析 dependencies | package.json |
框架检测规则:
FRAMEWORK_PATTERNS = {
# Python 框架
"fastapi": "FastAPI",
"flask": "Flask",
"django": "Django",
"pydantic-ai": "Pydantic AI",
"fastmcp": "FastMCP",
"mcp": "MCP",
# Node.js 框架
"express": "Express",
"next": "Next.js",
"react": "React",
"vue": "Vue.js"
}
输出示例:
{
"language": {
"name": "Python",
"version": "3.12",
"source": "Dockerfile"
},
"framework": [
{"name": "FastAPI", "version": ">=0.109.0"},
{"name": "Pydantic AI", "version": ">=0.0.14"},
{"name": "FastMCP", "version": ">=0.1.0"}
],
"dependencies": {
"production": [
"pydantic-ai>=0.0.14",
"mcp>=0.9.0",
"fastmcp>=0.1.0",
"fastapi>=0.109.0",
"uvicorn[standard]>=0.27.0",
"aiohttp>=3.9.0"
],
"development": []
},
"runtime": {
"container": "Docker",
"base_image": "python:3.12-slim"
}
}
2.1.2 目录结构提取详细设计
提取方法:
# structure.py - 目录结构提取器
class StructureExtractor:
"""项目结构提取器"""
# 忽略的目录和文件
IGNORE_PATTERNS = [
"__pycache__", ".git", ".venv", "node_modules",
"*.pyc", "*.pyo", ".DS_Store", "*.egg-info"
]
def extract(self, project_path: str) -> dict:
return {
"root_files": self._get_root_files(project_path),
"directories": self._get_directory_tree(project_path),
"key_files": self._identify_key_files(project_path),
"pattern": self._detect_project_pattern(project_path)
}
项目模式检测:
| 模式名称 | 检测条件 |
|---|---|
agent_templates |
存在 src/server/mcp_server.py 和 src/server/api_server.py |
fastapi_standard |
存在 main.py 或 app.py + FastAPI 依赖 |
python_package |
存在 setup.py 或 pyproject.toml |
monorepo |
存在多个独立的子项目目录 |
输出示例:
{
"root_files": [
"Dockerfile",
"README.md",
"requirements.txt",
"run_api_server.py"
],
"directories": {
"src": {
"__init__.py": "file",
"server": {
"__init__.py": "file",
"api_server.py": "file",
"mcp_server.py": "file"
}
}
},
"key_files": {
"entry_point": "run_api_server.py",
"mcp_tools": "src/server/mcp_server.py",
"api_routes": "src/server/api_server.py",
"dependencies": "requirements.txt",
"container": "Dockerfile"
},
"pattern": {
"name": "agent_templates",
"description": "基于 Pydantic AI 的 Agent 模板结构",
"confidence": 0.95
}
}
2.1.3 命名规范提取详细设计
提取方法:
# naming.py - 命名规范提取器
import ast
import re
class NamingExtractor:
"""命名规范提取器"""
def extract(self, project_path: str) -> dict:
# 收集所有 Python 文件中的命名
names = self._collect_names(project_path)
return {
"files": self._analyze_file_naming(project_path),
"classes": self._analyze_pattern(names["classes"]),
"functions": self._analyze_pattern(names["functions"]),
"variables": self._analyze_pattern(names["variables"]),
"constants": self._analyze_pattern(names["constants"])
}
def _analyze_pattern(self, names: list) -> dict:
"""分析命名模式"""
patterns = {
"snake_case": 0,
"camelCase": 0,
"PascalCase": 0,
"UPPER_SNAKE_CASE": 0
}
for name in names:
if re.match(r'^[a-z][a-z0-9_]*$', name):
patterns["snake_case"] += 1
elif re.match(r'^[a-z][a-zA-Z0-9]*$', name):
patterns["camelCase"] += 1
elif re.match(r'^[A-Z][a-zA-Z0-9]*$', name):
patterns["PascalCase"] += 1
elif re.match(r'^[A-Z][A-Z0-9_]*$', name):
patterns["UPPER_SNAKE_CASE"] += 1
# 返回最常用的模式
dominant = max(patterns, key=patterns.get)
return {
"dominant_pattern": dominant,
"distribution": patterns,
"consistency": patterns[dominant] / sum(patterns.values()) if sum(patterns.values()) > 0 else 0
}
使用 AST 解析 Python 代码:
def _collect_names(self, project_path: str) -> dict:
"""使用 AST 收集代码中的命名"""
names = {
"classes": [],
"functions": [],
"variables": [],
"constants": []
}
for py_file in self._find_python_files(project_path):
try:
with open(py_file, 'r') as f:
tree = ast.parse(f.read())
for node in ast.walk(tree):
if isinstance(node, ast.ClassDef):
names["classes"].append(node.name)
elif isinstance(node, ast.FunctionDef):
names["functions"].append(node.name)
elif isinstance(node, ast.Assign):
for target in node.targets:
if isinstance(target, ast.Name):
# 全大写视为常量
if target.id.isupper():
names["constants"].append(target.id)
else:
names["variables"].append(target.id)
except:
continue
return names
输出示例:
{
"files": {
"dominant_pattern": "snake_case",
"examples": ["api_server.py", "mcp_server.py", "run_api_server.py"],
"consistency": 1.0
},
"classes": {
"dominant_pattern": "PascalCase",
"distribution": {"PascalCase": 15, "snake_case": 0},
"examples": ["FastMCP", "Agent", "QueryRequest", "QueryResponse"],
"consistency": 1.0
},
"functions": {
"dominant_pattern": "snake_case",
"distribution": {"snake_case": 45, "camelCase": 2},
"examples": ["get_agent", "handle_mcp_request", "verify_api_key"],
"consistency": 0.96
},
"variables": {
"dominant_pattern": "snake_case",
"distribution": {"snake_case": 120, "camelCase": 5},
"consistency": 0.96
},
"constants": {
"dominant_pattern": "UPPER_SNAKE_CASE",
"examples": ["MODEL_NAME", "SYSTEM_PROMPT", "TOOL_MAP", "TOOL_LIST"],
"consistency": 1.0
}
}
2.1.4 代码模式提取详细设计
提取方法:
# patterns.py - 代码模式提取器
class PatternExtractor:
"""代码模式提取器"""
def extract(self, project_path: str) -> dict:
return {
"async_usage": self._analyze_async_usage(project_path),
"error_handling": self._analyze_error_handling(project_path),
"logging": self._analyze_logging(project_path),
"imports": self._analyze_import_style(project_path),
"docstrings": self._analyze_docstrings(project_path),
"type_hints": self._analyze_type_hints(project_path),
"common_patterns": self._detect_common_patterns(project_path)
}
检测的模式类型:
| 模式类型 | 检测方法 | 输出 |
|---|---|---|
| 异步使用 | 检测 async/await 关键字 | 是否强制异步、异步函数比例 |
| 错误处理 | 检测 try-except 模式 | 错误处理风格、是否返回 JSON 错误 |
| 日志方式 | 检测 print/logging 使用 | 日志库、日志格式 |
| 导入风格 | 分析 import 语句 | 绝对导入/相对导入比例 |
| 文档字符串 | 检测 docstring 存在 | docstring 覆盖率、格式风格 |
| 类型提示 | 检测类型注解 | 类型提示覆盖率 |
常见模式检测:
COMMON_PATTERNS = {
"mcp_tool_pattern": {
"description": "MCP 工具定义模式",
"signature": "@server.tool()",
"return_type": "JSON string"
},
"fastapi_endpoint_pattern": {
"description": "FastAPI 端点模式",
"signature": "@app.get/post/put/delete",
"features": ["async", "type hints", "docstring"]
},
"pydantic_model_pattern": {
"description": "Pydantic 模型模式",
"signature": "class XxxModel(BaseModel)",
"features": ["Field definitions", "validators"]
},
"singleton_agent_pattern": {
"description": "Agent 单例模式",
"signature": "def get_agent() -> Agent",
"purpose": "每次调用创建新 Agent 实例"
}
}
输出示例:
{
"async_usage": {
"async_required": true,
"async_function_ratio": 0.85,
"await_usage": "consistent"
},
"error_handling": {
"style": "try-except-json-response",
"pattern": "返回包含 success/error 字段的 JSON",
"example": "return json.dumps({\"success\": False, \"error\": str(e)})"
},
"logging": {
"method": "print",
"format": "emoji_prefix",
"examples": ["🚀 启动", "🛑 关闭"]
},
"imports": {
"style": "absolute",
"relative_import_ratio": 0.1,
"common_imports": ["json", "os", "typing", "fastapi", "pydantic"]
},
"docstrings": {
"coverage": 0.78,
"style": "google",
"required_sections": ["Args", "Returns"]
},
"type_hints": {
"coverage": 0.92,
"return_type_coverage": 0.95,
"parameter_type_coverage": 0.90
},
"common_patterns": [
{
"name": "mcp_tool_pattern",
"occurrences": 7,
"files": ["src/server/mcp_server.py"]
},
{
"name": "fastapi_endpoint_pattern",
"occurrences": 12,
"files": ["src/server/api_server.py"]
}
]
}
2.1.5 配置规范提取详细设计
提取方法:
# config.py - 配置规范提取器
class ConfigExtractor:
"""配置规范提取器"""
def extract(self, project_path: str) -> dict:
return {
"env_variables": self._extract_env_variables(project_path),
"config_files": self._analyze_config_files(project_path),
"secrets_handling": self._analyze_secrets_handling(project_path)
}
def _extract_env_variables(self, project_path: str) -> list:
"""从代码中提取使用的环境变量"""
env_vars = []
# 匹配 os.getenv() 和 os.environ.get()
patterns = [
r"os\.getenv\(['\"](\w+)['\"]",
r"os\.environ\.get\(['\"](\w+)['\"]",
r"os\.environ\[['\"](\w+)['\"]\]"
]
for py_file in self._find_python_files(project_path):
content = open(py_file).read()
for pattern in patterns:
matches = re.findall(pattern, content)
env_vars.extend(matches)
return list(set(env_vars))
输出示例:
{
"env_variables": [
{
"name": "OPENAI_API_KEY",
"required": true,
"default": null,
"description": "OpenAI API Key"
},
{
"name": "OPENAI_BASE_URL",
"required": false,
"default": "https://litellm...",
"description": "API Base URL"
},
{
"name": "MODEL_NAME",
"required": false,
"default": "taiji/gpt-4o-mini",
"description": "模型名称"
},
{
"name": "API_PORT",
"required": false,
"default": "8000",
"description": "服务端口"
}
],
"config_files": [
{
"file": "Dockerfile",
"type": "docker",
"purpose": "容器配置"
},
{
"file": "requirements.txt",
"type": "python_deps",
"purpose": "Python 依赖"
}
],
"secrets_handling": {
"hardcoded_secrets": false,
"env_based": true,
"pattern": "os.getenv with fallback"
}
}
2.2 规则定义(用户)
用户可定义以下类型的规则:
| 规则类型 | 示例 |
|---|---|
| 业务规则 | "所有 Agent 必须实现健康检查端点" |
| 技术规则 | "必须使用 async/await 进行异步操作" |
| 安全规则 | "禁止硬编码 API Key 或密码" |
| 架构规则 | "MCP 工具必须定义在 mcp_server.py 中" |
| 禁止事项 | "禁止使用 print 进行日志输出" |
| 必须遵循 | "所有函数必须有 docstring" |
2.3 输出格式
2.3.1 给 AI Agent 的结构化上下文(JSON)
{
"project_context": {
"name": "pingtai_agent",
"type": "agent_platform",
"tech_stack": {
"language": "Python 3.12",
"framework": ["FastAPI", "Pydantic AI", "FastMCP"],
"dependencies": ["pydantic-ai>=0.0.14", "fastapi>=0.109.0"]
},
"structure": {
"pattern": "agent_templates",
"directories": ["src/", "src/server/"],
"key_files": ["mcp_server.py", "api_server.py", "run_api_server.py"]
}
},
"naming_conventions": {
"files": "snake_case",
"classes": "PascalCase",
"functions": "snake_case",
"constants": "UPPER_SNAKE_CASE"
},
"code_patterns": {
"async_required": true,
"error_handling": "try-except with JSON response",
"logging": "print statements with emoji prefix"
},
"rules": {
"must": [
"所有 MCP 工具必须返回 JSON 格式",
"所有 API 端点必须有 docstring",
"必须实现 /health 健康检查端点"
],
"must_not": [
"禁止硬编码 API Key",
"禁止使用同步阻塞操作",
"禁止在工具函数中直接抛出异常"
],
"prefer": [
"优先使用 Pydantic 模型定义请求/响应",
"优先使用环境变量配置"
]
}
}
2.3.2 给人类阅读的 Markdown 文档
# 项目规范文档: pingtai_agent
## 技术栈
- **语言**: Python 3.12
- **框架**: FastAPI, Pydantic AI, FastMCP
- **依赖**: pydantic-ai>=0.0.14, fastapi>=0.109.0
## 目录结构规范
[agent_name]/
├── Dockerfile
├── README.md
├── requirements.txt
├── run_api_server.py
└── src/server/
├── api_server.py
└── mcp_server.py
## 命名规范
- 文件名: snake_case
- 类名: PascalCase
- 函数名: snake_case
## 必须遵循的规则
1. 所有 MCP 工具必须返回 JSON 格式
2. 所有 API 端点必须有 docstring
...
## 禁止事项
1. 禁止硬编码 API Key
2. 禁止使用同步阻塞操作
...
3. MCP 工具设计
3.1 工具清单
| 工具名称 | 功能 | 阶段 |
|---|---|---|
extract_project_knowledge |
从代码库提取项目知识 | 知识提取 |
add_rule |
添加用户定义规则 | 规则定义 |
remove_rule |
移除规则 | 规则定义 |
list_rules |
列出所有规则 | 规则定义 |
get_context |
获取完整项目上下文 | 使用 |
check_compliance |
检查代码是否符合规则 | 检查 |
generate_steering_doc |
生成人类可读的规范文档 | 输出 |
3.2 工具详细设计
3.2.1 extract_project_knowledge
async def extract_project_knowledge(
project_path: str, # 项目路径
include_patterns: Optional[List[str]] = None, # 包含的文件模式
exclude_patterns: Optional[List[str]] = None # 排除的文件模式
) -> str:
"""
从代码库自动提取项目知识。
提取内容:
- 技术栈信息(从 requirements.txt, Dockerfile 等)
- 目录结构
- 命名规范(分析现有代码)
- 代码模式(分析现有代码)
Returns:
提取的项目知识(JSON 格式)
"""
3.2.2 add_rule
async def add_rule(
rule_type: str, # 规则类型: must/must_not/prefer/security/architecture
rule_content: str, # 规则内容
category: Optional[str] = None, # 分类标签
priority: Optional[str] = "normal" # 优先级: high/normal/low
) -> str:
"""
添加用户定义的规则。
Returns:
添加结果(JSON 格式)
"""
3.2.3 get_context
async def get_context(
output_format: str = "json", # 输出格式: json/markdown
include_rules: bool = True, # 是否包含规则
include_patterns: bool = True # 是否包含代码模式
) -> str:
"""
获取完整的项目上下文,用于提供给其他 AI Agent。
Returns:
项目上下文(JSON 或 Markdown 格式)
"""
3.2.4 check_compliance
async def check_compliance(
code: str, # 待检查的代码
file_type: Optional[str] = None, # 文件类型
strict_mode: bool = False # 严格模式
) -> str:
"""
检查代码是否符合项目规则。
Returns:
检查结果(JSON 格式),包含:
- 是否通过
- 违反的规则列表
- 修改建议
"""
3.2.5 generate_steering_doc
async def generate_steering_doc(
output_format: str = "markdown", # 输出格式
include_examples: bool = True # 是否包含示例
) -> str:
"""
生成人类可读的项目规范文档。
Returns:
规范文档(Markdown 格式)
"""
4. 与其他 Agent 的协作
4.1 协作流程
sequenceDiagram
participant User as 用户
participant Steering as Steering Agent
participant Specs as Specs Agent
participant Code as Code Agent
participant Format as Format Police
User->>Steering: 1. 提取项目知识
Steering-->>Steering: 分析代码库
Steering-->>User: 返回项目上下文
User->>Steering: 2. 添加自定义规则
Steering-->>User: 规则已添加
User->>Steering: 3. 获取完整上下文
Steering-->>Specs: 提供项目上下文
User->>Specs: 4. 生成需求文档
Specs-->>User: 需求文档(遵循上下文约束)
User->>Code: 5. 生成代码
Code-->>Steering: 请求上下文
Steering-->>Code: 提供约束规则
Code-->>User: 生成的代码
User->>Steering: 6. 检查代码合规性
Steering-->>Format: 格式检查
Format-->>Steering: 格式检查结果
Steering-->>User: 合规性报告
4.2 与 specs_agent 配合
- Steering Agent 提供项目上下文给 specs_agent
- specs_agent 在生成需求/设计文档时遵循项目约束
- 确保生成的规范符合现有项目风格
4.3 与 format_police_agent 配合
- Steering Agent 调用 format_police 检查输出格式
- format_police 确保所有输出是有效 JSON
- Steering Agent 在合规检查中集成格式检查
5. 项目结构
steering_agent/
├── Dockerfile
├── README.md
├── USAGE.md
├── requirements.txt
├── run_api_server.py
└── src/
├── __init__.py
└── server/
├── __init__.py
├── api_server.py # FastAPI + MCP HTTP
├── mcp_server.py # MCP 工具定义
├── extractors/ # 知识提取器
│ ├── __init__.py
│ ├── tech_stack.py # 技术栈提取
│ ├── structure.py # 结构提取
│ ├── naming.py # 命名规范提取
│ └── patterns.py # 代码模式提取
└── rules/ # 规则管理
├── __init__.py
├── rule_store.py # 规则存储
└── checker.py # 合规检查器
6. API 端点设计
| 端点 | 方法 | 描述 |
|---|---|---|
/ |
GET | 服务状态 |
/health |
GET | 健康检查 |
/mcp |
POST | MCP JSON-RPC |
/mcp/sse |
GET/POST | MCP SSE 流式 |
/api/v1/extract |
POST | 提取项目知识 |
/api/v1/rules |
GET | 列出所有规则 |
/api/v1/rules |
POST | 添加规则 |
/api/v1/rules/{id} |
DELETE | 删除规则 |
/api/v1/context |
GET | 获取项目上下文 |
/api/v1/check |
POST | 检查代码合规性 |
/api/v1/doc |
GET | 生成规范文档 |
7. 使用示例
7.1 提取项目知识
输入:
curl -X POST http://localhost:8000/api/v1/extract \
-H "api-key: your-key" \
-d '{"project_path": "/path/to/project"}'
输出:
{
"success": true,
"knowledge": {
"tech_stack": {
"language": "Python 3.12",
"framework": ["FastAPI", "Pydantic AI"],
"dependencies": [...]
},
"structure": {
"pattern": "agent_templates",
"directories": ["src/", "src/server/"]
},
"naming": {
"files": "snake_case",
"classes": "PascalCase"
}
}
}
7.2 添加规则
输入:
curl -X POST http://localhost:8000/api/v1/rules \
-H "api-key: your-key" \
-d '{
"rule_type": "must",
"rule_content": "所有 MCP 工具必须返回 JSON 格式",
"category": "output"
}'
7.3 获取上下文(给 AI Agent)
输入:
curl http://localhost:8000/api/v1/context?format=json
输出: 完整的项目上下文 JSON,可直接作为其他 Agent 的 system prompt 补充。
7.4 检查代码合规性
输入:
curl -X POST http://localhost:8000/api/v1/check \
-H "api-key: your-key" \
-d '{
"code": "def my_tool():\n print(\"hello\")\n return \"result\"",
"file_type": "python"
}'
输出:
{
"compliant": false,
"violations": [
{
"rule": "所有 MCP 工具必须返回 JSON 格式",
"severity": "error",
"suggestion": "使用 json.dumps() 返回 JSON 字符串"
},
{
"rule": "禁止使用 print 进行日志输出",
"severity": "warning",
"suggestion": "使用 logging 模块或移除 print"
}
]
}
8. 实施计划
8.1 开发任务清单
- 创建项目目录结构
- 实现知识提取器
- 技术栈提取 (tech_stack.py)
- 结构提取 (structure.py)
- 命名规范提取 (naming.py)
- 代码模式提取 (patterns.py)
- 配置规范提取 (config.py)
- 实现规则管理
- 规则存储 (rule_store.py)
- 合规检查器 (checker.py)
- 实现 MCP 工具
- extract_project_knowledge
- add_rule / remove_rule / list_rules
- get_context
- check_compliance
- generate_steering_doc
- 实现 API 端点
- 编写文档
- 测试验证
9. 已确认事项
-
规则持久化:仅内存存储 ✅
-
项目路径:仅支持本地路径 ✅
-
增量更新:每次全量提取 ✅
-
规则模板:不提供预设模板 ✅
10. 风险与注意事项
-
代码分析准确性:自动提取的命名规范和代码模式可能不够准确,需要用户确认
-
性能考虑:大型代码库的分析可能耗时较长,需要考虑异步处理
-
规则冲突:用户定义的规则可能与提取的规范冲突,需要优先级机制
-
上下文长度:完整的项目上下文可能很长,需要考虑 token 限制
11. 已创建文件清单
steering_agent/
├── Dockerfile ✅
├── README.md ✅
├── USAGE.md ✅
├── requirements.txt ✅
├── run_api_server.py ✅
└── src/
├── __init__.py ✅
└── server/
├── __init__.py ✅
├── api_server.py ✅
├── mcp_server.py ✅
├── extractors/
│ ├── __init__.py ✅
│ ├── tech_stack.py ✅
│ ├── structure.py ✅
│ ├── naming.py ✅
│ ├── patterns.py ✅
│ └── config.py ✅
└── rules/
├── __init__.py ✅
├── rule_store.py ✅
└── checker.py ✅