Skip to main content
Glama

polyflow

Агент уже может возобновить приостановленный запуск. Но он не может сказать вам, что разрешено делать возобновлённому запуску.

polyflow — это движок рабочих процессов для ИИ-агентов. Агент рассуждает о рабочем процессе, а не о следующем вызове инструмента; polyflow допускает этот рабочий процесс только в том случае, если он проходит проверку модели, затем выполняет его надёжно и выдаёт агенту по одному рабочему заданию за раз.

Он поставляется как MCP-сервер, поэтому любой агент, поддерживающий MCP — OpenWorker, Claude Code, Cursor — может использовать его без изменений в ядре агента.

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

Цикл

tools → observe → reason → WORKFLOW ──▶ polyflow admits it (or refuses)
                                            │
                        ┌───────────────────┘
                        ▼
        one work order  →  the agent runs the tool, through its own
                           permission gates, with its own credentials
                        →  workflow_report
                        →  next work order … until terminal

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

Related MCP server: nano-vm-mcp

Почему так, а не постоянное разрешение

Сегодня автоматизация без присмотра утверждается по глаголу: «разрешить slack_send в #cs», навсегда, для всего, что модель решит с ним сделать. Это потолок, когда план — это строка инструкций в прозе, перепланируемая при каждом запуске.

polyflow утверждает план. workflows/customer-brief/effect-invariants.mjs содержит предложения, с которыми пользователь действительно может согласиться:

{ name: 'no-post-without-prior-approval',
  pred: (path) => path.emitted.every((e, i) =>
    e.kind !== 'post_brief' || path.actionBefore('APPROVED', i)) }

При запуске перечисляются все достижимые пути эмиссии по объявленной области контракта и проверяются. Рабочий процесс, который не проходит проверку, не регистрируется — не помечается, а становится невыполнимым:

[polyflow] admitted: customer-brief — paths explored: 5 · states seen: 10 · exhaustive within declared domains
[polyflow] REFUSED: unsafe-brief
[polyflow]   no-post-without-prior-approval

test/fixtures/unsafe-brief — это намеренно сломанный двойник: он публикует сообщение при входе в ревью, до того как человек ответит. Он по-прежнему вызывает ask_user, по-прежнему нацелен на тот же канал, по-прежнему удовлетворяет постоянному разрешению. Рецензент, читающий diff, легко может это пропустить. Шлюз — нет.

Быстрый старт

npm install                    # pulls polygraph (polyrun) as a dependency
npm test                       # 14 tests, no API key, deterministic
node bin/polyflow-mcp.mjs      # MCP stdio server

Запуск вместе с OpenWorker

Предварительные требования: Node 22+ (polyflow использует node:sqlite) и установленный OpenWorker. polyflow не требует собственного API-ключа — он никогда не вызывает модель.

1. Зарегистрируйте его. Из каталога polyflow:

node bin/polyflow-install.mjs --agent openworker/cowork --workspace acme
# --print shows the entry and the target path without writing anything

Это добавляет запись polyflow в глобальный файл mcpServers OpenWorker — тот же, который редактирует страница Connectors (%APPDATA%\coworker\mcp.json на Windows, ~/.config/coworker/mcp.json в остальных случаях, $COWORKER_STATE_DIR переопределяет оба). Он объединяет, а не заменяет, и отказывается трогать файл, который не может разобрать.

2. Перезапустите OpenWorker. Нет демона polyflow, который нужно запускать или контролировать: OpenWorker запускает bin/polyflow-mcp.mjs через stdio при открытии сессии и завершает его вместе с сессией. Состояние выполнения хранится в SQLite-файле по пути POLYFLOW_DB, поэтому оно переживает и то, и другое.

3. Проверьте, что он поднялся. Шесть инструментов появляются как mcp__polyflow__*. Попросите агента «перечислить рабочие процессы, которые вы можете запускать» — он должен вернуть customer-brief, его admitted: true и пять гарантий, под которыми он был допущен. Если этого не произошло, на странице Connectors будет постоянная ошибка, а строки запуска самого сервера (admitted: / REFUSED:) уходят в stderr.

