← Все статьи

Anthropic показала, как собрать фонового агента для утренних сводок из Slack и GitHub

Anthropic показала, как собрать фонового агента для утренних сводок из Slack и GitHub

8 октября инженеры Anthropic Ланс Мартин и Си Джей Авилла опубликовали разбор с рабочим примером: агент, который каждый будний день утром читает заданные Slack-каналы и пулл-реквесты GitHub и постит короткую сводку в один канал. Всё собрано на Claude Managed Agents (бета) — платформенной возможности, где агент живёт на серверах Anthropic и просыпается по cron-расписанию.

Ценность статьи не в примере как таковом, а в списке граблей. Фоновый агент — это не сессия в терминале: рядом нет человека, который одобрит действие или заметит, что что-то отвалилось. Авторы разобрали типичные отказы — «прочитал меньше, чем надо, но решил, что новостей нет», «запостил дважды», «назвал сегодняшнее вчерашним» — и для каждого показали простое правило. Ниже полный перевод, затем мой фактчек и инструкция, как это попробовать.

Получить код

Референсная реализация лежит в репозитории claude-quickstarts. Для интерактивного прохождения запусти в Claude Code команду ниже — скилл claude-api настроит агента по рекомендациям из этой статьи:

/claude-api managed-agents-onboard https://claude.dev/blog/building-effective-agent-automations/

Для примера нужны Slack-приложение (создаётся из готового манифеста) и GitHub-токен. Файлы шаблона — это конфигурация ресурсов Claude API: сам агент, его среда, хранилища памяти, хранилище секретов и деплой.

daily-brief/
├── agent.md                        модель, инструменты, инструкции
├── deployment.md                   расписание, часовой пояс, бюджет, стартовое сообщение
├── environment.yaml                сетевой белый список
├── memory_store_preferences.yaml   твои настройки
├── memory_store_state.yaml         закладки, учёт, заметки и записи о запусках агента
├── vault.yaml                      хранилище секретов (vault)
├── claude-lock.json                ID ресурсов, записывается командой ant apply
└── slack/manifest.yaml             одно бот-приложение

Команда ant apply из ant CLI читает эти файлы, создаёт ресурсы в рабочем пространстве Claude API (там платформа их хранит и запускает) и записывает их ID в claude-lock.json. Её мы используем и дальше. После настройки автоматизация работает по расписанию на инфраструктуре Anthropic — на твоей машине ничего держать включённым не нужно.

Обзор

У агента шесть компонентов, разбираем в этом порядке:

  • Источники — именованный список мест, откуда читать.
  • Получатель — одно место, куда агент может писать.
  • Агент — модель, инструменты и шаги запуска в agent.md.
  • Расписание — cron.
  • Память — твои настройки и собственная память агента.
  • Ограничители — доступ только на чтение там, где агент лишь читает, и лимит расходов на каждый запуск.

Схема агента: расписание будит агента, тот читает источники и постит сводку в один канал. Память хранит состояние агента и настройки читателя, вокруг агента — ограничители.

Источники

По умолчанию агент читает два источника: каналы Slack и пулл-реквесты GitHub. Каналы и репозитории перечислены в файле preferences. Шаблон можно расширить и другими источниками.

Схема с выделенными источниками: они доступны только для чтения, через MCP или HTTPS с доступами из хранилища секретов.

Дай агенту собственные ограниченные доступы

В Managed Agents секреты живут в хранилищах — vaults. Агент может ссылаться на них, но сами значения остаются в хранилище, за пределами песочницы, где выполняется код агента (см. здесь и здесь):

  • MCP-серверы (GitHub). Агент вызывает MCP-инструменты через прокси, который работает вне песочницы. Прокси находит в хранилище тот доступ, чей URL совпадает с адресом сервера.
  • Оболочка (Slack). Агент дёргает Slack API через curl обычным bash-инструментом внутри песочницы. В песочнице лежит только непрозрачная заглушка — $SLACK_BOT_TOKEN. Когда запрос покидает песочницу, платформа подставляет настоящий токен — но только для хостов из белого списка.

Создай хранилище через ant CLI и файл-шаблон из репозитория:

ant apply vault.yaml

