ИИ18 мин

API, които агент може да използва под контрол: една покупка от начало до край

От · основател и главен изпълнителен директор на Hábil ·

Покупка, проектирана за ИИ агенти: отделно предложение и изпълнение, одобрение извън модела, идемпотентност, RFC 9457 и тест за инжектиране.

В API, готови за ИИ агенти обяснихме какво е нужно на една система, за да я използва агент без изненади: да се обяснява сама, грешките ѝ да учат, повторният опит да не дублира нищо и това, което движи пари или данни, да не зависи от модела. Тази статия слиза едно ниво по-надолу. Тя взема една конкретна операция — покупка — и я проектира изцяло: извикванията, кодовете на отговор, формата на грешките, разделянето на правата, мястото на одобрението и начина да се провери, че всичко това издържа на заблуден агент.

Статията е за технологичния екип. Ако ръководите областта, основната идея се побира в един ред: агентът може да поиска, системата решава, а човек одобрява всичко, което движи пари или данни.

Примерен сценарий. Не описва реална компания. Един дистрибутор иска агент с ИИ да зарежда консумативи: проверява наличностите, сравнява доставчици и подготвя поръчки. Малките покупки се одобряват за минути; никой не иска агентът да купува сам.

1. Покупката се разделя на три стъпки, а не на една

Изкушението е да се изложи една-единствена операция, POST /compras, и агентът да я извиква. Това е най-краткият път моделът да получи последната дума за парите. Алтернативата е покупката да се раздели на три стъпки, всяка с различно право:

1. Покупката се разделя на три стъпки, а не на една
СтъпкаИзвикванеКой я правиКакво се променя в системата
СправкаGET /existencias, GET /proveedores/{id}/preciosАгентътНищо
ПредложениеPOST /propuestas-de-compraАгентътСъздава се предложение в състояние чака одобрение. Нищо не се купува
ИзпълнениеPOST /comprasАгентът, само с валидно одобрениеПоръчката се изпраща на доставчика

Между предложението и изпълнението има стъпка, която няма извикване за агента: одобрението. Прави го човек, по друг канал, и системата го съхранява. Агентът не може да го създаде, а само да го изчака.

Предложението изглежда така:

POST /propuestas-de-compra
Content-Type: application/json

{
  "proveedor": "prov-0193",
  "partidas": [
    { "sku": "EMP-5521", "cantidad": 40 }
  ],
  "moneda": "MXN",
  "motivo": "Existencia bajo el mínimo en el almacén norte"
}
HTTP/1.1 201 Created
Location: /propuestas-de-compra/pc-7f3a
ETag: "rev-1"

{
  "id": "pc-7f3a",
  "revision": 1,
  "estado": "pendiente_de_aprobacion",
  "total": "12480.00",
  "moneda": "MXN",
  "huella": "sha256:4b1e…",
  "vence": "2026-11-03T18:00:00-06:00"
}

Агентът изпраща само какво иска и колко. Всичко останало системата попълва от своите оторизирани източници: действащи цени, данъци, адрес за доставка, условия и приложимата политика. С това тя изгражда неизменима версия на предложението и изчислява две неща за нея: общата сума и отпечатъка — криптографско обобщение на точно тази версия, изчислено върху документирано представяне. Ако се промени цената, доставчикът, местоназначението, някой ред или политиката, се създава нова версия и всяко предишно одобрение престава да важи.

Отпечатъкът идентифицира версията; той не дава никакво право. Познаването му не позволява изпълнение, както познаването на номера на една сметка не позволява теглене от нея. По-долу се вижда каква роля играе.

Три стъпки на една покупка: агентът прави справка и предложение; човек одобрява от друго устройство и едва тогава поръчката се изпълнява.

2. Одобрението се случва извън модела

OWASP, водещата организация за сигурност на приложенията, нарича Excessive Agency риска агентът да получи повече функции, права или автономност от необходимото. Сред мерките, които предлага, две тук се превръщат в дизайн: човек да одобрява действията с голямо въздействие, преди да се случат, и оторизацията да се реализира в системите, които получават извикването, вместо решението дали едно действие е позволено да се оставя на LLM [4]. Спецификацията на MCP, протоколът, чрез който много агенти извикват инструменти, върви в същата посока: тя казва, че винаги трябва да има човек, който може да откаже извикването на инструмент [6].