4. Используйте его. Ничего особенного: дайте агенту задачу, покрываемую рабочим процессом, и он сам подхватит этот рабочий процесс — именно это измеряется в FINDINGS-phase3.md. Чтобы поставить на него повторяющуюся задачу, создайте обычную автоматизацию OpenWorker, инструкции которой описывают задачу; рабочий процесс повторно прикрепляется по производному ключу при каждом срабатывании, а не начинается заново.

Области. --agent — это область класса агента (какая библиотека рабочих процессов доступна этому виду агента), а --workspace — область экземпляра (чьи это запуски). Одна установка polyflow может обслуживать несколько рабочих областей — зарегистрируйте её один раз для каждой рабочей области с другим --workspace, указывая на тот же POLYFLOW_DB для общего хранилища или на разные файлы, чтобы держать их раздельно.

Добавление собственного рабочего процесса. Скопируйте workflows/customer-brief/ и отредактируйте шесть файлов (см. Рабочий процесс ниже). Перезапустите сервер: рабочий процесс, не прошедший проверку эмиссии, отклоняется при запуске и не может быть запущен вообще, так что плохое редактирование проявляется громко, а не в 3 часа ночи.

Разрешения. Установленная запись намеренно задаёт requires_approval: false — инструменты polyflow не достигают ничего за пределами машины, а реальные побочные эффекты запуска — это СОБСТВЕННЫЕ инструменты агента, у которых есть свои шлюзы. Запрос подтверждения на каждый workflow_report поставил бы диалог между агентом и его собственной бухгалтерией. Запись также объявляет tool_risk для инструментов только для чтения, что учитывается при применённом патче upstream/0001-mcp-per-tool-risk-level.patch и безвредно игнорируется без него.

Откуда берётся polyrun. polyflow встраивает polyrun в процесс, разрешая его из node_modules/polygraph, затем из соседнего checkout; POLYFLOW_POLYRUN переопределяет оба.

Другие хосты агентов

polyflow — это обычный MCP-сервер stdio, поэтому всё, что говорит на MCP, может его использовать. Установщик записывает правильный файл для каждого хоста:

node bin/polyflow-install.mjs --host kiro          # ~/.kiro/settings/mcp.json
node bin/polyflow-install.mjs --host kiro --scope workspace   # ./.kiro/settings/mcp.json
node bin/polyflow-install.mjs --host claude-code   # ./.mcp.json
node bin/polyflow-install.mjs --host generic       # prints the entry, writes nothing

Два хоста имеют другую форму и выводятся, а не записываются:

node bin/polyflow-install.mjs --host nemo      # YAML for a NeMo Agent Toolkit workflow
node bin/polyflow-install.mjs --host registry  # AWS CLI call to publish an Agent Registry record
  • Kiro / Kiro Crew читает mcpServers из ~/.kiro/settings/mcp.json (пользователь) или .kiro/settings/mcp.json (рабочая область, которая выигрывает при конфликте имён). Повторяющиеся автоматические задания Kiro Crew имеют ту же форму, что и запланированные задания OpenWorker, — это тот случай, о котором говорят результаты в FINDINGS-phase3.md.

  • NVIDIA NeMo Agent Toolkit подключается через свою группу функций mcp_client (требуется nvidia-nat-mcp). Выведенный блок объявляет группу и добавляет её в tool_names рабочего процесса. NeMo также может работать как MCP-сервер, поэтому рабочий процесс NeMo может быть одним из инструментов, которые называет рабочее задание polyflow.

  • AWS Agent Registry — это каталог, а не среда выполнения: публикация записи позволяет другим людям и агентам в организации обнаружить polyflow. Записи можно синхронизировать с HTTPS-эндпоинта, который stdio-сервер не может предложить, поэтому выведенная команда создаёт ручную запись MCP.

Только путь OpenWorker был проверен end-to-end (см. FINDINGS-phase2.md). Остальные построены на основе документированных форматов конфигурации каждого хоста и не запускались.

