feat: introduce unified agent runtime config and system task prompt framework

- Add structured runtime config files (AGENT_PROFILE.md, AGENT_WORKFLOW.md, AGENT_HOOKS.md, USER_PREFERENCES.md, SYSTEM_TASKS.md, CURRENT_PERSONA.md) for persona, workflow, hooks, and system tasks
- Implement agent_runtime_manager to load, validate, and render runtime config and system task prompts
- Refactor agent initialization to use runtime-managed directories for skills, jobs, memory, and activity logs
- Add AgentHooksMiddleware for structured pre/in/post hooks injection
- Replace hardcoded system task prompts with template-driven rendering from SYSTEM_TASKS.md
- Update tests to cover runtime config loading, migration, and system task prompt rendering
- Update .gitignore to exclude config/agent/
This commit is contained in:
jxxghp
2026-04-28 13:04:28 +08:00
parent 483fe55372
commit c5b716c231
16 changed files with 1335 additions and 200 deletions

View File

@@ -0,0 +1,68 @@
"""结构化 Agent hooks 中间件。"""
from collections.abc import Awaitable, Callable
from typing import Annotated, NotRequired, TypedDict
from langchain.agents.middleware.types import (
AgentMiddleware,
AgentState,
ContextT,
ModelRequest,
ModelResponse,
PrivateStateAttr, # noqa
ResponseT,
)
from langchain_core.runnables import RunnableConfig
from langgraph.runtime import Runtime
from app.agent.middleware.utils import append_to_system_message
from app.agent.runtime import agent_runtime_manager
class HooksState(AgentState):
"""hooks 中间件状态。"""
hooks_prompt: NotRequired[Annotated[str, PrivateStateAttr]]
class HooksStateUpdate(TypedDict):
"""hooks 状态更新。"""
hooks_prompt: str
class AgentHooksMiddleware(AgentMiddleware[HooksState, ContextT, ResponseT]): # noqa
"""在固定生命周期点注入结构化 pre/in/post hooks。"""
state_schema = HooksState
async def abefore_agent( # noqa
self, state: HooksState, runtime: Runtime, config: RunnableConfig
) -> HooksStateUpdate | None:
if "hooks_prompt" in state:
return None
runtime_config = agent_runtime_manager.load_runtime_config()
return HooksStateUpdate(hooks_prompt=runtime_config.render_hooks_prompt())
def modify_request(self, request: ModelRequest[ContextT]) -> ModelRequest[ContextT]: # noqa
hooks_prompt = request.state.get("hooks_prompt", "") # noqa
if not hooks_prompt:
return request
new_system_message = append_to_system_message(
request.system_message, hooks_prompt
)
return request.override(system_message=new_system_message)
async def awrap_model_call(
self,
request: ModelRequest[ContextT],
handler: Callable[
[ModelRequest[ContextT]], Awaitable[ModelResponse[ResponseT]]
],
) -> ModelResponse[ResponseT]:
return await handler(self.modify_request(request))
__all__ = ["AgentHooksMiddleware"]

View File

@@ -188,7 +188,8 @@ class MemoryMiddleware(AgentMiddleware[MemoryState, ContextT, ResponseT]): # no
支持多文件记忆组织:用户可以创建多个 `.md` 文件来按主题组织知识。
参数:
memory_dir: 记忆文件目录路径。
memory_dir: 记忆文件目录路径。建议使用独立的 `config/agent/memory`
目录,避免与 persona/workflow 等根层配置混写。
"""
state_schema = MemoryState
@@ -201,7 +202,7 @@ class MemoryMiddleware(AgentMiddleware[MemoryState, ContextT, ResponseT]): # no
"""初始化记忆中间件。
参数:
memory_dir: 记忆文件目录路径(例如,`"/config/agent"`)。
memory_dir: 记忆文件目录路径(例如,`"/config/agent/memory"`)。
该目录下所有 `.md` 文件都会被自动加载为记忆。
"""
self.memory_dir = memory_dir