Завершение долгой задачи AI-агента
Современный AI-coding flow — это «уходим на кофе, пока агент перебирает варианты». Claude Code, Codex CLI, Cline, Aider, OpenAI Agents SDK, LangGraph-runner — все они умеют работать минутами и часами. Возвращаться к терминалу каждые 30 секунд — не вариант.
Завернём любой такой запуск в одну обёртку, которая по завершении (или по ошибке) шлёт push в Notifly.
Универсальная обёртка agent-run
Заголовок раздела «Универсальная обёртка 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 ))
# попробуем достать «итоговый ответ» из последних строк, чтобы прислать его в текстTAIL=$(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 $RCИспользование:
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-декоратор для своего агента
Заголовок раздела «Python-декоратор для своего агента»Если пишете кастомный агент на LangGraph / Agents SDK / своём цикле:
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(): ...Резюме в push: что сложить
Заголовок раздела «Резюме в push: что сложить»Из удачного опыта:
- Длительность.
Сколько ушло секунд— главный сигнал, надо ли паниковать. - Стоимость. Если знаете —
~$2.40 на токенахили число вызовов tool-ов. - Diff/файлы. Для coding-агентов —
Изменено файлов: 12, +340 −180. - Хвост вывода. 1–2 КБ финального лога — обычно там итог.
- Ссылка. На PR / commit / dashboard — это работает даже из push, Notifly умеет extras с URL.
Связанные рецепты
Заголовок раздела «Связанные рецепты»- Зависший агент / loop — обратная сторона: «не закончил вовремя».
- Нужен human-in-the-loop — если агент остановился на approve.
- Завершение длинных задач — общий шаблон без ИИ-специфики.