Практические советы: устранение багов недетерминистичного повторения действий в циклах искусственных агентов
Пошаговое руководство по практическим рекомендациям: устранение недетерминистических ошибок воспроизведения в циклах искусственных агентов: контракты, проверки и готовые блоки кода для команд, использующих эту схему.
В следующих заметках описывается практический подход к решению проблемы «исправления недетерминистичных ошибок в циклах искусственного интеллект-агента». Основное внимание уделяется контрактам, проверкам и временным заменителям кода, а не мотивирующим аспектам. На этапе обзора сначала запишите контракт: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Рядом с функциональными результатами записывайте время выполнения и стоимость токенов или запросов. Отображение затрат с самого начала предотвращает неожиданные расходы при переходе от демо-версии к совместным средам.
Ошибка, прежде чем появятся названия
Баг на этапе до запуска лучше всего рассматривать как измеримую поверхность. Соберите один образец успешной работы, один пример сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь граф. Сохраняйте состояние графа простым и типизированным. Вложенные структуры данных скрывают информацию о том, какой узел записал какое поле, и мешают возобновлению работы после прерываний.
# ❌ What I almost wrote — LLM call INSIDE the workflow.
@workflow.defn
class SourcingWorkflow:
@workflow.run
async def run(self, brief: SourcingBriefInput) -> SourcingResult:
suppliers = await workflow.execute_activity(research_activity, brief)
scored = await workflow.execute_activity(score_activity, suppliers)
# The LLM call — right here, in the workflow. THIS IS THE BUG.
# If worker dies here, replay will re-call the LLM and mutate state/history.
response = await llm_client.complete(
messages=build_decide_prompt(scored),
temperature=0.0,
)
selected = parse_llm_decision(response.content, scored)
approval = await workflow.wait_condition(...)
# ...create PO, initiate payment
# ✅ The fix — LLM call moved into an activity.
@activity.defn
async def decide_activity(scored: list[dict], brief: SourcingBriefInput) -> dict:
"""The LLM call lives here — in the activity, not the workflow."""
from app.agentmesh.llm import get_llm_client
client = get_llm_client()
response = await client.complete(
messages=build_decide_prompt(scored),
temperature=0.0,
)
selected, rationale = parse_llm_decision(response.content, scored)
return {"selected_supplier": selected, "decision_reason": rationale}
@workflow.defn
class SourcingWorkflow:
@workflow.run
async def run(self, brief: SourcingBriefInput) -> SourcingResult:
suppliers = await workflow.execute_activity(research_activity, brief)
scored = await workflow.execute_activity(score_activity, suppliers)
# The LLM call is NOWHERE in the workflow.
# The activity result is recorded. On replay, it's injected.
decision = await workflow.execute_activity(
decide_activity,
args=(scored, brief),
)
Правило: повторная обработка должна воспроизводить ту же историю
Процесс повторной обработки по закону будет работать наилучшим образом, если рассматривать его как измеримую поверхность. Сначала зафиксируйте один успешный пример, один случай сбоя и запись о возврате к предыдущему состоянию, прежде чем расширять объем работ. Документируйте одновременно успешный и восстановительный пути выполнения. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не последующими доработками. Сохраняйте структуру графа простой и типизированной; вложенные структуры скрывают информацию о том, какой узел заполнил тот или иной поле, и мешают возобновлению работы после прерываний.
Нарушение: что происходит, когда LLM используется в рабочем процессе
Этап выявления нарушений работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. Когда какой-то шаг срабатывает некорректно, причина сбоя должна указывать на конкретный элемент ответственности, а не на запутанную цепочку операций. Установите лимиты на количество токенов за один ход и за сессию. Инструменты агентов активно расширяют объем контекста; жесткие ограничения предотвращают появление неожиданных счетов. Этап выявления нарушений работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Записывайте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счета при переходе от демо-версии к общим средам.
Почему параметр “temperature=0.0” не спасет вас
Для этапа температуры Why 0 0 необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Вводите ручное утверждение для операций, связанных с тратой денег или изменением производственных данных. Подключение на этапе компиляции не гарантирует полноты охвата бизнес-логики.
Граница: активность представляет собой мембрану недетерминизма
Для определения этапа выполнения задачи необходимо заранее установить входные данные, ответственного за шаг и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии системы. Необходимо документировать как успешный, так и аварийный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Внедрять утверждение человеком для операций, связанных с тратой денег или изменением производственных данных. Настройки на этапе компиляции не заменяют полноты бизнес-логики.
Код: как это выглядит на самом деле в AgentMesh
Для кода этого этапа необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага он должен указывать на конкретную причину, а не на сложную структуру обработки данных. Внедрять человеческое утверждение для операций, связанных с тратой денег или изменением производственных данных. Компиляционная настройка не гарантирует полноты функционала бизнес-приложения. Для кода этого этапа необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Регистрировать время выполнения, а также стоимость токенов или запросов вместе с функциональными результатами. Отображение стоимости на ранних этапах предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
Temporal Workflow (deterministic — replayed)
└── Activity: run_graph_until_interrupt (non-deterministic — recorded once)
└── LangGraph StateGraph
└── decide_node (async function)
└── get_llm_client().complete() ← the LLM call
Рабочий процесс — чистая оркестрация (workflow.py)
При работе над этапом чистой оркестрации рабочего процесса сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность последующих изменений в коде. Храните конфигурацию отдельно от кода приложения. Файлы с настройками окружения, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь граф задач. Вносите контрольные точки после дорогостоящих шагов. Функция возобновления выполнения не должна повторно взимать плату за один и тот же вызов большой языковой модели, когда оператор пытается выполнить более поздний узел.
@workflow.defn
class SourcingWorkflow:
@workflow.run
async def run(self, brief: SourcingBriefInput) -> SourcingResult:
# ↓ This is the boundary. The activity runs once. Result is recorded.
graph_result = await workflow.execute_activity(run_graph_until_interrupt, brief, ...)
# Wait for human signal — a Temporal primitive, not an LLM call.
# On replay, the signal is injected from history.
await workflow.wait_condition(lambda: self._approval_received, timeout=timedelta(hours=24))
# ↓ Another boundary. Resume activity runs once. Result is recorded.
resume_result = await workflow.execute_activity(resume_graph, self._approval_data, ...)
# ↓ Side effects — each is its own activity with its own retry policy.
po_result = await workflow.execute_activity(create_po_activity, args=(...), ...)
Активность — место проявления недетерминизма (activity.py)
При работе над заданием, связанным с этапами выполнения, сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист помогает сохранять честность при последующих изменениях кода. Документируйте одновременно успешный и восстановительный пути выполнения. Повторные попытки, проверки со стороны человека и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Устанавливайте контрольные точки после дорогостоящих операций. Механизм возобновления выполнения не должен повторно взимать плату за один и тот же вызов LLM при повторной попытке оператора обработать следующий узел.
@activity.defn
async def run_graph_until_interrupt(brief: SourcingBriefInput) -> dict:
graph = build_sourcing_graph(checkpointer=await get_checkpointer())
config = {"configurable": {"thread_id": activity.info().workflow_id}}
# ↓ Everything inside this call is non-deterministic. It runs ONCE.
# The result dict is recorded in the event history. On replay, it's injected.
final_state = await graph.ainvoke({"brief": brief, "suppliers": [], "attempts": 0, ...}, config)
return {"paused": True, "selected_supplier": selected, "suppliers": final_state.get("suppliers", [])}
Узел графа — место, где фактически запускается LLM (graph.py)
При работе над узлом графа, соответствующим определенной стадии, сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист помогает сохранять честность при последующих изменениях кода. Лучше использовать небольшие, тестируемые модули вместо обширных скриптов. Если какой-то шаг не сработает, причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций. Храните в кэше стабильные инструкции системы и схемы инструментов. Повторная отправка одинаковых данных — распространенная причина лишних затрат. При работе над узлом графа, соответствующим определенной стадии, сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист помогает сохранять честность при последующих изменениях кода. Регистрируйте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды.
async def decide_node(state: AgentState) -> dict:
scored = state.get("scored_suppliers", [])
messages = build_decide_prompt(brief.item, brief.quantity, brief.budget, scored, past_decisions)
# ↓ THE LLM CALL. This is the non-determinism that must never be in the workflow.
response = await get_llm_client().complete(messages=messages, temperature=0.0, max_tokens=1000)
selected, rationale = parse_llm_decision(response.content, scored)
return {"selected_supplier": selected, "decision_reason": rationale, "cost_incurred": response.cost_usd} # ↓ THE LLM CALL. This is the non-determinism that must never be in the workflow.
response = await get_llm_client().complete(messages=messages, temperature=0.0, max_tokens=1000)
Когда границы становятся нечеткими
Подход, при котором граница рассматривается как измеримая поверхность, работает наилучшим образом. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь граф. Сохраняйте структуру графа простой и типизированной. Вложенные структуры данных маскируют информацию о том, какой узел заполнил тот или иной поле, и приводят к нарушению возобновления работы после перерывов.
Temporal event history LangGraph checkpoint (Postgres)
└── ActivityCompleted(result) └── graph state at interrupt()
paused: True node: "approve"
selected: SupplierB selected: SupplierB
suppliers: [A, B, C] suppliers: [A, B, C]
Шаблон изоляции — одинаковые ограничения везде
Шаблон изоляции на той же стадии работает лучше всего, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Документируйте одновременно путь успешной работы и путь восстановления. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не последующими улучшениями. Сохраняйте состояние графа простым и типизированным. Вложенные структуры скрывают информацию о том, какой узел заполнил какое поле, и мешают возобновлению работы после прерываний.
Та же ограничение в других стеках агентов
Тот же принцип ограничений на этапе работает лучше всего, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Предпочитайте небольшие, тестируемые единицы вместо обширных скриптов. Когда какой-то шаг сбивается, причина сбоя должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Держите состояние графа простым и типизированным. Вложенные структуры скрывают информацию о том, какой узел заполнил тот или иной поле, и мешают возобновлению работы после прерываний. Тот же принцип ограничений на этапе работает лучше всего, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Записывайте временные показатели, а также стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды.
Стоимость: что вы теряете ради детерминизма
Перед изменением кода необходимо определить затраты, входные данные, ответственного за выполнение шага и критерии завершения. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь граф задач. Вводите утверждение человека для ребер, которые приводят к тратам денег или изменению производственных данных. Подключение на этапе компиляции не гарантирует полноты охвата бизнес-логики.
Особый случай 1: Длительные операции и проблема «пульса»
Для крайнего случая 1 с длительным этапом обработки необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо одновременно задокументировать успешный сценарий работы и сценарий восстановления. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Внедрять утверждение человеком для тех случаев, когда происходит трата средств или изменение данных в продакшене. Подключение компонентов на этапе компиляции не гарантирует полноты функционала продукта.
@activity.defn
async def run_graph_until_interrupt(brief: SourcingBriefInput) -> dict:
# Long-running: graph may run 5+ minutes with multiple LLM calls
for node in graph.stream(initial_state, config):
activity.heartbeat() # ← "I'm alive, don't timeout me"
# ... process node output
Крайний случай 2: Трансляция токенов LLM через Temporal
Для этапа потоковой обработки Edge case 2 необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной функцией, а не с запутанной структурой всего процесса. При следующем шаге, представляющем собой код или вызов инструмента, лучше использовать структурированные выходные данные с проверкой соответствия шаблону вместо свободного текста. Для этапа потоковой обработки Edge case 2 необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рядом с функциональными результатами следует записывать время выполнения, а также стоимость токенов или запросов. Отображение затрат на раннем этапе предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
Крайний случай 3: Политики повторной попытки выполнения задач — не все задачи должны повторяться одинаково
При работе над этапом «Крайний случай 3» сначала запишите условия выполнения задачи: необходимые входные данные, сигнал о успешном выполнении и что происходит при частичной неудаче. Такой чек-лист поможет сохранять честность последующих изменений в коде. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Создавайте точки контроля после дорогостоящих операций. Функция возобновления выполнения не должна снова взимать плату за один и тот же вызов большой языковой модели, когда оператор пытается выполнить более поздний элемент.
# Side effect — strict, non-retryable. Idempotency key handles safety.
po_result = await workflow.execute_activity(
create_po_activity,
args=(supplier, item, quantity, price),
retry_policy=workflow.RetryPolicy(
initial_interval=timedelta(seconds=1),
maximum_attempts=1, # ← don't retry. Idempotency key prevents duplicates.
non_retryable_error_types=["DuplicatePOError"],
),
)
# Verification — aggressive retry, but with backoff for eventual consistency
po_verification = await workflow.execute_activity(
verify_po_exists,
args=(po_result["po_id"],),
retry_policy=workflow.RetryPolicy(
initial_interval=timedelta(seconds=2), # ← give the DB time to sync
maximum_attempts=5,
),
)
Ментальная модель
При работе над этапом создания ментальной модели сначала запишите условия работы: необходимые входные данные, сигнал успешного завершения и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Документируйте одновременно успешный сценарий работы и сценарий восстановления. Повторные попытки, проверки со стороны человека и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Храните в кэше стабильные системные инструкции и схемы инструментов. Пересылка одинаковых заголовков — распространенная причина избыточных ресурсов.
Что будет в следующей статье
Во время работы на этапе определения требований сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Предпочитайте небольшие, тестируемые модули большим скриптам. Если какой-то шаг не сработает, причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций. Выполняйте проверки после дорогостоящих шагов. Система возобновления работы не должна снова взимать плату за один и тот же вызов большой языковой модели при повторной попытке обработки последующего элемента. Во время работы на этапе определения требований сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Записывайте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
Ссылки
Этап справочных материалов работает наилучшим образом, когда его рассматривают как измеримую структуру. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь граф. Сохраняйте состояние графа простым и типизированным. Вложенные структуры данных скрывают информацию о том, какой узел заполнил тот или иной поле, и приводят к нарушению последовательности выполнения после перерывов.
Чек-лист операционной деятельности
На этапе чек-листа операционной деятельности определите входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия элементам, определите критерии успеха и не допускайте безответственного частичного выполнения задач.
Необходимо получать одобрение человека для операций, связанных с тратой денег или изменением производственных данных. Подключение на этапе компиляции не гарантирует полноты функционала для бизнеса.
Напишите краткий руководство: как обновлять ключи, как опустошать очередь, как откатывать последнюю операцию ввода данных.
Записывайте время выполнения операций, а также стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счета при переходе с демо-среды в общедоступные среды.
Необходимо получать одобрение человека для операций, связанных с тратой денег или изменением производственных данных. Подключение на этапе компиляции не гарантирует полноты функционала для бизнеса.
Перед переходом на более сложную версию стека заморозьте существующие версии, сохраните эталонный вариант работы для критически важных процессов и убедитесь, что известны шаги отката. В общедоступных средах необходимы ограничения на частоту запросов, проверки принадлежности и четко определенный ответственный за обновление секретов. Лучше выбирать надежность, чем креативные, но единоразовые демонстрации.
Примечание к пакету обновлений для 11b06b04feeb: не включайте ключи поставщиков в репозиторий, установите лимит токенов на одну сессию и храните транскрипции рядом с фиксами для оценки, чтобы последующие замены моделей оставались сопоставимыми.
При работе над этапом 0 записи по усилению безопасности сначала опишите контракт: необходимые входные данные, сигнал успешного выполнения и последствия частичной неудачи. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Документируйте одновременно успешный сценарий и сценарий восстановления. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не последующими улучшениями.
Деталь усиления безопасности 0/898: измерьте время выполнения, класс ошибки и расход токенов для этого примечания, затем решите, следует ли сохранять изменение на основе фиксированного набора критериев, а не на основе устных замечаний.
Этап 1 усиления безопасности работает наилучшим образом, если рассматривать его как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Дайте названия соответствующим элементам, определите критерии успеха и не соглашайтесь на молчаливое частичное выполнение задач.
Подробности усиления безопасности 1/898: измерьте время выполнения, класс ошибки и количество использованных токенов для этой записи, затем решите, следует ли сохранять изменения, опираясь на заранее установленный набор критериев, а не на единичные примеры.
Для второго этапа усиления безопасности необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии системы. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь кодовый граф.
Подробности усиления безопасности 2/898: измеряйте время выполнения, класс ошибок и расход токенов для данного шага, затем принимайте решение о сохранении изменений на основе заранее определенного набора критериев, а не на основе устных оценок.
При работе над третьим этапом инструкций по усилению безопасности сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Лучше использовать небольшие, тестируемые модули вместо обширных скриптов. Если какой-то шаг не сработает, причина неудачи должна указывать на конкретную ответственность, а не на запутанную цепочку операций.
Подробности усиления безопасности 3/898: измерьте время выполнения, класс ошибки и расход токенов для данной инструкции, затем решите, следует ли сохранять изменение, опираясь на установленный набор критериев, а не на субъективные оценки.
Четвертый этап инструкций по усилению безопасности лучше всего работает, если рассматривать его как измеримую область. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Записывайте время выполнения, а также стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды.
Подробности усиления безопасности 4/898: измерьте время выполнения, класс ошибки и расход токенов для этой записи, затем решите, следует ли сохранить изменение на основе фиксированного набора вопросов, а не на основе единичных случаев.
На этапе 5 записи о усилении безопасности определите входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Документируйте как успешный путь, так и путь восстановления одновременно. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не последующими улучшениями.
Подробности усиления безопасности 5/898: измерьте время выполнения, класс ошибки и расход токенов для этой записи, затем решите, следует ли сохранить изменение на основе фиксированного набора вопросов, а не на основе единичных случаев.
На этапе 0 записей по укреплению безопасности лучше всего работает подход, при котором рассматривается измеримая поверхность. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Записывайте время выполнения, стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
Подробности укрепления безопасности 0/917: измерьте время выполнения, класс ошибки и расход токенов для данной записи, затем решите, следует ли сохранять изменения, опираясь на фиксированный набор вопросов, а не на устные описания.
Для этапа 1 записей по укреплению безопасности определите входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Документируйте как успешный путь выполнения, так и путь восстановления. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не элементами последующей доработки.
Подробности усиления безопасности 1/917: измерьте время работы стены, класс ошибки и расход токенов для этой записи, затем решите, следует ли сохранять изменения на основе фиксированного набора вопросов, а не на основе единичных примеров.