Просмотр исходного кода

refactor: memory/skill and knowledge config import

Talegorithm 4 часов назад
Родитель
Сommit
fd8359ed5d

+ 7 - 0
.env.template

@@ -0,0 +1,7 @@
+KNOWHUB_API=http://43.106.118.91:9999/
+BROWSER_USE_API_KEY=
+
+OPEN_ROUTER_API_KEY=
+ALI_API_KEY=
+ALI_BASE_URL=
+

+ 2 - 2
README.md

@@ -123,7 +123,7 @@ runner = AgentRunner(
 )
 ```
 
-内置 skills(`agent/memory/skills/`)始终自动加载,`skills_dir` 的内容额外追加。
+内置 skills(`agent/skill/skills/`)始终自动加载,`skills_dir` 的内容额外追加。
 
 ## 知识管理系统(Knowledge Management)
 
@@ -298,7 +298,7 @@ agent/
 ├── core/           # AgentRunner + 预设
 ├── tools/          # 工具系统(registry + 内置工具)
 ├── trace/          # 执行追踪 + 计划(GoalTree)+ API
-├── memory/         # Skills + Experiences
+├── skill/          # Skills(技能系统)
 └── llm/            # LLM Provider 适配
 ```
 

+ 3 - 4
agent/README.md

@@ -16,7 +16,7 @@ Agent Core 是一个完整的 Agent 执行框架,提供:
 - Trace、Message、Goal 管理
 - 工具系统(文件、命令、网络、浏览器)
 - LLM 集成(Gemini、OpenRouter、Yescode)
