AI-агент сверки банковских выписок с 1С:Бухгалтерией — АйТи Фреш
· 16 мин чтения

Как я построил AI-агента для еженедельной сверки банка с 1С и разбора расходов по счетам

Как я построил AI-агента для еженедельной сверки банка с 1С и разбора расходов по счетам

Раз в неделю бухгалтер компании до 50 рабочих мест открывает банковскую выписку и сверяет её с 1С:Бухгалтерией вручную — построчно, без чек-листа, по памяти. Расхождения всплывают поздно. Платёж завис на невыясненных, оплата поставщику задвоилась, эквайринговая выручка легла одной суммой вместо разбивки по заказам. Мы построили AI-агента, который каждую неделю сам забирает выписку, сверяет её с проводками 1С, раскладывает непонятные операции по счетам учёта и присылает не «всё ок», а конкретный список из 5–15 расхождений — с описанием каждого и вероятной причиной. Ниже — наша рабочая схема: с конфигами, порогами и именами сервисов. Без общих слов про «цифровую трансформацию».

Почему еженедельная сверка — не формальность, а страховка от кассовых разрывов

Компания на 20–50 рабочих мест — это от 40 до 300 операций через расчётный счёт за неделю. Оплаты поставщикам, поступления от покупателей, эквайринг, зарплатные переводы, комиссии банка, конверсия валюты. Бухгалтер разносит их в 1С по мере поступления выписки, но полная сверка «банк = 1С» обычно случается раз в месяц — перед закрытием. К тому моменту расхождения уже неделями сидят в учёте.

Вот типичная картина, которую мы видим у клиентов. Платёж от покупателя лёг на счёт 76.09 «Прочие расчёты с разными дебиторами и кредиторами» — бухгалтер просто не успел сопоставить его со счётом на оплату. Банковская комиссия за эквайринг ушла отдельной строкой и осталась неразнесённой. Один и тот же платёж поставщику провели дважды — из банк-клиента и из ДиректБанка. Каждое из этих событий по отдельности выглядит мелочью. Но накопленным итогом за квартал они искажают оборотку и всплывают при сверке с контрагентом или при подготовке отчётности — в самый неудобный момент.

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

На практике, наблюдая за действующими клиентами, мы выделили три типа расхождений, которые повторяются из недели в неделю почти в любой компании. Первый — платежи, разнесённые на счёт 76 «до выяснения»: назначение платежа не совпало ни с одним открытым счётом на оплату. Второй — агрегированные поступления от эквайринга и маркетплейсов: банк присылает одну сумму за смену, а в 1С её нужно либо разложить на несколько заказов, либо признать выручкой одной строкой. Третий — задвоенные платежи поставщикам при параллельной работе бухгалтера в двух каналах: веб-банк плюс офлайн-клиент. Ни один из этих случаев не требует «искусственного интеллекта» в смысле творческого решения. Это рутинная, но трудоёмкая сверка — и её удобно снять с человека правилами, подключая модель точечно там, где правил не хватает.

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

Архитектура конвейера: пять компонентов между банком и главной книгой

Мы намеренно не делали единый монолитный скрипт «выгрузил — сравнил — разнёс». Конвейер разбит на пять независимых компонентов. Каждый можно отладить и переиспользовать отдельно от остальных.

Такое разделение — не архитектурная мода. Это практическая необходимость. 80–90% операций в норме сопоставляются точным совпадением по ИНН, сумме и дате — без какого-либо ИИ. Гонять их через LLM — это лишние деньги и лишняя точка отказа. Модель мы подключаем только там, где формальные правила не справляются.

Физически весь конвейер живёт на небольшом выделенном контейнере — 2 vCPU, 4 ГБ RAM с запасом хватает на недельный объём в несколько сотен операций. Размещаем либо на инфраструктуре клиента, либо на нашей стороне, если клиент не готов держать своё окружение под это. База 1С при этом не модифицируется и не нагружается ничем, кроме коротких OData-запросов на чтение раз в неделю. Коннектор к банку и AI-классификатор работают полностью асинхронно от рабочего дня бухгалтера — запуск конвейера никак не мешает текущей работе в 1С в течение дня.

