refactor(skill-review): use make_lead_agent instead of create_react_agent
Reuses the full middleware chain (ToolErrorHandlingMiddleware, LLMErrorHandlingMiddleware, etc.) so tool errors like 'already exists' and invalid SKILL.md are converted to ToolMessages by the middleware, not silently swallowed or crashing the review task.
This commit is contained in:
1 parent
b2ed6f1acf
commit
ad5bd22c5e
1 file changed
+38
-17
+38
-17
@@ -108,17 +108,28 @@ _REVIEW_SYSTEM_PROMPT = textwrap.dedent("""\
|
||||
- The frontmatter block must start with `---` on its own line and end with `---`.
|
||||
- Do NOT add extra keys like "tags", "category", "type", etc.
|
||||
|
||||
## Avoiding duplicate-creation errors
|
||||
Before calling skill_manage with action="create":
|
||||
1. Always call skill_list first.
|
||||
2. If a skill with the same name already exists, use action="patch" instead.
|
||||
Creating over an existing skill will raise an error.
|
||||
3. If you get a tool error, read the message carefully and fix the issue
|
||||
(wrong name, bad frontmatter, duplicate, etc.) before retrying.
|
||||
|
||||
Be conservative. Fewer high-quality skills beat many noisy ones.
|
||||
""")
|
||||
|
||||
|
||||
async def _run_review(thread_id: str, messages: list[BaseMessage], app_config: "AppConfig") -> None:
|
||||
"""Core review logic: spin up a minimal React agent and invoke it."""
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
"""Core review logic: run a minimal lead agent with full middleware support.
|
||||
|
||||
from deerflow.models.factory import create_chat_model
|
||||
from deerflow.tools.builtins.skill_tools import skill_list_tool
|
||||
from deerflow.tools.skill_manage_tool import skill_manage_tool
|
||||
Reuses make_lead_agent so that ToolErrorHandlingMiddleware, LLMErrorHandlingMiddleware,
|
||||
and the rest of the middleware chain handle all error cases uniformly — no custom
|
||||
handle_tool_errors hack needed.
|
||||
"""
|
||||
from langchain_core.runnables import RunnableConfig
|
||||
|
||||
from deerflow.agents.lead_agent.agent import make_lead_agent
|
||||
|
||||
evolution_cfg = app_config.skill_evolution
|
||||
timeout = evolution_cfg.review_worker.timeout_seconds
|
||||
@@ -126,26 +137,36 @@ async def _run_review(thread_id: str, messages: list[BaseMessage], app_config: "
|
||||
model_name = evolution_cfg.review_worker.model_name
|
||||
|
||||
conversation_text = _format_messages_for_review(messages, max_messages)
|
||||
|
||||
try:
|
||||
model = create_chat_model(model_name)
|
||||
except Exception:
|
||||
logger.warning("skill_review_worker: could not load model %r, aborting review", model_name)
|
||||
return
|
||||
|
||||
tools = [skill_list_tool, skill_manage_tool]
|
||||
agent = create_react_agent(model, tools, prompt=_REVIEW_SYSTEM_PROMPT)
|
||||
|
||||
user_message = (
|
||||
"Review this conversation and apply any skill changes you deem appropriate.\n\n"
|
||||
_REVIEW_SYSTEM_PROMPT
|
||||
+ "\n\nReview this conversation and apply any skill changes you deem appropriate.\n\n"
|
||||
f"<conversation>\n{conversation_text}\n</conversation>"
|
||||
)
|
||||
|
||||
# Use a synthetic thread id so this review run is isolated from the source thread.
|
||||
review_thread_id = f"__skill-review__{thread_id}"
|
||||
|
||||
configurable: dict = {
|
||||
"thread_id": review_thread_id,
|
||||
"is_bootstrap": True, # skip MemoryMiddleware injection
|
||||
"is_scheduled_run": True, # skip TitleMiddleware
|
||||
"subagent_enabled": False, # no task-delegation tool
|
||||
"app_config": app_config,
|
||||
}
|
||||
if model_name:
|
||||
configurable["model_name"] = model_name
|
||||
|
||||
run_config = RunnableConfig(configurable=configurable)
|
||||
agent = make_lead_agent(run_config)
|
||||
|
||||
try:
|
||||
await asyncio.wait_for(
|
||||
asyncio.get_event_loop().run_in_executor(
|
||||
None,
|
||||
lambda: agent.invoke({"messages": [("user", user_message)]}),
|
||||
lambda: agent.invoke(
|
||||
{"messages": [("user", user_message)]},
|
||||
config=run_config,
|
||||
),
|
||||
),
|
||||
timeout=timeout,
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user