From 63eaece160da5e24d5dcb8cc33357fae776c4433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=B8=D0=BD=D0=B0=D1=80=20=D0=9C=D0=B8=D1=80=D0=B7?= =?UTF-8?q?=D0=B0=D0=B3=D0=B8=D1=82=D0=BE=D0=B2?= Date: Mon, 18 May 2026 11:32:24 +0000 Subject: [PATCH] Add hitl_agent.py --- hitl_agent.py | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 hitl_agent.py diff --git a/hitl_agent.py b/hitl_agent.py new file mode 100644 index 0000000..63e126a --- /dev/null +++ b/hitl_agent.py @@ -0,0 +1,65 @@ +from __future__ import annotations + +from typing import TypedDict + +from langgraph.graph import END, START, StateGraph +from langgraph.types import Command, interrupt + + +class GameState(TypedDict): + scene: str + inventory: list[str] + decision: str + + +def intro(state: GameState) -> GameState: + return { + "scene": "Вы стоите у двери лаборатории AI-агента.", + "inventory": state.get("inventory", []), + "decision": "", + } + + +def ask_human(state: GameState) -> GameState: + decision = interrupt( + { + "scene": state["scene"], + "question": "Открыть дверь или осмотреть коридор?", + "options": ["open", "look"], + } + ) + return {**state, "decision": str(decision)} + + +def resolve(state: GameState) -> GameState: + inventory = list(state.get("inventory", [])) + if state.get("decision") == "open": + inventory.append("access_card") + scene = "Дверь открыта, агент получил access_card." + else: + scene = "Вы нашли подсказку на стене и вернулись к двери." + return {**state, "scene": scene, "inventory": inventory} + + +def build_graph(): + graph = StateGraph(GameState) + graph.add_node("intro", intro) + graph.add_node("ask_human", ask_human) + graph.add_node("resolve", resolve) + graph.add_edge(START, "intro") + graph.add_edge("intro", "ask_human") + graph.add_edge("ask_human", "resolve") + graph.add_edge("resolve", END) + return graph.compile() + + +def main() -> None: + graph = build_graph() + config = {"configurable": {"thread_id": "demo-game"}} + print(graph.invoke({"scene": "", "inventory": [], "decision": ""}, config=config)) + print("Resume example:") + print(graph.invoke(Command(resume="open"), config=config)) # type: ignore[name-defined] + + +if __name__ == "__main__": + main()