Между компонентами данные передаются фиксированной JSON-схемой. Коннектор банка отдаёт список операций в едином формате независимо от источника. Ядро сопоставления возвращает три списка: сопоставлено, кандидат для AI, не найдено. Такой контракт позволяет безопасно перезапускать любой этап отдельно. Если сбоил только AI-классификатор — повторный запуск не выгружает заново выписку и проводки из 1С, а обращается к модели только по операциям, которые остались необработанными.

Как мы забираем банковскую выписку: ДиректБанк, kl_to_1c и API банков

Для еженедельного пакетного цикла реалтайм не нужен — нужен предсказуемый и полный набор операций за 7 дней. Мы используем один из трёх способов в зависимости от того, что уже настроено у клиента в 1С:Бухгалтерии 3.0.

СпособКак работаетКогда используем
1С:ДиректБанкПрямой обмен с банком из 1С без промежуточных файлов; выписка и статусы платежей приходят в базу автоматическиБанк поддерживает сервис ДиректБанк и клиент уже подключил интеграцию — приоритетный вариант
Формат 1CClientBankExchange (kl_to_1c.txt)Плановая выгрузка из банк-клиента файлом стандарта «Клиент банка», загрузка в 1С обработкой обмена с банкомДиректБанк не поддерживается банком; агент забирает файл по расписанию из папки выгрузки банк-клиента (FTP/сетевая папка)
REST/OpenAPI банкаПрямой запрос списка операций по счёту за период через API банка (у части банков есть отдельный контур для бизнес-клиентов)Банк даёт API с токеном для юрлица — тогда коннектор обращается к нему напрямую, минуя файловый обмен

Во всех трёх случаях коннектор приводит операции к единому внутреннему формату: дата, сумма, валюта, ИНН и наименование контрагента, номер и дата платёжного документа, назначение платежа текстом. Это тот же набор полей, что несёт классический kl_to_1c.txt — мы просто нормализуем его независимо от источника. Дальше по конвейеру уже не важно, откуда пришли данные.

Коннектор отдельно проверяет полноту периода. Если за отчётную неделю в выписке операций меньше, чем в среднем за предыдущие четыре недели — порог мы обычно ставим на уровне минус 40% от скользящего среднего — запуск не проваливается молча. Отчёт помечается флагом «возможно, выписка неполная». Это ловит ситуации, когда банк-клиент не успел выгрузить файл целиком или у ДиректБанка временно не было связи с банком.

Формат 1CClientBankExchange — обычный текстовый файл (кодировка Windows-1251 либо UTF-8 в новых банк-клиентах), размеченный секциями по ключевым словам: файл открывается строкой 1CClientBankExchange с версией формата, дальше идёт секция СекцияРасчетныйСчет с реквизитами счёта организации, а каждая операция описана блоком СекцияДокумент с полями ДатаПоступило, Номер, Дата, Сумма, ПлательщикИНН, ПолучательИНН, НазначениеПлатежа и закрывается строкой КонецДокумента. Коннектор парсит эти блоки построчно простым конечным автоматом, без сторонних библиотек — формат стабилен с 1990-х и почти не меняется между версиями банк-клиентов.

Что и как берём из 1С:Бухгалтерии через OData

Со стороны 1С коннектор читает три сущности через стандартный OData-интерфейс (публикуется на веб-сервере как /odata/standard.odata/): документы поступления и списания по расчётному счёту, регистр проводок и справочник контрагентов. Ничего дополнительно писать в конфигурации не нужно — интерфейс OData включается один раз в настройках публикации базы, доступ — по HTTP Basic Auth под отдельной служебной учётной записью с ролью только на чтение нужных объектов.

GET /base/odata/standard.odata/Document_ПоступлениеНаРасчетныйСчет? $filter=Дата ge datetime'2026-06-30T00:00:00' and Дата le datetime'2026-07-07T00:00:00' &$select=Ref_Key,Дата,Номер,СуммаДокумента,Контрагент_Key,НазначениеПлатежа,Проведен Authorization: Basic {{base64(login:password)}}