Команда создаст хранилище в рабочем пространстве Claude API и запишет его ID в claude-lock.json. Затем добавь каждый доступ в хранилище через TypeScript SDK. Пример добавления доступа к Slack:

const vaultId = process.env.VAULT_ID!; // the vault's ID, from claude-lock.json

await client.beta.vaults.credentials.create(vaultId, {
  display_name: "SLACK_BOT_TOKEN",
  auth: {
    type: "environment_variable",
    secret_name: "SLACK_BOT_TOKEN",
    secret_value: process.env.SLACK_BOT_TOKEN!,
    networking: { type: "limited", allowed_hosts: ["slack.com"] },
    injection_location: { header: true },
  },
});

После этого привяжи хранилище к деплою: скопируй его ID из claude-lock.json в поле vault_ids файла деплоя deployment.md.

Читай с того места, где остановился

Частая ошибка — просить агента читать фиксированное окно вроде «за последние 24 часа». Запуск с опозданием оставит дыру, запуск пораньше повторит уже показанное. Вместо этого заведи закладку на каждый источник. В конце каждого запуска агент пишет в один файл bookmarks.json метку времени самого свежего элемента по каждому источнику: "slack": "2026-09-14T13:02:11Z".

Следующий запуск стартует от этих закладок, поэтому окно само растягивается или сжимается, покрывая всё с прошлого раза. Закладки лежат в хранилище памяти state: это папка с текстовыми файлами, которую платформа монтирует в песочницу каждого запуска по пути /mnt/memory/ и сохраняет между запусками. Агент читает и пишет её обычными файловыми инструментами, а инструкции в agent.md объясняют, как именно.

Не путай неудавшееся чтение с тихим днём

Если MCP-сервер лежит или его токен протух, запуск всё равно начнётся — просто без инструментов этого сервера. В логах сессии будет ошибка, но агент ничего от этого источника не увидит и отчитается: «нового нет».

Три правила в agent.md это чинят. Когда источник недоступен, агент: оставляет его закладку на месте, пишет сводку по остальным источникам и заканчивает пост одной строкой о том, что прочитать не смог («пулл-реквесты в этом запуске недоступны»), чтобы читатель был в курсе.

Получатель

Шаблон постит в один канал Slack — датированный пост на каждый запуск.

Схема с выделенным получателем: после проверки, что сегодняшняя сводка ещё не опубликована, агент постит в одно место, и оно доставляет сводку читателю.

Агент постит в Slack bash-инструментом из своей песочницы, тем же токеном, которым и читает.

Ничто не должно одобрять пост: агент отправляет его bash-командой, а встроенный bash-инструмент по умолчанию выполняется без запроса разрешения. slack.com к тому же есть в белом списке среды — песочницы, где агент работает. Пост — один запрос:

curl -s https://slack.com/api/chat.postMessage \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{"channel": "C0123456789", "text": "Daily brief, Tue Sep 15 ..."}'

Убедись, что пост доставлен, прежде чем записывать его

Только после подтверждения поста агент обновляет свой учёт показанного и закладки. Если эти записи разойдутся с реально отправленным, возможны две беды. Если агент записал пост, который не ушёл, — закладки сдвинутся, и эти пункты уже никогда не попадут в сводку. Если он запостит ещё раз, потому что не уверен в первом, — читатели получат дубликат.

Три правила в agent.md это предотвращают. Первое: агент ищет сегодняшний заголовок среди недавних сообщений канала и не постит, если выпуск уже там. Второе: пост считается отправленным, только если Slack вернул "ok": true и идентификатор сообщения (ts). Третье: учёт и закладки обновляются только после этого подтверждения. Если результат неясен, агент помечает запуск «возможно, отправлено» и больше ничего не меняет — так ничего не теряется.

Каждый запуск агент фиксирует в хранилище памяти (runs/<date>.md): метка «posting» перед постом, затем «posted» с ID сообщения либо «maybe posted».

Агент

В Claude Managed Agents агент — это версионированная конфигурация: модель, системный промпт и инструменты. Каждый запуск проходит свои шаги и останавливается.

Схема с выделенным агентом: модель плюс промпт, в котором живут цикл запуска и правила рассуждения.

