Agent 执行耗时任务时如何主动汇报进度?四种方案的实战选型

从后台进程到多 Agent 协作,为不同场景选择最合适的进度上报机制

你让 AI Agent 帮你跑一个需要 30 分钟的数据迁移脚本,然后就没了下文——它在干嘛?卡住了?还是已经跑完了?你不知道,因为 Agent 只会在任务彻底完成或彻底失败时才告诉你结果。

这是 Agent 系统中一个普遍的痛点:耗时任务的进度黑洞。用户发出指令后陷入等待,没有进度条,没有中间反馈,只有最终的成功或失败。在 OpenClaw 的实际使用中,我总结了四种适用于不同场景的进度上报方案,每种都有其最佳适用场景。

问题的本质

传统的"请求-响应"模式天然不适合耗时任务。Agent 收到指令后开始执行,整个过程中用户端是空白的。这带来几个实际问题:

  • 焦虑感:用户不确定任务是否还在正常运行
  • 失控感:无法判断是否需要介入或调整
  • 资源浪费:如果任务早已失败,用户可能白等了很久才知道

核心挑战在于:Agent 在执行过程中如何"抬头"汇报,而不打断手头的工作?

方案一:直接写代码 + 后台进程

适用场景:一次性短任务(< 10 分钟)

最简单直接的方案。Agent 编写一个执行脚本,将其放到后台运行,然后通过轮询或回调机制检查结果。

典型例子:批量压缩项目中的图片

你告诉 Agent:“把 static/images/ 下所有大于 500KB 的图片压缩到 500KB 以内。”

Agent 的执行策略:

#!/bin/bash
# compress-images.sh
# 批量压缩图片,将进度写入状态文件

IMAGES=$(find static/images/ -size +500k -name "*.png" -o -name "*.jpg")
TOTAL=$(echo "$IMAGES" | wc -l)
DONE=0

echo '{"status":"running","total":'$TOTAL',"done":0}' > /tmp/compress-status.json

for img in $IMAGES; do
  convert "$img" -quality 85 -resize '1920x1920>' "$img"
  DONE=$((DONE + 1))
  echo '{"status":"running","total":'$TOTAL',"done":'$DONE'}' > /tmp/compress-status.json
done

echo '{"status":"completed","total":'$TOTAL',"done":'$TOTAL'}' > /tmp/compress-status.json
# generated by hugo's coding agent

Agent 启动这个脚本后,可以每隔一段时间读取 /tmp/compress-status.json,向用户汇报:“已完成 23/47 张图片压缩”。

方案特点

维度评价
实现复杂度低——写个脚本就行
适用时长< 10 分钟
进度精度可以精确到每一步
容错性一般——进程挂了就没了
Agent 占用需要 Agent 保持在线轮询

局限:Agent 必须在整个过程中保持会话,不断轮询状态文件。如果任务超过 10 分钟,这种"Agent 干等着"的模式就显得浪费了。

方案二:状态文件 + Cron 检查

适用场景:长程复杂任务(10 分钟 ~ 数小时)

对于耗时更长的任务,让 Agent 全程盯着是不经济的。更好的方式是:任务自己跑,定时来检查

典型例子:全站 SEO 审计

你让 Agent 对博客所有文章做一次完整的 SEO 审计——检查每篇文章的标题长度、meta description、内链密度、图片 alt 文本、死链等。博客有 135 篇文章,每篇需要抓取和分析,整个过程可能需要 30-60 分钟。

Agent 的执行策略分为两步:

第一步:启动任务,写入初始状态

Agent 编写并启动审计脚本,脚本将进度持续写入状态文件:

import json, os, time
from pathlib import Path

STATUS_FILE = "/home/node/.openclaw/workspace/tasks/seo-audit-status.json"

def update_status(status, current=0, total=0, message="", results=None):
    data = {
        "task": "seo-audit",
        "status": status,
        "current": current,
        "total": total,
        "message": message,
        "updated_at": time.strftime("%Y-%m-%d %H:%M:%S"),
        "results_file": "/home/node/.openclaw/workspace/tasks/seo-audit-results.json"
    }
    if results:
        data["summary"] = results
    os.makedirs(os.path.dirname(STATUS_FILE), exist_ok=True)
    with open(STATUS_FILE, "w") as f:
        json.dump(data, f, indent=2)

posts = list(Path("content/post").rglob("*.md"))
update_status("running", 0, len(posts), "Starting SEO audit...")

for i, post in enumerate(posts):
    # ... 分析每篇文章的 SEO 指标 ...
    update_status("running", i + 1, len(posts), f"Analyzing {post.name}")

update_status("completed", len(posts), len(posts), "Audit complete", {
    "issues_found": 42,
    "critical": 3,
    "warnings": 15,
    "info": 24
})
# generated by hugo's coding agent

第二步:配置 Cron 定期检查

Agent 告诉 OpenClaw 每 5 分钟检查一次任务状态:

