## Проблема, стоящая перед большинством строителей

Если вы запустите один агент для одного магазина, атрибуция будет тривиальной. Вы знаете, кто написал каждую строку. Вы написали агенту.

В тот момент, когда вы запускаете двух, трех, пяти агентов против одного и того же экземпляра Neotoma, [картина меняется](/posts/when-agents-share-state-everything-breaks). Каждый агент записывает наблюдения, связи, источники, интерпретации. Хранилище накапливает состояние всех из них. Если один из этих агентов начнет писать неверные данные, слегка неверные сводки, устаревшие даты, неправильно приписываемые связи, единственный способ решить, каким записям доверять, — это понять, какой агент их написал.

Без построчной атрибуции ваши варианты действий, когда что-то пойдет не так, грубы: стереть хранилище и повторно загрузить или оставить плохие строки и жить с дрейфом. Оба становятся хуже по мере роста магазина.

Эта проблема становится острее для тех, кто поставляет продукт, управляемый агентом. Записи ваших клиентов пишутся целой группой: вашими собственными агентами, сторонними агентами, интегрированными через MCP, возможно, плагином, который кто-то установил на прошлой неделе. Когда клиент спрашивает: «Кто написал это в мою учетную запись и по чьему поручению?», на этот вопрос нужно ответить на основе данных, а не на основе сопоставления журналов сервера и стенограмм разговоров.

Я запускаю агентов в Cursor, Claude Code, Codex и ChatGPT, и все они пишут в один экземпляр Neotoma. Я написал о том, [что на самом деле делает этот стек](/posts/what-my-agentic-stack-actually-does). Интеграция Neotoma с AAuth — это то, что закрывает пробел для моего стека и для всех, кто его использует: каждый агент приносит свой собственный ключ, и магазин может оставаться заслуживающим доверия по мере роста парка.

## Почему ААут