Аналогичным запросом читаем Document_СписаниеСРасчетногоСчета для исходящих платежей. Отдельно нам нужен регистр проводок (AccountingRegister_Хозрасчетный) — по нему коннектор строит историю: на какой счёт учёта бухгалтер в прошлом разносил операции с похожим назначением платежа и тем же контрагентом. Эта история — единственный источник «правильных ответов» для AI-классификатора, никакого отдельного обучения модели мы не делаем.

Сервисную учётную запись для OData мы заводим строго с правами чтения на конкретные объекты метаданных — никаких полных прав администратора. Коннектор физически не может ничего изменить в базе. Только прочитать.

Если у клиента несколько расчётных счетов или мультивалютные операции, коннектор дополнительно читает справочник Catalog_БанковскиеСчета, чтобы правильно сопоставить операцию не только с контрагентом, но и с конкретным своим счётом — без этого при двух счетах в одном банке легко перепутать, по какому именно счёту пришла выписка, и получить ложные расхождения там, где просто разные счета одной организации.

Для исходящих платежей запрос зеркальный — с фильтром по проведённым документам, чтобы черновики в сверку не попадали.

GET /base/odata/standard.odata/Document_СписаниеСРасчетногоСчета? $filter=Дата ge datetime'2026-06-30T00:00:00' and Проведен eq true &$select=Ref_Key,Дата,Номер,СуммаДокумента,Контрагент_Key,НазначениеПлатежа &$expand=Контрагент_Key&$top=500

$expand сразу подтягивает наименование и ИНН контрагента без второго запроса к справочнику, а $top защищает от случайного получения всей истории базы при неверном фильтре по дате. Право на запись мы не просто не выдаём в роли — на уровне публикации веб-сервиса для этой служебной учётной записи отключены методы POST, PATCH и DELETE.

Ядро сопоставления: окна, допуски и порядок применения правил

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

УровеньКритерий сопоставленияЧто происходит дальше
1. Точное совпадениеИНН контрагента + сумма день-в-день (до копейки) + дата операции совпадает с датой документа 1СПомечается «сопоставлено», в отчёт не попадает
2. Совпадение с окном по датеИНН + сумма совпадают, дата расходится в пределах ±3 календарных дней (банковский клиринг, выходные)Автосопоставление, но с пометкой «в пределах окна» для выборочной проверки
3. Совпадение с допуском по суммеИНН и дата совпадают, сумма расходится не более чем на 1% или на фиксированный порог (по умолчанию 50 ₽ — комиссия банка, курсовая разница)Автосопоставление с пометкой причины расхождения суммы
4. Нечёткое совпадение по контрагентуИНН в назначении платежа отсутствует (агрегированный эквайринг, самозанятые), сравнение по наименованию с порогом similarity ≥ 0.85Передаётся в AI-классификатор для финального решения
5. Не найденоНи один из предыдущих уровней не дал кандидата, либо найдено более одного равнозначного кандидатаПередаётся в AI-классификатор как расхождение с описанием ситуации

Пороги вынесены в отдельный конфиг-файл — чтобы при подключении нового клиента не лезть в код:

matching: date_window_days: 3 amount_tolerance_pct: 1.0 amount_tolerance_abs_rub: 50 fuzzy_name_threshold: 0.85 lookback_days_for_history: 180

На уровнях 1–3 модель вообще не трогается. Чистая арифметика и сравнение строк — порядка 100–200 строк на Python с rapidfuzz для нечёткого сравнения наименований. На нашей практике через эти три уровня проходит подавляющее большинство операций малого бизнеса. Открытыми остаются обычно десяток-другой в неделю, не больше.

Порядок правил в каскаде критичен — не меньше, чем сами пороги. Вот живой пример из практики: у клиента два контрагента с похожими названиями — ООО «Стройторг» и ИП Стройторг. Если сначала запустить нечёткое сравнение по наименованию, а потом точное по ИНН, модель легко перепутает их местами. Именно поэтому наш каскад строго последовательный и однонаправленный: сработал более строгий уровень — всё, последующие для этой операции не выполняются вообще.