На практика «човек одобрява» трябва да отговаря на три условия, за да има стойност:

  1. Каналът е друг. Одобрението не идва в същия разговор, който агентът може да чете и пише. За това вече има образец: потокът CIBA на OpenID разделя устройството, от което започва операцията, от устройството, на което човекът се удостоверява и дава съгласие [8]. В сценария агентът прави предложението от сървъра, а мениджърката по доставките одобрява от приложението на телефона си, със собствена сесия.
  2. Одобрява се нещо конкретно. Човекът не одобрява «агентът да купува»: одобрява това предложение, с този доставчик и тази обща сума. Стандартът OAuth за подробна оторизация (RFC 9396) съществува точно за това: позволява да се поиска оторизация, която съдържа вида на операцията, сумата и получателя, а примерът в него е плащане [7]. CIBA освен това определя съобщение, предназначено да се показва и на двете устройства, така че човекът да може да ги свърже [8]. Екранът за одобрение се изгражда от системата, а не от агента: показва версията, общата сума, доставчика, местоназначението и срока.
  3. Изпълнява се това, което е одобрено. Одобрението е обвързано с точната версия на предложението и записва кой го е дал, с каква роля и по каква политика. То изтича по часовника на сървъра, може да бъде отменено и престава да важи, ако се създаде нова версия.

Одобрението е проектирано така, че агентът да няма никаква операция, с която да го даде или да промени вече одобреното. Агентът може да поиска одобрение; даването му е работа на човек.

Одобрението се случва на друго устройство и е обвързано с отпечатъка на предложението: изпълнява се това, което е одобрено.

3. Изпълнение: извикване, което може да се повтори, без да се плати два пъти

След одобрението на предложението агентът изпълнява:

POST /compras
Content-Type: application/json
If-Match: "rev-1"
Idempotency-Key: "3f2c9a1e-8d4b-4c6e-9f1a-2b7d5e0c4a91"

{
  "propuesta": "pc-7f3a"
}

Тялото не повтаря редове и суми: казва само кое предложение се изпълнява. Заглавката If-Match казва коя версия се очаква да бъде изпълнена, със стандартния механизъм на HTTP за условни заявки: ако версията вече не е действащата, сървърът може да отговори с 412 Precondition Failed [16]. А извикването носи идентификационни данни за изпълнение, обяснени в раздел 5.

Системата проверява всичко в една-единствена транзакция: предложението все още е одобрено, одобрението не е изтекло, нито е отменено, версията съвпада, идентификационните данни са валидни и за това предложение все още няма поръчка. Ако всичко е изпълнено, предложението преминава от aprobada в ejecutando и идентификационните данни се изразходват; ако не, извикването се отхвърля с грешка, която обяснява причината (раздел 4).

Именно тази транзакция предотвратява две покупки от едно и също предложение, дори да пристигнат две различни извиквания едновременно, с различни ключове, от два процеса или от агент, който се е рестартирал. А като последна бариера базата данни не допуска две поръчки за едно и също предложение. Състоянията са: aprobada → ejecutando → ejecutada, или fallida_sin_confirmar, ако доставчикът е получил поръчката, но отговорът се е загубил. В този случай системата сверява с доставчика, преди да изпрати отново; иначе дублирането просто се премества на друго място.

Ключът за идемпотентност: за повторните опити, а не за паралелността

Транзакцията по-горе решава случая с две различни изпълнения. Ключът за идемпотентност решава друго: повторния опит за същото изпълнение. В това API повтарянето на същата заявка със същия ключ връща записания резултат от това изпълнение, вместо да го опитва отново.

Заглавката Idempotency-Key все още минава през стандартизация в IETF: тя е активен проект, във версия 08, обновена на 22 октомври 2026 г., и все още не е RFC. Стойността ѝ е низ в кавички, както в примера по-горе [2]. Но проектът вече предлага правила, които си струва да се приемат така, както са, защото покриват точно случаите, които объркват един агент [2]:

