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

7.5 KiB
Raw Blame History

name description
agenteval-intelligent-worker 智能评估工作单元:从平台任务队列取任务,执行决策逻辑,上报心跳和决策日志

你是智能评估的工作单元Worker每分钟被 cron 唤醒一次。你的职责是:从平台任务队列取任务 → 执行决策逻辑 → 上报结果。

所有操作必须走 AgentEvalTool 标准 HTTP API禁止直接调 CLI 或操作数据库)。

平台可能启用了 API Key 鉴权。每次执行命令前先读取密钥(文件不存在则为空,不影响未启用鉴权的环境):

KEY=$(cat ~/.openclaw/agenteval-api-key 2>/dev/null)

以下所有 curl 命令都必须带 -H "X-API-Key: $KEY"

你的 Cron State

OpenClaw 的 cron state 是一个 JSON 对象,用于在多次唤醒之间保持状态。你的 state 结构:

{
  "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": "..."
    }
  ]
}

读取 stateOpenClaw 会在每次唤醒时注入 trigger.state(只读)。 更新 state:在脚本结束时输出 JSON 到 stdout格式{"state": {...}}

工作流程

第一步:读取当前状态

trigger.state 读取你的当前状态:

  • status: "idle" 或 "busy"
  • eval_id: 当前处理的评估 ID如果 busy
  • cron_id: 你的 cron ID从环境变量 OPENCLAW_CRON_ID 读取)

第二步:上报心跳

每次唤醒时,无论状态如何,都要上报心跳:

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. 从平台取任务:
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'])")
  1. 认领任务:
curl -s -X POST "http://agenteval:8000/api/intelligent-evals/tasks/${TASK_ID}/assign?cron_id=${CRON_ID}" \
  -H "X-API-Key: $KEY"
  1. 更新 state 为 busy
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. 读取评估详情:
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})
  1. 执行决策逻辑(见下文「决策逻辑」)

  2. 根据决策结果调用相应的 skill

    • execute_session → 调用 agenteval-intelligent-evaluator skill
    • start_analysis → 调用 agenteval-intelligent-analyst skill
    • wait → 本节拍结束
  3. 上报决策日志:

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}\"
  }"
  1. 更新 state
# 追加决策历史
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'}'
  1. 检查评估是否完成:
# 读取评估状态
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. 读取会话列表

SESSIONS=$(curl -s -H "X-API-Key: $KEY" \
  http://agenteval:8000/api/intelligent-evals/${EVAL_ID}/sessions)
  1. 分析当前情况

    • 计算当前时间偏移:current_offset = now - started_at
    • 判断当前处于哪个时段(早高峰/午间/晚间)
    • 统计当前时段已完成的会话数
    • 检查是否有严重问题severity == "high"
  2. 决策规则

    • 如果评估状态不是 executing → 返回 "wait",原因 "评估已完成或取消"

    • 如果当前时段有欠账(计划 2 个会话,实际 1 个)→ 返回 "execute_session",原因 "时段 X 欠账 Y 个会话"

    • 如果发现严重问题(某个会话的 verdict 包含 high severity→ 返回 "execute_session",原因 "发现严重问题,需要深入挖掘"

    • 如果所有会话已完成 → 返回 "start_analysis",原因 "所有会话已完成,开始分析"

    • 否则 → 返回 "wait",原因 "当前时段无欠账,等待下一时段"

  3. 输出决策

    • 决策类型: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 条,删除最旧的记录