{
  "cron": {
    "seo-audit-check": {
      "schedule": "*/5 * * * *",
      "prompt": "读取 /home/node/.openclaw/workspace/tasks/seo-audit-status.json,如果任务还在运行,向用户汇报进度百分比和当前步骤。如果任务已完成,发送结果摘要并删除这个 cron 任务。如果状态文件超过 10 分钟没更新,告警任务可能已挂起。",
      "sessionTarget": "main"
    }
  }
}

用户会每隔几分钟收到这样的消息:

“SEO 审计进行中:67/135 篇文章已分析(49.6%),当前正在分析 108-compression-is-intelligence.md

任务完成后:

“SEO 审计已完成。共发现 42 个问题:3 个严重(死链)、15 个警告(标题过长)、24 个建议。详细报告已保存。需要我逐一修复吗?”

方案特点

维度评价
实现复杂度中等——需要状态文件协议 + Cron 配置
适用时长10 分钟 ~ 数小时
进度精度取决于 Cron 频率(通常 5-10 分钟)
容错性较好——状态文件可检测挂起
Agent 占用低——只在 Cron 触发时短暂占用

核心优势:任务和检查解耦。脚本只管跑,Agent 只管查。即使 Agent 会话中断,任务仍在执行;即使任务挂了,Cron 也能发现并告警。

方案三:多 Agent + 状态文件

适用场景:需要人工干预的长任务

有些任务不是一路跑到底的——中间可能需要人类做决策。比如遇到模棱两可的情况需要确认,或者某个步骤失败后需要人类选择恢复策略。这时需要一个 Agent 执行任务,另一个 Agent 与用户保持对话。

典型例子:服务器迁移

你要把一个 VPS 上的全部服务迁移到新机器。这个过程涉及:数据库备份和恢复、配置文件迁移、DNS 切换、服务启动和验证。每一步都可能遇到需要人类决策的情况。

架构如下:

┌─────────────┐     状态文件      ┌─────────────┐
│  main Agent │ ◄──────────────► │ coding Agent │
│  (对话交互)  │  migration-     │  (执行迁移)   │
│             │  status.json     │             │
└──────┬──────┘                  └──────┬──────┘
       │                                │
       ▼                                ▼
    用户通道                        远程服务器
  (DingTalk等)                  (SSH 执行命令)

coding Agent 负责执行迁移步骤,每完成一步或遇到问题时更新状态文件:

{
  "task": "server-migration",
  "status": "waiting_for_input",
  "phase": "database-restore",
  "completed_phases": ["backup", "config-sync"],
  "current_issue": {
    "type": "decision_required",
    "message": "目标数据库已存在同名表 user_sessions,包含 2,847 条记录。",
    "options": [
      "drop:删除旧表,用备份数据覆盖",
      "merge:合并两边数据(可能有主键冲突)",
      "rename:将旧表重命名为 user_sessions_bak,再恢复"
    ]
  },
  "updated_at": "2026-03-10T14:32:00+08:00"
}

main Agent 通过 Heartbeat 或 Cron 定期检查状态文件。当发现 waiting_for_input 状态时,立即将问题转发给用户:

“服务器迁移进行到数据库恢复阶段,需要你做一个决策:

目标数据库已存在 user_sessions 表(2,847 条记录)。选择处理方式:

  1. 删除旧表,用备份覆盖
  2. 合并数据(可能有主键冲突)
  3. 将旧表重命名为 _bak 后恢复”

用户回复"3"后,main Agent 将决策写入状态文件,coding Agent 读取后继续执行。

方案特点

维度评价
实现复杂度较高——需要双 Agent 协调 + 状态协议
适用时长数十分钟 ~ 数小时
人工介入原生支持,核心设计目标
容错性好——状态文件记录了完整的阶段信息,可断点恢复
Agent 占用分工明确——一个跑任务,一个保持对话

核心优势:执行和交互解耦。用户不需要等在终端前,Agent 遇到需要人类判断的节点会主动通知,用户回复后任务继续。这模拟了现实中"下属请示领导"的工作模式。

方案四:OpenClaw Cron + 状态文件

适用场景:周期性任务

有些任务不是一次性的,而是需要定期执行。比如每天检查 SSL 证书到期时间、每周生成流量报告、每月清理过期日志。这些任务本身可能很快(几秒到几分钟),但需要持续跟踪状态变化

典型例子:多域名 SSL 证书到期监控

你有多个域名,需要在证书到期前自动告警并续期:

#!/bin/bash
# check-ssl-certs.sh
# 检查 SSL 证书到期时间,结果写入状态文件

DOMAINS=("blog.hugozhu.site" "api.hugozhu.site" "git.hugozhu.site")
STATUS_FILE="/home/node/.openclaw/workspace/tasks/ssl-check-status.json"
RESULTS="["

for domain in "${DOMAINS[@]}"; do
  EXPIRY=$(echo | openssl s_client -servername "$domain" -connect "$domain":443 2>/dev/null \
    | openssl x509 -noout -enddate 2>/dev/null \
    | cut -d= -f2)

  EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s 2>/dev/null)
  NOW_EPOCH=$(date +%s)
  DAYS_LEFT=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 ))

  RESULTS+='{"domain":"'$domain'","expiry":"'$EXPIRY'","days_left":'$DAYS_LEFT'},'