Частичные оплаты обрабатываются отдельным правилом внутри уровня 3: если сумма операции меньше суммы открытого документа 1С, но совпадает с остатком к оплате по этому документу, движок помечает операцию не расхождением, а «частичной оплатой» и связывает её с исходным документом без похода к модели. Комиссии эквайринга и банка распознаются по ключевым словам в назначении платежа (комиссия, эквайринг) в сочетании с суммой в типичном для эквайринга диапазоне 1,5-3% от смежной по дате операции поступления — такие строки автоматически уходят на счёт 91.02 без участия AI-классификатора. А вот платёж, закрывающий сразу несколько документов частями, правилами мы не разбираем принципиально: слишком много вариантов разбивки, поэтому такая операция уходит в AI-классификатор с пометкой «требует распределения», а решение всё равно остаётся за бухгалтером.

AI-классификация: промпт, tool use и на чём мы экономим токены

Операции, которые не разложились правилами, уходят в Claude с принудительным вызовом инструмента (tool use, tool_choice: {"type": "tool", "name": "classify_operation"}) — модель обязана вернуть строго структурированный JSON, а не рассуждение в свободной форме. Схема инструмента задаёт обязательные поля:

{ "name": "classify_operation", "input_schema": { "type": "object", "properties": { "account": {"type": "string", "description": "Счёт учёта, например 60.01, 76.09, 91.02"}, "discrepancy_type": { "type": "string", "enum": ["дубль_платежа", "агрегированный_эквайринг", "комиссия_банка", "аванс_без_счета", "новый_контрагент", "курсовая_разница", "не_определено"] }, "suggested_counterparty": {"type": ["string", "null"]}, "confidence": {"type": "number"}, "comment": {"type": "string"} }, "required": ["account", "discrepancy_type", "confidence", "comment"] } }

В системный промпт мы кладём выжимку плана счетов клиента и 150-300 последних размеченных операций из регистра проводок как few-shot — это статичный блок на каждую неделю почти без изменений, поэтому мы помечаем его cache_control: {"type": "ephemeral"} и получаем экономию по прайсу Anthropic на повторных обращениях в пределах TTL кэша. При confidence ниже 0.75 мы не доверяем ответу модели с первого раза и переспрашиваем на более сильной модели.

Вот реальный пример того, что уходит в модель для одной операции четвёртого уровня (данные обезличены и упрощены):

Операция банка: 02.07.2026, сумма 18 400 ₽. Назначение платежа: "Оплата по реестру эквайринга за 01.07.2026, комиссия банка учтена" ИНН плательщика в назначении отсутствует. История за 180 дней: 14 похожих операций на счёте 62.02 с последующим зачётом, 3 операции — на счёте 91.02 как комиссия. Определи account, discrepancy_type, suggested_counterparty, confidence, comment.

Модель в такой ситуации обычно возвращает account: 62.02, discrepancy_type: агрегированный_эквайринг и невысокий confidence около 0.6-0.8 — видит неоднозначность между авансом и комиссией, и именно такие операции конвейер выносит на подтверждение бухгалтеру, а не проводит молча.

СценарийМодельПочему
Массовая классификация операций уровня 4-5Claude Haiku 4.5Дешёвый и быстрый первый проход, для однотипных формулировок назначения платежа точности достаточно (по нашей практике)
confidence < 0.75 после первого проходаClaude Sonnet 5Более точное распознавание нестандартных формулировок назначения платежа
Ежемесячный контроль качества классификатораClaude Opus 4.8Разово прогоняем через более мощную модель выборку решений за месяц, чтобы поймать систематический перекос порогов

Актуальные цены лучше сверять на странице pricing, но ориентир на момент публикации такой: Haiku 4.5 — около 1 $/5 $ за миллион входных/выходных токенов, Sonnet 5 — около 3 $/15 $, Opus 4.8 — около 5 $/25 $. При пакетной обработке через Batch API раз в неделю скидка составляет порядка 50% к обеим частям цены. При 20–40 операциях в неделю, которые реально доходят до модели, это заведомо не бюджетообразующая статья расходов клиента.

Хотите такую же еженедельную сверку для своей 1С