В референсной реализации конфигурация агента — это agent.md:

---
name: Daily brief
model: claude-sonnet-5-5
mcp_servers:
  - type: url
    name: github
    url: https://api.githubcopilot.com/mcp/
tools:
  - type: agent_toolset_20260401
    configs:
      - name: web_search
        enabled: false
      - name: web_fetch
        enabled: false
  - type: mcp_toolset
    mcp_server_name: github
    default_config:
      permission_policy:
        type: always_allow
---

[Восемь нумерованных шагов запуска; полный текст — в agent.md репозитория.]

Блок метаданных задаёт имя агента, модель, инструменты и MCP-серверы. Тело — инструкции агенту. MCP-инструменты по умолчанию требуют одобрения, а одобрять некому, поэтому тулсет GitHub выставлен в always_allow, а GitHub-токен — только на чтение.

Держи сводку короткой

agent.md направляет модель к краткости (шаг 4 из инструкций):

4. Решай. Пункт заслуживает строки, если читатель сегодня что-то с ним сделает или это меняет решение, которое он вот-вот примет. Сомневаешься — не включай. В обычный день это несколько пунктов, иногда ни одного. Число («12 открытых ревью») — не пункт; давай ссылки на те, что заблокированы. Пункт, уже попавший в учёт и всё ещё открытый, идёт одной помеченной строкой («всё ещё ждём, день 3»), а не сообщается заново; закрытый — исчезает без комментариев. Не возвращай тему, которую файл настроек уже похоронил.

Перепроверяй всё незакрытое прямо перед публикацией

Между чтением источников и публикацией ситуация может измениться. Прямо перед постом agent.md велит агенту перепроверить живой статус каждого пункта (шаг 5):

5. Проверяй. Мир сдвинулся, пока ты читал. Для каждого пункта, который собираешься сообщить, перепроверь его живой источник прямо перед постом: разрешился после того, как ты прочитал, — выкидывай; всё ещё открыт, но изменился, — правь строку; подтвердить не можешь, — выкидывай и заноси в cuts (отсечённое) в записи о запуске. Одно протухшее «всё ещё ждём от вас» стоит больше доверия, чем десять пропущенных пунктов, — поэтому никогда не мажь статус: либо утверждай, либо выкидывай. Каждая ссылка копируется из собственного поля ссылки источника (html_url пулл-реквеста, пермалинк Slack), никогда не собирается вручную.

Расписание

В Managed Agents сам агент — лишь файл конфигурации; запускает его деплой. Деплой называет агента, среду и первое сообщение каждого запуска, а также держит расписание, хранилище секретов, хранилища памяти и бюджет. Каждый раз, когда срабатывает расписание, платформа стартует новую сессию агента.

Схема с выделенным расписанием: деплой по расписанию будит агента на каждый запуск.

В шаблоне деплой описан в deployment.md, а первое сообщение — в его теле:

---
name: Daily brief
agent: ./agent.md
environment_id: ./environment.yaml
schedule:
  type: cron
  expression: "32 7 * * 1-5"
  timezone: America/New_York
vault_ids: [vlt_...]   # хранилище секретов, созданное в разделе «Источники»
resources:
  - path: ./memory_store_preferences.yaml
    access: read_only
    instructions: The reader's preferences. Re-read them every run. Never write here.
  - path: ./memory_store_state.yaml
    access: read_write
    instructions: Your state. Bookmarks, ledger, notes, proposals, and run records.

---

Напиши сегодняшнюю сводку.
Часовой пояс читателя — America/New_York. Все даты считай по нему.

Иди по шагам запуска по порядку. Сегодняшний выпуск называется "Daily brief, <день недели> <месяц> <число>".

Команда создаёт деплой с агентом, средой и хранилищами памяти, которые там указаны:

ant apply deployment.md

Чтобы проверить всё, не дожидаясь расписания, запусти вручную командой ant beta:deployments run --deployment-id <id>, взяв ID из claude-lock.json.

Считай даты в своём часовом поясе

Частый баг: агент называет сегодняшнее утро «вчера», потому что считает даты по часовому поясу сервера. В deployment.md поле timezone задаёт, когда срабатывает запуск, а вторая строка тела говорит агенту, по какому поясу считать даты.