done

RESULTS="${RESULTS%,}]"

cat > "$STATUS_FILE" <<STATUSEOF
{
  "task": "ssl-cert-check",
  "status": "completed",
  "checked_at": "$(date -Iseconds)",
  "certificates": $RESULTS
}
STATUSEOF
# generated by hugo's coding agent

OpenClaw Cron 配置:

{
  "cron": {
    "ssl-cert-monitor": {
      "schedule": "0 9 * * *",
      "prompt": "执行 /home/node/.openclaw/workspace/cron/check-ssl-certs.sh,然后读取状态文件。如果任何域名的证书在 30 天内到期,告警用户并建议续期。如果在 7 天内到期,标记为紧急。如果所有证书都正常,回复 HEARTBEAT_OK。",
      "sessionTarget": "isolated"
    }
  }
}

平时用户不会收到任何消息(HEARTBEAT_OK 被静默丢弃)。只有当某个证书即将到期时,用户才会收到通知:

“SSL 证书告警:

  • api.hugozhu.site 证书将在 12 天 后到期(2026-03-22),建议立即续期
  • blog.hugozhu.sitegit.hugozhu.site 证书正常(剩余 247 天)

需要我自动执行 certbot 续期吗?”

方案特点

维度评价
实现复杂度低——脚本 + Cron 配置
执行频率分钟级到天级
进度概念不是"进度"而是"状态变化"
容错性好——每次独立运行,上次失败不影响下次
Agent 占用极低——隔离会话中短暂运行

核心优势:完全自动化的"哨兵"模式。没问题时用户无感知,有问题时立即告警。结合 OpenClaw 的投递通道机制,告警可以精确送达正确的通道和设备。

四种方案的选型指南

维度方案一:后台进程方案二:Cron 检查方案三:多 Agent方案四:周期 Cron
任务类型一次性短任务一次性长任务需人工介入周期性任务
典型时长< 10 分钟10 分 ~ 数小时不确定持续运行
实现复杂度较高
进度汇报方式Agent 轮询Cron 定期读状态文件Agent 间状态协调状态变化时告警
人工介入支持不支持有限原生支持不需要
典型场景图片压缩、代码格式化SEO 审计、数据迁移服务器迁移、复杂部署证书监控、日志清理

决策流程很简单:

任务是否需要定期执行?
  ├─ 是 → 方案四:Cron + 状态文件
  └─ 否 → 任务预计耗时?
              ├─ < 10 分钟 → 方案一:后台进程
              └─ > 10 分钟 → 是否需要人工介入?
                                ├─ 是 → 方案三:多 Agent
                                └─ 否 → 方案二:Cron 检查

更好的方案?状态文件协议的标准化

以上四种方案有一个共同的核心组件:状态文件。它是任务进程和 Agent 之间的"通信协议"。如果我们把状态文件的格式标准化,就可以构建一个统一的任务监控层。

我正在考虑在 OpenClaw 中引入一个标准化的任务状态协议:

{
  "$schema": "openclaw-task-status-v1",
  "task_id": "seo-audit-2026-03-10",
  "task_type": "one-shot",
  "status": "running | waiting_for_input | completed | failed",
  "progress": {
    "current": 67,
    "total": 135,
    "percentage": 49.6,
    "eta_seconds": 1200
  },
  "message": "当前步骤的人类可读描述",
  "requires_input": null,
  "history": [
    {"at": "2026-03-10T14:00:00Z", "event": "started"},
    {"at": "2026-03-10T14:15:00Z", "event": "phase_completed", "phase": "crawl"}
  ],
  "updated_at": "2026-03-10T14:32:00Z"
}

有了统一的协议,Gateway 层可以提供通用的任务仪表盘——一个地方看到所有正在运行的任务、它们的进度、是否需要人工介入。Agent 不需要写自定义的状态检查逻辑,只需要读取标准格式的文件即可。

这也为未来的任务编排打下基础:一个任务完成后自动触发下一个任务,形成 Pipeline。但这是后话了。

结论

Agent 执行耗时任务时的进度上报,本质上是一个异步通信问题。四种方案对应四种异步模式:

  • 方案一是最原始的轮询——简单但浪费资源
  • 方案二是定时采样——平衡了开销和实时性
  • 方案三是事件驱动 + 人类参与——处理不确定性的最佳选择
  • 方案四是哨兵模式——适合"没有消息就是好消息"的场景

选择哪种方案,取决于两个核心变量:任务的持续时间是否需要人工介入。在实际使用中,这四种方案往往会组合使用——比如一个复杂的部署任务可能同时用到方案二(长流程进度追踪)和方案三(关键节点人工确认)。

最终的目标是让用户对 Agent 的工作有恰到好处的可见性:不是事无巨细地播报每一步,也不是完全黑盒地等到最后——而是在对的时间,告诉你对的信息。


See also