Completion of a long AI agent task
Modern AI-coding flow is “we go get coffee while the agent explores options.” Claude Code, Codex CLI, Cline, Aider, OpenAI Agents SDK, LangGraph-runner — they can all run for minutes or hours. Returning to the terminal every 30 seconds is not an option.
Let’s wrap any such run in a small wrapper that sends a push to Notifly on completion (or on error).
Universal wrapper agent-run
Section titled “Universal wrapper agent-run”#!/usr/bin/env bashset -uset -a; source ~/.notifly.env; set +a
CMD="$*"START=$(date +%s)HOST=$(hostname -s)LOG=$(mktemp)
if "$@" 2>&1 | tee "$LOG"; then RC=0else RC=$?fiDUR=$(( $(date +%s) - START ))
# try to extract the "final answer" from the last lines to include in the messageTAIL=$(tail -c 1200 "$LOG")LINES=$(wc -l < "$LOG")
if [[ $RC -eq 0 ]]; then TITLE="🤖✅ ${CMD:0:60}" PRIO=5else TITLE="🤖❌ ${CMD:0:60} (rc=$RC)" PRIO=9fi
curl -fsS "$NOTIFLY_URL/message?token=$NOTIFLY_TOKEN" \ -H "Content-Type: application/json" \ -d "$(jq -n --arg t "$TITLE" --arg m "Длительность: ${DUR}sХост: $HOSTСтрок лога: $LINES
Конец вывода:$TAIL" --argjson p $PRIO '{title:$t, message:$m, priority:$p}')" >/dev/null
rm -f "$LOG"exit $RCUsage:
agent-run claude --print "Перепиши auth-service на async и почини тесты"agent-run aider --yes "fix flaky tests in tests/integration/"agent-run codex exec "rebase feature branch onto main, resolve conflicts"Python decorator for your agent
Section titled “Python decorator for your agent”If you’re writing a custom agent on LangGraph / Agents SDK / your own loop:
import os, time, traceback, functools, requests
def notify_when_done(name=None, priority_ok=5, priority_fail=9): def deco(fn): @functools.wraps(fn) def wrap(*args, **kwargs): label = name or fn.__name__ t0 = time.time() try: result = fn(*args, **kwargs) _push(f"🤖✅ {label}", f"OK за {int(time.time()-t0)}s\n\n{_summary(result)}", priority_ok) return result except Exception: _push(f"🤖❌ {label}", f"FAIL за {int(time.time()-t0)}s\n\n{traceback.format_exc()[-1500:]}", priority_fail) raise return wrap return deco
def _summary(result): if isinstance(result, dict): steps = result.get("steps") or result.get("tool_calls") or [] return f"Итераций: {len(steps)}\nИтог: {str(result.get('output',''))[:600]}" return str(result)[:1000]
def _push(title, msg, prio): requests.post(f"{os.environ['NOTIFLY_URL']}/message", params={"token": os.environ["NOTIFLY_TOKEN"]}, json={"title": title, "message": msg, "priority": prio}, timeout=5)
@notify_when_done(name="rag-reindex")def reindex_all_docs(): ...Summary in the push: what to include
Section titled “Summary in the push: what to include”From successful experience:
- Duration.
Сколько ушло секунд— main signal whether to panic. - Cost. If known —
~$2.40 на токенахor the number of tool calls. - Diff/files. For coding agents —
Изменено файлов: 12, +340 −180. - Output tail. 1–2 KB of the final log — usually the result is there.
- Link. To a PR / commit / dashboard — this works even from push, Notifly supports extras with URL.
Related recipes
Section titled “Related recipes”- Stuck agent / loop — the flip side: “didn’t finish on time”.
- Need human-in-the-loop — if the agent stopped waiting for approval.
- Completion of long tasks — a general template without AI-specifics.