Уровень атрибуции построен на [AAuth](https://www.aauth.dev/), открытом протоколе, который предоставляет каждому HTTP-клиенту собственную криптографическую идентификацию. Никакой предварительной регистрации. Никаких общих секретов. Никаких жетонов на предъявителя. Каждый запрос подписывается с помощью подписей HTTP-сообщений [RFC 9421](https://datatracker.ietf.org/doc/html/rfc9421), поэтому украденный токен бесполезен без ключа подписи.

Я выбрал AAuth, потому что человек, стоящий за ним, Дик Хардт, мой друг и один из самых глубоких экспертов по идентификации, которых я знаю. Он редактировал OAuth 2.0 ([RFC 6749](https://www.rfc-editor.org/rfc/rfc6749)), был соавтором OpenID Authentication 2.0 и был одним из основателей [OpenID Foundation](https://openid.net/foundation/members/). Это та же самая линия, с которой большинство разработчиков сталкивается при использовании потоков кода авторизации и федеративного входа в систему. Когда кто-то с такой историей запускает новый протокол специально для агентов, именно против него стоит строить.

## Что теперь несет каждая запись

[v0.6.0](https://github.com/markmhendrickson/neotoma/releases/tag/v0.6.0) обеспечивает построчную атрибуцию агента на каждой поверхности записи: `/store`, `/observations/create`, `/create_relationship`, `/correct`, `/entities/split`, инструменты хранилища MCP, а CLI записывает как через MCP, так и через HTTP. Каждое наблюдение, взаимосвязь, источник и интерпретация отмечают:

— Подтвержденный идентификатор агента (отпечаток открытого ключа для подписанных средств записи, тема и эмитент JWT для токенов агента, имя и версия clientInfo в качестве запасного варианта).
- Уровень доверия, который классифицирует степень достоверности подтверждения личности.
- Транспорт, на котором прибыла запись.

Пять уровней охватывают весь спектр:

- «Аппаратное обеспечение»: агент предоставил конверт «cnf.attestation» (Apple Secure Enclave, упакованный WebAuthn или TPM2), который сервер проверил на соответствие доверенным корням.
- `operator_attested`: подпись проверена, и оператор внес эмитента или пару эмитент-субъект в белый список. Оператор ручается за работу агента, не требуя аттестации оборудования.
- `программное обеспечение`: агент подписал запрос действительным ключом, проверенным сервером. Именно сюда сегодня попадает большинство агентов, в том числе мой собственный прокси-сервер Cursor, подписывающий с помощью ES256 JWK с файловой поддержкой.
- `unverified_client`: агент заявил о себе с узнаваемой информацией clientInfo, но не подписался.
- «анонимный»: вообще никакой личности.

Результат: вы можете просмотреть любую строку в вашем магазине и ответить «какой агент это написал» как чтение первоклассных данных.

## Гранты вместо файлов конфигурации

В начале цикла версии 0.6.0 возможности загружались из файлов JSON с переменными среды. Это работало для статического набора агентов, но нарушалось в тот момент, когда вы хотели приостановить работу одного агента без перезапуска сервера.

Теперь: каждый `agent_grant` является первоклассной сущностью Neotoma. Он соответствует идентификатору AAuth (по субъекту, эмитенту, отпечатку пальца или их комбинации), содержит записи о возможностях, ограниченные для каждой операции и типа сущности, и имеет жизненный цикл: «активный», «приостановленный», «отмененный». Промежуточное программное обеспечение допуска преобразует проверенную идентичность AAuth в соответствующий грант при каждом запросе, отмечает пользователя и возможности гранта в контексте запроса, а последующие меры проверки проверяют каждую операцию на соответствие гранту.

Гранты управляются через пользовательский интерфейс Inspector, REST API (POST /agents/grants, PATCH, приостановка, отзыв, восстановление) или переносятся один раз из старой конфигурации env с помощью импорта грантов агентов neotoma. Устаревшие переменные окружения (`NEOTOMA_AGENT_CAPABILITIES_*`), если они все еще установлены, вызывают сбой во время загрузки со структурированной ошибкой, указывающей на команду миграции.

Приостановление гранта происходит мгновенно. Следующий запрос агента не принимается. Восстановление происходит столь же мгновенно. Никакого перезапуска сервера, никакой перезагрузки конфигурации.

Для любого, кто запускает продукт с агентами, работающими с клиентами, это означает, что реакция на инцидент переходит от «перезапуска службы с новой конфигурацией» к «приостановке одного гранта и исследованию». Радиус действия агента, ведущего себя плохо, ограничен операциями, дающими разрешение.

## Предварительная проверка личности

Теперь каждый агент может спросить Neotoma, прежде чем она предоставит какие-либо данные, признан ли он надежным автором.

Три эквивалентные точки входа:

- `GET/session` через HTTP.
- `get_session_identity` как инструмент MCP.
- `сеанс аутентификации neotoma` в CLI.

Каждый возвращает разрешенный уровень доверия, статус предоставления (разрешен или нет, с указанием причины), политику анонимной записи и логическое значение `eligible_for_trusted_writes`. Ответ включает диагностический блок, объясняющий, как разрешился уровень. Новый агент громко терпит неудачу при запуске сеанса вместо того, чтобы писать анонимные строки, пока кто-нибудь не заметит.

Поставляемые инструкции MCP предписывают каждому подключенному агенту выполнить эту проверку перед включением записи.

## Где я это запускаю

Сегодня три разных сервисных агента в моем стеке пишут в Neotoma под AAuth.

**Прокси-сервер Cursor MCP.** Каждый запрос MCP от Cursor проходит через прокси-сервер подписи (`mcp_identity_proxy.py`), который внедряет подпись RFC 9421 с токеном агента `aa-agent+jwt`. Neotoma проверяет подпись, разрешает идентификацию (`sub=cursor@markmhendrickson.com`, `iss=https://markmhendrickson.com`), сопоставляет `agent_grant` и разрешает запись на `tier=software`. Прокси-сервер также выполняет предварительную проверку сеанса при запуске и может завершиться неудачно, если сервер сообщает об анонимном уровне.

**Конвейер обратной связи.** Ретранслятор Netlify на `agent.neotoma.io` пересылает отчеты об ошибках агента в Neotoma через подписанный AAuth туннель [Cloudflare Access](https://www.cloudflare.com/zero-trust/). Его предоставление распространяется только на операции neotoma_feedback.

**[Darkmesh](https://github.com/markmhendrickson/darkmesh) обратная запись теплого вступления.** Моя [вилка Darkmesh](https://github.com/markmhendrickson/darkmesh/blob/main/docs/neotoma_integration.md) ([context](/posts/the-substrate-plancast-needed)) записывает обратное раскрытие теплого вступления Neotoma с подписями RFC 9421 и токеном aa-agent+jwt. Каждое раскрытие имеет атрибуты `agent_sub`, `agent_iss` и отпечаток ключа узла, ограниченные грантом для каждого узла.

Совместные испытания Darkmesh доказали, что правоприменение носит состязательный характер. Второй смоделированный агент с однорангового узла попытался написать `warm_intro_reveal` без этого типа объекта в своем гранте. Неотома отклонил запись. Записи авторизованного узла прошли без изменений.

Далее по плану: [публичный агент на markmhendrickson.com](https://markmhendrickson.com/agent/) оборачивает экземпляр Neotoma в свою память и сегодня обслуживает только объекты, которые я явно пометил как общедоступные. Я планирую добавить операции чтения с контролем AAuth, чтобы авторизованные посетители могли запрашивать определенные закрытые типы объектов. Тот же механизм подписанной идентификации плюс разрешение применяется к пути чтения.

## Обновление всего флота

Neotoma отправляет свои канонические инструкции MCP с сервера каждому подключенному клиенту при каждом рукопожатии. В версии 0.6.0 эти инструкции теперь кодифицируют предварительную проверку атрибуции, тегирование «observation_source», границы происхождения, цитируемые в ответе, группу отображения «Неоднозначное (N)» для предупреждений об эвристическом слиянии и структурированный цикл отправки обратной связи.

Когда я обновил свой сервер, мои хуки Cursor, Claude Code, Codex и OpenCode обрели новое поведение. Никаких клиентских релизов. Никакой миграции для каждого инструмента. Одно обновление сервера, обновление пяти агентов. Для всех, кто управляет парком клиентов, применяется та же схема: обновите экземпляр Neotoma, и каждый подключенный агент получит новые настройки по умолчанию без развертывания клиента.

## Поверхность аудита

Для производителей продуктов на регулируемых рынках последующий вопрос клиента редко звучит так: «Запомнила ли ваша система это?» Это «кто это написал, и можете ли вы доказать, что они были уполномочены».

После версии 0.6.0 это чтение данных первого класса:

- `GET /agents` перечисляет все идентификаторы агентов, которые видел сервер.
- `GET /agents/{key}` возвращает подробное представление каждого агента.
- Аудит GET /agents/{key}/records, который записывает автора данного агента.
- В GET /agents/grants перечислены все гранты, их возможности и статус их жизненного цикла.

Если вы предоставляете агентские функции клиентам в сфере здравоохранения, финансов, юриспруденции или корпоративного сектора, это именно та поверхность, которая в конечном итоге будет востребована вашими клиентами.

## Как включить

``` баш
Генератор ключей аутентификации Neotoma --alg ES256
Пример знака аутентификации neotoma
Сеанс аутентификации Neotoma
```

Создайте разрешение для нового удостоверения через Инспектор или REST API, определяя возможности операций, необходимых вашему агенту. Если вы обновляетесь со старой модели env-config, запустите `neotoma Agents Grants import --owner-user-id <your_user_id>` один раз, а затем отключите устаревшие переменные.

Для программного подписания [`@aauth/local-keys`](https://www.aauth.dev/) или эквивалентная библиотека AAuth подписывает запросы с помощью подписей HTTP-сообщений RFC 9421 плюс токен `aa-agent+jwt`. Neotoma проверяет подпись на необработанных байтах, подписанных клиентом.

Пишет без AAuth все равно работает. Они попадают на «анонимный» уровень. Строители, которым нужны серьезные сбои, могут изменить `NEOTOMA_AAUTH_STRICT=1` и добавить конкретные темы в `NEOTOMA_STRICT_AAUTH_SUBS`.

## Также отправлено

v0.6.0 — это не только AAuth. В том же выпуске реализовано разделение сущностей для чрезмерного объединения записей, экспорт снимков парка, а также инструменты для дрейфа, первоклассные межагентные диалоги через conversation_message и sender_kind, а также суженный периметр API. Полное дополнение находится в [примечаниях к выпуску версии 0.6.0](https://github.com/markmhendrickson/neotoma/releases/tag/v0.6.0).

## Установка и обновление

``` баш
npm install -g neotoma@[0.6.0](https://github.com/markmhendrickson/neotoma/releases/tag/v0.6.0)
неотома инициализация
генератор ключей авторизации Neotoma
Сеанс аутентификации Neotoma
```

Обновление сервера дает вам новую отметку атрибуции и обновление инструкций MCP при следующем рукопожатии клиента. Для агентов, уже подключенных через MCP, установка на стороне клиента не требуется.

Полная установка: [neotoma.io/install](https://neotoma.io/install). Репозиторий: [github.com/markmhendrickson/neotoma](https://github.com/markmhendrickson/neotoma). Примечания к выпуску: [v0.6.0](https://github.com/markmhendrickson/neotoma/releases/tag/v0.6.0).