AgentEvalTool/backend/plugins/openclaw/skills/agenteval-intelligent-worker/SKILL.md
sinohqb 30b9cac224 feat(intelligent-eval): implement worker skill and APIs (ticket 03)
- Create agenteval-intelligent-worker SKILL.md with decision logic
- Implement heartbeat API (POST /api/openclaw/crons/{id}/heartbeat)
- Implement decision log API (POST /api/intelligent-evals/{id}/decision-logs)
- Skill includes idle/busy state management and cron state handling
- Deployment script already syncs skills automatically
- Add 6 integration tests

All 784 tests passing.
2026-08-12 10:01:56 +08:00

246 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: agenteval-intelligent-worker
description: 智能评估工作单元:从平台任务队列取任务,执行决策逻辑,上报心跳和决策日志
---
你是智能评估的工作单元Worker每分钟被 cron 唤醒一次。你的职责是:从平台任务队列取任务 → 执行决策逻辑 → 上报结果。
所有操作必须走 AgentEvalTool 标准 HTTP API禁止直接调 CLI 或操作数据库)。
平台可能启用了 API Key 鉴权。每次执行命令前先读取密钥(文件不存在则为空,不影响未启用鉴权的环境):
```bash
KEY=$(cat ~/.openclaw/agenteval-api-key 2>/dev/null)
```
以下所有 curl 命令都必须带 `-H "X-API-Key: $KEY"`
## 你的 Cron State
OpenClaw 的 cron state 是一个 JSON 对象,用于在多次唤醒之间保持状态。你的 state 结构:
```json
{
"status": "idle | busy",
"eval_id": "uuid | null",
"started_at": "ISO8601 | null",
"last_decision_at": "ISO8601",
"completed_sessions": 0,
"decisions_history": [
{
"timestamp": "ISO8601",
"decision": "execute_session | wait | start_analysis",
"reason": "..."
}
]
}
```
**读取 state**OpenClaw 会在每次唤醒时注入 `trigger.state`(只读)。
**更新 state**:在脚本结束时输出 JSON 到 stdout格式`{"state": {...}}`。
## 工作流程
### 第一步:读取当前状态
`trigger.state` 读取你的当前状态:
- `status`: "idle" 或 "busy"
- `eval_id`: 当前处理的评估 ID如果 busy
- `cron_id`: 你的 cron ID从环境变量 `OPENCLAW_CRON_ID` 读取)
### 第二步:上报心跳
每次唤醒时,无论状态如何,都要上报心跳:
```bash
CRON_ID="${OPENCLAW_CRON_ID}"
curl -s -X POST "http://agenteval:8000/api/openclaw/crons/${CRON_ID}/heartbeat" \
-H "X-API-Key: $KEY" \
-H "Content-Type: application/json" \
-d "{
\"status\": \"${STATUS}\",
\"current_eval_id\": \"${EVAL_ID}\"
}"
```
### 第三步:根据状态执行
#### 如果 status == "idle"
1. 从平台取任务:
```bash
TASK_RESPONSE=$(curl -s -H "X-API-Key: $KEY" \
http://agenteval:8000/api/intelligent-evals/tasks/next)
TASK=$(echo "$TASK_RESPONSE" | python3 -c "import sys, json; print(json.dumps(json.load(sys.stdin).get('task')))")
if [ "$TASK" == "null" ]; then
# 无任务,本节拍结束
echo '{"state": {"status": "idle", "last_decision_at": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}}'
exit 0
fi
TASK_ID=$(echo "$TASK" | python3 -c "import sys, json; print(json.load(sys.stdin)['id'])")
EVAL_ID=$(echo "$TASK" | python3 -c "import sys, json; print(json.load(sys.stdin)['eval_id'])")
```
2. 认领任务:
```bash
curl -s -X POST "http://agenteval:8000/api/intelligent-evals/tasks/${TASK_ID}/assign?cron_id=${CRON_ID}" \
-H "X-API-Key: $KEY"
```
3. 更新 state 为 busy
```bash
echo '{
"state": {
"status": "busy",
"eval_id": "'${EVAL_ID}'",
"task_id": "'${TASK_ID}'",
"started_at": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'",
"last_decision_at": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'",
"completed_sessions": 0,
"decisions_history": []
}
}'
```
#### 如果 status == "busy"
1. 读取评估详情:
```bash
EVAL_ID=$(echo "$TRIGGER_STATE" | python3 -c "import sys, json; print(json.load(sys.stdin)['eval_id'])")
EVAL=$(curl -s -H "X-API-Key: $KEY" \
http://agenteval:8000/api/intelligent-evals/${EVAL_ID})
```
2. 执行决策逻辑(见下文「决策逻辑」)
3. 根据决策结果调用相应的 skill
- `execute_session` → 调用 `agenteval-intelligent-evaluator` skill
- `start_analysis` → 调用 `agenteval-intelligent-analyst` skill
- `wait` → 本节拍结束
4. 上报决策日志:
```bash
curl -s -X POST "http://agenteval:8000/api/intelligent-evals/${EVAL_ID}/decision-logs" \
-H "X-API-Key: $KEY" \
-H "Content-Type: application/json" \
-d "{
\"decision_type\": \"${DECISION}\",
\"reason\": \"${REASON}\",
\"context\": ${CONTEXT},
\"cron_id\": \"${CRON_ID}\"
}"
```
5. 更新 state
```bash
# 追加决策历史
NEW_HISTORY=$(echo "$TRIGGER_STATE" | python3 -c "
import sys, json
state = json.load(sys.stdin)
state['decisions_history'].append({
'timestamp': '$(date -u +%Y-%m-%dT%H:%M:%SZ)',
'decision': '${DECISION}',
'reason': '${REASON}'
})
state['last_decision_at'] = '$(date -u +%Y-%m-%dT%H:%M:%SZ)'
print(json.dumps(state))
")
echo '{"state": '$NEW_HISTORY'}'
```
6. 检查评估是否完成:
```bash
# 读取评估状态
EVAL_STATUS=$(echo "$EVAL" | python3 -c "import sys, json; print(json.load(sys.stdin)['status'])")
if [ "$EVAL_STATUS" == "completed" ] || [ "$EVAL_STATUS" == "failed" ] || [ "$EVAL_STATUS" == "cancelled" ]; then
# 评估已完成,标记任务完成
TASK_ID=$(echo "$TRIGGER_STATE" | python3 -c "import sys, json; print(json.load(sys.stdin)['task_id'])")
curl -s -X POST "http://agenteval:8000/api/intelligent-evals/tasks/${TASK_ID}/complete?success=true" \
-H "X-API-Key: $KEY"
# 归还 cron更新 state 为 idle
echo '{
"state": {
"status": "idle",
"eval_id": null,
"task_id": null,
"last_decision_at": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"
}
}'
fi
```
## 决策逻辑
你需要根据当前评估的状态,自主决定"现在该做什么"。决策依据:
1. **读取评估详情**
- `status`: 评估状态executing / completed / failed / cancelled
- `plan.time_distribution`: 时间分布计划
- `started_at`: 评估开始时间
2. **读取会话列表**
```bash
SESSIONS=$(curl -s -H "X-API-Key: $KEY" \
http://agenteval:8000/api/intelligent-evals/${EVAL_ID}/sessions)
```
3. **分析当前情况**
- 计算当前时间偏移:`current_offset = now - started_at`
- 判断当前处于哪个时段(早高峰/午间/晚间)
- 统计当前时段已完成的会话数
- 检查是否有严重问题severity == "high"
4. **决策规则**
- **如果评估状态不是 executing** → 返回 "wait",原因 "评估已完成或取消"
- **如果当前时段有欠账**(计划 2 个会话,实际 1 个)→ 返回 "execute_session",原因 "时段 X 欠账 Y 个会话"
- **如果发现严重问题**(某个会话的 verdict 包含 high severity→ 返回 "execute_session",原因 "发现严重问题,需要深入挖掘"
- **如果所有会话已完成** → 返回 "start_analysis",原因 "所有会话已完成,开始分析"
- **否则** → 返回 "wait",原因 "当前时段无欠账,等待下一时段"
5. **输出决策**
- 决策类型:`execute_session` / `wait` / `start_analysis`
- 决策原因:一句话说明为什么做这个决策
- 决策上下文JSON 对象,包含当前时段、已完成会话数、欠账数等
## 错误处理
- 如果 API 调用失败网络错误、404、500 等),记录错误到 decisions_history但不改变 state
- 如果连续 3 次 API 调用失败,将 state 的 status 改为 "idle",放弃当前任务
- 如果评估状态为 "cancelled",立即标记任务完成,归还 cron
## 调试
- 所有 API 调用的响应都应该记录到 decisions_history
- 使用 `echo` 输出调试信息到 stderr不会影响 state
- 可以在 state 中添加自定义字段(如 `debug_info`)用于调试
## 注意事项
- 请将 <eval_id><session_id> 等占位符替换为实际值
- 所有时间戳使用 ISO 8601 格式UTC
- State 大小限制为 16KB注意不要存储过多历史记录最多保留最近 50 条决策)
- 如果 decisions_history 超过 50 条,删除最旧的记录