Перейти к содержимому

Шаблоны

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

Шаблонные переменные используют двойные фигурные скобки:

{{variableName}}

Переменные разрешаются во время выполнения из контекста выполнения.

Имена переменных и ID узлов поддерживают:

  • camelCase: {{projectName}}, {{userInput}}
  • snake_case: {{project_name}}, {{user_input}}
  • kebab-case: {{my-project}}, {{user-input}}

Kebab-case поддерживается в первом сегменте ссылок на переменные:

{{my-variable}} - Простая переменная
{{setup-workspace.path}} - ID узла с доступом к полю
{{#each my-items}}...{{/each}} - Итерация по массиву

Последующие сегменты пути используют стандартные идентификаторы:

{{my-node.field_name}} - Kebab ID узла, snake_case поле
{{setup-workspace.result.data}} - Вложенный доступ к пути
{{executionId}} - ID текущего выполнения
{{workflowId}} - Выполняемый воркфлоу
{{currentNodeId}} - ID текущего узла

Глобальные переменные объявляются один раз в variableRegistry воркфлоу и используются по короткому имени:

{{projectName}} - Объявленная глобальная переменная
{{count}} - Объявленная глобальная (числовая)

Ссылка по короткому имени разрешается только из variableRegistry. Имя, не объявленное как глобальное (и не являющееся системной переменной), ни к чему не разрешается и не проходит валидацию.

Локальные выводы узла используются как node-id.name:

{{analyze-step.summary}} - Вывод 'summary' узла 'analyze-step'
{{review.issues_count}} - Вывод 'issues_count' узла 'review'

Объявляйте глобальные переменные в variableRegistry воркфлоу. Каждая запись — это JSON Schema property: type и description обязательны, а любой JSON Schema ключ (enum, items, properties, pattern, minLength, minimum, default, …) может быть добавлен для ограничения значения.

{
"variableRegistry": {
"projectName": { "type": "string", "description": "Название проекта" },
"count": { "type": "number", "description": "Счётчик элементов", "default": 0 },
"approved": { "type": "string", "description": "Гейт подтверждения", "enum": ["yes", "no"] },
"tags": { "type": "array", "description": "Выбранные теги", "items": { "type": "string" } }
}
}

Вся запись переносится в схему, против которой валидируется записывающий узел, поэтому объявленное ограничение enforced на ответе агента. Строковая глобальная переменная с enum (узел записывает её через inputSchema.globalInputs) обязана вернуть одно из перечисленных значений — используйте это для гейт-переменных, читаемых condition-узлами (например, approved == "yes"), чтобы ответ свободным текстом не проскочил мимо гейта. Типизированный массив с items enforces тип элементов каждого значения (например, tags должен быть массивом строк). Не ставьте enum на числовой счётчик, который узлы инкрементируют: это запиннит значение и отвергнет растущий счёт.

Узел записывает глобальную переменную только перечислив её имя в inputSchema.globalInputs; каждый остальной возвращаемый ключ — локальный вывод узла, описанный в inputSchema.properties:

{
"inputSchema": {
"type": "object",
"globalInputs": ["projectName"],
"properties": {
"summary": { "type": "string", "description": "Итог шага (локальный для узла)" }
}
}
}

Движок маршрутизирует ответ агента по этому объявлению: projectName становится глобальной {{projectName}}; summary доступна только как {{node-id.summary}}.

Используйте условные блоки для включения или исключения контента на основе значений контекста:

{{#if variable}}Контент если истина{{else}}Контент если ложь{{/if}}
{{#if variable}}Контент если истина{{/if}}

Ложные значения: null, undefined, false, 0, "", "нет", "no"

{{#if has_file_access}}Сохранить в ./output.md{{else}}Вернуть результат в ответе{{/if}}
{{#if approved}}Продолжаем деплой{{else}}Ожидаем подтверждения{{/if}}

Условные шаблоны обрабатываются в полях directive и completionCondition узлов agent-directive.

Переменная, которую проверяет блочный хелпер ({{#if VAR}}, {{#unless VAR}}, {{#each VAR}}, {{#eq VAR ...}}, {{#neq VAR ...}}), валидируется так же, как ссылка по bare-имени: она должна быть объявленным глобалом в variableRegistry, выводом node-id.name или системной переменной. Необъявленное имя не проходит валидацию.

Используйте {{#unless}} для обратного условия - контент показывается когда значение ложное:

{{#unless isLoggedIn}}Пожалуйста, войдите{{/unless}}
{{#unless hasError}}Успех!{{else}}Произошла ошибка{{/unless}}

Используйте {{#eq}} для сравнения переменной со строковым значением:

{{#eq variable 'value'}}Контент если равно{{/eq}}
{{#eq variable 'value'}}Контент если равно{{else}}Контент если не равно{{/eq}}

Пример:

{{#eq upload_target 'staging'}}Деплой на staging сервер{{/eq}}
{{#eq upload_target 'production'}}Деплой на production сервер{{/eq}}

Используйте {{#neq}} для показа контента когда переменная НЕ равна значению:

{{#neq variable 'value'}}Контент если не равно{{/neq}}
{{#neq variable 'value'}}Контент если не равно{{else}}Контент если равно{{/neq}}

Пример:

{{#neq test_info 'skip'}}Запусти тесты: {{test_command}}{{/neq}}

Доступ к элементам массива через квадратные скобки:

{{items[0].name}} - Поле name первого элемента
{{users[1].email}} - Поле email второго элемента
{{data[2].nested.value}} - Вложенный путь после доступа к массиву

Используйте переменные в качестве индексов для динамического доступа:

{{items[idx].field}} - Доступ через переменную idx
{{steps[current_step].action}} - Часто используется для навигации по шагам
{{matrix[row][col].value}} - Цепочка динамических индексов
{{data[outer].items[inner].name}} - Смешанные литералы и переменные

Поведение:

  • Переменная должна разрешаться в неотрицательное целое число
  • Строковые переменные типа "2" парсятся как числа
  • Невалидные индексы (отрицательные, дробные, нечисловые, null, объекты) возвращают плейсхолдер undefined
  • Выход за границы массива возвращает плейсхолдер undefined
{
"directive": "Выполни шаг {{current_step}} из {{total_steps}}:\n\nДействие: {{steps[current_step].action}}\nОжидаемый результат: {{steps[current_step].expected_result}}",
"completionCondition": "Шаг выполнен с доказательствами"
}

С контекстом:

{
"current_step": 0,
"total_steps": 3,
"steps": [
{ "action": "Инициализировать проект", "expected_result": "Папка проекта создана" },
{ "action": "Установить зависимости", "expected_result": "node_modules заполнен" },
{ "action": "Запустить тесты", "expected_result": "Все тесты проходят" }
]
}

Результат:

Выполни шаг 0 из 3:
Действие: Инициализировать проект
Ожидаемый результат: Папка проекта создана

Используйте {{#each}} для итерации по массивам:

{{#each items}}{{this}}, {{/each}}
{{#each users}}{{name}} ({{age}})\n{{/each}}
{{#each steps}}{{@index}}: {{action}}{{/each}}

Внутри {{#each}}:

  • {{this}} - текущий элемент (сериализуется для объектов)
  • {{this.fieldName}} - доступ к полю текущего объекта
  • {{this.nested.path}} - доступ к вложенным полям
  • {{@index}} - текущий индекс (начиная с 0)
  • {{fieldName}} - сокращение для {{this.fieldName}}

Поддержка условий внутри циклов:

{{#each tasks}}{{#if done}}[x]{{else}}[ ]{{/if}} {{name}}\n{{/each}}
{
"directive": "Реализуй фичу {{featureName}} в проекте {{projectName}}",
"completionCondition": "Фича {{featureName}} реализована и протестирована"
}

Ветвление через узел condition, читающий значение через contextPath:

{
"id": "check-tests",
"type": "condition",
"condition": { "operator": "eq", "left": { "contextPath": "testsPassed" }, "right": true },
"connections": { "true": "deploy", "false": "fix-and-retry" }
}

Цикл через узел expression для инкремента счётчика и узел condition для проверки лимита:

{
"id": "increment",
"type": "expression",
"expressions": ["iterationCount = iterationCount + 1"],
"connections": { "default": "check-limit" }
}
{
"id": "check-limit",
"type": "condition",
"condition": { "operator": "lt", "left": { "contextPath": "iterationCount" }, "right": 5 },
"connections": { "true": "improve", "false": "done" }
}

Помогите агентам понять ожидаемый формат:

{
"inputSchema": {
"type": "object",
"properties": {
"implementation": {
"type": "string",
"description": "Код для {{featureName}} на {{language}}"
}
}
}
}

Для вывода литеральных фигурных скобок используйте двойное экранирование:

\\{{notAVariable}} - Выводит: {{notAVariable}}
  1. Описательные имена — Используйте понятные имена переменных
  2. Значения по умолчанию — Предоставляйте fallback для опциональных переменных
  3. Согласованность типов — Сохраняйте согласованность типов переменных при использовании
  4. Документация — Документируйте пользовательские переменные в описании воркфлоу

Проверьте значения переменных в контексте выполнения:

Агент: Какие текущие переменные контекста?
[вызывает get_execution_context]