Мы разворачиваем этот конвейер под ключ: коннектор к вашему банку (ДиректБанк, kl_to_1c или API), сервисную учётную запись OData в 1С только на чтение, настройку порогов сопоставления под ваш поток операций и отчёт в Planfix или на почту. Напишите нам — посмотрим на вашу выписку за пару недель и покажем, сколько расхождений всплывёт уже в первом отчёте.

Еженедельный цикл целиком: от таймера до задачи в Planfix

Весь конвейер стартует по расписанию — раз в неделю, в понедельник утром. К этому моменту у банка уже закрылся операционный день пятницы и выписка за прошедшую неделю полная. На своей стороне мы поднимаем это systemd-таймером на выделенном контейнере агента:

# /etc/systemd/system/bank-recon.timer [Timer] OnCalendar=Mon *-*-* 07:00:00 Persistent=true [Install] WantedBy=timers.target

Сервис bank-recon.service запускает питоновский раннер, который последовательно вызывает коннектор банка, коннектор 1С, ядро сопоставления, при необходимости — AI-классификатор, и на выходе формирует таблицу расхождений в Excel (openpyxl) с тремя листами: «Сопоставлено автоматически», «Требует внимания» (уровни 4-5 с предложением модели) и «Не найдено соответствие». Каждая строка листа «Требует внимания» снабжена ссылкой на карточку документа 1С и колонкой discrepancy_type из ответа модели.

Готовый отчёт уходит по двум каналам. Файл прикладывается к новой задаче в Planfix на ответственного бухгалтера с дедлайном на текущую неделю. Краткая сводка — число операций, число расхождений, сумма под вопросом — летит в Telegram руководителю. Автоматическую разноску найденных расхождений в 1С мы намеренно не делаем: агент только предлагает счёт и причину, проводит документ всегда живой человек.

Что если в момент запуска недоступен API банка или Anthropic — кратковременный сбой, плановые работы? Раннер не падает молча и не пропускает неделю. Операции, которые не удалось обработать, получают статус «отложено» и автоматически подхватываются следующим запуском — без дублирования уже готовых результатов. Повторный прогон идемпотентен, потому что каждая операция идентифицируется уникальным ключом банка (номер и дата документа), а не порядковым номером в файле.

Персональные данные в банковской выписке и требования 152-ФЗ

Банковская выписка — это не счета поставщиков. Помимо реквизитов юрлиц там регулярно встречаются операции с физическими лицами: зарплатные переводы, выплаты самозанятым и ИП по номеру телефона или карте, возвраты подотчётных сумм. Такие строки содержат ФИО, иногда номер карты — персональные данные по 152-ФЗ. Передавать их во внешний API без правовых оснований мы просто не готовы.

Поэтому до отправки операции в AI-классификатор коннектор прогоняет маскирование. Зарплатные и подотчётные операции по счетам 70, 71, 73, 76 с признаком «расчёты с физлицами» в LLM вообще не уходят — они категоризируются детерминированным правилом по шаблону назначения платежа, категория для них и так фиксирована планом счетов. В LLM попадает только текст назначения платежа с вырезанными ФИО — по регулярному выражению плюс список известных сотрудников из справочника физлиц 1С, который коннектор подгружает отдельным закрытым запросом и никуда не передаёт. Плюс сумма и дата.

Это отдельно фиксируем в договоре с клиентом на обработку данных: агент работает как обработчик персональных данных строго в объёме обезличенных операций. Полный список операций с ФИО остаётся только внутри контура клиента — в 1С и на нашем сервере сопоставления, и нигде больше.

Технически маскирование — отдельный шаг перед формированием запроса к модели: коннектор вырезает из текста назначения платежа последовательности, похожие на ФИО (по словарю сотрудников и типовым речевым конструкциям вида «в пользу Иванова И.И.»), заменяя их плейсхолдером [ФИО], а логи с текстом запросов к модели мы храним не дольше срока, необходимого для разбора инцидента, после чего они удаляются по регламенту.

Что показывает практика: цифры, границы и где агент ошибается

По текущим внедрениям: доля операций, которые проходят уровни 1–3 ядра сопоставления без единого обращения к модели, держится в районе 80–90%. Это оценка по практике, не строгий бенчмарк — цифра зависит от того, насколько активно клиент пользуется агрегированным эквайрингом и переводами через СБП без указания ИНН. Из оставшихся 10–20% AI-классификатор уверенно закрывает большую часть при confidence ≥ 0.75. В финальный список расхождений для бухгалтера обычно попадает 5–15 строк в неделю — ровно тот объём, который реально просмотреть за 10–15 минут, а не за час ручной сверки.

Систематически модель ошибается там же, где с наскока ошибается и человек: агрегированные суммы эквайринга без разбивки по чекам, переводы между своими счетами внутри одной группы компаний, и случаи, когда один платёж закрывает сразу несколько документов в 1С. В последней ситуации мы не пытаемся угадывать пропорции — агент честно помечает это как «требует ручного распределения» вместо того, чтобы предложить произвольную разбивку.

Граница автоматизации здесь для нас принципиальна. Агент находит расхождение и объясняет его. Разносит документ по счёту всегда бухгалтер. Да, это медленнее, чем полностью автоматическая разноска. Зато не создаёт риска, что ошибка модели тихо осядет в оборотке и всплывёт только на сверке с налоговой.

Отдельный случай — аванс, который закрывает несколько будущих поставок или этапов сразу одной суммой. Агент не пытается угадать, как её разбить. Почему? Потому что пропорция зависит от условий конкретного договора, а в банковской выписке этих условий попросту нет. Любая автоматическая раскидка выглядела бы убедительно — но с высокой вероятностью оказалась бы неправильной. На нашей практике такие «умные» догадки только добавляют работы потом. Поэтому агент фиксирует операцию как аванс — с суммой и датой — и передаёт её бухгалтеру. Тот уже вручную привяжет платёж к конкретным отгрузкам по мере их появления в 1С.

Частые вопросы

Нужно ли подключать ДиректБанк, если банк-клиент и так работает?
Нет, это не обязательно. Если у клиента уже настроен только классический банк-клиент, коннектор просто забирает плановую выгрузку в формате 1CClientBankExchange (kl_to_1c.txt) по расписанию из папки выгрузки — для еженедельного пакетного цикла разница с ДиректБанком не критична, реалтайм здесь не нужен.
Может ли агент сам провести документ в 1С по результатам сверки?
Мы сознательно этого не делаем. Агент только предлагает счёт учёта и причину расхождения через OData на чтение и отчёт для бухгалтера — финальную разноску и проведение документа всегда выполняет человек. Автоматическая запись в бухгалтерский контур без проверки — это риск, который несопоставим с экономией нескольких минут.
Что если у банка нет ни ДиректБанка, ни API для юрлиц?
Тогда единственный вариант — плановая выгрузка файла из веб-банка или банк-клиента в формате 1CClientBankExchange, которую коннектор забирает по расписанию (вручную выгруженный клиентом файл кладётся в общую папку, либо мы настраиваем автоматическую выгрузку, если банк-клиент это поддерживает). Качество и полнота сверки от этого не страдают, меняется только способ доставки файла.
Безопасно ли отправлять данные о зарплате и физлицах во внешний AI-сервис?
Мы этого не делаем: операции с признаком расчётов с физлицами (зарплата, подотчётные суммы, выплаты самозанятым) исключены из AI-классификации и разбираются детерминированными правилами, а в модель уходит только обезличенный остаток — сумма, дата и назначение платежа без ФИО. Это зафиксировано отдельным пунктом в договоре на обработку персональных данных с клиентом.
Сколько занимает внедрение и что нужно от клиента на старте?
От клиента нужен доступ к выписке (ДиректБанк, файл выгрузки или API банка) и включённый интерфейс OData в 1С с отдельной служебной учётной записью на чтение — это делается один раз. Для типового клиента до 50 РМ настройка коннекторов, порогов сопоставления и первого тестового отчёта занимает одну-полторы недели, после чего конвейер работает по расписанию без нашего постоянного участия.
📄
Скачайте подробный разбор в PDF Кейсы, статистика, типовые ошибки и чек-лист самопроверки — 12 страниц
Скачать PDF

Подпишитесь на разборы ITfresh

Раз в неделю — короткая подборка практичных ИТ-материалов для бизнеса. Никакого спама, только то, что реально пригодится.