low-level agentic loops
сейчас для имплементации популярны provider agnostic библиотеки типа ai/sdk или pydantic ai. это реально удобно когда не надо париться об api calls разных провайдеров и можно в любой момент просто свапнуть модельку не переписывая код. я сам ими пользовался с самого начала и мне очень заходило.
но есть нюанс, который я сначала не замечал: эти библиотеки навязывают свои абстракции поверх обычных raw api calls.
типичный пример – класс Agent. он берет prompt, tools, ставишь ему max steps и он сам там внутри крутит цикл. но ты хз как(*). и как только нужен more low level control, начинаются костыли.
например, я хочу динамически менять prompt или tools прямо во время работы агента. в библиотеках для этого приходится либо все прерывать и перезапускать заново, либо пытаться использовать библиотеку как raw api, но это такой гемор, что проще уже без неё.
этой зимой решил написать проект вообще без этих оберток, на raw api calls(**). и это был прям отличный learning experience. оказалось, что в логике агента вообще ничего сложного нет (см. код выше прикрепил), зато у тебя полный контроль над всем процессом.
хочешь ограничить шаги? используешь for или break condition вместо while. хочешь обновить системный промпт? обновляешь message array перед след шагом. need to stream tool call progress to client? тоже просто.
даже сам факт того что ты видишь где tools вызываются у себя на бэкенде, думать о agent patterns становятся намного понятнее.
юзать библиотеки прикольно для скорости на старте, но когда нужен more granular control, реально стоит переходить на уровень api. а то получается, что вместо решения задачи ты борешься с ограничениями библиотеки, типа, пытаясь «упростить» тебе жизнь.
- – даже этот факт усложныет. для дебагинга нужно добавлять traces telemetry, иначе никак ** – я все равно использовал библиотеку, litellm, но это реально raw