В 2012 году я написал [postmortem для Plancast](https://markmhendrickson.com/posts/a-postmortem-for-plancast/), стартапа, на который я потратил три года. Идея была проста: люди строят планы, планами стоит поделиться, а лента предстоящих событий от людей, которым вы доверяете, выявит вещи, о которых вы даже не подозревали. Это не сработало. В статье было рассмотрено, почему.

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

В 2012 году я упустил из виду то, что ни одна из этих проблем на самом деле не была проблемой механики продукта. Это были проблемы с субстратом. Доступный в то время субстрат — лента внутри централизованной социальной сети — не подходил ни для одного из них. Я пытался спроектировать подложку с особенностями. Подложка по-прежнему оставалась низким потолком по всем показателям.

## Что было на самом деле не так

Фид не подходит для совместного использования планов, потому что:

- Лента предполагает постоянный поток контента. Планы не приходят как поток.
- Трансляция вознаграждений. Планы нуждаются в адресной аудитории.
- Лента имеет одну функцию свертывания. Plancast выбирает «самое раннее» по дате события, социальные сети выбирают «самое новое первым» по времени публикации. В любом случае, это один хронологический сорт. Планы выигрывают от множества функций запроса, а полезные из них (кто в вашем графе доверия собирается, что подходит в этот четверг, кто в городе) вообще редко имеют хронологическую сортировку.
- Лента делает каждую часть контента видимой для всех, кто подписан на вас. Планам нужны масштабы.
– Лента рассматривает потребление как поверхность, обращенную к пользователю. Планы нуждаются в сочетании с другими системами (календарями, ответами на запросы, транзитом, погодой).
- Канал централизует посредничество. Планы по своей сути находятся между людьми.

Как только этот список окажется на столе, каждый сбой Plancast, который я назвал в 2012 году, станет симптомом последующего процесса. Субстрат не мог выразить то, чем на самом деле должно быть разделение планов.

## Нужный мне субстрат

Подложка, на которой я сейчас буду строить, состоит из двух частей, ни одна из которых не существовала в пригодном для использования виде в 2012 году.

**Надежное состояние, доступное только для добавления, для персональных агентов ИИ.** Это то, что я создаю как [Neotoma](https://neotoma.io). Каждое наблюдение, сделанное агентом (добавленный контакт, приглашение на мероприятие, выданное приглашение, подтверждение присутствия) становится типизированной сущностью с происхождением, ограничениями схемы и неизменяемой историей. Собственный ИИ-агент пользователя читает и записывает с него. Централизованного социального графа не существует. Пользователь владеет состоянием.

**Суверенная сетка адресных книг и областей доверия.** Вот для чего предназначен [Darkmesh](https://github.com/markmhendrickson/darkmesh) (мой ответвление оригинала [Ананда Айера](https://www.anandiyer.com/)). Darkmesh позволяет человеку публиковать адресуемые фрагменты своего контекста (определенные контакты, определенные группы, определенные области действия) в узлах сетки других людей с явного согласия. Согласие сохраняется на границе сети. Агент отправителя не может перевести сообщение в состояние получателя, если узел сетки получателя не допустил область действия отправителя.

Персональные агенты ИИ общаются друг с другом через сеть. Заявите, что они постоянно заботятся о жизни каждого пользователя в Неотоме. Не существует центрального сервера, на котором хранятся всеобщие планы.

## Как первоначальная миссия становится выполнимой

Первоначальная идея Plancast заключалась в следующем: счастливые встречи, основанные на общем понимании планов. Ошибка заключалась в том, что они думали, что общая осведомленность должна исходить из ленты.

На этой новой подложке одна и та же смола распадается на разные произведения.

1. **Прием событий происходит автоматически.** Мой агент уже знает о мероприятиях, на которые я ответил на приглашение, в Luma, событиях в моем календаре, событиях в электронных письмах с подтверждением от Eventbrite или Meetup. Он записывает их в мою Неотому как «событийные» сущности с происхождением. Я их никогда и нигде не печатаю.

2. **Обмен осуществляется на основе согласия и адресуется.** Когда я отвечаю на что-то, мой агент может пометить области, которые должны знать, что я собираюсь. Это не посты в ленте. Это адресованные наблюдения, которые проходят через сетку только тем людям, чьи узлы допускают мою область охвата.

3. **Discovery — это запрос, а не лента.** Самая естественная поверхность для «того, что происходит в моем мире» — это не поток. Это вопрос, который я задаю своему агенту. *Кто из моей сети доверия куда пойдет в ближайшие две недели. Какое из этих событий подходит моему вечеру в этот четверг? Кто находится в городе, которого я не видел уже год.* Каждый запрос вычисляется во время извлечения данных по моей Neotoma плюс любые области видимости, которые допускает моя сетка. Корма нет.

4. **Приглашения — это первоклассно.** Это та часть, на которой настаивал автор 2012 года, и которую большинство попыток создания продукта пропустили.

## Как на самом деле должны работать приглашения

У Plancast были явные приглашения, но они были сделаны вручную. Они основывались на плане, который ваши подписчики уже могли видеть. Кормом по-прежнему была первая поверхность. Тег, упоминание или метаданные, которые отмечали вас, имели одинаковую форму: на первом месте была видимость вокруг, а на втором — личное касание. Настоящее приглашение должно изменить этот порядок.

В этом субстрате приглашение представляет собой типизированную сущность в собственном состоянии получателя. Примерно:

```
приглашение
  отправитель: contact_id
  получатель: contact_id
  event_ref: event_id
  объем: «1:1» | "маленькая_группа" | "co_attending_set"
  note_to_recipient: строка (обязательная, непустая)
  Relationship_Basis: строка (почему этот человек, почему это событие)
  slot_budget_used: целое число (бюджет на событие)
  expires_at: отметка времени
  Conditional_on: необязательный предикат кворума
  происхождение: агент/источник/временная метка
```

Из этой формы следует несколько вещей.

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

**Бюджеты приглашений для каждого мероприятия требуют избирательности.** Каждое мероприятие имеет небольшое настраиваемое количество слотов для приглашений, которые отправитель может потратить. Субстрат, а не сила воли, заставляет «не портить свою адресную книгу». В 2012 году напряжение между тщеславием и избирательностью становится основным параметром.

**Преобладающая модель — получение с предварительным разрешением.** Когда мой агент запускает постоянный запрос, он видит только людей, чьи собственные агенты отметили меня как кого-то, кого они хотели бы приветствовать на этом конкретном мероприятии. Пересечение «кто в моей сети собирается» и «кто меня там встретит» гораздо меньше, чем «кто в моей сети разместил сообщение». Это не корм. Это индекс с ограниченным доступом.

**Личный контекст является обязательным на уровне типа.** Поля «note_to_recipient» и «relationship_basis» являются обязательными. Пустое состояние не является допустимым. Мой агент может составить их из моего графика Neotoma (последнее перекрытие, общий контекст, общие контакты), но по умолчанию используется строка, подтвержденная человеком. Именно на это указывала статья 2012 года, когда она настаивала на том, что люди хотят чувствовать себя лично приглашенными. Подложка делает личное замечание структурным требованием, а не необязательной вежливостью.

**Отклонение происходит молча и без указания авторства.** Получатели отвечают словами «принять», «пропустить» или «карандаш». Отправителю видно только слово «принять». `pass` приводит к «нету ответа» без уведомления о прочтении и без причины. Получатель сохраняет частное происхождение. Вы можете проверить свою социальную нагрузку, не раскрывая ее.

**Кворум — это первоклассный примитив.** В статье 2012 года прокрастинация названа главным провалом: люди оставляют варианты открытыми и отказываются брать на себя обязательства раньше времени. Субстрат напрямую обращается к этому с помощью «conditional_on»: «Я перейду к X, если Аарон и Дивакер тоже согласятся». Субстрат наблюдает за предикатом и разрешает его. Никакой роли координатора, никаких веток группового чата, никаких фейков.

**Компонуемость с существующим графиком событий.** Когда приглашение принято, агент обращается к платформе, которой принадлежит канонический ответ на приглашение (Luma, Eventbrite, календарь), и записывает фактическое бронирование. Сущность Neotoma `attendance_commitment` остается канонической для того, кто-доверяет-кто-куда-идет. Сторонний ответ остается каноническим для места проведения и двери. Две записи, один источник правды для каждой проблемы, связаны между собой.

## Что на самом деле решают агенты

Описанная выше система работает только в том случае, если агенты выполняют нетривиальную работу локально. Два вопроса в обоих направлениях цикла конкретны.

**Исходящие, кто будет приветствовать этот план.** Когда мой агент видит, что я ответил на что-то, он оценивает мои контакты по событию, а не против меня. Полезные местные сигналы:

- контакты, чьи Neotoma обсуждает общие темы или посещают мероприятия вместе с этим,
- контакты, с которыми я был на подобных мероприятиях в прошлом году,
- контакты, которые явно выбрали категорию (отметить меня о живой музыке в этом городе),
- контакты, чье собственное наблюдаемое расписание или местоположение пересекается с окном событий.

Агент составляет рейтинговый список кандидатов, а не автоматический огонь. Бюджеты слотов расходуются мной или с моего подтверждения, а поле «relationship_basis» заполняется на основе того же результата, поэтому я могу видеть, почему человек был предложен, прежде чем отправить его.

**Входящие: планы, проходящие через сетку, заслуживают внимания.** Мой агент выполняет симметричный запрос на основе входящих приглашений и наблюдений внешней посещаемости, допускаемых моей областью действия. Местные сигналы:

- как недавно и как часто я присутствовал на мероприятии вместе с вовлеченными людьми,
- соответствует ли тема категории, с которой я продолжаю заниматься,
- есть ли место в моем календаре,
- формируется ли интересующий меня кворум.

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

Оба направления являются тяжелыми, и оба остаются локальными. Центрального ранкера нет. Агент каждого пользователя выполняет вычисления на основе состояния, которым владеет пользователь, и этот пользователь может проверить оценку. Именно поэтому этот опыт начинает выглядеть как инфраструктура, которая может действовать от вашего имени, не превращаясь в платформу.

## Как развиваются отношения, как мы наблюдаем

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

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

Обратное также верно. Края затухают, когда ничего не происходит. Контакт, которого вы не приглашали, не посещали и не писали о нем в течение года, представляет собой преимущество другого рода, чем контакт, который вы видели на прошлых выходных. Распад – это не удаление. История все еще доступна для поиска. Но завтрашний рейтинг релевантности агента использует актуальный вес, поэтому год молчания стоит известности, прежде чем он будет стоить самих отношений.

Это инвертирует модель подачи нужным образом. Ленты делают график входными данными, а активность — выходными данными. Этот субстрат делает действие входными данными, а график выходными данными. Отношения развиваются, потому что поведение — это структурированное состояние, а не потому, что кто-то однажды нажал «Следовать» в 2014 году, и с тех пор платформа делает вид, что преимущество все еще что-то значит.

## Что это не так

Это не попытка заменить приглашения, написанные людьми. Задача подложки состоит в том, чтобы сделать рукописное приглашение более дешевым в отправке, более надежным для получения и более трудным для рассылки спама. Каждый уровень выше предназначен для того, чтобы вернуть опыт к тому, что я правильно определил в 2012 году как настоящую социальную валюту: тот, кому вы доверяете, думал конкретно о вас. Субстрат не может произвести эту мысль. Он может отказаться поставлять заменители.

## Что еще открыто

На несколько вещей у меня пока нет хороших ответов.

- Как следует формировать и обновлять бюджеты приглашений. За событие, за неделю, за сетку? Привязано к скорости принятия?
- Как распространяются изменения области сетки при изменении отношений. Как выглядит отзыв области действия без сжигания отношений?
- Межсетевое взаимодействие, когда участники запускают разные реализации сетки. Требуется ли тонкий уровень протокола?
- Обработка нарушений, когда ранее допущенный отправитель начинает рассылать спам. Кто применяет штраф: узел сетки-получателя или подложка в целом?
- История миграции для событий, канонический ответ на приглашение которых находится за платным доступом или входом в систему.

Это реальные вопросы, но это вопросы о продуктах и ​​протоколах поверх уже работающей основы. Они не являются архитектурными неизвестными.

## Почему я пишу это сейчас

Несколько недель назад Оо Нвой оставил публичный комментарий к [недавней статье](https://markmhendrickson.com/posts/) о памяти агентов и в нескольких словах спросил, следует ли возродить Plancast в эпоху ИИ. Ответ тот же, что и выше. Первоначальная миссия была правильной. Субстрат был выбран неправильно. Субстрат теперь существует.

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

Если вы построили или строите что-нибудь в этом районе, я хотел бы поговорить.