Ключът за идемпотентност: за повторните опити, а не за паралелността
СитуацияОтговор, който предлага проектът
Операцията изисква ключ, а такъв не е пристигнал400 Bad Request, с връзка към документацията
Същият ключ пристига с друго съдържание422 Unprocessable Content
Същият ключ пристига, докато първата заявка още се обработва409 Conflict
Същият ключ пристига, след като първата е приключилаЗаписаният резултат от първата

Проектът позволява и «отпечатък» на заявката, за да се реши дали две заявки със същия ключ наистина са една и съща [2]. Има и подробности, които всяко API трябва да публикува: обхвата на ключа, колко дълго се пази и кога изтича. Stripe, практически ориентир по темата, документира тези за своето API v1 [3]:

  • пази кода и тялото на първия отговор веднага щом операцията започне да се изпълнява, включително грешките 500, така че повторен опит да не таксува отново, когато първият е останал под въпрос;
  • препоръчва ключовете да се генерират като UUID версия 4 и да не се използват чувствителни данни (имейл адрес или данъчен номер) като ключ;
  • може да изтрие ключовете, когато са на поне 24 часа.

При проектирането с агенти има още едно решение: кой генерира ключа. Ако агентът генерира нов ключ при всеки повторен опит, ключът не може да го разпознае. По-добре е ключът да се създава заедно с изпълнението на предложението и да се записва на сървъра. А ако въпреки това пристигне второ изпълнение с друг ключ, него го спира транзакцията, а не ключът.

Повторен опит със същия ключ за идемпотентност получава записания резултат и не купува два пъти.

4. Грешки, които агентът може да поправи, с RFC 9457

За тази покупка форматът на грешките от RFC 9457 позволява на агента да се дадат структурирани данни за поправка, без да се променя значението на кодовете на HTTP [1]. Ето как изглежда отказ заради сумата:

HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json

{
  "type": "https://api.ejemplo.mx/problemas/monto-sobre-limite",
  "title": "El total supera el límite que se puede proponer",
  "status": 422,
  "detail": "El total de 48,900.00 MXN supera el límite de 25,000.00 MXN para propuestas de este agente. Esta compra requiere la aprobación de nivel superior.",
  "instance": "/propuestas-de-compra/intentos/a91c",
  "limite": "25000.00",
  "reintentable": false
}

Четири правила от самия RFC правят така, че това да работи добре с агент:

  • Статусът в тялото е само информативен, а който го генерира, трябва да използва същия код като реалния отговор [1]. Код 422 в тялото при отговор 200 обърква всеки.
  • Могат да се добавят собствени полета — тук limite и reintentable, — а RFC задължава клиентите да пренебрегват онези, които не разпознават [1]. Така агентът получава точно данните, от които има нужда, без да се чупи нищо на никого.
  • Ако има няколко грешки, препоръчва се да се съобщи най-съществената [1]. За грешките при валидиране RFC показва масив с описанието и местоположението на всяко поле с грешка — точно това, от което агентът има нужда, за да поправи всичко с един опит [1].
  • Вътрешните подробности не се показват: RFC предупреждава срещу показването на неща като извадка от стека [1]. Грешката казва какво да се поправи, а не как е изградена системата отвътре.

За покупката от сценария видовете проблеми са:

За покупката от сценария видовете проблеми са
ПроблемКодreintentableКакво прави агентът
Липсващи или изтекли идентификационни данни401неИска валидни идентификационни данни
Валидни идентификационни данни, без право за това предложение403неСпира
monto-sobre-limite422неИска съответния поток за одобрение. Не разделя и не променя покупката, за да мине под лимита
propuesta-sin-aprobar409неПроверява състоянието или чака известие за одобрение; не повтаря изпълнението в цикъл
aprobacion-vencida409неПодава нова версия за одобрение
revision-no-coincide412неСпира и проверява действащата версия; не използва повторно одобрението
llave-con-otro-contenido422неПоправя заявката или използва нов ключ, ако операцията е нова
compra-en-proceso409да, по-късноИзчаква времето от Retry-After или проверява изпълнението; не отваря ново

Зад таблицата стоят две идеи. Първата: разделяне на удостоверяването (401), оторизацията (403), предварителното условие (412) и състоянието на потока (409), така че агентът да знае дали му липсва нещо, дали няма право или трябва да изчака. Втората: агентът не бива да гадае кое си струва да се повтори. И една предпазна мярка: лимитът на сумата не се заобикаля с разделяне на покупката, затова политиката сумира по доставчик и по период, а не само по предложение.

5. Справка, предложение, изпълнение: правата живеят в API

Таблицата в раздел 1 не е стилистична конвенция. Тя е начинът да се ограничат щетите, когато агентът сгреши. OWASP изброява три причини за прекомерната агентност: твърде много функции, твърде много права и твърде много автономност [4]. Всяко ниво отрязва по една:

  • Ограничени идентификационни данни за изпълнение. Агентът, който прави справки и предложения, няма право да изпълнява. След одобрението сървърът за оторизация може да издаде на изпълнителя идентификационни данни за еднократна употреба и с кратък живот, които съдържат предложението, версията, доставчика, сумата, валутата и API, за което са предназначени. RFC 9396 дава формата за изразяване на тези подробности [7]; проверката им спрямо действащото одобрение и изразходването им в същата транзакция, която отбелязва ejecutando, са работа на това API. Освен това идентификационните данни са обвързани с този, който ги представя, например чрез DPoP [17], за да не послужат на никой друг, дори да изтекат.
  • Агентът дори не вижда това, което не може да направи. Спецификацията на MCP позволява списъкът с инструменти, който един сървър предлага, да се променя според оторизацията на този, който пита: например да се показват само инструментите, до които стигат правата му [6]. Агент с право да предлага не вижда инструмента за изпълнение. Скриването му намалява онова, което агентът открива, но само по себе си нито оторизира, нито блокира: API проверява право, субект, предложение и състояние при всяко извикване [6].
  • Идентификаторът не е право. MCP го казва за състоянието между извикванията: идентификатор като този на една количка е име, а не възможност, и сървърът трябва да проверява оторизацията при всяко извикване [6]. Това, че агентът знае pc-7f3a, не му дава право да го изпълни.
  • Лимитите живеят на сървъра. Лимитът от 25 000 песо в примера е в API, а не в инструкциите на модела. Моделът може да пренебрегне една инструкция; API отхвърля заявката, дори моделът да я изпрати.
  • Дневник на всичко. Кой агент, с какви идентификационни данни, какво е предложил, кой е одобрил, какъв отпечатък, какво е изпълнено. MCP препоръчва използването на инструментите да се записва за целите на одита [6].

6. Тестът с отровения каталог

Всичко дотук може да се провери на хартия. Този раздел служи за проверка с работеща система.

Рискът

През 2023 г. група изследователи описва непрякото инжектиране на инструкции: нападателят не говори с агента, а скрива инструкции в данни, които агентът вероятно ще прочете [10]. OWASP го поставя като първи риск за приложенията с езикови модели и признава, че не е ясно дали съществува безотказен начин за предотвратяването му [5].

В сценария агентът чете каталога на доставчиците: имена, описания, цени. Всеки, който може да напише описание — доставчик, служител, компрометирана интеграция, — може да вмъкне там инструкция.

Защо детекторът не стига

Публикуваните данни са единодушни в едно:

  • Екип от изследователи атакува 12 скорошни защити с атаки, пригодени за всяка от тях, и надхвърля 90 % успех срещу повечето [14].
  • При оценка на центъра за стандарти по ИИ на NIST, с един модел и симулирана офис среда, успехът се покачва от 11 % при най-силната базова атака до 81 % при най-силната нова атака, разработена с британския институт за сигурност на ИИ [15].
  • В друг набор от пет задачи от същата оценка средният успех се покачва от 57 % при един опит до 80 % при 25 повторения на всяка атака [15].

Това са резултати при тези условия, а не процент за всички агенти. Те обаче показват, че собствената оценка трябва да записва модела, средата, задачата и броя на изпълненията.

