
AI агентът се върти в кръг: OpenTelemetry показва скъпата стъпка

За да откриете къде AI агентът повтаря действия и натрупва разход, проследете едно изпълнение като една следа с вложени spans за всяко извикване на модел и инструмент. Началото, краят и атрибутите на тези spans показват последователността, бавната операция и токените за отделните извиквания. Ръководството на Trodo за агентни следи описва това дърво и пренасянето на контекста между процеси.
Записвайте метаданни за операциите, а не текста на разговора: име на агент и инструмент, заявен модел, отчетени входни и изходни токени, вид грешка и брой завъртания. Повторението на една стъпка става видимо, а продължителността показва къде е изтекло времето. За паричен разход към токените е нужна тарифата за използвания модел; самата следа не съдържа цена по подразбиране.
Едно изпълнение, едно дърво от операции
Кореновият span започва с обработката на заявката и завършва с отговор или прекратяване. В него поставете отделен span за всяко действително извикване на модела и отделен span за всяко изпълнение на инструмент. Конвенциите на OpenTelemetry за агенти и инструменти описват операциите `invoke_agent` и `execute_tool`, имената на инструмента и модела, както и атрибутите за употреба на токени.
На корена е полезно да стоят стабилното име на агента, версията на приложението, броят итерации и крайният резултат. Броячът и резултатът са полета на приложението: например `app.agent.iterations` и `app.agent.outcome`. Така стойност като `limit_reached` ясно означава, че изпълнението е стигнало зададения от приложението предел, без да се представя за стандартен GenAI атрибут.
При извикването на модела запишете `gen_ai.operation.name`, заявения модел и токените, които доставчикът е отчел за този отговор. При инструмента запишете `gen_ai.tool.name` и безопасна категория за грешка, ако операцията се провали. Не добавяйте общия брой токени и към корена, и към вложените извиквания, ако после ще сумирате всички spans: така едно потребление би се преброило повторно.
Малък Python пример за агентния цикъл
Следните редове показват местата за ръчно инструментиране в съществуващ цикъл. Те предполагат конфигуриран OpenTelemetry tracer; `call_model()` и `call_tool()` са функции на приложението, а `response.usage` обозначава данните, върнати от конкретния доставчик. Структурата се повтаря при всяко ново завъртане, вместо да отваря един общ span за всички извиквания на модела.
- Отворете корена с `with tracer.start_as_current_span("invoke_agent assistant", record_exception=False, set_status_on_exception=False) as run:`. Задайте `run.set_attribute("gen_ai.operation.name", "invoke_agent")` и `run.set_attribute("gen_ai.agent.name", "assistant")`. Създайте `iterations = 0` и го увеличавайте при всяко влизане в цикъла.
- Вътре в цикъла обградете `response = call_model()` с `with tracer.start_as_current_span("chat", record_exception=False, set_status_on_exception=False) as model_span:`. Задайте операция `chat`, `gen_ai.request.model` и `gen_ai.provider.name` според действителната заявка. Когато отговорът съдържа отчет за употреба, запишете стойностите му като `gen_ai.usage.input_tokens` и `gen_ai.usage.output_tokens` на този span. Липсващ отчет оставете като липсващо измерване.
- Ако отговорът поиска инструмент, обградете `result = call_tool()` с `with tracer.start_as_current_span("execute_tool tool_name", record_exception=False, set_status_on_exception=False) as tool_span:`. Задайте `gen_ai.operation.name` на `execute_tool` и `gen_ai.tool.name` на устойчивото име на инструмента. При грешка задайте статус `ERROR` и контролирана стойност на `error.type`, без да копирате съобщението на изключението или резултата от инструмента.
- Преди затваряне на корена задайте `run.set_attribute("app.agent.iterations", iterations)` и резултат `completed`, `failed` или `limit_reached` в `app.agent.outcome`. При изключение задайте и на корена статус `ERROR` с празно описание. Ако приложението прекъсва цикъла при лимит, запишете този резултат в самия път на прекратяване.
Контекстният мениджър прави новия span дете на активния span в същия контекст. Когато работа премине през опашка или друг процес, trace контекстът трябва да пътува със задачата; иначе операциите в следващия процес ще се появят в отделна следа. Ако библиотека вече създава spans за извикванията на модела, не ги дублирайте ръчно: добавете корена и липсващите инструментални операции около тях.
Как повторението се превръща в измерим разход
Подредете вложените spans по начален момент. Редуване на `chat` и `execute_tool` със същото име на инструмент показва точно кои извиквания да разгледате. Еднаквото име само по себе си не доказва безполезен цикъл: инструментът може да обработва различни задачи. Броят итерации, крайният резултат и последователността заедно отличават нормална повторна работа от изпълнение, стигнало до лимита.
За забавянето сравнете продължителността на корена с тази на отделните моделни и инструментални spans. Дълъг span на инструмент насочва към неговото изпълнение, изчакване или повторен опит; дълъг span на модел насочва към конкретната заявка. При паралелни операции продължителностите на децата могат да се припокриват, затова сборът им не е равен непременно на времето на цялото изпълнение.
За употребата сумирайте отчетените входни и изходни токени само от моделните извиквания в следата. Ако един и същ въпрос минава многократно през модела, всяко ново извикване добавя своя отчет и така се вижда коя част от цикъла натрупва потреблението. Кешираните входни токени са част от общите входни токени; отделната им стойност служи за разбивка, а не се добавя втори път към общия брой. Паричната оценка изисква и приложимите тарифи, включително условията за кеширане.
Следа без съдържание на разговора
В минималната схема не записвайте промптове, отговори, аргументи към инструмента и върнати резултати. Те могат да съдържат имена, адреси или друга лична информация, а за търсене на цикъл и бавна стъпка са достатъчни време, операция, статус и токени. Използвайте контролирани категории за грешки вместо свободен текст от изключение.
Тук има важна особеност на Python API: според документацията за `start_as_current_span` записването на изключение и автоматичното задаване на статус при изключение са включени по подразбиране. Съобщението на изключението може да попадне в телеметрията, затова примерът изключва и двете автоматични действия за корена и децата и задава безопасен статус ръчно. Проверете и автоматичното инструментиране на използваните библиотеки, преди да разчитате, че ръчните spans са единствените експортирани данни.
Закрепете конвенцията, по която търсите
GenAI семантичните конвенции са в развитие, затова запишете използваната им версия или конкретната ревизия заедно с версиите на инструментариума. След обновяване сравнете действително експортираните имена на операции и атрибути с тези, по които търсят заявките ви. Така промяна в схема няма да изглежда като внезапно изчезване на токени или инструментални извиквания.
Една условна следа с повторено извикване на инструмент е достатъчна за първа проверка на схемата: всички операции трябва да споделят trace идентификатор, броячът да отразява завъртанията, а токените да стоят върху съответните извиквания на модела. Когато тези връзки са налице, редът на операциите, времето и отчетената употреба посочват мястото на натрупване, без да разкриват съдържанието на потребителската заявка.
Прочетете също:
Свързани статии


Локален модел от Hugging Face: Safetensors не прави чуждия код безопасен

Лимитът за OpenAI API спира разхода — и може да спре продукцията

AI агентът иска да изпрати имейл: сложете одобрението преди действието

Claude Code или Gemini CLI: дневният лимит не измерва надеждността

Substack с личен домейн: $50 не сменят адреса на имейлите
Абонирайте се за нашия бюлетин
Получавайте най-новите новини за Web3, AI и криптовалути директно във входящата си поща.