Память

Каждый запуск стартует в чистой песочнице без памяти о предыдущем. Без памяти обратная связь не приживается. Но и протухшая память путает агента: он сообщает пункт как «всё ещё ждём» после того, как всё разрешилось, или выкидывает живой пункт как «уже сообщал».

Схема с выделенной памятью: State — то, что читает и пишет агент; Preferences — то, что пишет читатель, а агент только читает.

Шаблон держит два хранилища памяти — те самые папки, монтируемые в /mnt/memory/ (см. «Источники»):

  • preferences (твоё, для агента — только чтение): какие каналы и репозитории читать, что опускать, лимит длины, получатель и когда останавливаться.

  • state (агента, чтение и запись): закладки, учёт того, что уже сообщено, по одной записи на запуск, предложения агента по правкам твоих настроек и заметки о поведении каждого источника («отдаёт только 50 свежайших элементов»).

ant apply deployment.md создаёт хранилище preferences, но не файл в нём. До первого запуска запиши туда свой preferences.md скриптом scripts/seed-preferences.sh из репозитория.

Перечитывай настройки в начале каждого запуска

Частая беда: копия настроек вшита в промпт — и продолжает применять правила, которые ты уже поменял. Пусть агент каждый раз читает файл заново. Если прочитать не вышло — остановиться и сказать об этом, а не работать на значениях по умолчанию.

Веди учёт уже сообщённого и сообщай об изменениях

Агент ведёт в ledger.md учёт каждого пункта, который уже попадал в сводку, — чтобы не повторяться. В каждой строке: когда сообщено, откуда взято, неизменяемый ID (метка времени Slack-сообщения или номер пулл-реквеста) и последний известный статус:

2026-09-09 slack:C0123456789 1788963600.000100 refund thread: customer waiting on a decision
2026-09-11 github 481 review blocked, day 2 (still waiting)
2026-09-11 slack:C0234567891 1789117333.000300 enterprise escalation: owner named, in progress

Ограничители

Раз автоматизация работает «в фоне» по расписанию, мы ставим пределы тому, что агент может делать и сколько может потратить.

Схема с выделенными ограничителями: граница вокруг агента с лимитами на шаги, время и расходы плюс контрольные сигналы, за которыми кто-то следит.

Ограничь то, что он может делать

Агент читает сообщения и задачи, написанные другими людьми, — а такой текст может притворяться инструкциями. Ограничь, что агент сможет сделать, если им последует. В нашем примере GitHub-токен и хранилище preferences — только на чтение, а среда ходит лишь на хосты из белого списка. Вживлённая инструкция всё же может повлиять на текст сводки — в том числе через заметки, которые агент хранит между запусками. Но писать в GitHub или править твои правила она не даст.

Slack — исключение: тем же токеном агент и постит, поэтому приглашай бота только туда, где ему действительно нужно читать или писать.

Стартовый лимит расходов задай по реальным запускам

Лимит защищает от убежавших вразнос расходов. Начни с трёх-пяти стоимостей обычного запуска и ужесточай, когда увидишь реальные цифры. Запуск, упёршийся в лимит, не падает, а ставится на паузу — так что слишком низкий лимит выглядит как сводка, которая просто замолчала. Лимит — это budget в deployment.md. Каждый запуск получает полную сумму, а упёршийся в неё ставится на паузу с причиной остановки budget_reached:

budget:
  type: limit
  max_list_cost:
    amount: "500" # строка, в центах: "500" — это $5.00
    currency: USD

С чего начать

Референсная реализация сводится к шести правилам:

  • Читай каждый источник от закладки, а не от фиксированного временного окна.
  • Сообщай о неудавшемся чтении как о сбое, а не как о тихом дне.
  • Перепроверяй каждый пункт прямо перед публикацией.
  • Считай пост отправленным, только когда Slack подтвердил, — и только потом обновляй закладки и учёт.
  • Перечитывай настройки при каждом запуске — из хранилища, которое агент не может править.
  • Везде, где агент только читает, давай доступ только на чтение — и ограничивай расходы каждого запуска.