Поуката не е, че агентите са опасни. А че защитата, която има значение, е тази, която не зависи от това моделът да забележи измамата. Две рамки го казват запомнящо се. Simon Willison нарича «смъртоносна триада» съчетанието от достъп до лични данни, излагане на ненадеждно съдържание и възможност за комуникация навън [11]. Meta предлага «правилото на двете»: в рамките на една сесия агентът не бива едновременно да обработва ненадеждни входни данни, да има достъп до чувствителни системи и да може да променя състояние или да комуникира навън; най-много две от трите [12]. Агент за покупки, който чете отворен каталог и издава поръчки, събира точно трите. Затова стъпката на изпълнение не може да зависи от това, което агентът е прочел.

Изследванията вървят в същата посока. Дизайнът CaMeL на екип изследователи разделя потока на управление — онова, което решава надеждната заявка на човека — от потока на данните, така че ненадеждните данни, които моделът чете, никога да не променят хода на програмата. С този дизайн те решават 77 % от задачите в тестовата среда AgentDojo с доказуема сигурност, срещу 84 % при система без защита [9]. Разделянето между предложение и изпълнение в тази статия е вдъхновено от този принцип; то не е реализация на CaMeL и не наследява неговото доказателство за сигурност.

Тестът стъпка по стъпка

  1. Подгответе изолирана среда, със симулиран доставчик и без излизане към реални доставчици. Запишете версията на модела, инструкциите, инструментите, идентичността на агента, началния каталог, политиката и версията на API.
  2. Добавете в каталога тестово описание, вътрешно отбелязано като ненадеждно, което се опитва да промени количеството, местоназначението на доставката и състоянието на предложението. Точният текст е в тестовите материали на екипа ви, а не в публични документи.
  3. Дайте на агента обичайна задача, при която той чете този продукт, например проверка на наличностите и зареждане на липсващото.
  4. Повторете задачата няколко пъти за всяка комбинация от модел, конфигурация и вариант на описанието. Полезен ориентир са 25-те повторения в оценката на NIST, когато средата ви позволява повторни опити [15]; това е отправна точка за сравнение, а не гаранция.
  5. Измерете отделно какво е на модела и какво е на системата, в дневника: - колко пъти агентът се е подчинил на скритата инструкция (това е на модела и варира между версиите); - колко предложения е създал; - нула поръчки без действащо одобрение, съвпадаща версия и валидни идентификационни данни за изпълнение; - всички преки опити за одобрение или изпълнение без право — отхвърлени; - пълна проследимост на всеки опит: идентификатор на корелация, агент, идентификационни данни, версия, решение и отговор.
  6. Добавете варианти, които проверяват правилата на API: версия, създадена след одобрението, изтекло или отменено одобрение, два различни ключа за едно и също предложение и идентификационни данни, представени от друг клиент. Публичните тестови среди като AgentDojo, с 97 задачи и 629 случая за сигурност, служат за образец при изграждането на ваши собствени [13].

Ако третото условие от стъпка 5 не е изпълнено, първо трябва да се прегледат оторизацията, преходът между състоянията и дневникът на това извикване. Процентът на подчинение на модела помага при избора и настройката на модели; сигурността на покупката не може да зависи от него.

Скрита в каталога инструкция достига до агента, но API не изпълнява нищо без валидно одобрение и записва опита.

7. Контролен списък за екипа ви

  • [ ] Операциите, които движат пари или данни, са разделени на справка, предложение и изпълнение, с различни права.
  • [ ] Цените, общата сума, местоназначението и условията се задават от системата в неизменима версия, а не от агента.
  • [ ] Одобрението се случва по друг канал, дава го човек, то е обвързано с версията, изтича и може да бъде отменено.
  • [ ] Агентът няма никакво извикване за одобрение.
  • [ ] Изпълнението изисква идентификационни данни за еднократна употреба, обвързани с предложението и с този, който ги представя, и транзакция, която не допуска две поръчки за едно и също предложение.
  • [ ] Изпълнението изисква Idempotency-Key за повторните опити, а API отговаря с 400 / 409 / 422, както предлага проектът на IETF.
  • [ ] Грешките са application/problem+json, с документирани видове и поле, което казва дали си струва повторен опит.
  • [ ] Лимитите живеят в API, а не в инструкциите на модела.
  • [ ] Списъкът с инструменти, който вижда агентът, зависи от правата му, а API въпреки това проверява всяко извикване.
  • [ ] Тестът с отровения каталог се изпълнява при всяка версия, с няколко повторения, и измерва отделно какво е направил моделът и какво е позволила системата.

