From 9824bc2d6c35564152b4fe1e56e1a5fd790b93e5 Mon Sep 17 00:00:00 2001 From: "DESKTOP-72TV0V4\\caoxiaozhu" Date: Sat, 21 Mar 2026 11:29:57 +0800 Subject: [PATCH] feat: add SkillRegistry for agent integration Co-Authored-By: Claude Opus 4.6 --- backend/app/agents/graph.py | 29 +++++++++++++++--- backend/app/agents/skill_registry.py | 46 ++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 backend/app/agents/skill_registry.py diff --git a/backend/app/agents/graph.py b/backend/app/agents/graph.py index 8ff9f0e..5bc6e24 100644 --- a/backend/app/agents/graph.py +++ b/backend/app/agents/graph.py @@ -13,6 +13,7 @@ from app.agents.prompts import ( ANALYST_SYSTEM_PROMPT, ) from app.agents.tools import ALL_TOOLS +from app.agents.skill_registry import build_skill_context from app.services.llm_service import get_llm @@ -69,8 +70,13 @@ async def planner_node(state: AgentState) -> AgentState: user_msgs = _filter_user_messages(state["messages"]) user_query = user_msgs[-1].content if user_msgs else "" + system_msgs = [SystemMessage(content=PLANNER_SYSTEM_PROMPT)] + skill_ctx = build_skill_context("planner") + if skill_ctx: + system_msgs.append(SystemMessage(content=skill_ctx)) + response = await llm.invoke( - [SystemMessage(content=PLANNER_SYSTEM_PROMPT), HumanMessage(content=f"用户请求: {user_query}")] + system_msgs + [HumanMessage(content=f"用户请求: {user_query}")] ) plan_text = response.content @@ -92,8 +98,13 @@ async def executor_node(state: AgentState) -> AgentState: user_msgs = _filter_user_messages(state["messages"]) user_query = user_msgs[-1].content if user_msgs else "" + system_msgs = [SystemMessage(content=EXECUTOR_SYSTEM_PROMPT)] + skill_ctx = build_skill_context("executor") + if skill_ctx: + system_msgs.append(SystemMessage(content=skill_ctx)) + response = await llm.bind_tools(ALL_TOOLS).invoke( - [SystemMessage(content=EXECUTOR_SYSTEM_PROMPT), HumanMessage(content=f"用户请求: {user_query}")] + system_msgs + [HumanMessage(content=f"用户请求: {user_query}")] ) tool_calls = getattr(response, "tool_calls", None) or [] @@ -131,8 +142,13 @@ async def librarian_node(state: AgentState) -> AgentState: user_msgs = _filter_user_messages(state["messages"]) user_query = user_msgs[-1].content if user_msgs else "" + system_msgs = [SystemMessage(content=LIBRARIAN_SYSTEM_PROMPT)] + skill_ctx = build_skill_context("librarian") + if skill_ctx: + system_msgs.append(SystemMessage(content=skill_ctx)) + response = await llm.bind_tools(ALL_TOOLS).invoke( - [SystemMessage(content=LIBRARIAN_SYSTEM_PROMPT), HumanMessage(content=f"用户请求: {user_query}")] + system_msgs + [HumanMessage(content=f"用户请求: {user_query}")] ) tool_calls = getattr(response, "tool_calls", None) or [] @@ -171,8 +187,13 @@ async def analyst_node(state: AgentState) -> AgentState: user_msgs = _filter_user_messages(state["messages"]) user_query = user_msgs[-1].content if user_msgs else "" + system_msgs = [SystemMessage(content=ANALYST_SYSTEM_PROMPT)] + skill_ctx = build_skill_context("analyst") + if skill_ctx: + system_msgs.append(SystemMessage(content=skill_ctx)) + response = await llm.bind_tools(ALL_TOOLS).invoke( - [SystemMessage(content=ANALYST_SYSTEM_PROMPT), HumanMessage(content=f"用户请求: {user_query}")] + system_msgs + [HumanMessage(content=f"用户请求: {user_query}")] ) tool_calls = getattr(response, "tool_calls", None) or [] diff --git a/backend/app/agents/skill_registry.py b/backend/app/agents/skill_registry.py new file mode 100644 index 0000000..c693a37 --- /dev/null +++ b/backend/app/agents/skill_registry.py @@ -0,0 +1,46 @@ +""" +Skill Registry - Agent 运行时加载 Skills +""" +from typing import Optional +from app.database import async_session +from app.services.skill_service import SkillService + +# 缓存:agent_type -> list[Skill] +_skill_cache: dict[str, list] = {} + +async def load_skills_for_agent(agent_type: str, force_reload: bool = False) -> list: + """加载指定 Agent 类型的可用 Skills""" + if not force_reload and agent_type in _skill_cache: + return _skill_cache[agent_type] + async with async_session() as db: + svc = SkillService(db) + skills = await svc.get_by_agent_type(agent_type) + _skill_cache[agent_type] = skills + return skills + +def get_skills_for_agent(agent_type: str) -> list: + """同步接口:返回缓存的 Skills(供 Agent 节点调用)""" + return _skill_cache.get(agent_type, []) + +def build_skill_context(agent_type: str) -> str: + """ + 构建 Skill 上下文,供注入到 Agent 系统提示 + 格式:Skill 名称 + 描述 + 工具列表 + """ + skills = get_skills_for_agent(agent_type) + if not skills: + return "" + lines = ["\n\n【可用的 Skills】"] + for s in skills: + tools_str = ", ".join(s.tools) if s.tools else "无" + lines.append(f""" +## {s.name} +- 描述: {s.description or '无'} +- 工具: {tools_str} +- 指令: {s.instructions[:200]}...""" if len(s.instructions) > 200 else f"- 指令: {s.instructions}") + return "\n".join(lines) + +def clear_cache(): + """清除缓存(配置变更时调用)""" + global _skill_cache + _skill_cache = {} \ No newline at end of file