Task Watcher Skill
by @lanyasheng
Monitor async tasks by polling their state and send Discord/Telegram notifications on changes or completion for workflows like CI/CD, deployments, or reviews.
clawhub install task-watcherπ About This Skill
task-watcher β Async Task Monitoring & Callback
> Version: 1.2.0
> Author: sly (OpenClaw)
> License: MIT
> Install: clawhub install task-watcher
Monitor long-running async tasks (content review, CI/CD, deployments) and get Discord/Telegram notifications when states change.
What It Does
Register tasks β Watcher polls for state changes β Sends notifications on change/completion.
Perfect for:
Architecture
Agent registers task β tasks.jsonl (shared-context)
β
Cron (*/3 * * * *) β watcher.py β Adapter checks state β state changed?
β Yes
Policy decides β Notifier sends Discord
Plugin architecture:
openclaw agent --deliver), Telegram, Session, Fileexpires_at timeout (default 6h), 3x delivery failure escalationQuick Start
1. Install
clawhub install task-watcher
2. Register a monitoring task
import sys, os
sys.path.insert(0, os.path.expanduser("~/.openclaw/workspace/skills/task-watcher/scripts/lib"))from models import CallbackTask
from stores import JsonlTaskStore
store = JsonlTaskStore("~/.openclaw/shared-context/monitor-tasks/tasks.jsonl")
task = CallbackTask(
task_id="tsk_my_task_001",
owner_agent="content",
target_system="xiaohongshu",
target_object_id="note_id_here",
reply_channel="discord",
reply_to="channel:YOUR_CHANNEL_ID",
current_state="submitted",
expires_at="2026-03-08T12:00:00", # 6h timeout recommended
)
store.create(task)
Or via CLI:
cd ~/.openclaw/workspace/skills/task-watcher
python3 scripts/register_task.py \
--task-id tsk_my_001 \
--system xiaohongshu \
--object-id note_abc123 \
--reply-to channel:1234567890 \
--expires-hours 6
3. Run watcher (cron)
# Add to crontab - every 3 minutes
*/3 * * * * cd ~/.openclaw/workspace/skills/task-watcher && \
python3 scripts/watcher.py --once >> ~/.openclaw/logs/watcher.log 2>&1
4. Custom adapter
from adapters import StateAdapter, StateResultclass MyAdapter(StateAdapter):
@property
def name(self): return "my-system"
def supports(self, task): return task.target_system == "my-system"
def health_check(self): return True
def check(self, task):
status = check_my_system(task.target_object_id)
return StateResult(state=status, terminal=(status == "done"))
File Structure
task-watcher/
βββ SKILL.md # This file
βββ _meta.json # ClawHub metadata
βββ scripts/
β βββ watcher.py # Cron entry point
β βββ register_task.py # CLI task registration
β βββ lib/
β βββ __init__.py # Package exports
β βββ models.py # Data models (CallbackTask, StateResult, SendResult)
β βββ stores.py # JSONL TaskStore with file locking
β βββ adapters.py # State adapters (XHS, GitHub, Cron)
β βββ notifiers.py # Discord/Telegram/File notifiers
β βββ policies.py # Notification policies
β βββ bus.py # WatcherBus orchestrator
βββ tests/
βββ test_models.py
βββ test_stores.py
βββ test_adapters.py
βββ test_notifiers.py
βββ test_policies.py
βββ test_bus.py
Data Paths
| File | Purpose |
|------|---------|
| ~/.openclaw/shared-context/monitor-tasks/tasks.jsonl | Active tasks |
| ~/.openclaw/shared-context/monitor-tasks/audit.log | Audit trail |
| ~/.openclaw/shared-context/monitor-tasks/notifications/ | Notification files |
Built-in Adapters
| Adapter | System | How It Checks |
|---------|--------|---------------|
| xiaohongshu-note-review | XHS content review | Mock file / packet file |
| github-pr-status | GitHub PR merge | Skeleton (extend for your use) |
| cron-job-completion | Cron job tracking | File-based status check |
Requirements
openclaw agent --deliver)π‘ Examples
1. Install
clawhub install task-watcher
2. Register a monitoring task
import sys, os
sys.path.insert(0, os.path.expanduser("~/.openclaw/workspace/skills/task-watcher/scripts/lib"))from models import CallbackTask
from stores import JsonlTaskStore
store = JsonlTaskStore("~/.openclaw/shared-context/monitor-tasks/tasks.jsonl")
task = CallbackTask(
task_id="tsk_my_task_001",
owner_agent="content",
target_system="xiaohongshu",
target_object_id="note_id_here",
reply_channel="discord",
reply_to="channel:YOUR_CHANNEL_ID",
current_state="submitted",
expires_at="2026-03-08T12:00:00", # 6h timeout recommended
)
store.create(task)
Or via CLI:
cd ~/.openclaw/workspace/skills/task-watcher
python3 scripts/register_task.py \
--task-id tsk_my_001 \
--system xiaohongshu \
--object-id note_abc123 \
--reply-to channel:1234567890 \
--expires-hours 6
3. Run watcher (cron)
# Add to crontab - every 3 minutes
*/3 * * * * cd ~/.openclaw/workspace/skills/task-watcher && \
python3 scripts/watcher.py --once >> ~/.openclaw/logs/watcher.log 2>&1
4. Custom adapter
from adapters import StateAdapter, StateResultclass MyAdapter(StateAdapter):
@property
def name(self): return "my-system"
def supports(self, task): return task.target_system == "my-system"
def health_check(self): return True
def check(self, task):
status = check_my_system(task.target_object_id)
return StateResult(state=status, terminal=(status == "done"))