Переменные окружения, какой бы хост вы ни использовали:

env

значение

по умолчанию

POLYFLOW_WORKFLOWS

каталог библиотеки рабочих процессов

./workflows

POLYFLOW_DB

путь к sqlite

.polyflow/polyflow.sqlite

POLYFLOW_AGENT

область класса агента

default

POLYFLOW_INSTANCE

область экземпляра (рабочая область)

имя базового каталога cwd

POLYFLOW_POLYRUN

checkout polygraph

../polygraph

Инструменты

инструмент

что делает

workflow_list

что этот агент умеет делать и гарантии, под которыми каждый был допущен

workflow_start

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

workflow_report

сообщить о результате инструмента, получить следующий заказ

workflow_state

состояние + открытые заказы, ничего не меняет

workflow_signal

внеполосное событие; действие, которое не применимо, — это наблюдаемый отказ

workflow_journal

каждый шаг, принятый или отклонённый, с причиной — также допустимый корпус трасс Polygraph

Области

Два уровня, и им не нужны новые поля в OpenWorker:

  • область агента — одна на класс агента (openworker/cowork). Владеет библиотекой рабочих процессов: что умеет этот вид агента. Соответствует ScheduledTask.agent.

  • область экземпляра — одна на запущенную копию (workspace). Владеет живыми запусками и их журналами. Соответствует workspace, который уже является coworker.memory.Scope.WORKSPACE.

Идентификатор экземпляра выводится из agent | instance | workflow | key, поэтому запуск и присоединение — это один вызов.

Рабочий процесс

Шесть файлов в каталоге:

polyflow.workflow.json   name, area, tools{effect kind -> agent tool},
                         key{template,fields} — the run's identity, derived
contract.json            states, actions, finite data domain
machine.cjs              SAM v2 strict-profile module
effects.cjs              pure mapper: transition -> work orders
effects.manifest.json    completion actions + retry policy per kind
effect-invariants.mjs    what may be EMITTED, on every reachable path

Инверсия, которая делает это рабочим для агентов: в polyrun среда выполнения выполняет эффекты. У polyflow нет учётных данных, коннекторов и механизма разрешений — у агента есть все три. Поэтому эффект — это рабочее задание, возвращаемое обратно. Обработчик паркуется; агент забирает заказ, запускает инструмент под своими собственными шлюзами и сообщает. Только после этого действие завершения диспетчеризуется.

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

Что доказывают тесты

✔ the admission gate certifies the demo workflow exhaustively
✔ workflow_list reports the guarantees the run was admitted under
✔ happy path: one order at a time, ending posted
✔ the run key is derived from input, not chosen by the caller
✔ an invalid key field is refused with an instruction, not honoured
✔ a finished run says so, and says not to start another
✔ start is idempotent: re-attaching returns the run in progress
✔ a denial is a result, not a fault — and no post is ever ordered
✔ zero tickets ends the run rather than posting an empty brief
✔ a duplicate report is refused, not double-executed
✔ an out-of-band action that does not apply is an observable reject
✔ a workflow that can post before approval is REFUSED and cannot be started
✔ a run outlives the process: restart re-offers the open work order
✔ initialize, tools/list, tools/call over stdio

Тест перезапуска — тот, который важен: сессия 1 доводит запуск до шага утверждения и умирает; сессия 2 — это другой процесс без разговора, без транскрипта и без воспроизведения — потому что состояние никогда не было в сообщениях с самого начала. Он подхватывает запуск ровно там, где тот был, и ровно одна публикация происходит в обеих сессиях.

Ещё не построено

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

  • Версионирование. polyvers ограничивает изменённый рабочий процесс относительно выполняющихся запусков; не подключено.

  • Аудит. Журнал уже является корпусом трасс; polyrun audit по нему не подключён.

  • Швы OpenWorker, требующие изменений ядра: маршрутизация приостановленного заказа во Входящие и workflow_ref на ScheduledTask. См. FINDINGS-phase0.md.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers