Назад в блог

Агент от имени пользователя: делегирование вместо shared-ключа

Сервисный аккаунт «на всё» стирает ответ, по чьему поручению действовал агент. On-behalf-of по RFC 8693, цепочка act, transaction tokens 2026 и чеклист делегирования для агентов.

Иллюстрация к материалу: Агент от имени пользователя: делегирование вместо shared-ключа

Типовое внедрение агента выглядит так: создают сервисный аккаунт, выдают ему широкие права «чтобы не падало», кладут ключ в конфиг — и агент работает от своего имени по поручениям десятков пользователей. Через полгода аудитор спрашивает: «вот это удаление — кто его разрешил?» Ответа нет. В журнале — сервисный аккаунт, поручения — в чатах, связь между ними — нигде. Проблема не в агенте, а в модели идентичности: shared-ключ стирает_principal_ — человека, чьей волей действие совершено. Решение известно из мира микросервисов и стандартизировано: on-behalf-of flow — действие от имени пользователя с сохраняющейся цепочкой делегирования. Для агентов 2026 год добавил к стандарту агентное расширение. Разберём механику целиком.

Проблема shared service account

Сервисный аккаунт с широкими правами — это три потери сразу. Потеря attribution: все действия свалены на одну идентичность, и отличить поручение CEO от поручения стажёра невозможно. Потеря least privilege: права выдаются по объединению потребностей всех пользователей — каждый отдельный вызов избыточен. Потеря отзыва: уволившийся сотрудник не отзывает ничего — ключ живёт своей жизнью, а «отозвать доступ уволенного» превращается в аудит всех мест, где агент мог действовать в его интересах. Альтернатива «выдать каждому пользователю своего агента с его правами» не масштабируется и плодит standing privilege. Нужна третья модель: одна агентная идентичность, действующая в контексте конкретного пользователя — с доказательствами.

Delegation vs impersonation

RFC 8693 фиксирует различие, на котором держится вся конструкция. При impersonation сторона A получает ограниченный credential, который продолжает идентифицировать B как уполномоченную сущность: система видит «B». При delegation у A остаётся собственная идентичность отдельно от B, и явно понимается: B делегировал часть прав A, действия выполняет A, представляя B. В каком-то смысле A — агент B. Так и написано в стандарте — буквально.

Для агентов правильная семантика — delegation: downstream-система обязана видеть обе стороны — кто действует (агент) и от чьего имени (пользователь). Impersonation стирает агента из картины и мешает применять к нему собственные политики: лимиты, allowlist, бюджет. Потребитель токена при контроле доступа смотрит только на top-level claims и текущего актора из act — вложенные act дают историю, но не права. Это и есть ответ аудитору «кто разрешил»: субъект плюс цепочка акторов.

RFC 8693 за десять минут

Протокол обменного STS: клиент предъявляет subject_token (в чьих интересах запрашивается — обычно токен пользователя) и опционально actor_token (кому делегируются права — идентичность агента), получает новый токен для downstream-сервиса. Ключевые элементы:

  • Сужение scope. Новый токен выпускается с меньшим или равным scope исходного — никогда шире. Сужение — обязательное направление: вниз по цепочке права только тают.
  • act claim. Вложенный объект в JWT, идентифицирующий действующего актора; цепочка делегирования выражается вложением act в act — внешний claim текущий актор, глубже — предыдущие.
  • may_act claim. Заявление, что одна сторона уполномочена становиться актором от имени другой: authorization server проверяет его в subject-токене, решая, разрешить ли обмен.
  • Безопасность обмена. Делегирование создаёт риск злоупотребления — стандарт прямо требует смягчать его через scope и проверять политики на каждом обмене, а не только на первом.

Практика Auth0 показывает, как это ложится на агентов: OBO-обмен сохраняет identity и RBAC пользователя через всю цепочку вызовов — сценарий из документации прямо называет MCP-серверы, которым нужно звать first-party API от имени пользователя. Цепочка ограничена пятью вложенными уровнями — обмен упадёт, если subject уже несёт четыре act: глубина делегирования проектируется, а не случается.

