智能体对话选 Agent 直达、澄清问题批量提交、LLM 错误中文化等
- 前端:新会话选 Agent 后直接跳转并自动发送,智能体页输入框宽度与首页对齐 - 前端:澄清卡片支持多选+多问题合并提交,消除单题逐一发送的割裂感 - 前端:定时任务弹窗 Agent 下拉支持长描述截断,避免撑破布局 - 后端:ask_clarification 支持同回合多次调用以提多个独立问题 - 后端:LLM 错误处理与定时任务失败提示统一改为中文 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
c74be2b789
commit
ba2bc46042
7 files changed
+327
-73
No files matched your search
+11
@@ -464,11 +464,22 @@ You are {agent_name}, an internal super agent.
|
||||
- ❌ DO NOT skip clarification for "efficiency" - accuracy matters more than speed
|
||||
- ❌ DO NOT make assumptions when information is missing - ALWAYS ask
|
||||
- ❌ DO NOT proceed with guesses - STOP and call ask_clarification first
|
||||
- ❌ DO NOT cram several unrelated questions into one `question` string — split them into separate tool calls
|
||||
- ✅ Analyze the request in thinking → Identify unclear aspects → Ask BEFORE any action
|
||||
- ✅ If you identify the need for clarification in your thinking, you MUST call the tool IMMEDIATELY
|
||||
- ✅ After calling ask_clarification, execution will be interrupted automatically
|
||||
- ✅ Wait for user response - do NOT continue with assumptions
|
||||
|
||||
**Batching multiple independent questions:**
|
||||
- When the request leaves **several independent aspects** unclear (e.g. project type AND tech stack
|
||||
AND deployment target), call `ask_clarification` multiple times in the same turn — one call per
|
||||
aspect, each with its own focused `question` and `options`.
|
||||
- The frontend groups all clarification cards from one turn into a single submission, so the user
|
||||
answers them together in one reply. You will then receive ONE combined user message addressing
|
||||
every question in order — read it carefully and match answers back to the questions you asked.
|
||||
- If the next question only makes sense after the previous answer (sequential dependency), ask
|
||||
only the first one this turn and wait for the reply before asking the next.
|
||||
|
||||
**How to Use:**
|
||||
```python
|
||||
ask_clarification(
|
||||
|
||||
+7
-7
@@ -171,21 +171,21 @@ class LLMErrorHandlingMiddleware(AgentMiddleware[AgentState]):
|
||||
|
||||
def _build_retry_message(self, attempt: int, wait_ms: int, reason: str) -> str:
|
||||
seconds = max(1, round(wait_ms / 1000))
|
||||
reason_text = "provider is busy" if reason == "busy" else "provider request failed temporarily"
|
||||
return f"LLM request retry {attempt}/{self.retry_max_attempts}: {reason_text}. Retrying in {seconds}s."
|
||||
reason_text = "服务繁忙" if reason == "busy" else "网络/连接异常"
|
||||
return f"大模型因{reason_text}调用失败,正在第 {attempt}/{self.retry_max_attempts} 次重试,{seconds} 秒后继续…"
|
||||
|
||||
def _build_circuit_breaker_message(self) -> str:
|
||||
return "The configured LLM provider is currently unavailable due to continuous failures. Circuit breaker is engaged to protect the system. Please wait a moment before trying again."
|
||||
return "大模型因连续多次调用失败已被熔断保护,请稍候再试。"
|
||||
|
||||
def _build_user_message(self, exc: BaseException, reason: str) -> str:
|
||||
detail = _extract_error_detail(exc)
|
||||
if reason == "quota":
|
||||
return "The configured LLM provider rejected the request because the account is out of quota, billing is unavailable, or usage is restricted. Please fix the provider account and try again."
|
||||
return "大模型因账户额度不足、账单异常或使用受限而拒绝请求,请检查模型账户后再试。"
|
||||
if reason == "auth":
|
||||
return "The configured LLM provider rejected the request because authentication or access is invalid. Please check the provider credentials and try again."
|
||||
return "大模型因鉴权失败或无访问权限而拒绝请求,请检查模型的 API Key 与权限配置后再试。"
|
||||
if reason in {"busy", "transient"}:
|
||||
return "The configured LLM provider is temporarily unavailable after multiple retries. Please wait a moment and continue the conversation."
|
||||
return f"LLM request failed: {detail}"
|
||||
return "大模型因服务繁忙或网络异常,多次重试后仍未恢复,请稍候再继续。"
|
||||
return f"大模型因「{detail}」原因调用失败。"
|
||||
|
||||
def _emit_retry_event(self, attempt: int, wait_ms: int, reason: str) -> None:
|
||||
try:
|
||||
|
||||
+1
-1
@@ -713,7 +713,7 @@ class ScheduledTaskService:
|
||||
retry_count: int = 0,
|
||||
) -> None:
|
||||
"""Mark a run failed and reflect the outcome on the parent task."""
|
||||
result = _build_result(task, scheduled_for=scheduled_for, content=f"Scheduled task failed: {error}")
|
||||
result = _build_result(task, scheduled_for=scheduled_for, content=f"定时任务执行失败:{error}")
|
||||
await self.store.update_run(
|
||||
run_id,
|
||||
{"status": "failed", "finished_at": datetime.now(UTC), "error": error, "result": result, "retry_count": retry_count},
|
||||
|
||||
+20
-7
@@ -36,18 +36,31 @@ def ask_clarification_tool(
|
||||
- You're about to perform a potentially dangerous operation
|
||||
- You have a recommendation but need user approval
|
||||
|
||||
Batching multiple independent questions:
|
||||
- **You CAN and SHOULD call ask_clarification multiple times in the same turn** when the user's
|
||||
request leaves several **independent** aspects unclear (e.g. project type AND tech stack AND
|
||||
deployment target). Emit one tool call per aspect — do NOT cram several unrelated questions
|
||||
into one `question` string.
|
||||
- The frontend automatically groups all clarification cards in one turn into a single submission,
|
||||
so the user answers them together in one reply. You will then receive one combined user message
|
||||
addressing every question in order.
|
||||
- When the questions DEPEND on each other (the second only makes sense after the first is answered),
|
||||
ask only the first one and wait for the reply before asking the next.
|
||||
|
||||
Best practices:
|
||||
- Ask ONE clarification at a time for clarity
|
||||
- Be specific and clear in your question
|
||||
- Don't make assumptions when clarification is needed
|
||||
- For risky operations, ALWAYS ask for confirmation
|
||||
- After calling this tool, execution will be interrupted automatically
|
||||
- One question per ask_clarification call — keep each `question` focused on a single decision.
|
||||
- Be specific and clear in your question.
|
||||
- Provide `options` (with concise labels) whenever there is a discrete set of reasonable choices —
|
||||
this lets the user multi-select in the UI instead of typing free text.
|
||||
- Don't make assumptions when clarification is needed.
|
||||
- For risky operations, ALWAYS ask for confirmation.
|
||||
- After calling this tool (or several in one turn), execution will be interrupted automatically.
|
||||
|
||||
Args:
|
||||
question: The clarification question to ask the user. Be specific and clear.
|
||||
question: The clarification question to ask the user. Focused on a single decision; be specific and clear.
|
||||
clarification_type: The type of clarification needed (missing_info, ambiguous_requirement, approach_choice, risk_confirmation, suggestion).
|
||||
context: Optional context explaining why clarification is needed. Helps the user understand the situation.
|
||||
options: Optional list of choices (for approach_choice or suggestion types). Present clear options for the user to choose from.
|
||||
options: Optional list of choices (for approach_choice or suggestion types). Present clear options for the user to choose from; the UI supports multi-select.
|
||||
"""
|
||||
# This is a placeholder implementation
|
||||
# The actual logic is handled by ClarificationMiddleware which intercepts this tool call
|
||||
|
||||
Reference in new issue
Block a user