Главная / Статьи

Практические заметки: Обучение LangGraph: путешествие среди агентов и досок

Пошаговое руководство по Practical notes: Learning LangGraph : A Journey Through Agents, Blackboards: contracts, checks, and drop-in code slots для команд, использующих эту архитектуру.

Издатель: 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)

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

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

Шаг 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 в любых условиях сначала запишите контракт: необходимые входные данные, сигнал о успехе и последствия частичной неудачи. Такой чек-лист помогает сохранять честность при последующих изменениях кода. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. Если какой-то шаг не сработает, причина неудачи должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Выполняйте контрольные точки после дорогостоящих шагов. Механизм возобновления работы не должен повторно взимать плату за один и тот же вызов большой языковой модели при повторной попытке обработки последующего элемента. При анализе причин медленной работы агента 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/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: измерьте время выполнения, класс ошибки и количество использованных токенов для этого пункта, затем решите, следует ли сохранять изменение, опираясь на фиксированный набор критериев, а не на устные описания.