通过定时轮询自动化长时间运行的异步任务的最佳实践。适用于监控后台 CLI 命令或 API 调...
投票最佳做法是一项面向实际任务的技能,主要用于一种指导式技能,用于使长期运行自动化, 使用与计算兼容的投票模式同步完成;当任务无法同步完成时( 例如, CLI c)。
从功能定位来看,该技能强调把分散的操作要求整理成清晰、可复用的处理流程,使用户能够围绕既定目标快速准备输入、选择执行方式并获得结构化结果。实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;
若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。
一种以指导风格设计的技能,用于通过 兼容 cron 的轮询模式 自动化长期运行、异步执行的任务。当某项任务无法同步完成时(例如:一个触发后台作业并返回作业 ID 的 CLI 命令),该技能将引导智能体完成以下步骤:(1) 判断轮询是否适用;(2) 与用户进行一次性预检确认;(3) 创建任务专属目录;(4) 编写轮询脚本;(5) 启动后台作业;(6) 持续监控直至完成或超时。
语言要求:所有面向用户的确认信息均须使用用户当前会话所用语言(请检查会话语言 — 若用户使用中文交流,则以中文回复;若为英文,则以英文回复)。
开始前,智能体必须回答以下问题:
若任务不适用于轮询,请告知用户,并建议替代方案(例如:同步执行、仅对最终等待阶段使用子智能体配合轮询等)。
启动任何轮询任务前,必须以单条消息向用户确认全部参数。此举可避免来回沟通,并明确各方预期。
确认信息须使用用户当前会话语言。
示例(英文):
Before starting, please confirm the following: ① Polling target - Task: [brief description] - Command to check status: [exact command] - Expected completion condition: [e.g., output contains "status: completed"] ② Poll interval: every [X] minutes (default: 5 minutes) ③ Max duration: up to [Y] polls = [Z] minutes max (default: 40 min / 8 polls) ④ On completion: [download file / run command / send message / do nothing] ⑤ On failure/timeout: [notify me / stay silent] ⑥ Output directory: [path] (default: ~/Downloads or relevant workspace folder) ⑦ Temp folder retention: keep for review after completion? [yes / no] Reply with any changes, or "ok" to proceed with defaults.
示例(中文 — 结构相同,内容翻译):
启动前请确认以下参数: ① 轮询对象 - 任务:[简短描述] - 状态查询命令:[具体命令] - 成功判定条件:[例如输出包含 "status": "completed"] ② 轮询频率:每 [X] 分钟一次(默认:5 分钟) ③ 最长持续时间:最多 [Y] 次轮询 = [Z] 分钟(默认:40 分钟 / 8 次) ④ 完成后动作:[下载文件 / 运行命令 / 发消息 / 不做处理] ⑤ 失败/超时时:[通知我 / 不通知] ⑥ 产物保存位置:[路径](默认:~/Downloads 或相关工作目录) ⑦ 临时文件夹保留:完成后保留供复查?[是 / 否] 直接回复修改项,或"确认"以默认参数启动。
未获用户确认前,不得启动轮询。 若用户在合理时间内未响应,请仅跟进一次。
每个轮询任务均拥有独立的临时目录。这使任务具备自包含性、可恢复性,也便于后续检查或清理。
/tmp// ← category:例如 notebooklm、deep-research、generic _ / ← 按时间戳命名的单任务目录 task.json ← 任务元数据及全部参数 progress.json ← 当前轮询状态(轮询次数、上次检查时间、各类句柄) poll.log ← 每次轮询尝试的日志(时间戳 + 结果) error.log ← 遇到的错误 done.flag ← 空文件,任务成功完成后创建
命名规则:
notebooklm-audio、deep-research、generic-async)YYMMDD-HHmm + _ + 清洗后的任务名(空格→连字符,最长 40 字符,剔除特殊字符)若分类目录尚不存在,则创建之;若任务子目录已存在(例如此前已有尝试),则询问用户:“继续之前任务,还是重新开始?”
task.json 格式定义{
"category": "notebooklm-audio",
"task_name": "example-notebook-audio",
"poll_command": "nlm studio status ",
"parse_rule": {
"type": "json",
"path": ".[0].status",
"success_value": "completed",
"failure_value": "failed"
},
"on_complete_command": "nlm download audio --id -o ",
"verify_output": true,
"poll_interval_seconds": 300,
"max_polls": 8,
"timeout_action": "notify",
"failure_action": "notify",
"output_path": "/path/to/output.m4a",
"temp_dir": "/tmp/notebooklm-audio/260325-1400_example-audio",
"created_at": "2026-03-25T22:00:00Z",
"user_confirmed": true
}
progress.json 格式定义{
"poll_count": 3,
"last_poll_at": "2026-03-25T22:15:00Z",
"last_poll_result": "in_progress",
"artifact_id": "abc123...",
"current_handle": "..."
}
将脚本写入任务临时目录()。脚本必须 完全自包含 —— 除标准 Unix 工具外,不得依赖任何外部组件。
必需特性:
set -euo pipefaildone.flag —— 若已存在,则立即以 0 退出(任务已完成)error.log 并在退出前保存当前进度progress.jsonpoll.log(含时间戳 + 截断后的输出)脚本模板(最小可用版):
#!/bin/bash
set -euo pipefail
TASK_DIR="/tmp/category/YYMMDD-HHmm_taskname"
cd "$TASK_DIR"
# Check if already done
[[ -f done.flag ]] && echo "Already complete." && exit 0
# Load progress
POLL_COUNT=$(grep '"poll_count"' progress.json 2>/dev/null | sed 's/[^0-9]//g') || POLL_COUNT=0
MAX_POLLS=8
INTERVAL=300
while true; do
POLL_COUNT=$((POLL_COUNT + 1))
if [[ $POLL_COUNT -gt $MAX_POLLS ]]; then
echo "[$(date)] TIMEOUT after $MAX_POLLS polls" >> error.log
exit 1
fi
echo "[$(date)] Poll $POLL_COUNT/$MAX_POLLS" >> poll.log
# Run the poll command
RESULT=$( 2>&1) || true
echo "$RESULT" >> poll.log
# Parse result — adapt to your command's output format
if echo "$RESULT" | grep -q '"status": "completed"'; then
touch done.flag
# Run on-complete command if set
echo "Done." >> poll.log
exit 0
fi
# Save progress
sed -i "s/"poll_count": [0-9]*/"poll_count": $POLL_COUNT/" progress.json
sleep "$INTERVAL"
done
nlm audio create ),以启动后台任务并捕获其 ID/句柄。progress.json 和 task.json。# In the task's temp dir: nohup bash poll.sh > /dev/null 2>&1 & echo "Polling started in background (PID: $!)"
轮询脚本应独立于 OpenClaw 会话长期存活。 智能体无需保持活跃即可维持轮询运行。
done.flag 或 poll.log 来回应,无需发起新的轮询。progress.json 判断当前进展。| 情形 | 操作 |
|---|---|
| 达到最大轮询次数(超时) | 记录至 error.log;若配置 timeout_action: notify 则通知用户;不得删除临时目录 |
| 认证过期 | 记录至 error.log;通知用户重新认证后退出 |
| 下载/生成失败 | 记录至 error.log;通知用户后退出 |
| 临时目录已存在(重复启动) | 询问用户:继续还是重启 |
超时/失败后:禁止自动重试。应明确告知用户任务未完成,并提供如下选项:
[[ -s "$output_path" ]])done.flagoutput_path 且用户确认了目标路径,则将文件移动或复制至该位置通知语言:使用用户当前会话语言。
若某类任务频繁执行(例如 NotebookLM 音频生成、Gemini Deep Research 状态检查),可将轮询逻辑提取为 可复用的脚本模板,存于分类目录层级:
/tmp/notebooklm-audio/ poll-template.sh ← 此分类专用的可复用模板 /260325-1400_task1/ ← 各个任务目录基于该模板生成 /260326-0915_task2/
各任务目录下的 poll.sh 可直接复制模板,或基于模板生成,从而保证任务目录本身尽可能精简。
启动轮询任务前,请确认全部满足以下条件:
task.json 与 progress.json 内容正确poll.sh 并通过语法校验(bash -n)nohup 启动后台进程相关专题
热门下载
相关下载
精品课程
共6课时 | 54.7万人学习
共89课时 | 134.1万人学习
共49课时 | 82.6万人学习
最新文章