Claude Code может провести тебя через рекомендации статьи. Сначала обновись:

claude update

Затем используй скилл claude-api:

/claude-api managed-agents-onboard https://claude.dev/blog/building-effective-agent-automations/

Скилл claude-api прочитает этот пост, предложит конфигурацию, запишет файлы в папку agents/ твоего проекта и создаст ресурсы через ant apply. Считай это отправной точкой — дальше подгоняй агента под свои источники, получателя и память.

Фактчек

  • Claude Managed Agents — бета-продукт платформы, и проверить его поведение мне нечем. Сам продукт — vaults, деплои, хранилища памяти, бюджеты, ant CLI — описан только в статьях и документации Anthropic, на которые ссылается текст. Тратить время на проверку я не буду: отдельного независимого источника по деталям (как именно прокси подменяет токены, как считается budget_reached) у меня нет.
  • Модель claude-sonnet-5-5 из конфигурации — новое имя, подтвердить его не могу. Линейка Sonnet у Anthropic точно существует, но конкретно эту версию проверить нечем — берём как есть из файла примера.
  • Идея «фиксированное окно против закладок» — проверяемая инженерная практика. Проблема «поздний запуск оставляет дыру, ранний дублирует» — классика для любых дайджестеров и кураторов очередей, тут не к чему придраться.
  • Риск внедрённых инструкций (prompt injection) описан честно, без маркетинга. Авторы прямо пишут, что злой текст в Slack всё равно может повлиять на содержимое сводки — в том числе через заметки агента, — а защищает лишь ограничение прав. Это соответствует общей линии Anthropic и здравому смыслу, без обещаний «полной защиты».
  • «Ничего не должно работать на твоей машине» — маркетингово верно, но с оговоркой. Речь о том, что платформа сама держит агента; твои деньги при этом тратятся с каждого запуска, и это в статье честно показано бюджетом.
  • Цены и цифры. Единственная цифра — пример лимита «500 центов = $5 на запуск» — это иллюстрация формата, а не прайс Anthropic. Сколько реально стоит обычный запуск, статья не говорит: проверять нечего.
  • Ссылка на тред в X про безопасность vaults — просто отсылка на публичное обсуждение; суть я проверить не могу, оставил как есть.
  • Совет «стартовый бюджет — три-пять стоимостей обычного запуска» — это опыт авторов, а не измеренный факт. Похоже на здравое правило, но подтверждать нечем.

Как применить

  • Обнови Claude Code. Нужна свежая версия: claude update. Без скилла claude-api ничего не выйдет.
  • Подготовь доступы. Создай Slack-приложение из манифеста (ссылка в разделе «Получить код») и GitHub-токен с правами только на чтение — здесь.
  • Прогони онбординг в Claude Code. В проекте выполни /claude-api managed-agents-onboard https://claude.dev/blog/building-effective-agent-automations/ — скилл прочитает статью, предложит конфигурацию и запишет файлы в папку agents/.
  • Создай ресурсы. ant apply vault.yaml, затем добавь токены через TypeScript SDK (пример в статье), впиши ID хранилища в deployment.md и выполни ant apply deployment.md.
  • Проверь вручную, не дожидаясь cron. ant beta:deployments run --deployment-id <id> с ID из claude-lock.json.
  • Не забудь настройки. До первого запуска запиши свой preferences.md скриптом scripts/seed-preferences.sh — без него агент не знает, что читать.
  • Задай бюджет с запасом. Первое время — три-пять стоимостей обычного запуска, потом ужесточай по реальным цифрам.

Полезно тем, у кого есть доступ к API Anthropic и кто уже тонет в Slack-шуме и пулл-реквестах: командные лиды, SRE, техлиды распределённых команд. Важная оговорка: Managed Agents — бета на платформе API, просто подписки на Claude Code для этого недостаточно. Если платформа недоступна, статья всё равно полезна как чек-лист: почти все шесть правил (закладки, честный репорт о сбоях, перепроверка перед постом, учёт показанного, отдельная память, ограничение прав и расходов) переносятся на любого фонового агента, хоть на cron с локальным CLI-агентом.

Источники

  1. https://claude.dev/blog/building-effective-agent-automations/