-- Skills 和 Memory(跨会话知识
+- Skills(领域知识注入
 - 子 Agent 机制
 
 **独立性**:Agent Core 不依赖任何其他模块,可以独立运行。
@@ -52,9 +52,8 @@ agent/
 │       ├── subagent.py    # 子 Agent 创建
 │       └── a2a_im.py      # A2A IM 工具(桥接到 Gateway)
-├── memory/                # 跨会话记忆
-│   ├── models.py          # Experience, Skill
-│   ├── stores.py          # 存储实现
+├── skill/                 # 技能系统
+│   ├── models.py          # Skill
 │   ├── skill_loader.py    # Skill 加载器
 │   └── skills/            # 内置 Skills

+ 5 - 13
agent/__init__.py

@@ -5,9 +5,9 @@ Reson Agent - 模块化、可扩展的 Agent 框架
 - AgentRunner: Agent 执行引擎
 - RunConfig: 运行配置
 - Trace, Message, Goal: 执行追踪
-- Experience, Skill: 记忆模型
+- Skill: 技能模型
 - tool: 工具装饰器
-- TraceStore, MemoryStore: 存储接口
+- TraceStore: 存储接口
 """
 
 # 核心引擎
@@ -20,10 +20,8 @@ from agent.trace.goal_models import Goal, GoalTree, GoalStatus
 from agent.trace.protocols import TraceStore
 from agent.trace.store import FileSystemTraceStore
 
-# 记忆系统
-from agent.memory.models import Experience, Skill
-from agent.memory.protocols import MemoryStore, StateStore
-from agent.memory.stores import MemoryMemoryStore, MemoryStateStore
+# 技能系统
+from agent.skill.models import Skill
 
 # 工具系统
 from agent.tools import tool, ToolRegistry, get_tool_registry
@@ -34,7 +32,6 @@ __version__ = "0.3.0"
 __all__ = [
     # Core
     "AgentRunner",
-    "AgentConfig",
     "CallResult",
     "RunConfig",
     "AgentPreset",
@@ -54,13 +51,8 @@ __all__ = [
     "GoalStatus",
     "TraceStore",
     "FileSystemTraceStore",
-    # Memory
-    "Experience",
+    # Skill
     "Skill",
-    "MemoryStore",
-    "StateStore",
-    "MemoryMemoryStore",
-    "MemoryStateStore",
     # Tools
     "tool",
     "ToolRegistry",

+ 1 - 1
agent/cli/interactive.py

@@ -229,7 +229,7 @@ class InteractiveController:
             prompt += f"\n\n请特别关注:{focus}"
 
         print("正在生成反思...")
-        reflect_cfg = RunConfig(trace_id=trace_id, max_iterations=1, tools=[])
+        reflect_cfg = RunConfig(trace_id=trace_id, max_iterations=10, tools=[])
 
         try:
             result = await self.runner.run_result(

+ 4 - 74
agent/core/runner.py

@@ -32,11 +32,11 @@ from agent.trace.compaction import (
     estimate_tokens,
     needs_level2_compression,
     build_compression_prompt,
-    build_reflect_prompt,
 )
-from agent.memory.models import Skill
-from agent.memory.skill_loader import load_skills_from_dir
+from agent.skill.models import Skill
+from agent.skill.skill_loader import load_skills_from_dir
 from agent.tools import ToolRegistry, get_tool_registry
+from agent.tools.builtin.knowledge import KnowledgeConfig
 from agent.core.prompts import (
     DEFAULT_SYSTEM_PREFIX,
     TRUNCATION_HINT,
@@ -46,7 +46,6 @@ from agent.core.prompts import (
     TASK_NAME_GENERATION_SYSTEM_PROMPT,
     TASK_NAME_FALLBACK,
     SUMMARY_HEADER_TEMPLATE,
-    COMPLETION_REFLECT_PROMPT,
     build_summary_header,
     build_tool_interrupted_message,
     build_agent_continue_hint,
@@ -55,60 +54,6 @@ from agent.core.prompts import (
 logger = logging.getLogger(__name__)
 
 
-# ===== 知识管理配置 =====
-
-@dataclass
-class KnowledgeConfig:
-    """知识提取与注入的配置"""
-
-    # 压缩时提取(消息量超阈值触发压缩时,在 Level 1 过滤前用完整 history 反思)
-    enable_extraction: bool = True         # 是否在压缩触发时提取知识
-    reflect_prompt: str = ""               # 自定义反思 prompt;空则使用默认,见 agent/core/prompts/knowledge.py:REFLECT_PROMPT
-
-    # agent运行完成后提取(不代表任务完成,agent 可能中途退出等待人工评估)
-    enable_completion_extraction: bool = True      # 是否在运行完成后提取知识
-    completion_reflect_prompt: str = ""            # 自定义复盘 prompt;空则使用默认,见 agent/core/prompts/knowledge.py:COMPLETION_REFLECT_PROMPT
-
-    # 知识注入(agent切换当前工作的goal时,自动注入相关知识)
-    enable_injection: bool = True          # 是否在 focus goal 时自动注入相关知识
-
-    # 默认字段(保存/搜索时自动注入)
-    owner: str = ""                            # 所有者(空则尝试从 git config user.email 获取,再空则用 agent:{agent_id})
-    default_tags: Optional[Dict[str, str]] = None      # 默认 tags(会与工具调用参数合并)
-    default_scopes: Optional[List[str]] = None         # 默认 scopes(空则用 ["org:cybertogether"])
-    default_search_types: Optional[List[str]] = None   # 默认搜索类型过滤
-    default_search_owner: str = ""                     # 默认搜索 owner 过滤(空则不过滤)
-
-    def get_reflect_prompt(self) -> str:
-        """压缩时反思 prompt"""
-        return self.reflect_prompt if self.reflect_prompt else build_reflect_prompt()
-
-    def get_completion_reflect_prompt(self) -> str:
-        """任务完成后复盘 prompt"""
-        return self.completion_reflect_prompt if self.completion_reflect_prompt else COMPLETION_REFLECT_PROMPT
-
-    def get_owner(self, agent_id: str = "agent") -> str:
-        """获取 owner(优先级:配置 > git email > agent:{agent_id})"""
-        if self.owner:
-            return self.owner
-
-        # 尝试从 git config 获取
-        try:
-            import subprocess
-            result = subprocess.run(
-                ["git", "config", "user.email"],
-                capture_output=True,
-                text=True,
-                timeout=2,
-            )
-            if result.returncode == 0 and result.stdout.strip():
-                return result.stdout.strip()
-        except Exception:
-            pass
-
-        return f"agent:{agent_id}"
-
-
 @dataclass
 class ContextUsage:
     """Context 使用情况"""
@@ -988,16 +933,6 @@ class AgentRunner:
                     args_display = args_str[:100] + "..." if len(args_str) > 100 else args_str
                     logger.info(f"[Tool Call] {tool_name}({args_display})")
 
-                    # 构建知识管理注入值
-                    inject_values = None
-                    if config.knowledge:
-                        inject_values = {
-                            "owner": config.knowledge.get_owner(config.uid or "agent"),
-                            "tags": config.knowledge.default_tags,
-                            "scopes": config.knowledge.default_scopes,
-                            "types": config.knowledge.default_search_types,
-                        }
-
                     tool_result = await self.tools.execute(
                         tool_name,
                         tool_args,
@@ -1010,7 +945,6 @@ class AgentRunner:
                             "goal_tree": goal_tree,
                             "knowledge_config": config.knowledge,
                         },
-                        inject_values=inject_values,
                     )
 
                     # 如果是 goal 工具,记录执行后的状态
@@ -1309,12 +1243,8 @@ class AgentRunner:
                         context={
                             "store": self.trace_store,
                             "trace_id": trace_id,
+                            "knowledge_config": config.knowledge,
                         },
-                        inject_values={
-                            "owner": config.knowledge.get_owner(config.uid or "agent"),
-                            "tags": config.knowledge.default_tags,
-                            "scopes": config.knowledge.default_scopes,
-                        } if config.knowledge else None,
                     )
                     saved_count += 1
                 except Exception as e:

+ 5 - 7
agent/docs/architecture.md

@@ -57,10 +57,8 @@ agent/
 │       ├── skill.py       # 技能加载
 │       └── subagent.py    # agent / evaluate 工具(子 Agent 创建与评估)
-├── memory/                # 跨会话记忆
-│   ├── models.py          # Experience, Skill
-│   ├── protocols.py       # MemoryStore 接口
-│   ├── stores.py          # 存储实现
+├── skill/                 # 技能系统
+│   ├── models.py          # Skill
 │   ├── skill_loader.py    # Skill 加载器
 │   └── skills/            # 内置 Skills(自动注入 system prompt)
 │       ├── planning.md    # 计划与 Goal 工具使用
@@ -81,7 +79,7 @@ agent/
 | **core/** | Agent 执行引擎 + 预设配置 |
 | **trace/** | 执行追踪 + 计划管理 |
 | **tools/** | 与外部世界交互(文件、命令、网络、浏览器) |
-| **memory/** | 跨会话知识(Skills、Experiences) |
+| **skill/** | 技能系统(Skills) |
 | **llm/** | LLM Provider 适配 |
 
 ### 三层记忆模型
@@ -1120,7 +1118,7 @@ ToolResult(
 ### 目录结构
 
 ```
-agent/memory/skills/         # 内置 Skills(始终加载)
+agent/skill/skills/         # 内置 Skills(始终加载)
 ├── planning.md              # 计划与 Goal 工具使用
 ├── research.md              # 搜索与内容研究
 └── browser.md               # 浏览器自动化
@@ -1141,7 +1139,7 @@ agent/memory/skills/         # 内置 Skills(始终加载)
 agent(task="...", agent_type="deconstruct", skills=["planning", "deconstruct"])
 ```
 
-**实现**:`agent/memory/skill_loader.py`
+**实现**:`agent/skill/skill_loader.py`
 
 **详细文档**:[Skills 使用指南](../agent/docs/skills.md)
 

+ 11 - 13
agent/docs/knowledge.md

@@ -75,10 +75,9 @@
         - Goal focus 时:检索与当前目标相关的知识
         - 主动调用:通过 get_knowledge 工具主动查询
 
-    实现位置(规划)
-        - agent/memory/knowledge_store.py: 知识存储接口
-        - agent/memory/knowledge_retriever.py: 检索逻辑
-        - agent/tools/builtin/knowledge.py: get_knowledge 工具
+    实现位置
+        - agent/tools/builtin/knowledge.py: 知识管理工具(KnowHub API 封装)+ KnowledgeConfig
+        - agent/tools/builtin/knowledge.py: knowledge_search / knowledge_save 工具
 知识提取机制
     触发时机
         - 主动表达:用户明确表达偏好、纠正、提供背景信息
@@ -103,8 +102,7 @@
 
     实现位置(规划)
         - agent/trace/compaction.py: 压缩时提取经验
-        - agent/tools/builtin/knowledge.py: save_knowledge 工具
-        - agent/memory/knowledge_extractor.py: 知识提取逻辑
+        - agent/tools/builtin/knowledge.py: knowledge_save 工具
 用户画像特殊处理
     用户画像是一种特殊的知识类型(type=user_profile),具有以下特点:
 
@@ -193,11 +191,11 @@
             └── ...
 
 TODO
-    1. 实现知识存储接口(agent/memory/knowledge_store.py)
-    2. 实现知识检索逻辑(agent/memory/knowledge_retriever.py)
-    3. 实现 get_knowledge 工具(agent/tools/builtin/knowledge.py)
-    4. 实现 save_knowledge 工具(agent/tools/builtin/knowledge.py)
-    5. 在 Agent 启动时集成知识检索
-    6. 在 Goal focus 时集成知识检索
-    7. 在压缩消息时集成知识提取
+    1. ~~实现知识存储接口~~ → 已通过 KnowHub API 实现(agent/tools/builtin/knowledge.py)
+    2. ~~实现知识检索逻辑~~ → knowledge_search 工具
+    3. ~~实现 knowledge_save 工具~~ → 已实现
+    4. ~~实现 knowledge_search 工具~~ → 已实现
+    5. ~~在 Agent 启动时集成知识检索~~ → 已实现(goal focus 时注入)
+    6. ~~在 Goal focus 时集成知识检索~~ → 已实现(agent/trace/goal_tool.py:inject_knowledge_for_goal)
+    7. ~~在压缩消息时集成知识提取~~ → 已实现(agent/core/runner.py:_run_reflect)
     8. 实现用户画像的特殊处理逻辑

+ 1 - 3
agent/docs/scope-design.md

@@ -296,9 +296,7 @@ def rank_by_scope_priority(results, context):
 
 ## 实现位置
 
-- `agent/memory/knowledge_store.py`:知识存储接口
-- `agent/memory/knowledge_retriever.py`:检索逻辑
-- `agent/tools/builtin/knowledge.py`:get_knowledge / save_knowledge 工具
+- `agent/tools/builtin/knowledge.py`:知识管理工具(KnowHub API 封装)+ KnowledgeConfig
 
 ## 扩展性
 

+ 2 - 2
agent/docs/skills.md

@@ -192,7 +192,7 @@ skill(skill_name="browser-use")
 ```
 
 **实现位置**:
-- `agent/memory/skill_loader.py:load_skills_from_dir()` - 自动加载机制
+- `agent/skill/skill_loader.py:load_skills_from_dir()` - 自动加载机制
 - `agent/tools/builtin/skill.py` - skill 工具(动态加载)
 
 详见 [`SKILLS_SYSTEM.md`](../SKILLS_SYSTEM.md)
@@ -231,4 +231,4 @@ SKILLS_DIR=./skills
 - 示例:`examples/feature_extract/run.py`
 - Skill 文件:`agent/skills/` 目录
 - 工具实现:`agent/tools/builtin/skill.py`
-- 加载器实现:`agent/memory/skill_loader.py`
+- 加载器实现:`agent/skill/skill_loader.py`

+ 0 - 37
agent/memory/__init__.py

@@ -1,37 +0,0 @@
-"""
-Memory - 记忆系统
-
-核心职责:
-1. Experience 和 Skill 数据模型
-2. MemoryStore 和 StateStore 接口定义
-3. 内存存储实现(MemoryMemoryStore, MemoryStateStore)
-4. Skill 加载器(从 markdown 加载技能)
-"""
-
-# 数据模型
-from agent.memory.models import Experience, Skill
-
-# 存储接口
-from agent.memory.protocols import MemoryStore, StateStore
-
-# 内存存储实现
-from agent.memory.stores import MemoryMemoryStore, MemoryStateStore
-
-# Skill 加载器
-from agent.memory.skill_loader import SkillLoader, load_skills_from_dir
-
-
-__all__ = [
-    # 模型
-    "Experience",
-    "Skill",
-    # 存储接口
-    "MemoryStore",
-    "StateStore",
-    # 存储实现
-    "MemoryMemoryStore",
-    "MemoryStateStore",
-    # Skill 加载
-    "SkillLoader",
-    "load_skills_from_dir",
-]

+ 0 - 106
agent/memory/protocols.py

@@ -1,106 +0,0 @@
-"""
-Storage Protocols - 存储接口定义
-
-使用 Protocol 定义接口,允许不同的存储实现(内存、PostgreSQL、Neo4j 等)
-
-TraceStore 已移动到 agent.execution.protocols
-"""
-
-from typing import Protocol, List, Optional, Dict, Any, runtime_checkable
-
-from agent.memory.models import Experience, Skill
-
-
-@runtime_checkable
-class MemoryStore(Protocol):
-    """Experience + Skill 存储接口"""
-
-    # ===== Experience 操作 =====
-
-    async def add_experience(self, exp: Experience) -> str:
-        """添加 Experience"""
-        ...
-
-    async def get_experience(self, exp_id: str) -> Optional[Experience]:
-        """获取 Experience"""
-        ...
-
-    async def search_experiences(
-        self,
-        scope: str,
-        context: str,
-        limit: int = 10
-    ) -> List[Experience]:
-        """
-        搜索相关 Experience
-
-        Args:
-            scope: 范围(如 "agent:researcher")
-            context: 当前上下文,用于语义匹配
-            limit: 最大返回数量
-        """
-        ...
-
-    async def update_experience_stats(
-        self,
-        exp_id: str,
-        success: bool
-    ) -> None:
-        """更新 Experience 使用统计"""
-        ...
-
-    # ===== Skill 操作 =====
-
-    async def add_skill(self, skill: Skill) -> str:
-        """添加 Skill"""
-        ...
-
-    async def get_skill(self, skill_id: str) -> Optional[Skill]:
-        """获取 Skill"""
-        ...
-
-    async def get_skill_tree(self, scope: str) -> List[Skill]:
-        """获取技能树"""
-        ...
-
-    async def search_skills(
-        self,
-        scope: str,
-        context: str,
-        limit: int = 5
-    ) -> List[Skill]:
-        """搜索相关 Skills"""
-        ...
-
-
-@runtime_checkable
-class StateStore(Protocol):
-    """短期状态存储接口(用于 Task State,通常用 Redis)"""
-
-    async def get(self, key: str) -> Optional[Dict[str, Any]]:
-        """获取状态"""
-        ...
-
-    async def set(
-        self,
-        key: str,
-        value: Dict[str, Any],
-        ttl: Optional[int] = None
-    ) -> None:
-        """
-        设置状态
-
-        Args:
-            key: 键
-            value: 值
-            ttl: 过期时间(秒)
-        """
-        ...
-
-    async def update(self, key: str, **updates) -> None:
-        """部分更新"""
-        ...
-
-    async def delete(self, key: str) -> None:
-        """删除"""
-        ...

+ 0 - 103
agent/memory/stores.py

@@ -1,103 +0,0 @@
-"""
-Memory Implementation - 内存存储实现
-
-用于测试和简单场景,数据不持久化
-"""
-
-from typing import Dict, List, Optional, Any
-from datetime import datetime
-
-from agent.memory.models import Experience, Skill
-
-
-class MemoryMemoryStore:
-    """内存 Memory 存储(Experience + Skill)"""
-
-    def __init__(self):
-        self._experiences: Dict[str, Experience] = {}
-        self._skills: Dict[str, Skill] = {}
-
-    # ===== Experience =====
-
-    async def add_experience(self, exp: Experience) -> str:
-        self._experiences[exp.exp_id] = exp
-        return exp.exp_id
-
-    async def get_experience(self, exp_id: str) -> Optional[Experience]:
-        return self._experiences.get(exp_id)
-
-    async def search_experiences(
-        self,
-        scope: str,
-        context: str,
-        limit: int = 10
-    ) -> List[Experience]:
-        # 简单实现:按 scope 过滤,按 confidence 排序
-        experiences = [
-            e for e in self._experiences.values()
-            if e.scope == scope
-        ]
-        experiences.sort(key=lambda e: e.confidence, reverse=True)
-        return experiences[:limit]
-
-    async def update_experience_stats(
-        self,
-        exp_id: str,
-        success: bool
-    ) -> None:
-        exp = self._experiences.get(exp_id)
-        if exp:
-            exp.usage_count += 1
-            if success:
-                # 更新成功率
-                total_success = exp.success_rate * (exp.usage_count - 1) + (1 if success else 0)
-                exp.success_rate = total_success / exp.usage_count
-            exp.updated_at = datetime.now()
-
-    # ===== Skill =====
-
-    async def add_skill(self, skill: Skill) -> str:
-        self._skills[skill.skill_id] = skill
-        return skill.skill_id
-
-    async def get_skill(self, skill_id: str) -> Optional[Skill]:
-        return self._skills.get(skill_id)
-
-    async def get_skill_tree(self, scope: str) -> List[Skill]:
-        return [s for s in self._skills.values() if s.scope == scope]
-
-    async def search_skills(
-        self,
-        scope: str,
-        context: str,
-        limit: int = 5
-    ) -> List[Skill]:
-        # 简单实现:按 scope 过滤
-        skills = [s for s in self._skills.values() if s.scope == scope]
-        return skills[:limit]
-
-
-class MemoryStateStore:
-    """内存状态存储"""
-
-    def __init__(self):
-        self._state: Dict[str, Dict[str, Any]] = {}
-
-    async def get(self, key: str) -> Optional[Dict[str, Any]]:
-        return self._state.get(key)
-
-    async def set(
-        self,
-        key: str,
-        value: Dict[str, Any],
-        ttl: Optional[int] = None
-    ) -> None:
-        # 内存实现忽略 ttl
-        self._state[key] = value
-
-    async def update(self, key: str, **updates) -> None:
-        if key in self._state:
-            self._state[key].update(updates)
-
-    async def delete(self, key: str) -> None:
-        self._state.pop(key, None)

+ 16 - 0
agent/skill/__init__.py

@@ -0,0 +1,16 @@
+"""
+Skill - 技能系统
+
+核心职责:
+1. Skill 数据模型
+2. Skill 加载器(从 Markdown 加载技能)
+"""
+
+from agent.skill.models import Skill
+from agent.skill.skill_loader import SkillLoader, load_skills_from_dir
+
+__all__ = [
+    "Skill",
+    "SkillLoader",
+    "load_skills_from_dir",
+]

+ 4 - 82
agent/memory/models.py → agent/skill/models.py

@@ -1,93 +1,17 @@
 """
-Memory 数据模型
-
-Experience: 经验规则(条件 + 规则 + 证据)
-Skill: 技能(从经验归纳的高层知识)
+Skill 数据模型
 """
 
 from dataclasses import dataclass, field
 from datetime import datetime
-from typing import Dict, Any, List, Optional, Literal
+from typing import Dict, Any, List, Optional
 import uuid
 
 
-@dataclass
-class Experience:
-    """
-    经验规则
-
-    从执行过程或人工反馈中提取的规则,格式:
-    - condition: 什么情况下适用
-    - rule: 应该怎么做
-    - evidence: 证据(step_ids)
-    """
-    exp_id: str
-    scope: str  # "agent:{type}" 或 "user:{uid}"
-
-    # 核心三元组
-    condition: str
-    rule: str
-    evidence: List[str] = field(default_factory=list)  # step_ids
-
-    # 元数据
-    source: Literal["execution", "feedback", "manual"] = "feedback"
-    confidence: float = 0.5
-    usage_count: int = 0
-    success_rate: float = 0.0
-
-    # 时间
-    created_at: datetime = field(default_factory=datetime.now)
-    updated_at: datetime = field(default_factory=datetime.now)
-
-    @classmethod
-    def create(
-        cls,
-        scope: str,
-        condition: str,
-        rule: str,
-        evidence: List[str] = None,
-        source: Literal["execution", "feedback", "manual"] = "feedback",
-        confidence: float = 0.5,
-    ) -> "Experience":
-        """创建新的 Experience"""
-        now = datetime.now()
-        return cls(
-            exp_id=str(uuid.uuid4()),
-            scope=scope,
-            condition=condition,
-            rule=rule,
-            evidence=evidence or [],
-            source=source,
-            confidence=confidence,
-            created_at=now,
-            updated_at=now,
-        )
-
-    def to_dict(self) -> Dict[str, Any]:
-        """转换为字典"""
-        return {
-            "exp_id": self.exp_id,
-            "scope": self.scope,
-            "condition": self.condition,
-            "rule": self.rule,
-            "evidence": self.evidence,
-            "source": self.source,
-            "confidence": self.confidence,
-            "usage_count": self.usage_count,
-            "success_rate": self.success_rate,
-            "created_at": self.created_at.isoformat() if self.created_at else None,
-            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
-        }
-
-    def to_prompt_text(self) -> str:
-        """转换为可注入 Prompt 的文本"""
-        return f"当 {self.condition} 时,{self.rule}"
-
-
 @dataclass
 class Skill:
     """
-    技能 - 从经验归纳的高层知识
+    技能 - 从 Markdown 文件加载的领域知识
 
     技能可以形成层次结构(通过 parent_id)
     """
@@ -104,7 +28,7 @@ class Skill:
     # 内容
     content: Optional[str] = None  # 完整的 skill 内容(Markdown)
     guidelines: List[str] = field(default_factory=list)
-    derived_from: List[str] = field(default_factory=list)  # experience_ids
+    derived_from: List[str] = field(default_factory=list)
 
     # 版本
     version: int = 1
@@ -164,11 +88,9 @@ class Skill:
 
         优先使用完整的 content(如果有),否则使用 description + guidelines
         """
-        # 如果有完整的 content,直接使用
         if self.content:
             return self.content.strip()
 
-        # 否则使用旧的格式(向后兼容)
         lines = [f"### {self.name}", self.description]
         if self.guidelines:
             lines.append("指导原则:")

+ 2 - 2
agent/memory/skill_loader.py → agent/skill/skill_loader.py

@@ -39,7 +39,7 @@ from pathlib import Path
 from typing import List, Dict, Optional
 import logging
 
-from agent.memory.models import Skill
+from agent.skill.models import Skill
 
 logger = logging.getLogger(__name__)
 
@@ -383,7 +383,7 @@ def load_skills_from_dir(skills_dir: Optional[str] = None) -> List[Skill]:
     """
     all_skills = []
 
-    # 1. 加载内置 skills(agent/memory/skills/)
+    # 1. 加载内置 skills(agent/skill/skills/)
     builtin_skills_dir = Path(__file__).parent / "skills"
     if builtin_skills_dir.exists():
         loader = SkillLoader(str(builtin_skills_dir))

+ 0 - 0
agent/memory/skills/browser.md → agent/skill/skills/browser.md


+ 0 - 0
agent/memory/skills/core.md → agent/skill/skills/core.md


+ 0 - 0
agent/memory/skills/planning.md → agent/skill/skills/planning.md


+ 0 - 0
agent/memory/skills/research.md → agent/skill/skills/research.md


+ 72 - 5
agent/tools/builtin/knowledge.py

@@ -6,9 +6,12 @@
 
 import os
 import logging
+import subprocess
 import httpx
+from dataclasses import dataclass
 from typing import List, Dict, Optional, Any
 from agent.tools import tool, ToolResult, ToolContext
+from agent.core.prompts import build_reflect_prompt, COMPLETION_REFLECT_PROMPT
 
 logger = logging.getLogger(__name__)
 
@@ -16,11 +19,75 @@ logger = logging.getLogger(__name__)
 KNOWHUB_API = os.getenv("KNOWHUB_API", "http://localhost:8000")
 
 
+# ===== 知识管理配置 =====
+
+@dataclass
+class KnowledgeConfig:
+    """知识提取与注入的配置"""
+
+    # 压缩时提取(消息量超阈值触发压缩时,在 Level 1 过滤前用完整 history 反思)
+    enable_extraction: bool = True         # 是否在压缩触发时提取知识
+    reflect_prompt: str = ""               # 自定义反思 prompt;空则使用默认,见 agent/core/prompts/knowledge.py:REFLECT_PROMPT
+
+    # agent运行完成后提取(不代表任务完成,agent 可能中途退出等待人工评估)
+    enable_completion_extraction: bool = True      # 是否在运行完成后提取知识
+    completion_reflect_prompt: str = ""            # 自定义复盘 prompt;空则使用默认,见 agent/core/prompts/knowledge.py:COMPLETION_REFLECT_PROMPT
+
+    # 知识注入(agent切换当前工作的goal时,自动注入相关知识)
+    enable_injection: bool = True          # 是否在 focus goal 时自动注入相关知识
+
+    # 默认字段(保存/搜索时自动注入)
+    owner: str = ""                            # 所有者(空则尝试从 git config user.email 获取,再空则用 agent:{agent_id})
+    default_tags: Optional[Dict[str, str]] = None      # 默认 tags(会与工具调用参数合并)
+    default_scopes: Optional[List[str]] = None         # 默认 scopes(空则用 ["org:cybertogether"])
+    default_search_types: Optional[List[str]] = None   # 默认搜索类型过滤
+    default_search_owner: str = ""                     # 默认搜索 owner 过滤(空则不过滤)
+
+    def get_reflect_prompt(self) -> str:
+        """压缩时反思 prompt"""
+        return self.reflect_prompt if self.reflect_prompt else build_reflect_prompt()
+
+    def get_completion_reflect_prompt(self) -> str:
+        """任务完成后复盘 prompt"""
+        return self.completion_reflect_prompt if self.completion_reflect_prompt else COMPLETION_REFLECT_PROMPT
+
+    @property
+    def resolved_owner(self) -> str:
+        """解析后的 owner(优先级:配置 > git email > 'agent')
+
+        供 inject_params key path 使用:knowledge_config.resolved_owner
+        """
+        if self.owner:
+            return self.owner
+
+        # 尝试从 git config 获取
+        try:
+            result = subprocess.run(
+                ["git", "config", "user.email"],
+                capture_output=True,
+                text=True,
+                timeout=2,
+            )
+            if result.returncode == 0 and result.stdout.strip():
+                return result.stdout.strip()
+        except Exception:
+            pass
+
+        return "agent"
+
+    def get_owner(self, agent_id: str = "agent") -> str:
+        """获取 owner(优先级:配置 > git email > agent:{agent_id})"""
+        owner = self.resolved_owner
+        if owner == "agent" and agent_id != "agent":
+            return f"agent:{agent_id}"
+        return owner
+
+
 @tool(
     hidden_params=["context"],
     inject_params={
-        "types": {"mode": "default"},
-        "owner": {"mode": "default"},
+        "types": {"mode": "default", "key": "knowledge_config.default_search_types"},
+        "owner": {"mode": "default", "key": "knowledge_config.default_search_owner"},
     }
 )
 async def knowledge_search(
@@ -104,9 +171,9 @@ async def knowledge_search(
 @tool(
     hidden_params=["context", "owner"],
     inject_params={
-        "owner": {"mode": "default"},
-        "tags": {"mode": "merge"},
-        "scopes": {"mode": "merge"},
+        "owner": {"mode": "default", "key": "knowledge_config.resolved_owner"},
+        "tags": {"mode": "merge", "key": "knowledge_config.default_tags"},
+        "scopes": {"mode": "merge", "key": "knowledge_config.default_scopes"},
     }
 )
 async def knowledge_save(

+ 3 - 3
agent/tools/builtin/skill.py

@@ -10,12 +10,12 @@ from pathlib import Path
 from typing import Optional
 
 from agent.tools import tool, ToolResult
-from agent.memory.skill_loader import SkillLoader
+from agent.skill.skill_loader import SkillLoader
 
 # 默认 skills 目录(优先级:项目 skills > 框架 skills)
 DEFAULT_SKILLS_DIRS = [
     os.getenv("SKILLS_DIR", "./skills"),      # 项目特定 skills(优先)
-    "./agent/memory/skills"                    # 框架内置 skills
+    "./agent/skill/skills"                    # 框架内置 skills
 ]
 
 # 默认单一目录(用于 list_skills)
@@ -36,7 +36,7 @@ def _check_skill_setup(skill_name: str) -> Optional[str]:
     if skill_name in ["browser-use", "browser_use"]:
         try:
             # 动态导入 browser-use skill 的 setup 模块
-            from agent.memory.skills.browser_use.setup import (
+            from agent.skill.skills.browser_use.setup import (
                 _check_browser_use_cli,
                 _check_chromium_installed
             )

+ 27 - 2
agent/tools/registry.py

@@ -117,6 +117,29 @@ class ToolRegistry:
 			f"url_patterns={url_patterns or 'none'})"
 		)
 
+	@staticmethod
+	def _resolve_key_path(context: Dict[str, Any], key_path: str) -> Any:
+		"""
+		从 context 中按路径取值。
+
+		支持 "obj.field" 格式:第一段从 context dict 取值,后续段用 getattr。
+		例如 "knowledge_config.default_tags" → context["knowledge_config"].default_tags
+
+		Args:
+			context: 上下文字典
+			key_path: 取值路径
+
+		Returns:
+			取到的值,路径无效返回 None
+		"""
+		parts = key_path.split(".")
+		value = context.get(parts[0])
+		for part in parts[1:]:
+			if value is None:
+				return None
+			value = getattr(value, part, None)
+		return value
+
 	def is_registered(self, tool_name: str) -> bool:
 		"""检查工具是否已注册"""
 		return tool_name in self._tools
@@ -242,8 +265,10 @@ class ToolRegistry:
 					continue
 
 				mode = rule["mode"]
-				# 从 inject_values 中获取值
-				value = (inject_values or {}).get(param_name)
+				key_path = rule.get("key")
+
+				# 从 context 中按路径取值
+				value = self._resolve_key_path(context, key_path) if key_path and context else None
 
 				if value is None:
 					continue

+ 1 - 1
docs/README.md

@@ -74,7 +74,7 @@ Agent 系统
 | **agent/core/** | Agent 执行引擎 + 预设配置 | [架构设计](../agent/docs/architecture.md) |
 | **agent/trace/** | 执行追踪 + 计划管理 | [Trace API](../agent/docs/trace-api.md) |
 | **agent/tools/** | 与外部世界交互 | [工具系统](../agent/docs/tools.md) |
-| **agent/memory/** | 跨会话知识 | [Skills 指南](../agent/docs/skills.md) |
+| **agent/skill/** | 技能系统 | [Skills 指南](../agent/docs/skills.md) |
 | **agent/llm/** | LLM Provider 适配 | [架构设计](../agent/docs/architecture.md#llm-provider-适配) |
 | **gateway/core/** | Agent 注册和消息路由 | [Gateway 架构](../gateway/docs/architecture.md) |
 | **gateway/client/** | Gateway 客户端 SDK | [A2A IM](../gateway/client/a2a_im.md) |

+ 3 - 3
docs/a2a-im.md

@@ -72,7 +72,7 @@ A2A IM 在整体架构中的定位:
 │ - Trace、Message、Goal 管理                                  │
 │ - 工具系统(文件、命令、网络、浏览器)                          │
 │ - LLM 集成(Gemini、OpenRouter、Yescode)                    │
-│ - Skills 和 Memory(跨会话知识)
+│ - Skills(领域知识注入)          
 │ - 子 Agent 机制(agent 工具)                                 │
 │                                                              │
 │ 实现位置: agent/                                              │
@@ -482,7 +482,7 @@ async def get_contacts(
 - 如何查询联系人
 - 最佳实践
 
-**实现位置**:`agent/memory/skills/a2a_im.md`
+**实现位置**:`agent/skill/skills/a2a_im.md`
 
 ---
 
@@ -612,7 +612,7 @@ contacts = await get_contacts(
 **实现位置**:
 - `gateway/core/`
 - `agent/tools/builtin/a2a_im.py`
-- `agent/memory/skills/a2a_im.md`
+- `agent/skill/skills/a2a_im.md`
 
 ### Phase 2:联系人管理(1 周)
 

+ 1 - 1
examples/archive/deep_research/run.py

@@ -281,7 +281,7 @@ async def main():
         print(f"   - 已加载项目 presets: {list(project_presets.keys())}")
 
     # Skills 目录(可选:用户自定义 skills)
-    # 注意:内置 skills(agent/memory/skills/)会自动加载
+    # 注意:内置 skills(agent/skill/skills/)会自动加载
     skills_dir = str(base_dir / "skills")
 
     print("=" * 60)

+ 1 - 1
examples/archive/how/run.py

@@ -302,7 +302,7 @@ async def main():
         print(f"   - 已加载项目 presets: {list(project_presets.keys())}")
 
     # Skills 目录(可选:用户自定义 skills)
-    # 注意:内置 skills(agent/memory/skills/)会自动加载
+    # 注意:内置 skills(agent/skill/skills/)会自动加载
     skills_dir = str(base_dir / "skills")
 
     print("=" * 60)

+ 1 - 1
examples/archive/restore/run.py

@@ -320,7 +320,7 @@ async def main():
         print(f"   - 已加载项目 presets: {list(project_presets.keys())}")
 
     # Skills 目录(可选:用户自定义 skills)
-    # 注意:内置 skills(agent/memory/skills/)会自动加载
+    # 注意:内置 skills(agent/skill/skills/)会自动加载
     skills_dir = str(base_dir / "skills")
 
     print("=" * 60)

+ 1 - 1
examples/archive/restore_old/run.py

@@ -314,7 +314,7 @@ async def main():
         print(f"   - 已加载项目 presets: {list(project_presets.keys())}")
 
     # Skills 目录(可选:用户自定义 skills)
-    # 注意:内置 skills(agent/memory/skills/)会自动加载
+    # 注意:内置 skills(agent/skill/skills/)会自动加载
     skills_dir = str(base_dir / "skills")
 
     print("=" * 60)

+ 1 - 1
gateway/docs/enterprise/overview.md

@@ -194,7 +194,7 @@
 
 **详细设计**:见 [知识管理文档](./knowledge.md) 和 [Scope 设计文档](./scope-design.md)
 
-**实现位置**:`agent/memory/knowledge_store.py`
+**实现位置**:`agent/tools/builtin/knowledge.py`
 
 #### 代码库
 

+ 2 - 2
knowhub/docs/knowledge-management.md

@@ -444,7 +444,7 @@ return ToolResult(
 
 ### 调研 Skill
 
-调研指南存储在 `agent/memory/skills/research.md`。
+调研指南存储在 `agent/skill/skills/research.md`。
 
 ---
 
@@ -619,7 +619,7 @@ return ToolResult(
 | KnowHub Server | `knowhub/server.py` |
 | Agent 工具 | `agent/tools/builtin/knowledge.py` |
 | goal 工具(知识注入) | `agent/trace/goal_tool.py:focus_goal` |
-| 调研 skill | `agent/memory/skills/research.md` |
+| 调研 skill | `agent/skill/skills/research.md` |
 
 ---