Перейти к содержимому

Завершение долгой задачи AI-агента

Современный AI-coding flow — это «уходим на кофе, пока агент перебирает варианты». Claude Code, Codex CLI, Cline, Aider, OpenAI Agents SDK, LangGraph-runner — все они умеют работать минутами и часами. Возвращаться к терминалу каждые 30 секунд — не вариант.

Завернём любой такой запуск в одну обёртку, которая по завершении (или по ошибке) шлёт push в Notifly.

/usr/local/bin/agent-run
#!/usr/bin/env bash
set -u
set -a; source ~/.notifly.env; set +a
CMD="$*"
START=$(date +%s)
HOST=$(hostname -s)
LOG=$(mktemp)
if "$@" 2>&1 | tee "$LOG"; then
RC=0
else
RC=$?
fi
DUR=$(( $(date +%s) - START ))
# попробуем достать «итоговый ответ» из последних строк, чтобы прислать его в текст
TAIL=$(tail -c 1200 "$LOG")
LINES=$(wc -l < "$LOG")
if [[ $RC -eq 0 ]]; then
TITLE="🤖✅ ${CMD:0:60}"
PRIO=5
else
TITLE="🤖❌ ${CMD:0:60} (rc=$RC)"
PRIO=9
fi
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"

Если пишете кастомный агент на 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():
...

Из удачного опыта:

  • Длительность. Сколько ушло секунд — главный сигнал, надо ли паниковать.
  • Стоимость. Если знаете — ~$2.40 на токенах или число вызовов tool-ов.
  • Diff/файлы. Для coding-агентов — Изменено файлов: 12, +340 −180.
  • Хвост вывода. 1–2 КБ финального лога — обычно там итог.
  • Ссылка. На PR / commit / dashboard — это работает даже из push, Notifly умеет extras с URL.