Transaction Tokens для агентов (2026)

Весной 2026 года IETF-черновик Transaction Tokens for Agents надстроил над обменом агентную семантику. Три клейма несут нагрузку: act — агент-исполнитель в терминах actor-токенов RFC 8693, sub — принципал, от имени которого идёт транзакция, agentic_ctx — атрибуты агента и его операционных ограничений для авторизации, аудита и политик. Ключевые правила жёсткие и правильные:

  • TTS (сервис выпуска) не верит самодекларации агента: agentic_ctx заполняется через verified exchange из авторитетного источника идентичности, а не из слов агента о себе.
  • Делегат не получает токен делегатора: суб-агенту выпускается суженный токен через replacement flow с scope/purpose под конкретную подзадачу.
  • Сохранение lineage опционально, но сужение обязательно: каждый переход вниз — меньше прав, уже purpose, короче жизнь.

Это ровно та механика, которой не хватало multi-agent системам: оркестратор не раздаёт свой ключ «детям», а выбивает каждому пропуск под задачу.

Сужение вниз по цепочке

Правило, которое стоит повесить над рабочим местом: права текут только вниз. Пользователь → агент: scope пользователя минус всё, что агенту не нужно для задачи. Агент → суб-агент: минус всё, что не нужно подзадаче. Агент → инструмент: минимум на вызов. На каждом переходе — короткое время жизни: токен живёт минуты, а не месяцы, потому что цепочка дешёвая в построении и дорогая в компрометации. Отдельно — purpose: токен под «прочитать сделку X» не работает для «прочитать сделку Y», даже если scope формально позволяет. Purpose превращает scope из забора вокруг поля в пропуск в конкретную комнату.

Sender-constraining и отзыв

Украденный bearer-токен использует кто угодно — поэтому обмен поддерживает привязку к владельцу: DPoP или mTLS. При OBO middle-tier предъявляет свой DPoP-proof или сертификат — выпущенный токен привязывается к держателю, и кража токена без ключа бесполезна. Отзыв строится двухуровнево: отзыв subject (пользователь отозвал согласие, уволен, скомпрометирован) инвалидирует всю цепочку вниз — проверять это обязан каждый STS при обмене, а не только конечный ресурс. Плюс короткий TTL как страховка: даже пропущенный отзыв умирает за минуты.

Чеклист внедрения

  • Агент имеет собственную идентичность отдельно от пользователей; shared-ключи без attribution запрещены.
  • Downstream-вызовы идут через token exchange: subject — пользователь, actor — агент, scope сужается.
  • Цепочка act пишется и проверяется; глубина спроектирована (лимит 5 — не сюрприз).
  • may_act — какие агенты вправе действовать от чьего имени — задан явно, а не «все ото всех».
  • Суб-агентам — только суженные токены через replacement flow; передача своего токена запрещена.
  • Токены короткоживущие, с purpose под задачу; sender-constraining там, где цена кражи высока.
  • Отзыв subject инвалидирует цепочку; TTL — минуты.
  • Журнал хранит связку «поручение → обмены → вызовы» — аудитор читает по пользователю.

Где Codenik

Codenik реализует именно эту модель: поручение пользователя фиксируется, агент получает суженный короткоживущий доступ под задачу с цепочкой «кто поручил → кто исполняет», каждый вызов downstream несёт обе идентичности. Суб-агентам и инструментам права только тают вниз, отзыв пользователя рвёт цепочку целиком, журнал читается в обе стороны — и по агенту, и по человеку. Shared-ключ «на всё» в этой архитектуре просто негде выдать: его место занято обменом с доказательствами.

Короткий вывод

Агент без пользовательского контекста — это действие без автора. On-behalf-of по RFC 8693 и агентные transaction tokens дают механику: delegation вместо impersonation, сужение scope вниз, цепочка act, короткая жизнь, привязка к владельцу. Постройте обмен до первого продакшен-вызова — и вопрос «кто разрешил» всегда будет иметь ответ с подписью.

Источники и дальнейшее чтение