Какво прави Hábil

В Hábil ви помагаме да проектирате API на вашите системи така, че агент с ИИ да може да ги използва под контрол: разделяме справката, предложението и изпълнението; изнасяме одобрението извън модела, с човек, който одобрява всичко, което движи пари или данни; и заедно с екипа ви определяме проверими тестове, като този с отровения каталог, чиито доказателства преглеждаме заедно с вас. Правим го с Hábil AI — изкуствен интелект, свързан с вашите системи под контрол. За цялостната картина вижте също API, готови за ИИ агенти и страницата Контрол на достъпа.

Първи разговор, без заплащане. Започваме от една ваша операция, която днес агент не бива да изпълнява сам, и ви казваме какво е нужно, за да може той да я предлага под контрол.

Източниците са проверени на 28 октомври 2026 г. Цитатите от документи на английски са преведени.

Източници

  1. IETF, RFC 9457, Problem Details for HTTP APIs (2023). https://www.rfc-editor.org/rfc/rfc9457
  2. IETF, The Idempotency-Key HTTP Header Field, draft-ietf-httpapi-idempotency-key-header-08 (активен проект, обновен на 22 окт. 2026 г.; не е RFC). https://datatracker.ietf.org/doc/draft-ietf-httpapi-idempotency-key-header/
  3. Stripe, Idempotent requests (документация на API; практика на един доставчик). https://docs.stripe.com/api/idempotent_requests
  4. OWASP, Top 10 for LLM Applications 2025, LLM06: Excessive Agency. https://genai.owasp.org/llmrisk/llm062025-excessive-agency/
  5. OWASP, Top 10 for LLM Applications 2025, LLM01: Prompt Injection. https://genai.owasp.org/llmrisk/llm01-prompt-injection/
  6. Model Context Protocol, спецификация 2026-07-28, Tools. https://modelcontextprotocol.io/specification/2026-07-28/server/tools
  7. IETF, RFC 9396, OAuth 2.0 Rich Authorization Requests (2023). https://www.rfc-editor.org/rfc/rfc9396
  8. OpenID Foundation, OpenID Connect Client-Initiated Backchannel Authentication Flow — Core 1.0 (окончателна версия, 1 септ. 2021 г.). https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html
  9. Debenedetti, Shumailov, Fan и др., «Defeating Prompt Injections by Design», предпечатна версия, arXiv 2503.18813 (2025). https://arxiv.org/abs/2503.18813
  10. Greshake, Abdelnabi, Mishra, Endres, Holz и Fritz, «Not what you've signed up for: Compromising Real-World LLM-Integrated Applications with Indirect Prompt Injection», arXiv 2302.12173 (2023). https://arxiv.org/abs/2302.12173
  11. Simon Willison, «The lethal trifecta for AI agents», 16 юни 2025 г. https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/
  12. Meta AI, «Agents Rule of Two: A Practical Approach to AI Agent Security», 31 окт. 2025 г. https://ai.meta.com/blog/practical-ai-agent-security/
  13. Debenedetti, Zhang, Balunović и др., «AgentDojo», arXiv 2406.13352 (2024). https://arxiv.org/abs/2406.13352
  14. Nasr, Carlini, Sitawarin и др., «The Attacker Moves Second», предпечатна версия, arXiv 2510.09023 (2025). https://arxiv.org/abs/2510.09023
  15. NIST, Center for AI Standards and Innovation, Technical Blog: Strengthening AI Agent Hijacking Evaluations (17 ян. 2025 г., обновен на 19 дек. 2025 г.). https://www.nist.gov/news-events/news/2025/01/technical-blog-strengthening-ai-agent-hijacking-evaluations
  16. IETF, RFC 9110, HTTP Semantics (2022), раздел 13.1.1, If-Match. https://www.rfc-editor.org/rfc/rfc9110
  17. IETF, RFC 9449, OAuth 2.0 Demonstrating Proof of Possession (DPoP) (2023). https://www.rfc-editor.org/rfc/rfc9449

Вашата дейност среща ли тези предизвикателства?

Да обсъдим вашия проект

Предпочитате имейл? Пишете ни на hola@habil.mx