Головна / Статті

Практичні нотатки: Вивчення LangGraph: Подорож серед агентів та дошок

Покроковий посібник з практичних нотаток: Навчання LangGraph – подорож серед агентів, дошки: контракти, перевірки та слоти для коду для команд, які використовують цю схему.

Видавець: REACTAPP.TOP14 хв читання3277 слів

Джерела: Learning LangGraph : A Journey Through Agents, Blackboards, and Bottlenecks

Наведені нижче примітки описують практичний підхід до вивчення «Learning LangGraph : A Journey Through Agents, Blackboards, and Bottlenecks». Основна увага приділяється контрактам, перевіркам та місцям для вставки коду, а не мотиваційному опису. Під час вивчення огляду спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Записуйте час виконання та витрати на токени або запити поруч із функціональними результатами. Відображення витрат заздалегідь запобігає несподіваним рахункам під час переходу від демо-версії до спільних середовищ.

Крок 1: Мінімальний агент

Крок 1: Мінімальний агент найкраще функціонує, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь граф. Зберігайте стан графа у простій та типованій формі. Вкладені блоки приховують інформацію про те, який вузол заповнив яке поле, і ускладнюють продовження роботи після перерв.

from langchain.agents import create_agent          # langchain 1.x (NOT langgraph.prebuilt)
from langchain.tools import tool
from langchain_anthropic import ChatAnthropic

# 1. Model
llm = ChatAnthropic(model="claude-haiku-4-5", max_tokens=1024)

# 2. Tool — a plain function + @tool.
#    - type hints (drug_name: str) become the input schema
#    - the docstring is what the LLM reads to decide WHEN to call it
#    The model only "sees" the signature + docstring, so write the docstring
#    like an API description.
@tool
def get_drug_targets(drug_name: str) -> str:
    """Return the protein targets for a given drug name."""
    return "EGFR, BRAF"   # real data-source call goes here

# 3. System prompt — a plain string
SYSTEM_PROMPT = "You are a research assistant. Use the tools to gather evidence."

# 4. Build the agent
agent = create_agent(model=llm, tools=[get_drug_targets], system_prompt=SYSTEM_PROMPT)

# 5. Run it — pass in {"messages": [...]}, get the full message list back
result = agent.invoke({"messages": [{"role": "user", "content": "What does metformin target?"}]})
print(result["messages"][-1].content)   # last message = final answer
@tool
def calculator(expression: str) -> str:
    """Evaluate a basic arithmetic expression like '2 + 2 * 3'."""
    return str(eval(expression))   # fine for learning; never eval untrusted input in prod

Крок 2: Змусити два агенти спілкуватися

Крок 2: Найкращий спосіб змусити двох агентів взаємодіяти — це розглядати його як вимірювану структуру. Збережіть один ідеальний запис розмови, один випадок невдачі та примітку про скасування дій перед розширенням обсягу. Документуйте як успішний, так і відновлювальний сценарії одночасно. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації. Зберігайте стан графа у простій та типованій формі. Вкладені структури приховують інформацію про те, який вузол заповнив яке поле, і ускладнюють продовження роботи після перерв.

Варіант 1: Повідомлення

Варіант 1: Система Messages найкраще функціонує, коли її розглядають як вимірювану структуру. Збережіть один ідеальний запис діяльності, один випадок збою та примітку щодо скасування змін перед розширенням обсягу роботи. Віддавайте перевагу невеликим, тестованим одиницям перед складними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій. Зберігайте стан графа у простій та типованій формі. Вкладені структури приховують інформацію про те, який вузол заповнив яке поле, що ускладнює продовження роботи після перерв. Варіант 1: Система Messages найкраще функціонує, коли її розглядають як вимірювану структуру. Збережіть один ідеальний запис діяльності, один випадок збою та примітку щодо скасування змін перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Чітке бачення витрат заздалегідь запобігає несподіваним витратам під час переходу від демо-версії до спільних середовищ.

Варіант 2: Blackboard

Для варіанту 2: Blackboard — необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Конфігурацію слід тримати окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь граф. Необхідно передбачити людське схвалення для дій, які призводять до витрат грошей чи змінюють дані у продакшені. Підключення на етапі компіляції не є гарантією повноти бізнес-функціоналу.

Крок 3: Виведення введених даних з одного агента

Для кроку 3: отримання введених даних з одного агента, перед зміною коду необхідно визначити вхідні дані, власника кроку та критерії завершення. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не здогадуючись про прихований стан. Необхідно задокументувати як шлях успішного виконання, так і шлях відновлення. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації. Встановлюйте людське схвалення для операцій, які призводять до витрат грошей чи змінюють дані у продакшені. Підключення на етапі компіляції не є гарантією повності функціоналу продукту.

from pydantic import BaseModel, Field

class ResearchOutput(BaseModel):
    attraction: str = Field(description="2 sentences about the attraction")
    city: str = Field(description="1 sentence about the city it is in")

agent = create_agent(
    model=llm,
    tools=[attraction_info, city_info],
    system_prompt=SYSTEM_PROMPT,
    response_format=ResearchOutput,   # <- agent emits this typed object
)
result = agent.invoke({"messages": [...]})
out = result["structured_response"]   # a ResearchOutput instance
out.attraction   # str
out.city         # str
def research_node(state):
    out = research(state["topic"])           # ResearchOutput
    return {"research": out.attraction, "city": out.city}

Зв’язок, який це створює

Для зв’язку, який це створює, необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Краще використовувати невеликі, тестовані одиниці замість об’ємних скриптів. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану систему. Встановлюйте людське схвалення для операцій, які призводять до витрат грошей чи змінюють дані у продакшені. Підключення на етапі компіляції не є гарантією повноти бізнес-функціоналу. Для зв’язку, який це створює, необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Візуалізація витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища у спільні середовища.

SYSTEM_PROMPT = "...\n" + "\n".join(f"- {t.name}: {t.description}" for t in TOOLS)

Чотири варіанти, по одному дисплею кожен

Під час роботи з форматом «Чотири варіанти, по одному дисплею кожен» спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Зберігайте конфігурацію окремо від коду додатку. Файли середовища, сховища секретних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь код. Робіть контрольні пункти після дорогих операцій. Функція відновлення не повинна знову стягувати плату за той самий виклик LLM, коли оператор перезапускає пізнішу ланку.

Крок 4: Чому це так повільно — і що насправді це виправляє

Під час виконання кроку 4: «Чому це так повільно — і що насправді це виправляє?», спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається при частковій невдачі. Цей перелік допоможе зберегти чесність подальших змін у коді. Одночасно задокументуйте шлях успішного виконання та шлях відновлення. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації. Робіть контрольні пункти після дорогих кроків. Система відновлення не повинна знову стягувати плату за той самий виклик LLM, коли оператор намагається знову виконати пізніший етап.

def _crowd_score_sync(attraction: str) -> str:   # plain blocking function
    total = 0
    for i in range(60_000_000):
        total += i
    return f"... {total % 100} ..."

@tool
async def crowd_score(attraction: str) -> str:
    return await asyncio.to_thread(_crowd_score_sync, attraction)

Чому агент ReAct все одно залишається повільним

Під час роботи над питанням, чому агент ReAct все одно залишається повільним, спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається при частковій невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Віддавайте перевагу невеликим, тестованим одиницям перед об’ємними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність операцій. Робіть контрольні пункти після дорогих кроків. Функція відновлення не повинна знову оплачувати один і той самий виклик LLM, коли оператор намагається виконати пізніший етап. Під час роботи над питанням, чому агент ReAct все одно залишається повільним, спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається при частковій невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Записуйте час виконання та витрати на токени або запити поруч із функціональними результатами. Відображення витрат на ранньому етапі запобігає несподіваним оплатам, коли процес переходить від демо-версії до спільних середовищ.

Крок 5: Одночасна робота з цілими пайплайнами

Крок 5: Одночасна робота з цілими пайплайнами найкраще функціонує, якщо її розглядати як вимірювану характеристику. Зберігайте один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь граф. Зберігайте стан графа у простій та типованій формі. Вкладені структури приховують інформацію про те, який вузол записав яке поле, і ускладнюють продовження роботи після перерв.

Крок 6: Забезпечення ефективної роботи кешування

Крок 6: Щоб кешування справді функціонувало ефективно, його краще розглядати як показник, який можна виміряти. Зафіксуйте один ідеальний варіант роботи, один випадок збою та примітки щодо скасування змін перед розширенням обсягу. Документуйте як успішний, так і відновлювальний сценарії роботи разом. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації. Зберігайте стан графа у простому та типованому вигляді. Вкладені структури приховують інформацію про те, який вузол заповнив яке поле, і ускладнюють продовження роботи після перерв.

system_prompt = "You are a travel research agent..."   # string: no keys

content = [{                                            # dict: has keys
    "type": "text",
    "text": "You are a travel research agent...",
    "cache_control": {"type": "ephemeral"},            # <- attaches here
}]
from langchain_anthropic.middleware import AnthropicPromptCachingMiddleware

agent = create_agent(
    model=llm, tools=[...], system_prompt=SYSTEM_PROMPT,  # plain string
    middleware=[AnthropicPromptCachingMiddleware()],
)

Крок 7: Забезпечення довговічності «чорної дошки»

Крок 7: Забезпечення довговічності дошки записів найкраще ефективне, якщо її розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Віддавайте перевагу невеликим, тестованим одиницям перед складними сценаріями. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій. Зберігайте стан графа у простому та типованому вигляді. Вкладені структури приховують інформацію про те, який вузол заповнив яке поле, що ускладнює продовження роботи після перерв. Крок 7: Забезпечення довговічності дошки записів найкраще ефективне, якщо її розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Чітке бачення витрат заздалегідь запобігає несподіваним витратам під час переходу з демо-середовища до спільних.

Чек-лист операцій

Для контрольного списку операцій необхідно визначити вхідні дані, відповідальну особу за кожен крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан.

Розглядайте цю стадію як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового завершення роботи.

Забезпечте людське схвалення для операцій, які призводять до витрат грошей чи змінюють дані у продакшені. Компіляційна налаштування не є гарантією повності виконання завдань у бізнес-середовищі.

Напишіть короткий посібник: як змінювати ключі, як спорожнювати чергу, як скасовувати останнє введення даних.

Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Чітке бачення витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища у спільні середовища.

Встановіть людське схвалення для тих етапів, де витрачаються гроші або змінюються дані виробництва. Підключення під час компіляції не є гарантією повноти бізнес-функціоналу.

Перш ніж переходити на нову версію стеку, заморозьте існуючі версії, створіть остаточний запис для критичного шляху виконання та підтвердьте кроки для скасування змін. У спільних середовищах необхідні обмеження на частоту використання, перевірки прав доступу та чіткий власник для зміни секретних ключів. Віддавайте перевагу надійності перед креативними одноразовими демонстраціями.

Примітка до версії 7a480fca3eb9: не включайте ключі постачальника до репозиторію, встановіть ліміт на токени на кожну сесію та зберігайте записи поруч із фіксами для оцінки, щоб подальша заміна моделей залишалася порівнянною.

Під час роботи над приміткою щодо зміцнення №0 спочатку запишіть умови договору: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Документуйте як шлях успішної роботи, так і шлях відновлення одночасно. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої доробки.

Деталь зміцнення 0/913: вимірюйте час виконання, клас помилки та кількість витрачених токенів для цієї примітки, а потім вирішуйте, чи залишити зміну, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Примітка щодо зміцнення №1 найкраще робити, якщо розглядати її як вимірювану поверхню. Збережіть один ідеальний запис, один випадок невдачі та примітку про скасування змін перед розширенням обсягу роботи. Розглядайте цей етап як договір між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового завершення роботи.

Деталь посилення безпеки 1/913: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Для запису про посилення безпеки 2 визначте вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не здогадуючись про прихований стан. Зберігайте конфігурацію поза кодом додатку. Файли середовища, сховища секретів та флаги функцій мають знаходитися в одному місці, яке оператори можуть перевірити, не читаючи весь граф.

Деталь посилення безпеки 2/913: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Під час роботи над пунктом 3 щодо посилення безпеки спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається при частковій невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Віддавайте перевагу невеликим, тестованим одиницям перед об’ємними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій.

Деталь посилення безпеки 3/913: вимірюйте час виконання, клас помилки та кількість витрачених токенів для цього пункту, а потім вирішуйте, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Пункт 4 щодо посилення безпеки найкраще працює, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис виконання, один випадок невдачі та запис про скасування змін перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени або запити поруч із функціональними результатами. Відомість витрат заздалегідь запобігає несподіваним рахункам, коли процес переходить від демо-версії до спільних середовищ.

Деталь посилення безпеки 4/913: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Для запису посилення безпеки 5 визначте вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не здогадуючись про прихований стан. Документуйте як успішний, так і відновлювальний сценарії. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації.

Деталь посилення безпеки 5/913: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Під час роботи над приміткою 6 щодо зміцнення спочатку запишіть угоду: необхідні вхідні дані, сигнал про успіх та те, що відбувається при частковій невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Розглядайте цей етап як угоду між вхідними даними та перевіреними результатами. Дайте назви елементам, визначте критерії успіху та не допускайте мовчазного часткового виконання.

Деталь зміцнення 6/913: вимірюйте час виконання, клас помилки та кількість витрачених токенів для цієї примітки, а потім вирішуйте, чи залишити зміну, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Примітка 7 щодо зміцнення найкраще функціонує, якщо її розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок невдачі та примітку про скасування перед розширенням обсягу робіт. Тримайте конфігурацію окремо від коду програми. Файли середовища, сховища секретів та флаги функцій мають знаходитися в одному місці, де оператори можуть перевіряти їх, не читаючи весь код.

Деталь посилення безпеки 7/913: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Для запису про посилення безпеки 8 визначте вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не здогадуючись про прихований стан. Краще використовувати невеликі, перевірювані одиниці коду замість об’ємних скриптів. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на складну ієрархію процесів.

Деталь посилення безпеки 8/913: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Під час роботи над пунктом 9 щодо посилення безпеки спочатку запишіть умови виконання: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Поруч із функціональними результатами задокументуйте час виконання та витрати на токени або запити. Чітке бачення витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища до спільних.

Деталь посилення безпеки 9/913: виміряйте час виконання, клас помилки та витрати на токени для цього пункту, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на індивідуальних спостереженнях.

Пункт 10 щодо посилення безпеки найкраще працює, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис виконання, один випадок невдачі та запис про скасування змін перед розширенням обсягу роботи. Документуйте як успішний, так і відновлювальний сценарії. Повторні спроби, людські контролі та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої доробки.

Деталь посилення безпеки 10/913: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Для запису посилення безпеки 11 визначте вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не здогадуючись про прихований стан. Вважайте цю стадію контрактом між вхідними даними та перевіреними результатами. Позначте елементи, визначте критерії успіху та відмовляйтесь від мовчазного часткового завершення.

Деталь посилення безпеки 11/913: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Під час роботи над пунктом позачерствлення 12 спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається при частковій невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Зберігайте конфігурацію окремо від коду додатку. Файли середовища, сховища секретів та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь код.

Деталь позачерствлення 12/913: вимірюйте час виконання, клас помилки та кількість витрачених токенів для цього пункту, а потім вирішуйте, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на індивідуальних спостереженнях.

Пункт позачерствлення 13 найкраще працює, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок невдачі та запис про скасування змін перед розширенням обсягу роботи. Віддавайте перевагу невеликим, тестованим одиницям перед об’ємними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій.

Деталь посилення безпеки 13/913: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Для запису посилення безпеки 14 визначте вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не здогадуючись про прихований стан. Записуйте час виконання та витрати на токени або запити поруч із функціональними результатами. Відображення витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища у спільні середовища.

Деталь посилення безпеки 14/913: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Під час роботи над пунктом позачерствлення 15 спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається при частковій невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Документуйте одночасно шлях успішного виконання та шлях відновлення. Повторні спроби, людські контролі та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої доробки.

Деталі позачерствлення 15/913: вимірюйте час виконання, клас помилки та кількість витрачених токенів для цього пункту, а потім вирішуйте, чи залишити зміну, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.