от инжиниринга циклов к инжинирингу графов: создание надежных решений
От инженерии циклов к инженерии графов: агентный цикл как инженерная единица, при которой один цикл нарушается из-за запутанности состояний, и почему графы помогают.
Источники: From Loop Engineering to Graph Engineering: Building Reliable Agentic Systems in Tech Startups
В этом руководстве пошагово описывается путь от сырья до готовой к работе системы для проекта «От инжиниринга циклов к инжинирингу графов: создание надежных агентных систем в технологических стартапах». Основное внимание уделяется практическим шагам, четким проверкам и коду, который можно просто добавить в репозиторий без необходимости догадываться о его назначении. На этапе обзора необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии системы. Рядом с функциональными результатами следует записывать время выполнения и стоимость токенов или запросов. Отображение затрат с самого начала помогает избежать неожиданных расходов при переходе от демо-версии к общедоступным средам.
while not finished:
context = build_context(state)
action = model.decide(context)
observation = tools.execute(action)
state = update(state, action, observation)
1. Цикл агента как инженерный объект
При работе над этапом «Цикл агента» сначала запишите условия работы: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Создавайте контрольные точки после дорогостоящих операций. Функция возобновления работы не должна повторно оплачивать один и тот же вызов большой языковой модели, когда оператор пытается выполнить следующий шаг.
action = model(current_state)
observation = execute(action)
next_state = transition(current_state, action, observation)
continue_execution =
task_is_not_complete
and execution_budget_is_available
MAX_ITERATIONS = 12
MAX_TOOL_CALLS = 30
MAX_RUNTIME_SECONDS = 600
MAX_TOKEN_COST = 250_000
while budgets_available(state):
action = agent.next_action(state)
if not policy.allows(action):
return TerminalFailure("policy_violation")
result = execute_idempotently(action)
state = persist_transition(state, action, result)
verification = verifier.evaluate(state)
if verification.passed:
return VerifiedSuccess(
state=state,
evidence=verification.evidence
)
return TerminalFailure("budget_exhausted")
2. Где начинаются проблемы с однократным циклом
При работе над этапом «Где однократный цикл» сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Задокументируйте одновременно успешный и восстановительный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не последующими улучшениями. Устанавливайте контрольные точки после дорогостоящих операций. Механизм возобновления работы не должен повторно оплачивать один и тот же вызов большой языковой модели, когда оператор пытается выполнить следующий узел.
Переплетение состояний
При работе над этапом взаимосвязи состояний сначала запишите контракт: необходимые входные данные, сигнал о успехе и действия при частичной неудаче. Такой список помогает сохранять честность последующих изменений в коде. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое какого-либо шага причина неудачи должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Вносите контрольные точки после дорогостоящих шагов. Механизм возобновления работы не должен повторно взимать плату за один и тот же вызов большой языковой модели при повторной попытке обработки последующего узла. При работе над этапом взаимосвязи состояний сначала запишите контракт: необходимые входные данные, сигнал о успехе и действия при частичной неудаче. Такой список помогает сохранять честность последующих изменений в коде. Записывайте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отображение стоимости на ранних этапах предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
Неоднозначное завершение
Этап неоднозначного завершения работает наилучшим образом, когда его рассматривают как измеримую структуру. Соберите один идеальный пример выполнения, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь граф. Сохраняйте состояние графа простым и типизированным. Вложенные структуры данных скрывают информацию о том, какой узел заполнил тот или иной поле, и приводят к нарушению возобновления работы после перерывов.
Глобальные попытки повтора
Этап глобальных попыток повтора работает наилучшим образом, когда его рассматривают как измеримую структуру. Соберите один идеальный пример работы, один случай сбоя и записку о откате перед расширением объёма задачи. Документируйте одновременно успешный сценарий работы и сценарий восстановления. Попытки повтора, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Сохраняйте структуру графа простой и типизированной; вложенные структуры данных скрывают информацию о том, какой узел заполнил тот или иной поле, и мешают возобновлению работы после прерываний.
Слабая изоляция неисправностей
Этап слабой изоляции ошибок работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. Когда какой-то шаг сбивается, причина сбоя должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Сохраняйте структуру графа простой и типизированной. Вложенные структуры данных скрывают информацию о том, какой узел заполнил тот или иной поле, что приводит к нарушению возобновления работы после перерывов. Этап слабой изоляции ошибок работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Записывайте временные показатели, а также стоимость обработки токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды.
Агрегация привилегий
На этапе агрегации привилегий необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии системы. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь кодовый граф. Для операций, связанных с тратой денег или изменением производственных данных, необходимо предусмотреть утверждение человеком. Подключения, созданные во время компиляции, не гарантируют полноты обработки бизнес-логики.
Ограниченная конкурентность
На этапе ограниченной одновременности необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг, исходя из известной точки контроля, без необходимости угадывания скрытого состояния. Необходимо документировать как успешный, так и восстановительный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Внедрять утверждение человеком для операций, связанных с тратой денег или изменением производственных данных. Настройки на этапе компиляции не заменяют полноты реализации бизнес-логики.
Низкая воспроизводимость
На этапе ограниченной возможности повторного выполнения необходимо заранее определить входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций. Внедрять человеческий контроль там, где происходит трата средств или изменение производственных данных. Компиляционная настройка не гарантирует полноты функционала бизнес-приложения. На этапе ограниченной возможности повторного выполнения необходимо заранее определить входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Регистрировать время выполнения, а также стоимость токенов или запросов вместе с функциональными результатами. Отображение стоимости на ранних этапах предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
3. Какие изменения в инженерии графов
При работе над третьим этапом инженерии графов сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность последующих изменений в коде. Храните конфигурацию отдельно от кода приложения. Файлы с настройками окружения, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь граф. Создавайте контрольные точки после дорогостоящих операций. Функция возобновления работы не должна повторно взимать плату за один и тот же вызов большой языковой модели, когда оператор пытается выполнить следующий узел заново.
Graph:
nodes
edges
shared state
terminal states
interface Node<Input, Output> {
id: string;
inputSchema: Schema<Input>;
outputSchema: Schema<Output>;
timeoutMs: number;
retryPolicy: RetryPolicy;
requiredCapabilities: Capability[];
execute(
input: Input,
context: RunContext
): Promise<Output>;
verify(
output: Output,
context: RunContext
): Promise<Evidence>;
}
interface Edge {
from: NodeId;
to: NodeId;
condition: (
state: WorkflowState
) => boolean;
}
const edges = [
edge(
"build",
"tests",
state => state.build.exitCode === 0
),
edge(
"build",
"repair",
state =>
state.build.exitCode !== 0 &&
state.repairAttempts < 3
),
edge(
"build",
"failed",
state =>
state.build.exitCode !== 0 &&
state.repairAttempts >= 3
)
];
4. Граф для системы доставки с помощью ИИ
При разработке графа 4 A для соответствующей стадии сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Документируйте одновременно успешный и восстановительный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Устанавливайте контрольные точки после дорогостоящих операций. Механизм возобновления работы не должен повторно взимать плату за один и тот же вызов большой языковой модели при повторной попытке оператора обработки последующего узла.
+----------------+
| Threat Model |
+--------+-------+
|
Intake -> Normalize -> Plan ------+-----> Implementation
| | |
| +-------v--------+ |
+--->| Test Planning |-----+
+----------------+ |
v
Build
|
+----------------------+------------------+
| pass | fail
v v
Integration Tests Diagnose -> Repair
| |
+----+----+ +-> Build
| |
pass fail
| |
v +-> Diagnose
Security Check
|
+----+----+
| |
pass high risk
| |
v v
PR Creation Human Approval
| |
+----+----+
|
v
Canary Deploy
|
Runtime Verify
| |
pass fail
| |
v v
Done Rollback -> Failed
5. Состояние должно быть задано, устойчивым и разделенным
При работе над этапом «5 Состояния должны быть заданы» сначала запишите условия работы: необходимые входные данные, сигнал о успехе и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое на каком-либо этапе причина неудачи должна указывать на конкретную ответственность, а не на запутанную структуру обработки. Вносите контрольные точки после дорогостоящих операций. Механизм возобновления работы не должен повторно взимать плату за один и тот же вызов большой языковой модели при повторной попытке обработки последующего элемента. При работе над этапом «5 Состояния должны быть заданы» сначала запишите условия работы: необходимые входные данные, сигнал о успехе и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Регистрируйте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отображение стоимости на ранних этапах предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
{
"runId": "run_93af",
"goal": {
"ticketId": "ENG-482",
"repository": "payments-api",
"baseRevision": "5df87a1"
},
"plan": {
"artifactId": "sha256:71d...",
"version": 2
},
"implementation": {
"commit": "81f3ce2",
"changedFiles": [
"src/refunds/service.ts",
"tests/refunds/service.test.ts"
]
},
"build": {
"exitCode": 0,
"artifactId": "sha256:932..."
},
"verification": {
"unitTests": "passed",
"integrationTests": "passed",
"security": "pending"
},
"budgets": {
"repairAttempts": 1,
"toolCalls": 18,
"tokens": 84320
}
}
{
"eventId": "evt_1092",
"runId": "run_93af",
"nodeId": "integration-tests",
"attempt": 2,
"inputHash": "sha256:8a2...",
"outputHash": "sha256:19c...",
"status": "succeeded",
"startedAt": "2026-09-14T08:41:02Z",
"completedAt": "2026-09-14T08:43:18Z"
}
6. Переходы, управляемые доказательствами
Этап 6 «Переходы, управляемые доказательствами», работает наилучшим образом, если рассматривать его как измеримую структуру. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь граф. Сохраняйте состояние графа простым и типизированным. Вложенные структуры данных скрывают информацию о том, какой узел заполнил тот или иной поле, и приводят к нарушению возобновления работы после перерывов.
type TestEvidence = {
command: string;
revision: string;
exitCode: number;
totalTests: number;
failedTests: number;
reportArtifact: ArtifactRef;
};
function testsPassed(
evidence: TestEvidence,
workflow: WorkflowState
): boolean {
return (
evidence.exitCode === 0 &&
evidence.totalTests > 0 &&
evidence.failedTests === 0 &&
evidence.revision === workflow.currentRevision
);
}
repository_valid
and build_passed
and tests_passed
and security_accepted
and deployment_verified
7. Происхождение артефактов и селективная переигровка
Подход, основанный на концепции происхождения артефактов и этапах выполнения, наилучшим образом работает, если рассматривать его как измеримую структуру. Сначала зафиксируйте один успешный пример выполнения, один случай сбоя и записку о возврате к предыдущему состоянию, прежде чем расширять объем исследования. Документируйте одновременно путь успешного выполнения и путь восстановления. Повторные попытки, проверки со стороны оператора и обработка некорректных сообщений являются частью продукта, а не этапом последующей доработки. Сохраняйте структуру графа простой и типизированной. Вложенные структуры данных маскируют информацию о том, какой узел заполнил тот или иной поле, и мешают возобновлению работы после прерываний.
{
"artifactId": "sha256:f39...",
"type": "test_report",
"producedBy": "integration-tests",
"graphVersion": "delivery-v4",
"inputs": [
"sha256:source-revision-81f3ce2",
"sha256:test-config-a17"
]
}
Source code changed:
invalidate build artifact
invalidate unit-test report
invalidate integration-test report
invalidate deployment artifact
Threat model unchanged:
preserve existing threat-model artifact
Requirements unchanged:
preserve normalized requirements
preserve approved implementation plan
8. Идемпотентность и контроль побочных эффектов
Этап 8 «Идемпотентность и контроль побочных эффектов» работает наилучшим образом, когда рассматривается как измеримая структура. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работы. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое какого-либо шага причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций. Сохраняйте простую и типизированную структуру данных. Вложенные структуры скрывают информацию о том, какой узел заполнил тот или иной поле, что мешает возобновлению работы после прерываний. Этап 8 «Идемпотентность и контроль побочных эффектов» работает наилучшим образом, когда рассматривается как измеримая структура. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работы. Записывайте временные показатели, а также стоимость обработки токенов или запросов вместе с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды.
const idempotencyKey = [
runId,
nodeId,
inputArtifactHash
].join(":");
await deploymentApi.deploy({
idempotencyKey,
revision,
environment
});
deploy_canary -> verify_runtime
|
+-> failure -> rollback_canary
9. Детерминистическое и модельно-ориентированное маршрутизирование
На этапе 9 «Детерминистическое и модельно-ориентированное маршрутизирование» необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища конфиденциальных данных и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. При следующем шаге, представляющем собой выполнение кода или вызов инструмента, предпочтительнее использовать структурированные выходные данные с проверкой соответствия шаблону, а не свободный текст.
if (testReport.failedTests > 0) {
return "repair";
}
if (securityReport.criticalFindings > 0) {
return "human-review";
}
return "deploy";
const decision = await riskClassifier.run({
changeSummary,
affectedServices,
dataClassification,
migrationPlan
});
type RiskDecision = {
level: "low" | "medium" | "high";
reasons: string[];
requiredChecks: CheckId[];
};
10. Планирование, параллелизм и объединение данных
Для этапа 10 «Планирование, параллелизм и объединение данных» необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии системы. Необходимо документировать как успешный, так и аварийный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Человеческое утверждение требуется для операций, связанных с тратой денег или изменением производственных данных. Настройки, выполняемые во время компиляции, не гарантируют полноты функционала продукта.
all required predecessor nodes are complete
and the incoming transition conditions are satisfied
+-> Generate Tests --+
Plan Complete ---+-> Threat Model ----+-> Join -> Implementation Review
+-> API Analysis ----+
Все
На этапе «Все» необходимо заранее определить входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной областью ответственности, а не с запутанной структурой процессов. Внедрять человеческое утверждение для операций, связанных с тратой денег или изменением производственных данных. Наличие связей во время компиляции не гарантирует полноты бизнес-логики. На этапе «Все» необходимо заранее определить входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Регистрировать время выполнения, а также стоимость токенов или запросов вместе с функциональными результатами. Отображение стоимости на ранних этапах предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
Любой
При работе с любым этапом сначала запишите условия контракта: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист помогает сохранять честность при последующих изменениях кода. Храните конфигурацию отдельно от кода приложения. Файлы с настройками окружения, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Создавайте контрольные точки после дорогостоящих операций. Функция возобновления работы не должна снова взимать плату за один и тот же вызов большой языковой модели, когда оператор пытается выполнить следующий узел заново.
Кворум
При работе над этапом Quorum сначала запишите контракт: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Документируйте одновременно успешный сценарий работы и сценарий восстановления. Повторные попытки, проверки со стороны человека и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Создавайте контрольные точки после дорогостоящих операций. Механизм возобновления работы не должен повторно оплачивать один и тот же вызов LLM, когда оператор пытается выполнить задачу снова.
Максимальные усилия
На этапе максимальных усилий сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Предпочитайте небольшие, тестируемые модули большим скриптам. Если какой-то шаг не сработает, причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций. Вносите контрольные точки после дорогостоящих шагов. Система возобновления работы не должна снова взимать плату за один и тот же вызов большой языковой модели при повторной попытке обработки последующего элемента. На этапе максимальных усилий сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Записывайте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
Быстро обнаруживать ошибки
Этап быстрого сбоя работает наилучшим образом, когда его рассматривают как измеримую структуру. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь граф. Сохраняйте состояние графа простым и типизированным. Вложенные структуры данных скрывают информацию о том, какой узел заполнил тот или иной поле, и мешают возобновлению работы после прерываний.
11. Семантика сбоев
Этап 11 «Семантика сбоев» работает наилучшим образом, когда его рассматривают как измеримую структуру. Соберите один идеальный пример транскрипции, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работы. Документируйте одновременно «успешный путь» и «путь восстановления». Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. Сохраняйте структуру графа простой и типизированной. Вложенные структуры скрывают информацию о том, какой узел заполнил тот или иной поле, и мешают возобновлению работы после прерываний.
type FailureClass =
| "transient_dependency"
| "invalid_input"
| "verification_failed"
| "policy_denied"
| "budget_exhausted"
| "human_rejected"
| "unknown";
transient_dependency -> retry with backoff
invalid_input -> return to the upstream producer
verification_failed -> diagnose and repair
policy_denied -> terminal failure
budget_exhausted -> human escalation
human_rejected -> terminal cancellation
unknown -> quarantine and inspect
repair_attempts_remaining
and runtime_budget_available
and token_budget_available
and permitted_blast_radius_not_exceeded
12. Границы безопасности принадлежат узлам
Этап «12 Границ безопасности принадлежат узлам» работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. Когда какой-то шаг сбивается, причина сбоя должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Сохраняйте структуру графа простой и типизированной. Вложенные структуры данных скрывают информацию о том, какой узел заполнил тот или иной поле, и мешают возобновлению работы после прерываний. Этап «12 Границ безопасности принадлежат узлам» работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Записывайте временные показатели, а также стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды.
nodes:
repository_analysis:
capabilities:
- repository:read
implementation:
capabilities:
- repository:read
- workspace:write
create_pull_request:
capabilities:
- repository:pull_request:create
deploy_canary:
capabilities:
- deployment:preview:create
production_release:
capabilities:
- deployment:production:create
approval:
required: true
13. Версионирование и воспроизводимость
На этапе 13 «Версионирование и воспроизводимость» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии системы. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища конфиденциальных данных и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь кодовый граф. Для операций, связанных с тратой денег или изменением данных в производстве, необходимо предусмотреть утверждение человеком. Настройки, заданные на этапе компиляции, не гарантируют полноты обработки бизнес-логики.
{
"runId": "run_93af",
"graph": {
"name": "software-delivery",
"version": "4.2.1"
},
"nodes": {
"planner": "planner@2.3.0",
"implementation": "coding-agent@5.1.2",
"security-review": "security-review@1.8.0"
},
"models": {
"planner": "model-a-2026-08",
"implementation": "model-b-2026-09"
},
"policyVersion": "delivery-policy@3.4.0",
"baseRevision": "5df87a1"
}
14. Наблюдаемость на уровне графа
На этапе 14 «Наблюдаемость на уровне графа» необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии системы. Необходимо документировать как успешный, так и восстановительный пути работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Внедрять утверждение человеком для операций, связанных с тратой денег или изменением производственных данных. Подключение компонентов во время компиляции не гарантирует полноты функционала продукта.
workflow_run_id
graph_version
node_id
node_attempt
parent_node_id
artifact_ids
model_version
prompt_version
15. Минимальная реализация стартапа
На этапе 15 A Minimal Startup необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага он должен указывать на конкретную причину, а не на сложную структуру обработки данных. Внедрять человеческое утверждение для операций, связанных с тратой денег или изменением производственных данных. Наличие связей во время компиляции не гарантирует полноты бизнес-логики. На этапе 15 A Minimal Startup необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Регистрировать время выполнения, а также стоимость токенов или запросов вместе с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
>workflow_definitions
workflow_versions
workflow_runs
node_definitions
node_attempts
transition_events
artifacts
approvals
capability_grants
def schedule(run):
state = load_state(run.id)
candidates = find_pending_nodes(run.graph_version)
for node in candidates:
if dependencies_satisfied(node, state):
if incoming_guards_allow(node, state):
enqueue(
run_id=run.id,
node_id=node.id,
graph_version=run.graph_version
)
def execute_node(job):
attempt = create_attempt(job)
try:
inputs = resolve_inputs(job)
validate(inputs, job.node.input_schema)
capabilities = issue_capabilities(job.node)
output = job.node.execute(inputs, capabilities)
validate(output, job.node.output_schema)
evidence = job.node.verify(output)
persist_success(attempt, output, evidence)
evaluate_outgoing_edges(job.run_id, job.node.id)
except Exception as error:
failure = classify_failure(error)
persist_failure(attempt, failure)
apply_failure_transition(job, failure)
finally:
revoke_capabilities(job.node)
16. Переход от цикла к графу
При работе над пунктом 16 «Переход от цикла к графу» сначала запишите спецификацию: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист поможет сохранять честность последующих изменений в коде. Храните конфигурацию отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь граф. Создавайте контрольные точки после дорогостоящих операций. Функция возобновления выполнения не должна повторно взимать плату за один и тот же вызов большой языковой модели, когда оператор пытается выполнить следующий узел заново.
Шаг 1: Добавление инструментов к существующему циклу
При разработке этапа 1 инструмента запишите сначала контракт: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Документируйте одновременно успешный сценарий работы и сценарий восстановления. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Выполняйте контрольные точки после дорогостоящих шагов. Механизм возобновления работы не должен повторно взимать плату за один и тот же вызов LLM, когда оператор пытается выполнить последующий узел заново.
Шаг 2: Определение стабильных этапов
При работе над этапом 2 «Определение стабильной версии» сначала запишите контракт: необходимые входные данные, сигнал о успехе и действия при частичной неудаче. Такой чек-лист помогает сохранять честность при последующих изменениях кода. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. Когда какой-то шаг терпит неудачу, ошибка должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Вносите контрольные точки после дорогостоящих шагов. Система возобновления работы не должна снова взимать плату за один и тот же вызов LLM при повторной попытке обработки последующего узла. При работе над этапом 2 «Определение стабильной версии» сначала запишите контракт: необходимые входные данные, сигнал о успехе и действия при частичной неудаче. Такой чек-лист помогает сохранять честность при последующих изменениях кода. Записывайте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отображение стоимости заранее предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
Этап 3: Определение типизированных артефактов
Этап 3 «Определение типизированной структуры» наилучшим образом работает, если рассматривать его как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь граф. Сохраняйте состояние графа простым и типизированным. Вложенные структуры данных скрывают информацию о том, какой узел заполнил тот или иной поле, и мешают возобновлению работы после прерываний.
Шаг 4: Внешняя реализация переходов
Этап 4 «Внешняя обработка переходов» работает наилучшим образом, если рассматривать его как измеримую структуру. Соберите один идеальный пример выполнения, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Документируйте одновременно успешный и восстановительный пути выполнения. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не этапом последующей доработки. Сохраняйте структуру графа простой и типизированной; вложенные структуры скрывают информацию о том, какой узел заполнил тот или иной поле, и мешают возобновлению работы после прерываний.
Шаг 5: Добавление независимой верификации
Этап «5. Добавить независимую стадию» работает наилучшим образом, когда его рассматривают как измеримую среду. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое какого-либо шага причина должна быть связана с конкретной ответственностью, а не с запутанной цепочкой операций. Сохраняйте простую структуру графа и чёткое указание типов данных. Вложенные структуры скрывают информацию о том, какой узел заполнил тот или иной поле, что приводит к нарушению работоспособности после перерывов. Этап «5. Добавить независимую стадию» работает наилучшим образом, когда его рассматривают как измеримую среду. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Записывайте временные показатели, а также стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные расходы при переходе от демо-среды к общедоступным средам.
Шаг 6: Введение контрольных точек
На этапе 6 «Введение контрольных точек» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной контрольной точки, не догадываясь о скрытом состоянии. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Для операций, связанных с тратой денег или изменением производственных данных, необходимо предусмотреть утверждение человеком. Подключения, созданные во время компиляции, не гарантируют полноты обработки бизнес-логики.
Шаг 7: Изоляция функциональных возможностей
На этапе 7 «Изоляция функционала» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии системы. Необходимо задокументировать как успешный, так и аварийный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Внедрять утверждение человеком там, где происходит трата средств или изменение производственных данных. Наличие связей во время компиляции не гарантирует полноты функционала продукта.
Шаг 8: Добавление ограниченных механизмов восстановления
Для этапа «Добавить ограниченную область» в Шаге 8 необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций. Внедрять утверждение человека для операций, связанных с тратой денег или изменением производственных данных. Наличие связей во время компиляции не гарантирует полноты бизнес-логики. Для этапа «Добавить ограниченную область» в Шаге 8 необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Регистрировать время выполнения, а также стоимость токенов или запросов вместе с функциональными результатами. Отображение стоимости на ранних этапах предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
Шаг 9: Параллелизация независимых операций
При выполнении шага 9 «Параллелизация независимых операций» сначала запишите описание процесса: необходимые входные данные, сигнал успешного завершения и действия при частичной неудаче. Такой чек-лист поможет сохранять честность последующих изменений в коде. Храните конфигурацию отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь граф. Создавайте контрольные точки после дорогостоящих операций. Функция возобновления работы не должна повторно запрашивать тот же вызов большой языковой модели, когда оператор пытается выполнить следующий узел.
Шаг 10: Версионирование графа
При работе над этапом версии 10 сначала запишите условия контракта: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Документируйте одновременно успешный и восстановительный пути выполнения. Повторные попытки, проверки со стороны оператора и обработка некорректных сообщений являются частью продукта, а не элементами последующей доработки. Выполняйте контрольные точки после дорогостоящих шагов. Механизм возобновления работы не должен повторно взимать плату за один и тот же вызов LLM при повторной попытке оператора обработать следующий узел.
17. Распространённые антипаттерны проектирования графов
При работе над 17 этапами проектирования графов сначала запишите контракт: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой чек-лист помогает сохранять честность при последующих изменениях кода. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. Когда какой-то шаг терпит неудачу, ошибка должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Вносите контрольные точки после дорогостоящих шагов. Механизм возобновления работы не должен повторно оплачивать один и тот же вызов большой языковой модели, когда оператор пытается выполнить более поздний узел.
Один агент на узел
Детерминистичные решения, контролируемые моделью
Общее изменяемое состояние
Бесконечные циклы
Проверка, сообщаемая агентом
Глобальные учетные данные
Отсутствующие пути компенсации
Графы без информации о происхождении
Преждевременное динамическое маршрутизирование
18. Когда граф не нужен
Заключение
Implicit control flow
becomes
explicit workflow topology
Conversation state
becomes
typed durable state
Agent-declared success
becomes
evidence-gated completion
Global retries
become
bounded local recovery
Shared privileges
become
node-scoped capabilities
Complete reruns
become
dependency-aware replay
Sequential execution
becomes
controlled concurrency
Opaque behavior
becomes
graph-level observability