diff --git a/apps/llm/generator.py b/apps/llm/generator.py
index b62bcb29909206dee8d8169499763e5e7a7b3220..e3b5bee7f4fa19dcc60d3fa0c2cc0c38e2a9065d 100644
--- a/apps/llm/generator.py
+++ b/apps/llm/generator.py
@@ -139,6 +139,8 @@ class JsonGenerator:
formatted_prompt = template.render(use_xml_format=use_xml_format)
result = await self._call_without_function(function, formatted_prompt, conversation, retry_messages)
+
+ _logger.info("[JSONGenerator] 函数调用结果: %s", result)
try:
validator.validate(result)
except Exception as err:
diff --git a/apps/llm/providers/base.py b/apps/llm/providers/base.py
index 5c5757ae8622f38397e32601bc8bc4d00f7e75f1..a60ef217f2aa79275a0f9bb19e9b6974cd105cbd 100644
--- a/apps/llm/providers/base.py
+++ b/apps/llm/providers/base.py
@@ -50,9 +50,9 @@ class BaseProvider:
async def chat(
self, messages: list[dict[str, str]],
+ tools: list[LLMFunctions] | None = None,
*, include_thinking: bool = False,
streaming: bool = True,
- tools: list[LLMFunctions] | None = None,
) -> AsyncGenerator[LLMChunk, None]:
"""聊天"""
yield LLMChunk(content="")
diff --git a/apps/llm/providers/ollama.py b/apps/llm/providers/ollama.py
index dd3e6d50d4322eb7ff3dcd834b2fc46545b5ef2c..176419753d4c7e2dd7bb2bfddbc3741000b04aae 100644
--- a/apps/llm/providers/ollama.py
+++ b/apps/llm/providers/ollama.py
@@ -218,7 +218,7 @@ class OllamaProvider(BaseProvider):
raise RuntimeError(err)
# 构建请求参数
- embed_kwargs = {"input": text}
+ embed_kwargs: dict[str, Any] = {"input": text}
# 如果modelName存在,则传递该参数
if self.config.modelName:
diff --git a/apps/llm/providers/openai.py b/apps/llm/providers/openai.py
index 682656fb4d40dea50025f7bd316ce3dd7dd425b0..8291ba48d47b6b83a6a3c2ef3c439ffe604ddad5 100644
--- a/apps/llm/providers/openai.py
+++ b/apps/llm/providers/openai.py
@@ -3,7 +3,7 @@
import logging
from collections.abc import AsyncGenerator
-from typing import cast
+from typing import Any, cast
import httpx
from openai import AsyncOpenAI, AsyncStream
@@ -298,7 +298,7 @@ class OpenAIProvider(BaseProvider):
raise RuntimeError(err)
# 构建请求参数
- embedding_kwargs = {"input": text}
+ embedding_kwargs: dict[str, Any] = {"input": text}
# 如果modelName存在,则传递该参数
if self.config.modelName:
diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py
index 499d0a6d4075e0cdebef1a60a8d01c68a0228605..649b3f7d2b91f6dd7a6aaf4246fbe71451d76e73 100644
--- a/apps/scheduler/executor/agent.py
+++ b/apps/scheduler/executor/agent.py
@@ -591,7 +591,7 @@ class MCPAgentExecutor(BaseExecutor):
if self.task.state.executorStatus == ExecutorStatus.INIT:
# 初始化状态
self.task.state.executorId = str(uuid.uuid4())
- self.task.state.executorName = (await self._planner.get_flow_name()).flow_name
+ self.task.state.executorName = await self._planner.get_flow_name(self.llm)
await self.get_next_step()
self.task.state.executorStatus = ExecutorStatus.RUNNING
diff --git a/apps/scheduler/mcp/host.py b/apps/scheduler/mcp/host.py
index 514edc182477c5776ffec99fa5598ad7e776dc8e..f1d73f1d0c86b024421c4e469331f25f86310c8e 100644
--- a/apps/scheduler/mcp/host.py
+++ b/apps/scheduler/mcp/host.py
@@ -45,11 +45,6 @@ class MCPHost(MCPNodeBase):
async def get_client(self, mcp_id: str) -> MCPClient | None:
"""获取MCP客户端"""
- if not await MCPServiceManager.is_user_actived(self._user_id, mcp_id):
- logger.warning("用户 %s 未启用MCP %s", self._user_id, mcp_id)
- return None
-
- # 获取MCP配置(如果失败会抛出RuntimeError)
try:
return await mcp_pool.get(mcp_id, self._user_id)
except (KeyError, RuntimeError) as e:
@@ -182,10 +177,6 @@ class MCPHost(MCPNodeBase):
# 获取工具列表
tool_list = []
for mcp_id in mcp_id_list:
- # 检查用户是否启用了这个mcp
- if not await MCPServiceManager.is_user_actived(self._user_id, mcp_id):
- logger.warning("用户 %s 未启用MCP %s", self._user_id, mcp_id)
- continue
# 获取MCP工具配置
try:
tool_list.extend(await MCPServiceManager.get_mcp_tools(mcp_id))
diff --git a/apps/scheduler/mcp_agent/base.py b/apps/scheduler/mcp_agent/base.py
index c09263347462b3ab94cd7dda0d9b29fe098eade6..bd6728e1913c427f91b6143f951d5632825642dd 100644
--- a/apps/scheduler/mcp_agent/base.py
+++ b/apps/scheduler/mcp_agent/base.py
@@ -11,6 +11,7 @@ from jinja2.sandbox import SandboxedEnvironment
from apps.common.config import config
from apps.models import LanguageType
+from apps.models.task import StepStatus
from apps.scheduler.mcp.prompt import MEMORY_TEMPLATE
from apps.schemas.task import TaskData
@@ -61,8 +62,9 @@ class MCPBase:
history = []
template = MEMORY_TEMPLATE[task.runtime.language]
- for index, item in enumerate(task.context, start=1):
- # 用户消息:步骤描述和工具调用
+ filtered_context = [item for item in task.context if item.stepStatus != StepStatus.WAITING]
+
+ for index, item in enumerate(filtered_context, start=1):
step_goal = item.extraData["step_goal"]
user_content = _env.from_string(template).render(
msg_type="user",
@@ -76,7 +78,6 @@ class MCPBase:
"content": user_content,
})
- # 助手消息:步骤执行结果
assistant_content = _env.from_string(template).render(
msg_type="assistant",
step_index=index,
diff --git a/apps/scheduler/mcp_agent/func.py b/apps/scheduler/mcp_agent/func.py
index aad54cdc35680e236a67442652dfb45b10c3f102..b9d7b3ec796be9c8ee9cfcd9365c7575bd0c517a 100644
--- a/apps/scheduler/mcp_agent/func.py
+++ b/apps/scheduler/mcp_agent/func.py
@@ -5,39 +5,6 @@ from textwrap import dedent
from apps.models import LanguageType
-GET_FLOW_NAME_FUNCTION: dict[LanguageType, dict] = {
- LanguageType.CHINESE: {
- "name": "get_flow_name",
- "description": "根据用户目标生成当前工作流程的描述性名称",
- "parameters": {
- "type": "object",
- "properties": {
- "flow_name": {
- "type": "string",
- "description": "MCP 流程名称",
- "default": "",
- },
- },
- "required": ["flow_name"],
- },
- },
- LanguageType.ENGLISH: {
- "name": "get_flow_name",
- "description": "Generate a descriptive name for the current workflow based on the user's goal",
- "parameters": {
- "type": "object",
- "properties": {
- "flow_name": {
- "type": "string",
- "description": "MCP workflow name",
- "default": "",
- },
- },
- "required": ["flow_name"],
- },
- },
-}
-
CREATE_NEXT_STEP_FUNCTION: dict[LanguageType, dict] = {
LanguageType.CHINESE: {
"name": "create_next_step",
diff --git a/apps/scheduler/mcp_agent/host.py b/apps/scheduler/mcp_agent/host.py
index 72b5b3559ae289e156442d8314cb5e9bd14abb3f..2597f6c09093669ba0e46b9943d12bed7920096b 100644
--- a/apps/scheduler/mcp_agent/host.py
+++ b/apps/scheduler/mcp_agent/host.py
@@ -58,11 +58,16 @@ class MCPHost(MCPBase):
"parameters": mcp_tool.inputSchema,
}
+ # 组装对话历史,包含步骤上下文
+ conversation = [
+ {"role": "system", "content": "You are a helpful assistant."},
+ ]
+ memory = await self.assemble_memory(task)
+ conversation.extend(memory)
+ conversation.append({"role": "user", "content": llm_query})
+
return await json_generator.generate(
function=function,
- conversation=[
- {"role": "system", "content": "You are a helpful assistant."},
- {"role": "user", "content": llm_query},
- ],
+ conversation=conversation,
prompt=prompt,
)
diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py
index 8cbba10c00fb23b7902ddebbd7c71b9fea97cb3e..3fad54be9b3fd2de931288f6473a1db457f397aa 100644
--- a/apps/scheduler/mcp_agent/plan.py
+++ b/apps/scheduler/mcp_agent/plan.py
@@ -14,7 +14,6 @@ from apps.models import MCPTools
from apps.scheduler.slot.slot import Slot
from apps.schemas.llm import LLMChunk
from apps.schemas.mcp import (
- FlowName,
IsParamError,
Step,
ToolRisk,
@@ -26,7 +25,6 @@ from .func import (
CREATE_NEXT_STEP_FUNCTION,
EVALUATE_TOOL_RISK_FUNCTION,
FINAL_ANSWER,
- GET_FLOW_NAME_FUNCTION,
GET_MISSING_PARAMS_FUNCTION,
IS_PARAM_ERROR_FUNCTION,
)
@@ -43,19 +41,23 @@ logger = logging.getLogger(__name__)
class MCPPlanner(MCPBase):
"""MCP 用户目标拆解与规划"""
- async def get_flow_name(self) -> FlowName:
+ async def get_flow_name(self, llm: LLM) -> str:
"""获取当前流程的名称"""
template = _env.from_string(await self._load_prompt("gen_agent_name"))
prompt = template.render(goal=self._goal)
- result = await json_generator.generate(
- function=GET_FLOW_NAME_FUNCTION[self._language],
- conversation=[
- {"role": "system", "content": "You are a helpful assistant."},
- ],
- prompt=prompt,
- )
- return FlowName.model_validate(result)
+ messages = [
+ {"role": "system", "content": "You are a helpful assistant."},
+ {"role": "user", "content": prompt},
+ ]
+
+ agent_name = ""
+ async for chunk in llm.call(messages, streaming=False):
+ agent_name += chunk.content or ""
+
+ result = agent_name.strip()
+ logger.info("[MCPPlanner] 生成流程名称: %s", result)
+ return result
async def create_next_step(self, tools: list[MCPTools], task: TaskData, llm: LLM) -> Step:
"""创建下一步的执行步骤"""
@@ -76,12 +78,12 @@ class MCPPlanner(MCPBase):
thinking_content += chunk.content or ""
logger.info("[MCPPlanner] 思考分析: %s", thinking_content)
- step_template = _env.from_string(await self._load_prompt("gen_step"))
- step_prompt = step_template.render(goal=self._goal, tools=tools)
-
function = deepcopy(CREATE_NEXT_STEP_FUNCTION[self._language])
function["parameters"]["properties"]["tool_name"]["enum"] = [tool.toolName for tool in tools]
+ step_template = _env.from_string(await self._load_prompt("gen_step"))
+ step_prompt = step_template.render(goal=self._goal, tools=tools, function_schema=function)
+
step = await json_generator.generate(
function=function,
conversation=[
diff --git a/apps/schemas/mcp.py b/apps/schemas/mcp.py
index 78d995a525c1ce1b8fcc55b7fdbf565d3b37d525..db5dfea5d802ed732ac6d5f8044c6f872379cbda 100644
--- a/apps/schemas/mcp.py
+++ b/apps/schemas/mcp.py
@@ -79,12 +79,6 @@ class Risk(str, Enum):
MEDIUM = "medium"
HIGH = "high"
-
-class FlowName(BaseModel):
- """MCP 流程名称"""
-
- flow_name: str = Field(description="MCP 流程名称", default="")
-
class ToolRisk(BaseModel):
"""MCP工具风险评估结果"""
diff --git a/apps/services/task.py b/apps/services/task.py
index 552f50af14eab968bd6207e1779f525b7cf72b50..2b9fa8c51728b3229b6ec20cd9a4ad877de66d23 100644
--- a/apps/services/task.py
+++ b/apps/services/task.py
@@ -16,7 +16,7 @@ from apps.models import (
)
from apps.schemas.task import TaskData
-logger = logging.getLogger(__name__)
+_logger = logging.getLogger(__name__)
class TaskManager:
@@ -48,9 +48,9 @@ class TaskManager:
conversationId=conversation_id,
userId=user_id,
)
- logger.info("[TaskManager] 创建新任务对象 (未保存)")
+ _logger.info("[TaskManager] 创建新任务对象 (未保存)")
return new_task
- logger.info("[TaskManager] 找到已存在的任务 %s", task.id)
+ _logger.info("[TaskManager] 找到已存在的任务 %s", task.id)
return task
@@ -62,7 +62,7 @@ class TaskManager:
select(Task).where(Task.id == task_id),
)).one_or_none()
if not task_data:
- logger.error("[TaskManager] 任务不存在 %s", task_id)
+ _logger.error("[TaskManager] 任务不存在 %s", task_id)
return None
runtime = (await session.scalars(
@@ -174,21 +174,48 @@ class TaskManager:
@staticmethod
async def save_flow_context(context: list[ExecutorHistory]) -> None:
- """保存Flow上下文信息到PostgreSQL"""
+ """保存Flow上下文信息到PostgreSQL,确保数据库与内存状态一致"""
+ if not context:
+ return
+
async with postgres.session() as session:
+ task_id = context[0].taskId
+ memory_ids = {ctx.id for ctx in context}
+
+ existing_histories = list((await session.scalars(
+ select(ExecutorHistory).where(ExecutorHistory.taskId == task_id),
+ )).all())
+
+ existing_map = {history.id: history for history in existing_histories}
+
+ deleted_count = 0
+ for existing_id, existing_history in existing_map.items():
+ if existing_id not in memory_ids:
+ await session.delete(existing_history)
+ deleted_count += 1
+ _logger.debug(
+ "[TaskManager] 删除已从内存移除的History记录 - task_id: %s, history_id: %s, status: %s",
+ task_id, existing_id, existing_history.stepStatus.value,
+ )
+
+ updated_count = 0
+ inserted_count = 0
for ctx in context:
- # 查询是否存在该ExecutorHistory
- existing_history = (await session.scalars(
- select(ExecutorHistory).where(ExecutorHistory.id == ctx.id),
- )).one_or_none()
+ existing_history = existing_map.get(ctx.id)
if existing_history:
- # 更新现有History
for key, value in ctx.__dict__.items():
if not key.startswith("_"):
setattr(existing_history, key, value)
+ updated_count += 1
else:
- # 插入新History
session.add(ctx)
+ inserted_count += 1
await session.commit()
+
+ if deleted_count > 0 or inserted_count > 0 or updated_count > 0:
+ _logger.info(
+ "[TaskManager] 保存Flow上下文 - task_id: %s, 插入: %d, 更新: %d, 删除: %d",
+ task_id, inserted_count, updated_count, deleted_count,
+ )
diff --git a/data/prompts/system/mcp/agent_thinking.en.md b/data/prompts/system/mcp/agent_thinking.en.md
index f89d0cbecee6b2d131c92c7d41b622310e4e9755..437aaec9d3edad5d4eacc85ffca28b240b495d72 100644
--- a/data/prompts/system/mcp/agent_thinking.en.md
+++ b/data/prompts/system/mcp/agent_thinking.en.md
@@ -1,15 +1,21 @@
-Now let's review the step history context. My goal is: {{goal}}
+Please review the step history context. The current goal is: {{goal}}
-Available tools:
+You can use the following tools:
{% for tool in tools %}
- {{tool.toolName}}: {{tool.description}}
{% endfor %}
-Please think step by step:
+Please provide a concise analysis and your thinking process, including the following points:
-- How far along is my goal now
-- What should be done next to achieve the goal
-- Which tool should be used and why
+- What is the progress towards completing the current goal
+- What action should be taken next to achieve the goal
+- Which tool should be used and the rationale for choosing that tool
-Think and analyze first, then provide a specific plan for the next step.
\ No newline at end of file
+**Important Notes**:
+
+- Please provide your analysis and thinking directly, without repeating or restating the results returned by tools
+- The tool outputs are already visible, you only need to reason and make decisions based on this information
+- Keep responses concise and focused on the next action plan
+
+Now, please begin thinking step by step:
\ No newline at end of file
diff --git a/data/prompts/system/mcp/agent_thinking.zh.md b/data/prompts/system/mcp/agent_thinking.zh.md
index 2ba00aa856342537128a7d8dedb46104ea593c7d..88085e3b2bbbfa088e15fc027e02d2ca83c1555c 100644
--- a/data/prompts/system/mcp/agent_thinking.zh.md
+++ b/data/prompts/system/mcp/agent_thinking.zh.md
@@ -1,15 +1,21 @@
-现在回顾一下步骤历史上下文,我的目标是:{{goal}}
+请回顾历史步骤上下文,当前目标是:{{goal}}
-可用的工具有:
+你可以使用以下工具:
{% for tool in tools %}
- {{tool.toolName}}: {{tool.description}}
{% endfor %}
-请你一步一步分析思考:
+请简明扼要地分析并给出你的思考过程,包含以下要点:
-- 我的目标现在完成到什么程度了
-- 接下来应该做什么才能达成目标
-- 应该用哪个工具,为什么
+- 当前目标的完成进度如何
+- 下一步需要采取什么行动来达成目标
+- 应该使用哪个工具以及选择该工具的理由
-先思考分析,然后再给出下一步的具体方案。
+**重要说明**:
+
+- 请直接给出你的分析和思考,不要复述或重复工具返回的结果
+- 工具的输出内容已经可见,你只需要基于这些信息进行推理和决策
+- 保持回复简洁,专注于下一步行动方案
+
+现在,请开始一步一步地思考:
diff --git a/data/prompts/system/mcp/gen_agent_name.en.md b/data/prompts/system/mcp/gen_agent_name.en.md
index 542ac20e31a89d45b06794e87d9f45a79f5d3033..60fc90d56439ad3e16f943ee7569e6d0c59a5cb1 100644
--- a/data/prompts/system/mcp/gen_agent_name.en.md
+++ b/data/prompts/system/mcp/gen_agent_name.en.md
@@ -4,51 +4,24 @@
You are a professional Agent name generation assistant, capable of generating accurate, concise, and descriptive Agent names based on user goals.
-## Generation Requirements
-
-1. **Accuracy**: Accurately express the core process of achieving the user's goal
-2. **Conciseness**: Keep the length under 20 characters, be brief and to the point
-3. **Descriptiveness**: Include key operational steps (e.g., "Scan", "Analyze", "Optimize", etc.)
-4. **Clarity**: Use easy-to-understand language, avoiding overly technical terms
-
-## Tools
-
-You can call the following tools to complete the Agent name generation task.
-
-{% raw %}{% if use_xml_format %}{% endraw %}
-When calling tools, use XML-style tags for formatting. The format specification is as follows:
-
-```xml
-
-Agent Name
-
-```
+## Task
-{% raw %}{% endif %}{% endraw %}
+Generate a short Agent name within 20 characters based on the user's goal.
-### generate_agent_name
-
-Description: Generate a descriptive Agent name based on the user's goal
-
-Parameters:
-
-- name: Agent name
-
-Usage example:
+## Generation Requirements
-- User goal: I need to scan the current mysql database, analyze performance bottlenecks, and tune it
-- Name should be: Scan MySQL database, analyze performance bottlenecks, and tune
+1. Accurately express the core process of the user's goal
+2. Keep length under 20 characters
+3. Output the name directly without additional formatting or explanation
-{% raw %}{% if use_xml_format %}{% endraw %}
+## Example
-```xml
-
-Scan MySQL database, analyze performance bottlenecks, and tune
-
-```
+**User Goal**: I need to scan the current mysql database, analyze performance bottlenecks, and tune it
-{% raw %}{% endif %}{% endraw %}
+**Output**: Scan MySQL database, analyze performance bottlenecks, and tune
---
**User Goal**: {{goal}}
+
+**Output**:
diff --git a/data/prompts/system/mcp/gen_agent_name.zh.md b/data/prompts/system/mcp/gen_agent_name.zh.md
index 671dd37a5c7054e97adaee72a3d025929e13281d..56229e0c84714aed3b9dc0d7c5ec9942c036b1b3 100644
--- a/data/prompts/system/mcp/gen_agent_name.zh.md
+++ b/data/prompts/system/mcp/gen_agent_name.zh.md
@@ -4,51 +4,24 @@
你是一个专业的Agent名称生成助手,能够根据用户目标生成准确、简洁且具有描述性的Agent名称。
-## 生成要求
-
-1. **准确性**:准确表达达成用户目标的核心过程
-2. **简洁性**:长度控制在20字以内,言简意赅
-3. **描述性**:包含关键操作步骤(如"扫描"、"分析"、"调优"等)
-4. **易懂性**:使用通俗易懂的语言,避免过于专业的术语
-
-## 工具
-
-你可以调用以下工具来完成Agent名称生成任务。
-
-{% raw %}{% if use_xml_format %}{% endraw %}
-调用工具时,采用XML风格标签进行格式化。格式规范如下:
-
-```xml
-
-Agent名称
-
-```
+## 任务
-{% raw %}{% endif %}{% endraw %}
+根据用户目标,生成一个20字以内的简短Agent名称。
-### generate_agent_name
-
-描述:根据用户目标生成描述性的Agent名称
-
-参数:
-
-- name:Agent名称
-
-用法示例:
+## 生成要求
-- 用户目标:我需要扫描当前mysql数据库,分析性能瓶颈,并调优
-- 名称应为:扫描MySQL数据库并分析性能瓶颈,进行调优
+1. 准确表达用户目标的核心过程
+2. 长度控制在20字以内
+3. 直接输出名称文本,无需额外格式或说明
-{% raw %}{% if use_xml_format %}{% endraw %}
+## 示例
-```xml
-
-扫描MySQL数据库并分析性能瓶颈,进行调优
-
-```
+**用户目标**:我需要扫描当前MySQL数据库,分析性能瓶颈,并调优
-{% raw %}{% endif %}{% endraw %}
+**输出**:MySQL性能分析与调优
---
**用户目标**:{{goal}}
+
+**输出**:
diff --git a/data/prompts/system/mcp/gen_step.en.md b/data/prompts/system/mcp/gen_step.en.md
index ec2b1eb19b93292b86b36fefe07bd96a385a4474..605f9e4ff894723a9279e06011d3727ba33eae4d 100644
--- a/data/prompts/system/mcp/gen_step.en.md
+++ b/data/prompts/system/mcp/gen_step.en.md
@@ -1,75 +1,78 @@
# Step Planning Task
-## Role
+## Task Description
-You are a professional workflow planning assistant who can intelligently plan the next execution step based on user goals and thinking analysis.
+You need to immediately call the `create_next_step` function to plan the next execution step based on the previous thinking analysis and user goal.
-## Task Objective
+**Important**: You must call the function, not just describe or explain, but actually execute the function call.
-Based on the previous thinking analysis and user goal, call the `create_next_step` function to plan the next execution step.
+## Function Definition
-## Planning Requirements
+### Function Name
-1. **Accuracy**: Plan based on the conclusions from the thinking analysis
-2. **Relevance**: Select the most appropriate tool for the current stage
-3. **Clarity**: Step description should be concise and clear, explaining specific operations
-4. **Completeness**: Ensure each step is independent and complete, directly executable
+`{{function_schema['name']}}`
-## Functions
+### Function Description
-You can call the following functions to complete the step planning task.
+{{function_schema['description']}}
-{% raw %}{% if use_xml_format %}{% endraw %}
-When calling tools, use XML-style tags for formatting. The format specification is as follows:
+### JSON Schema
-```xml
-
-Function Name
-Step Description
-
+```json
+{{function_schema | tojson(indent=2)}}
```
-{% raw %}{% endif %}{% endraw %}
-
-### create_next_step
+### Parameter Details
-Description: Create the next execution step
+#### 1. tool_name (required)
-Parameters:
-
-- tool_name: External tool name, must be selected from the following list
+- **Type**: string
+- **Constraint**: Must be one of the following enum values
{% for tool in tools %}
- - `{{tool.toolName}}`: {{tool.description}}
+ - `"{{tool.toolName}}"` - {{tool.description}}
{% endfor %}
-- description: Step description, clearly explain what this step will do
+ - `"Final"` - Use when the user goal is completed
+- **Description**: Select the most appropriate tool name from the available tools list for the current step
-Calling Specifications:
+#### 2. description (required)
-- **Fixed function name**: Must use `create_next_step`, do not use external tool names as function names
-- **tool_name value**: Must be one of the tool names from the external tools list
-- **description value**: Describe the specific operations of this step
-- **When task completes**: If the user goal is achieved, set `tool_name` parameter to `Final`
+- **Type**: string
+- **Description**: Clearly describe the specific operation to be performed in this step
+- **Requirements**:
+ - Explain why this tool is chosen
+ - Describe what task needs to be completed
+ - Be concise and clear, typically 1-2 sentences
-Usage Example:
+## Calling Requirements
-- Scenario: User goal is "Analyze MySQL database performance", thinking analysis shows database connection established, need to perform performance analysis
-- Next step should be: Call performance analysis tool to retrieve database performance metrics
+✓ **Must call the function**: Don't just describe, actually call the `create_next_step` function
+✓ **Fixed function name**: The function name must be `create_next_step`, not the tool name
+✓ **tool_name exact match**: The tool_name value must exactly match one of the enum values
+✓ **Complete parameters**: Both tool_name and description parameters must be provided
+✓ **Based on thinking conclusion**: Select the most appropriate tool based on the previous thinking analysis
{% raw %}{% if use_xml_format %}{% endraw %}
+## XML Format Call Example
+
+When using XML format, please call in the following format:
+
```xml
mysql_analyzer
-Retrieve slow query logs and performance metrics from the database
+Retrieve slow query logs and performance metrics from the database to analyze performance bottlenecks
```
-{% raw %}{% endif %}{% endraw %}
+**Note**:
+
+- The tool_name value must strictly match a tool name from the available tools list
+- If the task is completed, set tool_name to `Final`
----
+{% raw %}{% endif %}{% endraw %}
-## Current Task
+## Execution Instruction
**User Goal**: {{goal}}
-Now based on the thinking and analysis above, call the `create_next_step` function to plan the next step.
+Based on the thinking and analysis above, immediately call the `create_next_step` function now, select the most appropriate tool and plan the next operation.
diff --git a/data/prompts/system/mcp/gen_step.zh.md b/data/prompts/system/mcp/gen_step.zh.md
index ba235d914a7c6ab125931e03f8638b90fb66571b..498414cf6455734a4a48ad26538701e81c416bbe 100644
--- a/data/prompts/system/mcp/gen_step.zh.md
+++ b/data/prompts/system/mcp/gen_step.zh.md
@@ -1,75 +1,78 @@
# 步骤规划任务
-## 角色
+## 任务说明
-你是一个专业的工作流程规划助手,能够根据用户目标和思考分析,智能规划下一个执行步骤。
+你需要根据前面的思考分析和用户目标,立即调用 `create_next_step` 函数来规划下一个执行步骤。
-## 任务目标
+**重要**: 你必须调用函数,不要只是描述或说明,而是实际执行函数调用。
-基于前面的思考分析和用户目标,调用 `create_next_step` 函数来规划下一个执行步骤。
+## 函数定义
-## 规划要求
+### 函数名称
-1. **准确性**:基于思考分析中的结论进行规划
-2. **针对性**:选择最适合当前阶段的工具
-3. **清晰性**:步骤描述简洁明确,说明具体操作内容
-4. **完整性**:确保每个步骤独立完整,可直接执行
+`{{function_schema['name']}}`
-## 函数
+### 函数描述
-你可以调用以下函数来完成步骤规划任务。
+{{function_schema['description']}}
-{% raw %}{% if use_xml_format %}{% endraw %}
-调用工具时,采用XML风格标签进行格式化。格式规范如下:
+### JSON Schema
-```xml
-
-函数名称
-步骤描述
-
+```json
+{{function_schema | tojson(indent=2)}}
```
-{% raw %}{% endif %}{% endraw %}
-
-### create_next_step
+### 参数详细说明
-描述:创建下一个执行步骤
+#### 1. tool_name (必填)
-参数:
-
-- tool_name: 外置工具名称,必须从以下列表中选择
+- **类型**: string
+- **约束**: 必须是以下枚举值之一
{% for tool in tools %}
- - `{{tool.toolName}}`: {{tool.description}}
+ - `"{{tool.toolName}}"` - {{tool.description}}
{% endfor %}
-- description: 步骤描述,清晰说明本步骤要做什么
+ - `"Final"` - 当用户目标已完成时使用
+- **说明**: 从可用工具列表中选择最适合当前步骤的工具名称
-调用规范:
+#### 2. description (必填)
-- **函数名固定**: 必须使用 `create_next_step`,不要使用外置工具名作为函数名
-- **tool_name的值**: 必须是外置工具列表中的某个工具名称
-- **description的值**: 描述本步骤的具体操作内容
-- **任务完成时**: 如果用户目标已经完成,将 `tool_name` 参数设为 `Final`
+- **类型**: string
+- **说明**: 清晰描述本步骤要执行的具体操作内容
+- **要求**:
+ - 说明选择该工具的原因
+ - 描述具体要完成什么任务
+ - 简洁明确,通常1-2句话
-用法示例:
+## 调用要求
-- 场景:用户目标是"分析MySQL数据库性能",思考分析显示已连接到数据库,需要进行性能分析
-- 下一步应为:调用性能分析工具,获取数据库的性能指标
+✓ **必须调用函数**: 不要只描述,要实际调用 `create_next_step` 函数
+✓ **函数名固定**: 函数名必须是 `create_next_step`,不是工具名
+✓ **tool_name 精确匹配**: tool_name 的值必须完全匹配枚举列表中的某个值
+✓ **参数完整**: tool_name 和 description 两个参数都必须提供
+✓ **基于思考结论**: 根据前面的思考分析选择最合适的工具
{% raw %}{% if use_xml_format %}{% endraw %}
+## XML 格式调用示例
+
+当使用 XML 格式时,请按以下格式调用:
+
```xml
mysql_analyzer
-获取数据库的慢查询日志和性能指标
+获取数据库的慢查询日志和性能指标,以分析性能瓶颈
```
-{% raw %}{% endif %}{% endraw %}
+**注意**:
+
+- tool_name 的值必须严格匹配可用工具列表中的工具名称
+- 如果任务已完成,tool_name 设置为 `Final`
----
+{% raw %}{% endif %}{% endraw %}
-## 当前任务
+## 执行指令
**用户目标**: {{goal}}
-现在基于上面的思考分析结果,调用 `create_next_step` 函数规划下一步。
+基于上面的思考分析,现在立即调用 `create_next_step` 函数,选择最合适的工具并规划下一步操作。
diff --git a/data/sysagent.service b/data/sysagent.service
index ca5a8e5999d7334c2c5789ca3fb27e0ba87f04ec..630c3816e0f4b4c1dcbb8061c66191a5a1e70aa7 100644
--- a/data/sysagent.service
+++ b/data/sysagent.service
@@ -5,6 +5,7 @@ User=root
WorkingDirectory=/usr/lib/sysagent
Environment="PYTHONPATH=/usr/lib/sysagent"
Environment="CONFIG=/etc/sysagent/config.toml"
+Environment="TIKTOKEN_CACHE_DIR=/var/lib/sysagent/tiktoken_cache"
ExecStart=/usr/bin/python3 -m apps.main
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure