Статья
19 окт. 2026 г.
читать
Некоторые данные не просто должны оставаться вне памяти. Им вообще не место в разговоре.
Апарна Мишра
Менеджер по продукту
Создавайте бесплатно.
Создайте пространство и запустите свой первый поток вызовов за считанные минуты.
Голосовой ИИ
ИИ-агенты
Соответствие требованиям и безопасность
Руководства для разработчиков
Номер карты, который никто не должен был слышать
В первой части мы говорили о данных, которые незваными попадают в контекст вашего ИИ-агента. Номер счета, случайно попавший в ответ инструмента. Токен авторизации, который просочился, потому что запрос захватил его по пути. Это раздражает, немного рискованно, но вполне исправимо!
Платежные данные — это гость другого рода. Они не пробираются через черный ход. У них есть персональное приглашение, зарезервированное место и кто-то, кто объявляет их имя на входе.
Обычно все начинается с промпта, который звучит вполне разумно: собрать номер карты, срок действия и CVV, а затем зачитать номер обратно, чтобы вызывающий абонент мог его подтвердить. Агент, будучи услужливым хозяином, делает именно это. Абонент диктует шестнадцать цифр. Модель принимает их и тут же зачитывает обратно, по одной цифре за раз, во время живого звонка, как будто называет выигрышные номера лотереи. Теперь эти шестнадцать цифр обосновались в контексте модели, записи разговора, транскрипте и в каждом запросе, который ваш агент отправляет провайдеру LLM до конца звонка.
Итак, промпт сделал именно то, что было сказано, но настоящая проблема в том, кого он об этом попросил. Агент, который вел разговор, — это последний, кто должен находиться рядом с картой.
Почему ИИ — неподходящее место для номера карты
Как только номер карты попадает в окно контекста, он не исчезает, когда разговор продолжается. Он остается там до конца звонка. Каждое следующее слово, произнесенное моделью, генерируется с этими шестнадцатью цифрами, находящимися прямо там, в комнате. А модели склонны к галлюцинациям. Поэтому модель, которая видела номер карты, может позже радостно выдать слегка искаженную его версию, вставив ее в сводку или строку подтверждения, совершенно без всякого умысла.
Затем есть бумажный след. Все, к чему прикасается модель, где-то записывается: журналы разговоров, сводки после звонков, контекст, который вы отправляете провайдеру LLM. Вы могли бы вернуться и очистить все это постфактум, но вы упретесь в ту же стену, что и в первой части.
Поэтому и решение такое же. Не допускайте попадания данных в контекст модели в первую очередь. Для платежей это означает, что ИИ вообще никогда не должен слышать номер карты.
Слышать номер карты против обработки платежа
Представьте оплату в ресторане. Официант приносит терминал для карт к столу, передает его вам и вежливо отходит. Вы прикладываете или вставляете карту и вводите PIN-код. Терминал проводит короткий частный разговор с банком. Через несколько секунд официант получает ровно одну новость: одобрено или отклонено.
Официант руководил всем процессом. Он знал, что вы заказали, сколько вы должны и когда пришло время расплатиться. В какой-то момент ему не понадобился номер вашей карты или PIN-код, чтобы сделать все это. Его работа заключалась в том, чтобы знать, что счет оплачен, а не как он был оплачен.
Ваш ИИ-агент должен работать так же. Агент ведет разговор и решает, когда пришло время платить. Платформа собирает данные карты. Ваш платежный процессор проводит списание. Агент получает результат и продолжает разговор.
Именно для этого предназначен SignalWire Markup Language (SWML) pay.
Неправильный способ обработки платежей с помощью ИИ
Это версия, которая кажется нормальной, пока кто-нибудь не прочитает логи:
И это работает! Агент собирает данные карты, зачитывает их обратно, и абонент уходит довольным. Но это также сбрасывает полный номер карты и CVV прямо в контекст модели, а затем просит языковую модель произнести данные держателя карты вслух во время живого звонка. Никакое последующее редактирование не сделает это безопасным. К тому моменту карта уже была услышана.
Правильный способ обработки платежей с помощью ИИ: передача управления агентом
Начните с промпта. Задача агента — вести заказ и знать, когда пришло время платить. Он никогда не должен запрашивать данные карты, и он должен знать, что делать, если абонент все равно начинает их диктовать:
Эта последняя строка выполняет реальную работу. Пока не наступит этап оплаты, агент продолжает слушать. Абонент, который услужливо зачитывает номер своей карты вслух, прямо вводит его в контекст модели. Промпт — это ваша первая линия обороны.
Далее — ценообразование. Функция calculate_total оценивает заказ из вашего собственного меню, и итоговая сумма попадает в метаданные, а не просто в ответ. Модель отправляет названия товаров, но она никогда не влияет на цены:
Когда абонент готов платить, агент вызывает collect_payment. Эта функция передает вызов в pay, и она извлекает сумму из метаданных, а не из того, что помнит модель:
Вот что происходит дальше. Значение true, переданное в FunctionResult, говорит агенту сначала произнести свою реплику, чтобы абонент услышал: «Вы введете данные своей карты с помощью клавиатуры телефона». Затем агент перестает слушать и ждет. pay предлагает абоненту ввести данные карты на клавиатуре и отправляет их вашему платежному коннектору. Шаг set записывает последующую реплику агента, и агент возобновляет работу с одним новым фрагментом контекста: статусом платежа.
В этих примерах используется обычный сервер Express, чтобы их было легко читать, и требуется Node 22 или более поздняя версия. В рабочей среде встроенный сервер Agents SDK берет на себя безопасность запросов. Запуск SWML из функций разрешен по умолчанию; если вы отключили swaig_allow_swml, шаг pay будет пропущен.
Три детали, которые удерживают номер карты вне модели
Сумма берется из бэкенда, а не из разговора. Модель решает, когда списать средства. Она не решает, сколько. Абонент, который уговорит агента «просто списать с меня пять баксов», не добьется успеха, потому что агент вообще не держал номер карты. То же самое касается цен: модель называет товары, а ваш сервер решает, сколько они стоят.
pay выполняется первым, затем следует последующая реплика. SWML заполняет переменные, такие как ${pay_result}, в момент выполнения шага, а не до него. Если бы шаг set был перед pay, результата для заполнения еще не было бы, и агент вернулся бы, не зная, как прошел платеж. Поэтому порядок здесь действительно важен.
Модель узнает результат, а не детали. Как только pay завершается, модель знает ровно две вещи: реплику, которую ваша функция произнесла до начала оплаты, и текст ai_response с заполненным ${pay_result}. Она знает, прошел ли платеж, но понятия не имеет, какая карта была использована, потому что никто ей этого не говорил.
Ошибка в одну строку, которой следует избегать
Текст ai_response может ссылаться на любую переменную SWML. Это включает pay_payment_results, которая содержит подробные платежные данные. Номер карты и CVV там замаскированы, но срок действия и почтовый индекс находятся на виду.
Так что эта одна безобидная на вид строка перечеркнула бы все вышесказанное:
Все, что попадает в ai_response, попадает в разговор и в логи. То же самое касается вашего промпта для сводки после звонка и любых последующих функций, настроенных на получение переменных вызова, поскольку pay_payment_results остается в вызове до его завершения. После всех усилий по выводу карты через «черный ход», это было бы равносильно тому, чтобы оставить парадную дверь широко открытой.
Агенту нужно знать только то, прошел ли платеж. ${pay_result} охватывает именно это.
Что знает модель от начала и до конца
Вот тот же самый звонок с точки зрения модели.
Она помогла звонящему сформировать заказ и озвучила итоговую сумму. Когда он был готов к оплате, она вызвала collect_payment и попросила воспользоваться клавиатурой телефона. Затем она стала ждать. Следующее, что она услышала, был статус платежа, поэтому она подтвердила заказ и сообщила время доставки.
Что касается ИИ, это весь звонок целиком. Карта никогда не появляется в его контексте или журнале разговоров.
Ваш бэкенд, тем временем, имеет все необходимое. ID заказа и итоговая сумма находятся в метаданных, а данные карты отправились в ваш платежный коннектор и больше никуда. Это делает коннектор единственной частью этой настройки, которая действительно обрабатывает данные карт, поэтому держите его отдельно от сервера, на котором работают функции вашего агента.
Что дальше с безопасностью платежей: транскрипция, перевод и потоковая передача
Этот пост посвящен одной вещи: исключению платежных данных из вашего ИИ-агента. Именно здесь кроется большая часть риска в платежном потоке на базе ИИ, и именно здесь шаблон метаданных работает лучше всего.
Однако во время звонка может происходить больше событий, чем просто работа агента. Если ваши звонки также используют транскрипцию в реальном времени, перевод или потоковую передачу аудио, они заслуживают отдельного внимания. Мы рассмотрим безопасность платежей на протяжении всего звонка в Части 3.
Краткий контрольный список
Собирайте данные карт с помощью pay, никогда не используйте для этого речь в разговоре с ИИ. Скажите своему агенту никогда не запрашивать данные карты и перенаправлять звонящих, которые начинают их диктовать. Берите цены и сумму списания из состояния бэкенда, а не из аргументов модели. Сначала запустите pay, затем установите последующую реплику агента и ограничьте эту реплику значением ${pay_result}. Затем запустите поток в тестовом режиме вашего процессора и прочитайте журнал разговоров агента от начала до конца. Если вы не сможете найти в нем ни одной цифры данных карты, значит, вы все сделали правильно.
Создайте платежный поток, о котором модель никогда не узнает
У вас есть вопросы о добавлении передачи платежа вашему собственному агенту или о том, как не допустить попадания данных карт в ваши логи? Задайте их в SignalWire Discord, где сообщество разработчиков и команда SignalWire помогут вам разобраться.
Почему ИИ-агент никогда не должен слышать номер кредитной карты?
Как только номер карты попадает в контекст модели, он остается там до конца звонка и попадает в транскрипты, записи и каждый запрос, отправляемый вашему провайдеру LLM. Модель, которая видела карту, может позже повторить искаженную версию в сводке или строке подтверждения. Исключение карты из контекста — единственное надежное решение.
Что произойдет, если голосовой ИИ-агент зачитает номер карты для подтверждения?
Цифры попадают в контекст модели, запись звонка, транскрипт и каждый последующий запрос к LLM до конца звонка. Редактирование логов после этого не решает проблему, потому что модель уже слышала номер и может воспроизвести его в другом месте.
Как принять платеж, чтобы ИИ не услышал данные карты?
Передайте звонок на выделенный платежный этап. Агент решает, когда списать средства, затем функция платформы, такая как SWML pay, собирает данные карты через клавиатуру и отправляет их в ваш платежный коннектор. Агент возобновляет разговор, зная результат, а не цифры.
Можно ли удалить данные карты из логов ИИ после звонка?
Это очистит только лог. Карта все равно прошла через контекст модели и каждый запрос к LLM, сделанный во время звонка, и модель могла повторить ее где-то еще. Более безопасный подход — с самого начала не допускать попадания карты в контекст.
Какая самая распространенная ошибка, из-за которой платежные данные утекают обратно в ИИ?
Передача подробных результатов платежа в последующий текст агента. Переменная, содержащая полные результаты, все равно раскрывает срок действия и почтовый индекс. Ограничьте последующую реплику только статусом платежа, который сообщает агенту, прошел ли платеж, и ничего более.












