{"id":23298,"date":"2026-04-30T20:10:29","date_gmt":"2026-04-30T20:10:29","guid":{"rendered":"https:\/\/umang.pk\/2026\/04\/30\/langgraph%d8%8c-mcp%d8%8c-%d8%a7%d9%88%d8%b1-a2a-%da%a9%d8%a7-%d8%a7%d8%b3%d8%aa%d8%b9%d9%85%d8%a7%d9%84-%da%a9%d8%b1%d8%aa%db%92-%db%81%d9%88%d8%a6%db%92-%d9%85%d9%84%d9%b9%db%8c-%d8%a7%db%8c%d8%ac\/"},"modified":"2026-04-30T20:10:42","modified_gmt":"2026-04-30T20:10:42","slug":"langgraph%d8%8c-mcp%d8%8c-%d8%a7%d9%88%d8%b1-a2a-%da%a9%d8%a7-%d8%a7%d8%b3%d8%aa%d8%b9%d9%85%d8%a7%d9%84-%da%a9%d8%b1%d8%aa%db%92-%db%81%d9%88%d8%a6%db%92-%d9%85%d9%84%d9%b9%db%8c-%d8%a7%db%8c%d8%ac","status":"publish","type":"post","link":"https:\/\/umang.pk\/ur\/2026\/04\/30\/langgraph%d8%8c-mcp%d8%8c-%d8%a7%d9%88%d8%b1-a2a-%da%a9%d8%a7-%d8%a7%d8%b3%d8%aa%d8%b9%d9%85%d8%a7%d9%84-%da%a9%d8%b1%d8%aa%db%92-%db%81%d9%88%d8%a6%db%92-%d9%85%d9%84%d9%b9%db%8c-%d8%a7%db%8c%d8%ac\/","title":{"rendered":"LangGraph\u060c MCP\u060c \u0627\u0648\u0631 A2A \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 AI \u0633\u0633\u0679\u0645 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4 [Full Book]"},"content":{"rendered":"\n<div id=\"\">\n<p>\u06a9\u0633\u06cc \u0633\u0648\u0627\u0644 \u06a9\u0627 \u062c\u0648\u0627\u0628 \u062f\u06cc\u0646\u06d2 \u06cc\u0627 \u062a\u0644\u0627\u0634 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f AI \u0627\u06cc\u062c\u0646\u0679 \u0628\u0646\u0627\u0646\u0627 \u0627\u06cc\u06a9 \u062d\u0644 \u0634\u062f\u06c1 \u0645\u0633\u0626\u0644\u06c1 \u06c1\u06d2\u06d4 \u0686\u0646\u062f \u0633\u0628\u0642 \u0627\u0648\u0631 \u0686\u0646\u062f \u06af\u06be\u0646\u0679\u0648\u06ba \u06a9\u06d2 \u06a9\u0627\u0645 \u06a9\u06d2 \u0633\u0627\u062a\u06be\u060c \u0622\u067e \u0627\u067e\u0646\u06d2 \u0645\u0642\u0635\u062f \u062a\u06a9 \u067e\u06c1\u0646\u0686 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u062c\u0648 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0633\u0628\u0642 \u0686\u06be\u0648\u0691\u062a\u06d2 \u06c1\u06cc\u06ba \u0648\u06c1 \u0627\u0646\u062c\u06cc\u0646\u0626\u0631\u0646\u06af \u06a9\u06cc \u067e\u0631\u062a \u06c1\u06d2 \u062c\u0648 \u0627\u06af\u0644\u06cc \u0622\u062a\u06cc \u06c1\u06d2\u06d4 \u06cc\u0639\u0646\u06cc \u0648\u06c1 \u062d\u0635\u06c1 \u062c\u0648 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645 \u06a9\u0648 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0645\u0627\u062d\u0648\u0644 \u0645\u06cc\u06ba \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0627\u0641\u06cc \u0645\u0633\u062a\u062d\u06a9\u0645 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0645\u06cc\u06ba \u0639\u0645\u0644 \u06a9\u06d2 \u06a9\u0631\u06cc\u0634 \u06a9\u06d2 \u0628\u0639\u062f \u062d\u0627\u0644\u062a \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0628\u062d\u0627\u0644 \u06a9\u0631\u0648\u06ba\u061f \u0622\u067e \u06c1\u0631 \u0627\u0646\u0636\u0645\u0627\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0644\u06a9\u06cc\u062a\u06cc \u0627\u0688\u0627\u067e\u0679\u0631 \u0644\u06a9\u06be\u06d2 \u0628\u063a\u06cc\u0631 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0679\u0648\u0644\u0632 \u062a\u06a9 \u0645\u0639\u06cc\u0627\u0631\u06cc \u0631\u0633\u0627\u0626\u06cc \u06a9\u06cc\u0633\u06d2 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u061f \u0622\u067e \u0645\u062e\u062a\u0644\u0641 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u067e\u0631 \u0628\u0646\u0627\u0626\u06d2 \u06af\u0626\u06d2 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0645\u0631\u0628\u0648\u0637 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u061f \u0645\u062c\u06be\u06d2 \u06a9\u06cc\u0633\u06d2 \u067e\u062a\u06c1 \u0686\u0644\u06d2 \u06af\u0627 \u06a9\u06c1 \u062c\u0628 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06cc \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u06a9\u0627 \u0645\u0639\u06cc\u0627\u0631 \u06af\u0631 \u0631\u06c1\u0627 \u06c1\u06d2\u061f<\/p>\n<p>\u06cc\u06c1 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u06be\u0627\u0646\u0686\u06d2 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0633\u0648\u0627\u0644\u0627\u062a \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u06cc\u06c1 \u06a9\u062a\u0627\u0628 \u0627\u0646 \u06a9\u0627 \u062c\u0648\u0627\u0628 \u0648\u0631\u06a9\u0646\u06af \u06a9\u0648\u0688 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062f\u06cc\u062a\u06cc \u06c1\u06d2 \u062c\u0633\u06d2 \u0622\u067e \u0627\u067e\u0646\u06d2 \u06a9\u0645\u067e\u06cc\u0648\u0679\u0631 \u067e\u0631 \u0686\u0644\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06a9\u0648\u0626\u06cc \u06a9\u0644\u0627\u0624\u0688 \u0627\u06a9\u0627\u0624\u0646\u0679\u0633\u060c API \u06a9\u06cc\u0632\u060c \u06cc\u0627 \u062c\u0627\u0631\u06cc \u0627\u062e\u0631\u0627\u062c\u0627\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06c1\u0645 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u06a9\u06cc \u0633\u0637\u062d \u067e\u0631 \u0627\u0646 \u0645\u0633\u0627\u0626\u0644 \u06a9\u0648 \u062d\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0686\u0627\u0631 \u062a\u06a9\u0646\u06cc\u06a9 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<ol>\n<li>\n<p><strong>\u0644\u06cc\u0646\u06af\u0631\u0627\u0641<\/strong> \u0627\u0633\u0679\u06cc\u0679\u0641\u0648\u0644 \u0627\u06cc\u062c\u0646\u0679 \u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2<\/p>\n<\/li>\n<li>\n<p><strong>\u0645\u0627\u0688\u0644 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 (MCP)<\/strong> \u0645\u0639\u06cc\u0627\u0631\u06cc \u0679\u0648\u0644 \u0627\u0646\u0636\u0645\u0627\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c<\/p>\n<\/li>\n<li>\n<p><strong>A2A (\u0627\u06cc\u062c\u0646\u0679 \u0633\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644)<\/strong> \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0645\u06cc\u06ba \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0645\u0631\u0628\u0648\u0637 \u06a9\u0631\u0646\u0627<\/p>\n<\/li>\n<li>\n<p><strong>\u0645\u0633\u062a\u0642\u0628\u0644 \u0645\u06cc\u06ba\u060c<\/strong> \u0645\u0642\u0627\u0645\u06cc LLM \u062a\u062e\u0645\u06cc\u0646\u06c1 \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4<\/p>\n<\/li>\n<\/ol>\n<p>\u0622\u067e \u06c1\u0631 \u062a\u0635\u0648\u0631 \u06a9\u0648 \u0679\u06be\u0648\u0633 \u0628\u0646\u0627\u0646\u06d2\u060c \u0627\u067e\u0646\u06d2 \u0646\u0648\u0679\u0648\u06ba \u0645\u06cc\u06ba \u0645\u0648\u0636\u0648\u0639\u0627\u062a \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u0646\u06d2\u060c \u06a9\u0648\u0626\u0632 \u0686\u0644\u0627\u0646\u06d2\u060c \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u062f\u0646\u06cc\u0627 \u06a9\u0627 \u0646\u0638\u0627\u0645 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u06cc\u06a9\u06be\u0646\u06d2 \u06a9\u0627 \u0627\u06cc\u06a9 \u0631\u0648\u0688 \u0645\u06cc\u067e \u062a\u06cc\u0627\u0631 \u06a9\u0631\u06cc\u06ba \u06af\u06d2 &#8211; \u0627\u06cc\u06a9 \u0633\u06cc\u06a9\u06be\u0646\u06d2 \u06a9\u0627 \u0633\u0631\u0639\u062a \u06a9\u0627\u0631 \u062c\u0648 \u0646\u062a\u0627\u0626\u062c \u06a9\u06cc \u0628\u0646\u06cc\u0627\u062f \u067e\u0631 \u0627\u06cc\u0688\u062c\u0633\u0679\u0645\u0646\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06d2 \u0645\u0639\u0627\u0645\u0644\u0627\u062a \u0627\u06cc\u06a9 \u062a\u062f\u0631\u06cc\u0633\u06cc \u0622\u0644\u06c1 \u06c1\u06cc\u06ba\u06d4 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u0627\u0635\u0644 \u0645\u0648\u0636\u0648\u0639 \u06c1\u06d2\u06d4<\/p>\n<p>\u0648\u06c1 \u0622\u0631\u06a9\u06cc\u0679\u06cc\u06a9\u0686\u0631\u0644 \u067e\u06cc\u0679\u0631\u0646 (\u0627\u0648\u067e\u0646 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644\u0632 \u067e\u0631 \u06a9\u0648\u0622\u0631\u0688\u06cc\u0646\u06cc\u0634\u0646 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0645\u0627\u06c1\u0631 \u0627\u06cc\u062c\u0646\u0679) \u0641\u06cc \u0627\u0644\u062d\u0627\u0644 \u0633\u06cc\u0644\u0632 \u0627\u06cc\u0628\u0644\u0645\u0646\u0679 (\u0627\u06cc\u062c\u0646\u0679\u0633 \u0622\u0646 \u0628\u0648\u0631\u0688\u0646\u06af \u0646\u0645\u0627\u0626\u0646\u062f\u0648\u06ba \u0627\u0648\u0631 \u062a\u0631\u0628\u06cc\u062a \u06a9\u06d2 \u0631\u0627\u0633\u062a\u0648\u06ba \u06a9\u0648 \u0645\u0631\u0628\u0648\u0637 \u06a9\u0631\u0646\u06d2)\u060c \u062a\u0639\u0645\u06cc\u0644 \u06a9\u06cc \u062a\u0631\u0628\u06cc\u062a (\u0631\u06cc\u06af\u0648\u0644\u06cc\u0679\u0631\u06cc \u0646\u0635\u0627\u0628 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0645\u0644\u0627\u0632\u0645\u06cc\u0646 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0627\u06cc\u062c\u0646\u0679)\u060c \u06a9\u0633\u0679\u0645\u0631 \u0633\u067e\u0648\u0631\u0679 (\u0627\u06cc\u062c\u0646\u0679\u0633 \u0627\u06cc\u06a9 \u0646\u0627\u0644\u062c \u0628\u06cc\u0633 \u0628\u0646\u0627 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba) \u0627\u0648\u0631 \u0627\u0646\u062c\u06cc\u0646\u0626\u0631\u0646\u06af \u0628\u0648\u0631\u0688 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0646\u0626\u06d2 \u0633\u0631\u0627\u063a \u0644\u06af\u0627\u0646\u0627 (\u062a\u0639\u0631\u06cc\u0641 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0627\u06cc\u062c\u0646\u0679\u0633) \u06a9\u06cc \u062a\u06cc\u0627\u0631\u06cc \u0645\u06cc\u06ba \u0686\u0644 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06a9\u0648\u0688 \u0628\u06cc\u0633)\u06d4<\/p>\n<p>\u0688\u0648\u0645\u06cc\u0646 \u0628\u062f\u0644 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u06be\u0627\u0646\u0686\u06d2 \u06a9\u06d2 \u0646\u0645\u0648\u0646\u06d2 \u0627\u06cc\u0633\u0627 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-get-the-complete-code\"> <strong>\u0645\u06a9\u0645\u0644 \u06a9\u0648\u0688 \u062d\u0627\u0635\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong><\/h3>\n<p>\u0627\u0633 \u06c1\u06cc\u0646\u0688 \u0628\u06a9 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u06a9\u0645\u0644\u060c \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0627\u0631 \u0630\u062e\u06cc\u0631\u06c1 GitHub \u067e\u0631 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2\u06d4 \u0627\u0633 \u06a9\u0648 \u06a9\u0644\u0648\u0646 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0633\u0627\u062a\u06be \u06cc\u0627 \u067e\u0691\u06be\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u0633\u06d2 \u062d\u0648\u0627\u0644\u06c1 \u06a9\u06d2 \u0646\u0641\u0627\u0630 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-table-of-contents\">\u0627\u0646\u0688\u06cc\u06a9\u0633<\/h2>\n<h2 id=\"heading-introduction\">\u062a\u0639\u0627\u0631\u0641<\/h2>\n<h3 id=\"heading-what-youll-build\">\u06a9\u06cc\u0627 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0631\u0646\u0627 \u06c1\u06d2<\/h3>\n<p>\u0628\u0646\u0627\u0626\u06d2 \u062c\u0627\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba \u0686\u0627\u0631 \u0627\u06cc\u062c\u0646\u0679\u0633 \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba \u062c\u0648 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0645\u0631\u0628\u0648\u0637 \u06c1\u06cc\u06ba\u060c \u0627\u0646 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0628\u06cc\u0631\u0648\u0646\u06cc \u0679\u0648\u0644\u0632 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0648 MCP \u0633\u0631\u0648\u0631\u0632\u060c \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u0648\u0641\u062f \u06a9\u0648 \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0648 A2A \u062e\u062f\u0645\u0627\u062a\u060c \u0645\u06a9\u0645\u0644 \u0646\u0634\u0627\u0646\u0627\u062a \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 Langfuse\u060c \u0627\u0648\u0631 \u062e\u0648\u062f\u06a9\u0627\u0631 \u0645\u0639\u06cc\u0627\u0631 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0648 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 DeepEval \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1 \u0622\u062e\u0631 \u0633\u06d2 \u0622\u062e\u0631 \u062a\u06a9 \u06a9\u06cc\u0633\u0627 \u0644\u06af\u062a\u0627 \u06c1\u06d2:<\/p>\n<p><em>\u0634\u06a9\u0644 1. \u0645\u06a9\u0645\u0644 \u0646\u0638\u0627\u0645\u06d4 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0686\u0627\u0631 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0645\u0631\u0628\u0648\u0637 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0631 \u0627\u06cc\u062c\u0646\u0679 MCP \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0679\u0648\u0644 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u062d\u0627\u0635\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u06a9\u0648\u0686 \u0628\u06cc\u0631\u0648\u0646\u06cc \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 A2A \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0645\u0646\u062f\u0648\u0628 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0628\u0634\u0645\u0648\u0644 CrewAI \u0627\u06cc\u062c\u0646\u0679\u0633\u060c \u0627\u06cc\u06a9 \u0628\u0627\u0644\u06a9\u0644 \u0645\u062e\u062a\u0644\u0641 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9\u06d4 \u0627\u0648\u0644\u0627\u0645\u0627 \u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u062a\u0645\u0627\u0645 \u062a\u062e\u0645\u06cc\u0646\u06c1 \u0686\u0644\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 Langfuse \u062a\u0645\u0627\u0645 \u0646\u0634\u0627\u0646\u0627\u062a \u067e\u0631 \u0642\u0628\u0636\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/em><\/p>\n<p>\u0622\u067e \u06c1\u0631 \u067e\u0631\u062a \u06a9\u0648 \u0628\u062a\u062f\u0631\u06cc\u062c \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0633\u0633\u0679\u0645 \u0645\u06a9\u0645\u0644 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u0622\u067e \u0646\u06c1 \u0635\u0631\u0641 \u06cc\u06c1 \u0633\u0645\u062c\u06be\u06cc\u06ba \u06af\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u0679\u06cc\u06a9\u0646\u0627\u0644\u0648\u062c\u06cc\u0632 \u06a9\u06cc\u0633\u06d2 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0641\u0679 \u0628\u06cc\u0679\u06be\u062a\u06cc \u06c1\u06cc\u06ba\u060c \u0628\u0644\u06a9\u06c1 \u06cc\u06c1 \u0628\u06be\u06cc \u0633\u0645\u062c\u06be\u06cc\u06ba \u06af\u06d2 \u06a9\u06c1 \u06c1\u0631 \u0679\u06cc\u06a9\u0646\u0627\u0644\u0648\u062c\u06cc \u06a9\u06cc\u0648\u06ba \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2 \u0627\u0648\u0631 \u06cc\u06c1 \u06a9\u0648\u0646 \u0633\u06d2 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u0637\u0631\u06cc\u0642\u0648\u06ba \u06a9\u0648 \u0631\u0648\u06a9\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-the-technology-stack\">\u0679\u06cc\u06a9\u0646\u0627\u0644\u0648\u062c\u06cc \u0627\u0633\u0679\u06cc\u06a9<\/h3>\n<table>\n<thead>\n<tr>\n<th>\u0679\u06cc\u06a9\u0646\u0627\u0644\u0648\u062c\u06cc<\/th>\n<th>\u0648\u0631\u0698\u0646<\/th>\n<th>\u06a9\u0631\u062f\u0627\u0631<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u0644\u06cc\u0646\u06af\u0631\u0627\u0641<\/td>\n<td>1.1.0<\/td>\n<td>\u0627\u0633\u0679\u06cc\u0679\u0641\u0648\u0644 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u06af\u0631\u0627\u0641 \u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0634\u0646<\/td>\n<\/tr>\n<tr>\n<td>\u0627\u06cc\u0645 \u0633\u06cc \u067e\u06cc<\/td>\n<td>1.26.0<\/td>\n<td>\u0645\u0639\u06cc\u0627\u0631\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0679\u0648\u0644 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644<\/td>\n<\/tr>\n<tr>\n<td>A2A SDK<\/td>\n<td>0.3.25<\/td>\n<td>\u06a9\u0631\u0627\u0633 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u0633\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644<\/td>\n<\/tr>\n<tr>\n<td>\u0645\u0633\u062a\u0642\u0628\u0644 \u0645\u06cc\u06ba\u060c<\/td>\n<td>\u062d\u0627\u0644\u06cc\u06c1<\/td>\n<td>\u0645\u0642\u0627\u0645\u06cc LLM \u062a\u062e\u0645\u06cc\u0646\u06c1 (\u06a9\u0648\u0626\u06cc API \u06a9\u0644\u06cc\u062f \u0646\u06c1\u06cc\u06ba)<\/td>\n<\/tr>\n<tr>\n<td>\u0639\u0645\u0644\u06c1 AI<\/td>\n<td>1.13.0<\/td>\n<td>A2A \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0627\u0646\u0679\u0631\u0622\u067e\u0631\u06cc\u0628\u0644\u0679\u06cc<\/td>\n<\/tr>\n<tr>\n<td>Langfuss<\/td>\n<td>4.0.1<\/td>\n<td>\u062a\u0642\u0633\u06cc\u0645 \u0634\u062f\u06c1 \u0679\u0631\u06cc\u06a9\u0646\u06af \u0627\u0648\u0631 \u0645\u0634\u0627\u06c1\u062f\u06c1<\/td>\n<\/tr>\n<tr>\n<td>\u0688\u06cc\u067e \u0627\u06cc\u0648\u0644<\/td>\n<td>3.9.1<\/td>\n<td>\u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u062c\u062c \u06a9\u06cc \u062a\u0634\u062e\u06cc\u0635<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3 id=\"heading-prerequisites\">\u0634\u0631\u0637\u06cc\u06ba<\/h3>\n<p>\u0622\u067e \u06a9\u0648 \u0627\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0622\u0631\u0627\u0645 \u062f\u06c1 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2:<\/p>\n<ul>\n<li>\n<p><strong>Python 3.11 \u06cc\u0627 \u0627\u0633 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1<\/strong>: \u0627\u0634\u0627\u0631\u06d2\u060c \u0688\u06cc\u0679\u0627 \u06a9\u0644\u0627\u0633\u0632\u060c async\/await \u06a9\u06cc \u0628\u0646\u06cc\u0627\u062f\u06cc \u0628\u0627\u062a\u06cc\u06ba \u0679\u0627\u0626\u067e \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u06d2 \u0628\u0646\u06cc\u0627\u062f\u06cc \u062a\u0635\u0648\u0631\u0627\u062a<\/strong>: \u0641\u0648\u0631\u06cc\u060c \u062a\u06a9\u0645\u06cc\u0644\u060c \u0679\u0648\u0644 \u06a9\u0627\u0644<\/p>\n<\/li>\n<li>\n<p><strong>\u06a9\u0645\u0627\u0646\u0688 \u0644\u0627\u0626\u0646<\/strong>: \u0648\u0631\u0686\u0648\u0626\u0644 \u0645\u0627\u062d\u0648\u0644 \u0628\u0646\u0627\u0626\u06cc\u06ba\u060c \u0627\u0633\u06a9\u0631\u067e\u0679 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>LangGraph\u060c MCP\u060c A2A\u060c \u06cc\u0627 \u0627\u06cc\u062c\u0646\u0679 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u0633\u06cc \u067e\u06cc\u0634\u06af\u06cc \u062a\u062c\u0631\u0628\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06cc\u06c1 \u06a9\u062a\u0627\u0628\u0686\u06c1 \u067e\u06c1\u0644\u06d2 \u0627\u0635\u0648\u0644\u0648\u06ba \u067e\u0631 \u0645\u0628\u0646\u06cc \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-hardware-requirements\">\u06c1\u0627\u0631\u0688 \u0648\u06cc\u0626\u0631 \u06a9\u06d2 \u062a\u0642\u0627\u0636\u06d2<\/h3>\n<table>\n<thead>\n<tr>\n<th>\u062a\u0631\u062a\u06cc\u0628<\/th>\n<th>\u0631\u0627\u0645<\/th>\n<th>VRAM<\/th>\n<th>\u0645\u0627\u0688\u0644<\/th>\n<th>\u0645\u06cc\u0645\u0648<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u06a9\u0645 \u0627\u0632 \u06a9\u0645<\/td>\n<td>16 \u062c\u06cc \u0628\u06cc<\/td>\n<td>8 \u062c\u06cc \u0628\u06cc<\/td>\n<td><code>qwen2.5:7b<\/code><\/td>\n<td>\u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0641\u0639\u0627\u0644<\/td>\n<\/tr>\n<tr>\n<td>\u062a\u062c\u0648\u06cc\u0632<\/td>\n<td>32 \u062c\u06cc \u0628\u06cc<\/td>\n<td>24 \u062c\u06cc \u0628\u06cc<\/td>\n<td><code>qwen2.5-coder:32b<\/code><\/td>\n<td>\u0628\u06c1\u062a\u0631\u06cc\u0646 \u0679\u0648\u0644 \u06a9\u0627\u0644 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f<\/td>\n<\/tr>\n<tr>\n<td>\u0635\u0631\u0641 \u0633\u06cc \u067e\u06cc \u06cc\u0648<\/td>\n<td>32 \u062c\u06cc \u0628\u06cc<\/td>\n<td>\u0645\u0648\u062c\u0648\u062f \u0646\u06c1\u06cc\u06ba \u06c1\u06d2<\/td>\n<td><code>qwen2.5:7b<\/code><\/td>\n<td>\u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 5-10x \u0633\u0633\u062a<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3 id=\"heading-why-model-size-matters-for-agents\"> \u0645\u0627\u0688\u0644 \u06a9\u0627 \u0633\u0627\u0626\u0632 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u06cc\u0648\u06ba \u0627\u06c1\u0645\u06cc\u062a \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4<\/h3>\n<p>\u0627\u06cc\u062c\u0646\u0679 \u0633\u0627\u062e\u062a\u06cc JSON \u062f\u0644\u0627\u0626\u0644 \u0628\u0646\u0627 \u06a9\u0631 \u0679\u0648\u0644 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0648\u06c1 \u0645\u0627\u0688\u0644 \u062c\u0648 \u0679\u0648\u0644 \u06a9\u06d2 \u0646\u0627\u0645 \u0645\u06cc\u06ba \u063a\u0644\u0637\u06cc \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u06cc\u0627 \u0627\u0633 \u06a9\u06d2 \u062f\u0644\u0627\u0626\u0644 \u06a9\u0648 \u063a\u0644\u0637 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0641\u0627\u0631\u0645\u06cc\u0679 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u0648\u06c1 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2\u06d4 \u0679\u0648\u0644 \u06a9\u0627\u0644 \u067e\u0631 \u0639\u0645\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u06cc\u062c\u0646\u0679 \u062a\u06a9\u0631\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u062a\u06a9\u0631\u0627\u0631 \u06a9\u06cc \u062d\u062f \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc \u0648\u0627\u0636\u062d \u063a\u0644\u0637\u06cc \u06a9\u06d2 \u067e\u06c1\u0646\u0686 \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>7B \u067e\u06cc\u0631\u0627\u0645\u06cc\u0679\u0631\u0632 \u06a9\u06d2 \u062a\u062d\u062a \u0645\u0627\u0688\u0644\u0632 \u06a9\u0648 \u0627\u06a9\u062b\u0631 \u0627\u0633 JSON \u0641\u0627\u0631\u0645\u06cc\u0679 \u06a9\u06cc \u062e\u0631\u0627\u0628\u06cc \u06a9\u0627 \u0633\u0627\u0645\u0646\u0627 \u06a9\u0631\u0646\u0627 \u067e\u0691\u062a\u0627 \u06c1\u06d2\u06d4 7-9B \u0631\u06cc\u0646\u062c \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0679\u0648\u0644 \u06a9\u0627\u0644\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0645 \u0627\u0632 \u06a9\u0645 \u0642\u0627\u0628\u0644 \u0639\u0645\u0644 \u062f\u0631\u062c\u06c1 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-chapter-1-when-to-use-multiple-agents\">\u0628\u0627\u0628 1: \u0645\u062a\u0639\u062f\u062f \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u06a9\u0628 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4<\/h2>\n<p>\u0627\u0633 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06a9\u06c1 \u0622\u067e \u06a9\u0648\u0626\u06cc \u06a9\u0648\u0688 \u0644\u06a9\u06be\u06cc\u06ba\u060c \u0622\u067e \u06a9\u0648 \u0627\u06cc\u06a9 \u0633\u0648\u0627\u0644 \u06a9\u0627 \u062c\u0648\u0627\u0628 \u062f\u06cc\u0646\u0627 \u06c1\u0648\u06af\u0627 \u062c\u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0686\u06be\u0648\u0691 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba: \u06a9\u06cc\u0627 \u0648\u0627\u0642\u0639\u06cc \u0627\u0633 \u0645\u0633\u0626\u0644\u06d2 \u06a9\u0648 \u0645\u062a\u0639\u062f\u062f \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u061f<\/p>\n<p>\u06cc\u06c1 \u0627\u06c1\u0645 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0634\u0627\u0645\u0644 \u06a9\u0631\u0646\u0627 \u062d\u0642\u06cc\u0642\u06cc \u0627\u062e\u0631\u0627\u062c\u0627\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0622\u062a\u0627 \u06c1\u06d2\u06d4 \u0632\u06cc\u0627\u062f\u06c1 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u062d\u0631\u06a9\u062a \u067e\u0630\u06cc\u0631 \u062d\u0635\u06d2\u060c \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0645\u06a9\u0646\u06c1 \u067e\u0648\u0627\u0626\u0646\u0679\u0633\u060c \u0645\u0634\u062a\u0631\u06a9\u06c1 \u062d\u0627\u0644\u062a \u062c\u0648 \u0645\u062a\u0639\u062f\u062f \u0633\u0645\u062a\u0648\u06ba \u0645\u06cc\u06ba \u06a9\u0631\u067e\u0679 \u06c1\u0648 \u0633\u06a9\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0688\u06cc\u0628\u06af\u0646\u06af \u062c\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0639\u0645\u0644 \u06a9\u06cc \u062d\u062f\u0648\u062f \u0645\u06cc\u06ba \u0628\u0639\u062f \u0645\u06cc\u06ba \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u0686\u06be\u06d2 \u0627\u0648\u0632\u0627\u0631\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u06c1\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0627\u06a9\u062b\u0631 \u0622\u0633\u0627\u0646\u060c \u062a\u06cc\u0632\u060c \u0627\u0648\u0631 \u0632\u06cc\u0627\u062f\u06c1 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u062d\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u062a\u0648 \u0633\u0648\u0627\u0644 \u06cc\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u06a9\u06c1 &quot;\u06a9\u06cc\u0627 \u0645\u062c\u06be\u06d2 \u0627\u06cc\u06a9 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0627\u06cc\u062c\u0646\u0679 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2\u061f&#8221; \u06af\u0648\u06cc\u0627 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0641\u0637\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0628\u0631\u062a\u0631 \u06c1\u06d2\u06d4 \u0633\u0648\u0627\u0644 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1\u060c &quot;\u06a9\u06cc\u0627 \u0645\u06cc\u0631\u06d2 \u0645\u0633\u0626\u0644\u06d2 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u0627\u06cc\u0633\u06cc \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u06c1\u06cc\u06ba \u062c\u0648 \u0679\u06cc\u0648\u0646\u0646\u06af \u0627\u0648\u0648\u0631 \u06c1\u06cc\u0688 \u06a9\u0648 \u062f\u0631\u0633\u062a \u062b\u0627\u0628\u062a \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u061f&#8221;<\/p>\n<h3 id=\"heading-11-when-a-single-agent-is-the-right-answer\">1.1 \u062c\u0628 \u0627\u06cc\u06a9 \u06c1\u06cc \u0627\u06cc\u062c\u0646\u0679 \u062c\u0648\u0627\u0628 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/h3>\n<p>\u0627\u06af\u0631 \u0622\u067e \u06a9\u06d2 \u0645\u0633\u0626\u0644\u06d2 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0628\u0646\u06cc\u0627\u062f\u06cc \u06a9\u0627\u0645 \u06c1\u06d2 \u062c\u0648 \u0627\u06cc\u06a9 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u06a9\u06cc \u06a9\u06be\u0691\u06a9\u06cc \u0645\u06cc\u06ba \u0641\u0679 \u0628\u06cc\u0679\u06be\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u06cc\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 \u0635\u062d\u06cc\u062d \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u062c\u0648 \u0645\u0648\u0636\u0648\u0639\u0627\u062a \u06a9\u06cc \u062a\u062d\u0642\u06cc\u0642 \u0627\u0648\u0631 \u062e\u0644\u0627\u0635\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: \u0627\u06cc\u06a9 \u06a9\u0627\u0645\u060c \u0627\u06cc\u06a9 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u06a9\u06cc \u06a9\u06be\u0691\u06a9\u06cc\u060c \u0627\u06cc\u06a9 \u0627\u06cc\u062c\u0646\u0679\u06d4 \u0627\u06cc\u062c\u0646\u0679 \u067e\u0644 \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u0648\u06ba \u06a9\u0627 \u062c\u0627\u0626\u0632\u06c1 \u0644\u06d2 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u062a\u0628\u0635\u0631\u06d2 \u067e\u0648\u0633\u0679 \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba: \u0627\u06cc\u06a9 \u06a9\u0627\u0645\u06d4 \u0639\u0644\u0645\u06cc \u0628\u0646\u06cc\u0627\u062f \u0633\u06d2 \u06af\u0627\u06c1\u06a9 \u06a9\u06d2 \u0633\u0648\u0627\u0644\u0627\u062a \u06a9\u0627 \u062c\u0648\u0627\u0628 \u062f\u06cc\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0627\u06cc\u062c\u0646\u0679: \u0627\u06cc\u06a9 \u06a9\u0627\u0645\u06d4 \u0627\u06cc\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u062c\u0648 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u0627\u062a \u0633\u06d2 \u0633\u0627\u062e\u062a\u06cc \u0688\u06cc\u0679\u0627 \u0646\u06a9\u0627\u0644\u062a\u0627 \u06c1\u06d2: \u0627\u06cc\u06a9 \u06a9\u0627\u0645\u06d4<\/p>\n<p>\u0627\u0646 \u0635\u0648\u0631\u062a\u0648\u06ba \u0645\u06cc\u06ba\u060c \u062f\u0648\u0633\u0631\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648 \u0634\u0627\u0645\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u06a9\u0686\u06be \u0628\u06be\u06cc \u0622\u0633\u0627\u0646 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0639\u0645\u06cc\u0631\u0627\u062a\u06cc \u0641\u0627\u0626\u062f\u06d2 \u06a9\u06d2 \u0628\u063a\u06cc\u0631\u060c \u0627\u0633 \u0645\u06cc\u06ba \u06a9\u0648\u0622\u0631\u0688\u06cc\u0646\u06cc\u0634\u0646 \u0644\u06cc\u0626\u0631\u0632\u060c \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0631\u06cc\u0627\u0633\u062a\u06cc \u0645\u0639\u0627\u06c1\u062f\u0648\u06ba\u060c \u0646\u0626\u06cc \u062e\u0631\u0627\u0628\u06cc \u06a9\u06cc \u0633\u0637\u062d\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0688\u06cc\u0628\u06af\u0646\u06af \u06a9\u06cc \u067e\u06cc\u0686\u06cc\u062f\u06af\u06cc \u0634\u0627\u0645\u0644 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u06c1\u06cc \u0627\u06cc\u062c\u0646\u0679 \u067e\u0648\u0631\u0627 \u06a9\u0627\u0645 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633\u06d2 \u0627\u0686\u06be\u06d2 \u0627\u0648\u0632\u0627\u0631 \u062f\u06cc\u06ba \u0627\u0648\u0631 \u06cc\u06c1 \u06a9\u0627\u0645 \u06a9\u0631\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u0633\u0646\u06af\u0644 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627 \u0645\u0627\u0688\u0644 \u0622\u0633\u0627\u0646 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-plaintext\">User input \u2192 Agent (with tools) \u2192 Response\n<\/code><\/pre>\n<p>\u0627\u06cc\u062c\u0646\u0679 \u0679\u0648\u0644\u0632 \u06a9\u0648 \u0627\u06cc\u06a9 \u0644\u0648\u067e \u0645\u06cc\u06ba \u06a9\u0627\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba ( \u0628\u0627\u0632\u06cc\u0627\u0641\u062a\u060c \u067e\u0691\u06be\u0646\u0627\u060c \u0644\u06a9\u06be\u0646\u0627\u060c \u0686\u06cc\u06a9 \u06a9\u0631\u0646\u0627)\u060c \u0644\u06cc\u06a9\u0646 \u0635\u062d\u06cc\u062d \u0679\u0648\u0644 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0648\u0627\u062d\u062f LLM \u067e\u0648\u0631\u06d2 \u06a9\u0627\u0645 \u06a9\u0648 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 AI \u0622\u0679\u0648\u0645\u06cc\u0634\u0646 \u06a9\u0627\u0645\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0635\u062d\u06cc\u062d \u0646\u0642\u0637\u06c1 \u0622\u063a\u0627\u0632 \u0627\u0648\u0631 \u0627\u06a9\u062b\u0631 \u0635\u062d\u06cc\u062d \u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u0646\u0642\u0637\u06c1 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-12-the-real-criteria-for-multiple-agents\">1.2 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u0639\u0645\u0644\u06cc \u0645\u0639\u06cc\u0627\u0631\u0627\u062a<\/h3>\n<p>\u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u0645\u0633\u0626\u0644\u06c1 \u06c1\u06d2 \u062a\u0648 \u0622\u067e \u06a9\u0648 \u0645\u062a\u0639\u062f\u062f \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06af\u06cc\u06d4 <em>\u0648\u0627\u0642\u0639\u06cc \u0627\u06cc\u06a9 \u0627\u0645\u062a\u06cc\u0627\u0632\u06cc \u062e\u0635\u0648\u0635\u06cc\u062a<\/em>: \u0630\u06cc\u0644\u06cc \u06a9\u0627\u0645\u0648\u06ba \u0645\u06cc\u06ba \u0627\u062a\u0646\u06d2 \u0645\u062e\u062a\u0644\u0641 \u0679\u0648\u0644\u0632\u060c LLM \u06a9\u0627\u0644 \u067e\u06cc\u0679\u0631\u0646\u060c \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u06a9\u06d2 \u062a\u0642\u0627\u0636\u06d2\u060c \u06cc\u0627 \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u0645\u0648\u0688\u0632 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0646\u06c1\u06cc\u06ba \u0627\u06cc\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u0645\u06cc\u06ba \u062c\u0648\u0691\u0646\u06d2 \u0633\u06d2 \u0627\u0633 \u06a9\u06d2 \u062d\u0644 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0633\u0627\u0626\u0644 \u067e\u06cc\u062f\u0627 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06a9\u0648\u0622\u0631\u0688\u06cc\u0646\u06cc\u0634\u0646 \u0627\u0648\u0648\u0631 \u06c1\u06cc\u0688 \u06a9\u0648 \u062c\u0648\u0627\u0632 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06cc \u0645\u062e\u0635\u0648\u0635 \u0634\u0631\u0627\u0626\u0637 \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba:<\/p>\n<h4 id=\"heading-different-tools-for-different-subtasks\">\u0645\u062e\u062a\u0644\u0641 \u0630\u06cc\u0644\u06cc \u06a9\u0627\u0645\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u062e\u062a\u0644\u0641 \u0679\u0648\u0644\u0632<\/h4>\n<p>\u062c\u0628 \u0648\u0631\u06a9 \u0641\u0644\u0648 \u06a9\u06d2 \u0627\u06cc\u06a9 \u062d\u0635\u06d2 \u06a9\u0648 \u0641\u0627\u0626\u0644 \u0633\u0633\u0679\u0645 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u060c \u062f\u0648\u0633\u0631\u06d2 \u06a9\u0648 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0631\u0627\u0626\u0679 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 \u062a\u06cc\u0633\u0631\u06d2 \u06a9\u0648 \u0628\u06cc\u0631\u0648\u0646\u06cc APIs \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u060c \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06cc \u0639\u0644\u06cc\u062d\u062f\u06af\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u0642\u062f\u0631\u062a\u06cc \u062d\u062f\u0648\u062f \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0686\u0648\u0646\u06a9\u06c1 \u06c1\u0631 \u0627\u06cc\u062c\u0646\u0679 \u0635\u0631\u0641 \u0648\u06c1\u06cc \u0679\u0648\u0644\u0632 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0633 \u06a9\u06cc \u0627\u0633\u06d2 \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0627\u0646\u0641\u0631\u0627\u062f\u06cc \u0637\u0648\u0631 \u067e\u0631 \u06c1\u0631 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u062c\u0627\u0646\u0686 \u0627\u0648\u0631 \u0627\u0633\u062a\u062f\u0644\u0627\u0644 \u06a9\u0631\u0646\u0627 \u0622\u0633\u0627\u0646 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-different-llm-call-patterns\">\u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u0627\u0644 \u06a9\u06d2 \u0645\u062e\u062a\u0644\u0641 \u0646\u0645\u0648\u0646\u06d2\u06d4<\/h4>\n<p>\u06a9\u0686\u06be \u0622\u067e\u0631\u06cc\u0634\u0646\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u0646\u06af\u0644 \u0633\u0679\u0631\u06a9\u0686\u0631\u0688 \u0622\u0624\u0679 \u067e\u0679 \u06a9\u0627\u0644 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u060c \u062c\u06cc\u0633\u06d2: <code>temperature=0<\/code>. \u062f\u0648\u0633\u0631\u0648\u06ba \u06a9\u0648 \u0645\u0644\u0679\u06cc \u0631\u0648\u0679\u06cc\u0634\u0646 \u0679\u0648\u0644 \u06a9\u0627\u0644 \u0644\u0648\u067e \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u062c\u0648 \u0627\u0633 \u0648\u0642\u062a \u062e\u062a\u0645 \u06c1\u0648 \u062c\u0627\u062a\u06cc \u06c1\u06d2 \u062c\u0628 LLM \u0627\u0633 \u0628\u0627\u062a \u06a9\u0627 \u062a\u0639\u06cc\u0646 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06a9\u0627\u0641\u06cc \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0646 \u0646\u0645\u0648\u0646\u0648\u06ba \u06a9\u0648 \u0627\u06cc\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u0645\u06cc\u06ba \u0645\u0644\u0627\u0646\u06d2 \u0633\u06d2 \u0627\u06cc\u06a9 \u0627\u06cc\u0633\u0627 \u0641\u0646\u06a9\u0634\u0646 \u0628\u0646\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0628\u06c1\u062a \u0632\u06cc\u0627\u062f\u06c1 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0645\u062e\u062a\u0644\u0641 \u0637\u0631\u06cc\u0642\u0648\u06ba \u0633\u06d2 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0633 \u0631\u0627\u0633\u062a\u06d2 \u067e\u0631 \u0645\u0646\u062d\u0635\u0631 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-different-temperature-and-model-requirements\">\u0645\u062e\u062a\u0644\u0641 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u0627\u0648\u0631 \u0645\u0627\u0688\u0644 \u06a9\u06cc \u0636\u0631\u0648\u0631\u06cc\u0627\u062a<\/h4>\n<p>\u0633\u0627\u062e\u062a\u06cc \u0645\u0646\u0635\u0648\u0628\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u06d2 \u0646\u062a\u0627\u0626\u062c \u0645\u0633\u062a\u0642\u0644 \u0645\u0632\u0627\u062c\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0645 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062a\u062e\u0644\u06cc\u0642\u06cc \u0648\u0636\u0627\u062d\u062a\u06cc\u06ba \u0645\u062e\u062a\u0644\u0641 \u0642\u0633\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0642\u062f\u0631\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u0686\u0627\u06c1\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0627\u0633\u06a9\u0648\u0631\u0646\u06af \u0645\u06cc\u06ba\u060c \u062a\u062c\u0632\u06cc\u0627\u062a\u06cc \u0645\u0633\u062a\u0642\u0644 \u0645\u0632\u0627\u062c\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0645 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u0645\u0637\u0644\u0648\u0628 \u06c1\u06d2\u06d4<\/p>\n<p>\u062c\u0628 \u06cc\u06c1 \u062a\u06cc\u0646 \u06a9\u0627\u0645 \u0627\u06cc\u06a9 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627 \u0627\u0634\u062a\u0631\u0627\u06a9 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u062a\u0645\u0627\u0645 \u0633\u0645\u062a\u0648\u06ba \u0645\u06cc\u06ba \u0633\u0645\u062c\u06be\u0648\u062a\u06c1 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-fault-isolation-requirements\">\u0641\u0627\u0644\u0679 \u0622\u0626\u0633\u0648\u0644\u06cc\u0634\u0646 \u06a9\u06cc \u0636\u0631\u0648\u0631\u06cc\u0627\u062a<\/h4>\n<p>\u0633\u0628 \u0679\u0627\u0633\u06a9 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u062d\u062f\u0648\u062f \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u062c\u0628 \u0627\u06cc\u06a9 \u0633\u0628 \u0679\u0627\u0633\u06a9 \u062f\u0648\u0633\u0631\u06d2 \u0633\u0628 \u0679\u0627\u0633\u06a9 \u06a9\u0648 \u0631\u0648\u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u0646\u0635\u0627\u0628 \u06a9\u06cc \u0645\u0646\u0635\u0648\u0628\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0686\u0627\u06c1\u06d2 \u06a9\u0648\u0626\u0632 \u06af\u0631\u06cc\u0688\u0646\u06af \u06a9\u06cc \u062e\u062f\u0645\u0627\u062a \u0639\u0627\u0631\u0636\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0645\u0639\u0637\u0644 \u06a9\u0631 \u062f\u06cc \u062c\u0627\u0626\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0627\u0633\u06cc \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06cc \u0633\u0637\u062d \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u06c1\u06cc \u0639\u0645\u0644 \u0645\u06cc\u06ba \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u06cc \u062e\u0631\u0627\u0628\u06cc \u0628\u06be\u06cc \u0622\u067e \u06a9\u06d2 \u0645\u0646\u0635\u0648\u0628\u06d2 \u06a9\u0648 \u062e\u0631\u0627\u0628 \u06a9\u0631 \u062f\u06d2 \u06af\u06cc\u06d4<\/p>\n<h4 id=\"heading-independent-deployment-needs\">\u0622\u0632\u0627\u062f \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u06a9\u06d2 \u062a\u0642\u0627\u0636\u06d2<\/h4>\n<p>\u062c\u0628 \u0646\u0638\u0627\u0645 \u06a9\u06d2 \u0645\u062e\u062a\u0644\u0641 \u062d\u0635\u0648\u06ba \u06a9\u0648 \u0645\u062e\u062a\u0644\u0641 \u067e\u06cc\u0645\u0627\u0646\u06d2 \u067e\u0631 \u0686\u0644\u0627\u0646\u06d2\u060c \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u0627\u067e \u0688\u06cc\u0679 \u06c1\u0648\u0646\u06d2\u060c \u06cc\u0627 \u0645\u062e\u062a\u0644\u0641 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9\u0633 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0645\u062a\u0639\u062f\u062f \u0679\u06cc\u0645\u0648\u06ba \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648 \u062a\u0648 \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u0639\u0644\u06cc\u062d\u062f\u06af\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u0633\u06d2 \u0639\u0644\u06cc\u062d\u062f\u06af\u06cc \u06a9\u0627 \u0646\u0642\u0634\u06c1\u06d4 A2A \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 (\u0628\u0627\u0628 8) \u0627\u0633 \u06a9\u0648 \u0679\u06be\u0648\u0633 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-cross-framework-collaboration\">\u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0645\u06cc\u06ba \u062a\u0639\u0627\u0648\u0646<\/h4>\n<p>\u0627\u06af\u0631 \u0622\u067e \u0627\u06cc\u06a9 \u06a9\u0627\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 CrewAI \u0627\u06cc\u062c\u0646\u0679 \u0627\u0648\u0631 \u062f\u0648\u0633\u0631\u06d2 \u06a9\u0627\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 LangGraph \u0627\u06cc\u062c\u0646\u0679 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u06a9\u0648 \u0645\u0648\u0627\u0635\u0644\u0627\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06af\u06cc \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06c1\u0631 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u06d2 \u0645\u062e\u062a\u0644\u0641 \u0641\u0648\u0627\u0626\u062f \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 A2A \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0646 \u062d\u0627\u0644\u0627\u062a \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0627\u06cc\u06a9 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0627\u0646 \u0645\u06cc\u06ba \u0633\u06d2 \u062f\u0648 \u0634\u0627\u06cc\u062f \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0633\u0628 \u0645\u0636\u0628\u0648\u0637 \u062f\u0639\u0648\u06d2 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-13-the-cost-youre-paying\">1.3 \u062c\u0648 \u0622\u067e \u0627\u062f\u0627 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/h3>\n<p>\u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0648 \u0627\u067e\u0646\u0627\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u0627\u0633 \u0628\u0627\u062a \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u0622\u067e \u0627\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u062a\u0646\u06cc \u0631\u0642\u0645 \u0627\u062f\u0627 \u06a9\u0631\u0646\u06d2 \u06a9\u0648 \u062a\u06cc\u0627\u0631 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p><strong>\u0645\u0634\u062a\u0631\u06a9\u06c1 \u0631\u06cc\u0627\u0633\u062a \u06a9\u06cc \u067e\u06cc\u0686\u06cc\u062f\u06af\u06cc:<\/strong> \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679 \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0631\u06cc\u0627\u0633\u062a\u06cc \u0627\u0634\u06cc\u0627\u0621 \u06a9\u0648 \u067e\u0691\u06be\u062a\u06d2 \u0627\u0648\u0631 \u0644\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u062f\u0648 \u0627\u06cc\u062c\u0646\u0679 \u0627\u06cc\u06a9 \u06c1\u06cc \u0641\u06cc\u0644\u0688 \u0645\u06cc\u06ba \u0644\u06a9\u06be \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u0627\u0646\u0636\u0645\u0627\u0645 \u06a9\u06cc \u062d\u06a9\u0645\u062a \u0639\u0645\u0644\u06cc \u062f\u0631\u06a9\u0627\u0631 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0627\u06cc\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u063a\u0644\u0637 \u0688\u06cc\u0679\u0627 \u0644\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u0633 \u06a9\u06d2 \u0628\u0639\u062f \u06a9\u06d2 \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u063a\u0644\u0637 \u0627\u0646 \u067e\u0679 \u0645\u0644\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u0631\u06cc\u0627\u0633\u062a \u06a9\u06cc \u062a\u0639\u0631\u06cc\u0641 \u0627\u06cc\u06a9 \u0645\u0639\u0627\u06c1\u062f\u06c1 \u0628\u0646 \u062c\u0627\u062a\u06cc \u06c1\u06d2 \u062c\u0633 \u067e\u0631 \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0639\u0645\u0644 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u060c \u0627\u0648\u0631 \u0627\u0633 \u0645\u0639\u0627\u06c1\u062f\u06d2 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644\u06cc\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0688\u06cc\u0628\u06af \u06a9\u0631\u0646\u0627 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0634\u06a9\u0644:<\/strong> \u0627\u06cc\u06a9 \u06c1\u06cc \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06cc \u062e\u0627\u0645\u06cc\u0627\u06ba \u0627\u06cc\u06a9 \u0627\u0633\u0679\u06cc\u06a9 \u0679\u0631\u06cc\u0633 \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba \u062e\u0631\u0627\u0628\u06cc\u0627\u06ba \u0645\u0631\u062d\u0644\u06c1 3 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u063a\u0644\u0637 \u0622\u0624\u0679 \u067e\u0679 \u06a9\u06cc \u0648\u062c\u06c1 \u0633\u06d2 \u06c1\u0648 \u0633\u06a9\u062a\u06cc \u06c1\u06cc\u06ba\u060c \u062c\u0648 \u067e\u06be\u0631 \u062d\u0627\u0644\u062a \u0645\u06cc\u06ba \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06c1\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u062f\u0648\u0633\u0631\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648 \u0645\u0646\u062a\u0642\u0644 \u06c1\u0648 \u062c\u0627\u062a\u06cc \u06c1\u06d2\u060c \u062c\u0633 \u06a9\u06cc \u0648\u062c\u06c1 \u0633\u06d2 \u0648\u06c1 \u0622\u0624\u0679 \u067e\u0679 \u067e\u06cc\u062f\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0622\u067e \u0641\u06cc \u0627\u0644\u062d\u0627\u0644 \u062f\u06cc\u06a9\u06be \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u06d4 causal \u0633\u0644\u0633\u0644\u06c1 \u0627\u062f\u0627\u06a9\u0627\u0631 \u06a9\u06cc \u062d\u062f\u0648\u062f \u06a9\u0648 \u0639\u0628\u0648\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u062a\u0627\u062e\u06cc\u0631 \u0645\u06cc\u06ba \u0627\u0636\u0627\u0641\u06c1:<\/strong> \u06c1\u0631 \u0627\u06cc\u062c\u0646\u0679 \u0627\u06cc\u06a9 \u06cc\u0627 \u0632\u06cc\u0627\u062f\u06c1 LLM \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0686\u0627\u0631 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0627 \u0646\u0638\u0627\u0645 \u0641\u06cc \u0633\u06cc\u0634\u0646 \u06a9\u0645 \u0627\u0632 \u06a9\u0645 \u0686\u0627\u0631 LLM \u06a9\u0627\u0644 \u06a9\u0631\u06d2 \u06af\u0627\u060c \u0627\u06a9\u062b\u0631 \u0632\u06cc\u0627\u062f\u06c1 \u0627\u06af\u0631 \u0627\u06cc\u062c\u0646\u0679 \u0679\u0648\u0644\u0632 \u06a9\u0648 \u0627\u06cc\u06a9 \u0644\u0648\u067e \u0645\u06cc\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 2-5 \u0633\u06cc\u06a9\u0646\u0688 \u0641\u06cc \u0627\u0648\u0644\u0627\u0645\u0627 \u06a9\u0627\u0644 \u067e\u0631\u060c \u0627\u0633 \u0645\u06cc\u06ba \u062a\u06cc\u0632\u06cc \u0633\u06d2 \u0627\u0636\u0627\u0641\u06c1 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0645\u0632\u06cc\u062f \u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u06be\u0627\u0646\u0686\u06c1:<\/strong> \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645 \u0631\u06cc\u0627\u0633\u062a\u06cc \u0627\u0633\u062a\u0642\u0627\u0645\u062a\u060c \u0645\u0634\u0627\u06c1\u062f\u06c1\u060c \u062a\u0634\u062e\u06cc\u0635\u060c \u0627\u0648\u0631 \u0627\u0646\u0633\u0627\u0646\u06cc \u0646\u06af\u0631\u0627\u0646\u06cc \u0633\u06d2 \u0641\u0627\u0626\u062f\u06c1 \u0627\u0679\u06be\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062c\u0646 \u06a9\u0648 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0646\u06d2 \u0645\u06cc\u06ba \u0648\u0642\u062a \u0644\u06af\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f \u0627\u06cc\u062c\u0646\u0679 \u0627\u06a9\u062b\u0631 \u0627\u0646 \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u0686\u0644 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0645\u0627\u062d\u0648\u0644 \u0645\u06cc\u06ba \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645 \u0648\u0627\u0642\u0639\u06cc \u0627\u06cc\u0633\u0627 \u0646\u06c1\u06cc\u06ba \u06a9\u0631 \u0633\u06a9\u062a\u0627\u06d4<\/p>\n<p>\u06c1\u0645\u06cc\u06ba \u0627\u0646 \u0627\u062e\u0631\u0627\u062c\u0627\u062a \u0633\u06d2 \u0622\u06af\u0627\u06c1 \u06c1\u0648\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0646 \u0645\u062e\u0635\u0648\u0635 \u0641\u0648\u0627\u0626\u062f \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2 \u062c\u0648 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u0645\u06cc\u06ba \u062c\u0627\u0646\u06d2 \u06a9\u0627 \u062c\u0648\u0627\u0632 \u067e\u06cc\u0634 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-14-why-this-system-uses-four-agents\">1.4 \u06cc\u06c1 \u0633\u0633\u0679\u0645 4 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u06a9\u06cc\u0648\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u061f<\/h3>\n<p>\u0644\u0631\u0646\u0646\u06af \u0627\u06cc\u06a9\u0633\u0644\u0631\u06cc\u0679\u0631 \u0686\u0627\u0631 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1\u0627\u06ba \u06c1\u0631 \u0639\u0644\u06cc\u062d\u062f\u06af\u06cc \u06a9\u06d2 \u0644\u0626\u06d2 \u0627\u06cc\u06a9 \u0648\u0627\u0636\u062d \u062a\u06a9\u0646\u06cc\u06a9\u06cc \u062c\u0648\u0627\u0632 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u067e\u06be\u0631\u060c \u06cc\u06c1 \u0627\u0633 \u0644\u06cc\u06d2 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u06a9\u06c1 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0628\u06c1\u062a\u0631 \u06c1\u06d2\u060c \u0628\u0644\u06a9\u06c1 \u0627\u0633 \u0644\u06cc\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u0686\u0627\u0631 \u06a9\u0627\u0645 \u06a9\u0627\u0641\u06cc \u062d\u062f \u062a\u06a9 \u0645\u062e\u062a\u0644\u0641 \u06c1\u06cc\u06ba \u06a9\u06c1 \u062f\u0648\u0646\u0648\u06ba \u06a9\u0648 \u0645\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0646\u062a\u06cc\u062c\u06d2 \u0645\u06cc\u06ba \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0627\u06cc\u062c\u0646\u0679 \u062f\u0648\u0646\u0648\u06ba \u0645\u06cc\u06ba \u0628\u062f\u062a\u0631 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<table>\n<thead>\n<tr>\n<th>\u0646\u0627\u0626\u0628<\/th>\n<th>\u0641\u0646\u06a9\u0634\u0646<\/th>\n<th>\u0627\u0644\u06af \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06cc\u0648\u06ba\u061f<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>\u0646\u0635\u0627\u0628 \u0645\u0646\u0635\u0648\u0628\u06c1 \u0633\u0627\u0632<\/strong><\/td>\n<td>\u0633\u06cc\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0627\u06c1\u062f\u0627\u0641 \u0637\u06d2 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0645\u0646\u0638\u0645 \u0633\u06cc\u06a9\u06be\u0646\u06d2 \u06a9\u0627 \u0631\u0648\u0688 \u0645\u06cc\u067e \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4<\/td>\n<td>\u0627\u06cc\u06a9 LLM \u06a9\u0627\u0644\u061b <code>temperature=0.1<\/code>\u060c <code>format=\"json\"<\/code>. \u0632\u06cc\u0631\u0648 \u0679\u0648\u0644\u0632\u06d4 \u06cc\u06c1 \u062a\u06cc\u0632\u060c \u062a\u0639\u06cc\u06cc\u0646 \u067e\u0633\u0646\u062f \u06c1\u06d2\u060c \u0627\u0648\u0631 \u063a\u0644\u0637 \u0627\u0646 \u067e\u0679 \u067e\u0631 \u062a\u06cc\u0632\u06cc \u0633\u06d2 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1\u0627\u06ba \u0679\u0648\u0644 \u06a9\u0627\u0644 \u06a9\u06d2 \u0631\u0648\u06cc\u06d2 \u06a9\u0648 \u0645\u06a9\u0633 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0633\u0627\u062e\u062a\u06cc \u0622\u0624\u0679 \u067e\u0679 \u0645\u06cc\u06ba \u0634\u0648\u0631 \u0634\u0627\u0645\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/td>\n<\/tr>\n<tr>\n<td><strong>\u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u0627<\/strong><\/td>\n<td>MCP \u0633\u0648\u0631\u0633 \u0646\u0648\u0679\u0633 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0637\u0644\u0628\u0627\u0621 \u06a9\u0648 \u0645\u0648\u0636\u0648\u0639\u0627\u062a \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/td>\n<td>\u0627\u06cc\u06a9 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u06af\u0631\u062f\u0634 \u0679\u0648\u0644 \u06a9\u0627\u0644 \u0644\u0648\u067e\u0633\u06d4 <code>temperature=0.3<\/code>. \u0644\u0648\u067e\u0633 \u06a9\u06cc \u062a\u0639\u062f\u0627\u062f \u063a\u06cc\u0631 \u0645\u0642\u0631\u0631\u06c1 \u06c1\u06d2\u06d4 LLM \u0637\u06d2 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u06a9\u0628 \u06a9\u0627\u0641\u06cc \u06c1\u06d2\u06d4 \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u06a9\u0627 \u0646\u0645\u0648\u0646\u06c1 \u067e\u0644\u0627\u0646\u0631 \u0633\u06d2 \u0628\u0627\u0644\u06a9\u0644 \u0645\u062e\u062a\u0644\u0641 \u06c1\u06d2\u06d4<\/td>\n<\/tr>\n<tr>\n<td><strong>\u06a9\u0648\u0626\u0632 \u062c\u0646\u0631\u06cc\u0679\u0631<\/strong><\/td>\n<td>\u0633\u0648\u0627\u0644\u0627\u062a (\u062a\u062e\u0644\u06cc\u0642\u06cc) \u0627\u0648\u0631 \u0627\u0633\u06a9\u0648\u0631 \u062c\u0648\u0627\u0628\u0627\u062a (\u062a\u062c\u0632\u06cc\u0627\u062a\u06cc) \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4<\/td>\n<td>\u0645\u062e\u062a\u0644\u0641 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062f\u0648 \u0627\u0644\u06af \u0627\u0644\u06af \u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u0627\u0644\u0632\u06d4 \u0627\u0646\u0679\u0631\u0627\u06cc\u06a9\u0679\u0648: \u0635\u0627\u0631\u0641 \u06a9\u06d2 \u0627\u0646 \u067e\u0679 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0648\u0642\u0648\u0641\u06d4 \u06cc\u06c1 \u0627\u0633\u0679\u06cc\u0646\u0688 \u0627\u0633\u0679\u0648\u0646 A2A \u0633\u0631\u0648\u0633 (\u0628\u0627\u0628 8) \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0628\u06be\u06cc \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u06cc\u06c1 \u06a9\u0633\u06cc \u062f\u0648\u0633\u0631\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0628\u0646\u0688\u0644 \u06c1\u0648 \u062a\u0648 \u0627\u06cc\u0633\u0627 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627\u06d4<\/td>\n<\/tr>\n<tr>\n<td><strong>\u062a\u0631\u0642\u06cc \u06a9\u0648\u0686<\/strong><\/td>\n<td>\u0645\u062c\u0645\u0648\u0639\u06cc \u0646\u062a\u0627\u0626\u062c\u060c \u0645\u0648\u0636\u0648\u0639 \u06a9\u06cc \u062d\u06cc\u062b\u06cc\u062a \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0627\u06af\u0644\u06d2 \u0645\u0648\u0636\u0648\u0639 \u06cc\u0627 \u0628\u0627\u06c1\u0631 \u0646\u06a9\u0644\u0646\u06d2 \u06a9\u0627 \u0631\u0627\u0633\u062a\u06c1\u06d4<\/td>\n<td>\u0645\u0646\u0641\u0631\u062f \u0627\u06cc\u062c\u0646\u0679 \u0633\u06d2 \u0627\u06cc\u062c\u0646\u0679 A2A \u06a9\u0627\u0644\u0632 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 (CrewAI Study Buddy \u06a9\u0648)\u06d4 MCP \u0645\u06cc\u0645\u0648\u0631\u06cc \u06a9\u0648 \u067e\u0691\u06be\u062a\u0627 \u0627\u0648\u0631 \u0644\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4 \u0631\u0648\u0679\u0646\u06af \u06a9\u06d2 \u0641\u06cc\u0635\u0644\u0648\u06ba \u06a9\u0627 \u0627\u0646\u062a\u0638\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0627 \u062a\u0639\u06cc\u0646 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u06cc\u0627 \u06af\u0631\u0627\u0641 \u0644\u0648\u067e \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u06cc\u0627 \u062e\u062a\u0645 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u0646\u0635\u0627\u0628 \u06a9\u06d2 \u0645\u0646\u0635\u0648\u0628\u06c1 \u0633\u0627\u0632 \u0627\u0648\u0631 \u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u06c1\u06cc \u0639\u0644\u06cc\u062d\u062f\u06af\u06cc \u06a9\u0627 \u062c\u0648\u0627\u0632 \u067e\u06cc\u0634 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u06cc\u06a9 \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc \u0679\u0648\u0644\u0632 \u06a9\u06d2 \u0633\u0679\u0631\u06a9\u0686\u0631\u0688 JSON \u0622\u0624\u0679 \u067e\u0679 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u062f\u0648\u0633\u0631\u0627 \u0645\u0644\u0679\u06cc \u0679\u0631\u0646 \u0679\u0648\u0644 \u06a9\u0627\u0644 \u0644\u0648\u067e \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633\u06d2 \u0627\u06cc\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u0645\u06cc\u06ba \u0688\u0627\u0644\u0646\u06d2 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u0627\u06cc\u06a9 \u0641\u0646\u06a9\u0634\u0646 \u062c\u0648 \u06a9\u0628\u06be\u06cc \u06a9\u0628\u06be\u06cc \u0679\u0648\u0644 \u06a9\u0648 \u0644\u0648\u067e \u0645\u06cc\u06ba \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u06a9\u0628\u06be\u06cc \u06a9\u0628\u06be\u06cc \u0645\u062e\u062a\u0644\u0641 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u067e\u0631 \u0645\u062e\u062a\u0644\u0641 \u0642\u0633\u0645 \u06a9\u06cc \u0622\u0624\u0679 \u067e\u0679 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0635\u0644\u0627\u062d\u06cc\u062a\u0648\u06ba \u06a9\u06cc \u0627\u06cc\u06a9 \u0648\u0633\u06cc\u0639 \u0631\u06cc\u0646\u062c \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2. \u0627\u06cc\u06a9 \u06c1\u0648\u0646\u06d2 \u06a9\u0627 \u0628\u06c1\u0627\u0646\u06c1 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u062f\u0648 \u0627\u06cc\u062c\u0646\u0679 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06a9\u0648\u0626\u0632 \u062c\u0646\u0631\u06cc\u0679\u0631 \u06a9\u0627 \u062f\u0648\u06c1\u0631\u0627 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u067e\u06cc\u0679\u0631\u0646 (\u062a\u062e\u0644\u06cc\u0642\u06cc \u0633\u0648\u0627\u0644 \u067e\u06cc\u062f\u0627 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 0.4\u060c \u062a\u062c\u0632\u06cc\u0627\u062a\u06cc \u0627\u0633\u06a9\u0648\u0631\u0646\u06af \u06a9\u06d2 \u0644\u06cc\u06d2 0.1) \u0627\u0648\u0631 \u06cc\u06c1 \u062d\u0642\u06cc\u0642\u062a \u06a9\u06c1 \u0627\u0633\u06d2 \u0627\u0633\u0679\u06cc\u0646\u0688 \u0627\u0633\u0679\u0648\u0646 A2A \u0633\u0631\u0648\u0633 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2 \u0627\u0633 \u06a9\u06cc \u0627\u067e\u0646\u06cc \u062d\u062f\u0648\u062f \u06a9\u06cc \u062d\u0645\u0627\u06cc\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0633\u06c1\u0648\u0644\u062a \u06a9\u0648\u0686 \u06a9\u0648\u0622\u0631\u0688\u06cc\u0646\u06cc\u0679\u0631 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0633\u0628 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0631\u06a9\u06be\u06cc\u06ba \u0627\u0648\u0631 \u0631\u0648\u0679\u0646\u06af \u06a9\u06d2 \u0641\u06cc\u0635\u0644\u06d2 \u06a9\u0631\u06cc\u06ba\u06d4 \u062f\u0648\u0633\u0631\u06d2 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0634\u062a\u0631\u0627\u06a9 \u06a9\u0631\u0646\u0627 \u0628\u0627\u0644\u06a9\u0644 \u063a\u0644\u0637 \u0686\u06cc\u0632 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u0622\u067e \u06a9\u06d2 \u0627\u067e\u0646\u06d2 \u0645\u0633\u0627\u0626\u0644 \u0645\u06cc\u06ba \u062a\u0644\u0627\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u0627\u06cc\u06a9 \u0646\u0645\u0648\u0646\u06c1 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0627\u0633 \u0628\u0627\u062a \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u0646\u06c1\u06cc\u06ba \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u062f\u0648\u0646\u0648\u06ba \u0627\u0639\u0645\u0627\u0644 \u06a9\u0648 \u0627\u06cc\u06a9 \u06c1\u06cc \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06cc\u0648\u06ba \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u060c \u062a\u0648 \u0634\u0627\u06cc\u062f \u0648\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1\u06cc \u0627\u0633\u062a\u062f\u0644\u0627\u0644 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0646\u0638\u0627\u0645 \u067e\u0631 \u0644\u0627\u06af\u0648 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0639\u0645\u06cc\u0644 \u06a9\u06d2 \u062a\u0631\u0628\u06cc\u062a\u06cc \u067e\u0644\u06cc\u0679 \u0641\u0627\u0631\u0645 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0646\u0635\u0627\u0628 \u0627\u06cc\u062c\u0646\u0679 (\u0627\u06cc\u06a9 \u0633\u0631\u0679\u06cc\u0641\u06cc\u06a9\u06cc\u0634\u0646 \u06a9\u0627 \u0631\u0627\u0633\u062a\u06c1 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2)\u060c \u0627\u06cc\u06a9 \u0645\u0648\u0627\u062f \u06a9\u06cc \u062a\u0631\u0633\u06cc\u0644 \u06a9\u0627 \u0627\u06cc\u062c\u0646\u0679 (\u0645\u0648\u0627\u062f MCP \u0633\u0631\u0648\u0631\u0632 \u0633\u06d2 \u0631\u06cc\u06af\u0648\u0644\u06cc\u0679\u0688 \u0645\u0648\u0627\u062f \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2)\u060c \u0627\u06cc\u06a9 \u062a\u0634\u062e\u06cc\u0635\u06cc \u0627\u06cc\u062c\u0646\u0679 (\u0679\u06cc\u0633\u0679 \u0641\u06c1\u0645\u060c \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u06d2 \u0646\u062a\u0627\u0626\u062c)\u060c \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0633\u0631\u0679\u06cc\u0641\u06cc\u06a9\u06cc\u0634\u0646 \u0627\u06cc\u062c\u0646\u0679 (\u0622\u0645\u0627\u062f\u06af\u06cc \u06a9\u0627 \u0627\u0646\u062f\u0627\u0632\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0633\u0631\u0679\u06cc\u0641\u06a9\u06cc\u0679 \u062c\u0627\u0631\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2)\u06d4<\/p>\n<p>\u06c1\u0631 \u0627\u06cc\u06a9 \u06a9\u06d2 \u067e\u0627\u0633 \u0645\u062e\u062a\u0644\u0641 \u0679\u0648\u0644\u0632\u060c \u0645\u062e\u062a\u0644\u0641 \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u0637\u0631\u06cc\u0642\u06d2\u060c \u0627\u0648\u0631 \u0645\u062e\u062a\u0644\u0641 \u0627\u067e \u0688\u06cc\u0679 \u0633\u0627\u0626\u06cc\u06a9\u0644 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0639\u0644\u06cc\u062d\u062f\u06af\u06cc \u0627\u06cc\u06a9 \u062a\u0639\u0645\u06cc\u0631\u0627\u062a\u06cc \u0641\u0644\u0633\u0641\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06cc\u06c1 \u06c1\u0631 \u06a9\u0627\u0645 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06a9\u0627 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u0646\u062a\u06cc\u062c\u06c1 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-15-setting-up-the-project\">1.5 \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628\u0627\u062a<\/h3>\n<p>\u0627\u0628 \u062c\u0628 \u06a9\u06c1 \u06c1\u0645\u0627\u0631\u0627 \u062a\u0639\u0645\u06cc\u0631\u0627\u062a\u06cc \u0627\u0633\u062a\u062f\u0644\u0627\u0644 \u0642\u0627\u0626\u0645 \u06c1\u0648 \u0686\u06a9\u0627 \u06c1\u06d2\u060c \u0622\u0626\u06cc\u06d2 \u0646\u0638\u0627\u0645 \u06a9\u06cc \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<h4 id=\"heading-install-ollama-and-pull-your-model\">\u0627\u0648\u0644\u0627\u0645\u0627 \u0627\u0646\u0633\u0679\u0627\u0644 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0627\u067e\u0646\u0627 \u0645\u0627\u0688\u0644 \u062f\u0631\u0622\u0645\u062f \u06a9\u0631\u06cc\u06ba\u06d4<\/h4>\n<p>\u0627\u0648\u0644\u0627\u0645\u0627 \u0645\u0642\u0627\u0645\u06cc LLM \u06a9\u0648 OpenAI \u06a9\u06d2 \u0645\u0648\u0627\u0641\u0642 \u0633\u0631\u0648\u0631 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>localhost:11434<\/code>.<\/p>\n<p>\u0645\u06cc\u06a9\u0648\u0633 \u0627\u0648\u0631 \u0644\u06cc\u0646\u06a9\u0633:<\/p>\n<pre><code class=\"language-bash\">curl -fsSL https:\/\/ollama.com\/install.sh | sh\n<\/code><\/pre>\n<p>\u0648\u0646\u0688\u0648\u0632: ollama.com \u0633\u06d2 \u0627\u0646\u0633\u0679\u0627\u0644\u0631 \u0688\u0627\u0624\u0646 \u0644\u0648\u0688 \u0627\u0648\u0631 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<p>\u0648\u06c1 \u0645\u0627\u0688\u0644 \u0645\u0646\u062a\u062e\u0628 \u06a9\u0631\u06cc\u06ba \u062c\u0648 \u0622\u067e \u06a9\u06d2 \u06c1\u0627\u0631\u0688 \u0648\u06cc\u0626\u0631 \u0633\u06d2 \u0645\u0645\u0627\u062b\u0644 \u06c1\u0648:<\/p>\n<pre><code class=\"language-bash\"># 8 GB VRAM\nollama pull qwen2.5:7b\n\n# 24 GB VRAM: stronger tool calling, recommended if you have it\nollama pull qwen2.5-coder:32b\n\n# Verify it works\nollama run qwen2.5:7b \"Say hello in one sentence.\"\n<\/code><\/pre>\n<p>\u0627\u06cc\u06a9 \u0645\u062e\u062a\u0635\u0631 \u062c\u0648\u0627\u0628 \u062f\u06a9\u06be\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 \u0627\u0648\u0644\u0627\u0645\u0627 \u06a9\u0648 \u0628\u06cc\u06a9 \u06af\u0631\u0627\u0624\u0646\u0688 \u0633\u0631\u0648\u0631 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0686\u0644\u0627\u062a\u06d2 \u0631\u06c1\u06cc\u06ba\u06d4 \u06a9\u0627\u0644\u0648\u06ba \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0641\u0639\u0627\u0644 \u0631\u06c1\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-clone-the-repository\">\u0630\u062e\u06cc\u0631\u06c1 \u0646\u0642\u0644<\/h4>\n<pre><code class=\"language-bash\">git clone https:\/\/github.com\/sandeepmb\/freecodecamp-multi-agent-ai-system\ncd freecodecamp-multi-agent-ai-system\n<\/code><\/pre>\n<h4 id=\"heading-set-up-the-virtual-environment\">\u0648\u0631\u0686\u0648\u0626\u0644 \u0645\u0627\u062d\u0648\u0644 \u06a9\u0627 \u0633\u06cc\u0679 \u0627\u067e<\/h4>\n<pre><code class=\"language-bash\">python -m venv .venv\nsource .venv\/bin\/activate      # Windows: .venvScriptsactivate\npip install -r requirements.txt\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>requirements.txt<\/code> \u0679\u06cc\u0633\u0679 \u0634\u062f\u06c1 \u0648\u0631\u0698\u0646 \u067e\u0631 \u062a\u0645\u0627\u0645 \u0627\u0646\u062d\u0635\u0627\u0631 \u067e\u0646 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-plaintext\"># requirements.txt\nlanggraph==1.1.0\nlanggraph-checkpoint-sqlite==3.0.3\nlangchain-core==1.0.0\nlangchain-ollama==1.0.0\n\nmcp==1.26.0\na2a-sdk==0.3.25\ncrewai==1.13.0\n\nlangfuse==4.0.1\ndeepeval==3.9.1\n\nlitellm==1.82.4\nopenai==2.8.0\nhttpx==0.28.1\nfastapi==0.115.0\nuvicorn==0.34.0\nstreamlit==1.43.2\n\npydantic==2.11.9\npython-dotenv==1.1.1\ntenacity==8.5.0\n\npytest==8.3.0\npytest-asyncio==0.25.0\n<\/code><\/pre>\n<p> <strong>\u0627\u0646\u062d\u0635\u0627\u0631\u06cc \u0648\u0631\u0698\u0646 \u06a9\u0648 \u0627\u067e \u06af\u0631\u06cc\u0688 \u0646\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0627\u0633 \u0627\u0633\u0679\u06cc\u06a9 \u0645\u06cc\u06ba \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9\u060c \u062e\u0627\u0635 \u0637\u0648\u0631 \u067e\u0631 LangGraph\u060c langchain-core\u060c \u0627\u0648\u0631 A2A SDK \u0645\u06cc\u06ba \u0645\u0639\u0645\u0648\u0644\u06cc \u0648\u0631\u0698\u0646 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0641\u06a9\u0633\u0688 \u0648\u0631\u0698\u0646 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0622\u0632\u0645\u0627\u0626\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0686\u0644 \u0631\u06c1\u0627 \u06c1\u06d2 <code>pip install --upgrade<\/code> \u0627\u0646 \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0633\u06cc \u0645\u06cc\u06ba \u0628\u06be\u06cc \u0622\u067e \u06a9\u06cc \u0622\u0645\u062f\u0646\u06cc \u06cc\u0627 \u0627\u0639\u0645\u0627\u0644 \u06a9\u06d2 \u0679\u0648\u0679\u0646\u06d2 \u06a9\u0627 \u062e\u0637\u0631\u06c1 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-configure-your-environment\">\u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628<\/h4>\n<pre><code class=\"language-bash\">cp .env.example .env\n<\/code><\/pre>\n<p>\u06a9\u06be\u0644\u0627 <code>.env<\/code> \u0627\u067e\u0646\u0627 \u0645\u0627\u0688\u0644 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\"># .env: set this to match what you pulled\nOLLAMA_MODEL=qwen2.5:7b\nOLLAMA_BASE_URL=http:\/\/localhost:11434\n\n# Storage\nCHECKPOINT_DB=data\/checkpoints.db\nNOTES_PATH=study_materials\/sample_notes\n\n# A2A services (used in Chapter 8)\nQUIZ_SERVICE_URL=http:\/\/localhost:9001\nSTUDY_BUDDY_URL=http:\/\/localhost:9002\nUSE_A2A_QUIZ=true\nUSE_STUDY_BUDDY=true\n\n# Langfuse: leave empty for now, configured in Chapter 6\nLANGFUSE_PUBLIC_KEY=\nLANGFUSE_SECRET_KEY=\nLANGFUSE_HOST=http:\/\/localhost:3000\n<\/code><\/pre>\n<h4 id=\"heading-verify-the-setup\">\u062a\u0631\u062a\u06cc\u0628\u0627\u062a \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/h4>\n<pre><code class=\"language-bash\">python main.py --help\n<\/code><\/pre>\n<p>\u0622\u067e \u06a9\u0648 \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc \u063a\u0644\u0637\u06cc \u06a9\u06d2 argparse \u0645\u062f\u062f \u0622\u0624\u0679 \u067e\u0679 \u062f\u06cc\u06a9\u06be\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u062f\u0631\u0622\u0645\u062f \u06a9\u06cc \u062e\u0631\u0627\u0628\u06cc\u0627\u06ba \u062f\u06cc\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u0626\u06cc\u06ba \u06a9\u06c1 \u0622\u067e \u06a9\u0627 \u0648\u0631\u0686\u0648\u0626\u0644 \u0645\u0627\u062d\u0648\u0644 \u0641\u0639\u0627\u0644 \u06c1\u06d2\u06d4<\/p>\n<p> <strong>\u0686\u0648\u06a9\u06cc:<\/strong> \u0627\u0648\u0644\u0627\u0645\u0627 \u0686\u0644 \u0631\u06c1\u0627 \u06c1\u06d2\u060c \u0627\u0646\u062d\u0635\u0627\u0631 \u0627\u0646\u0633\u0679\u0627\u0644 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0645\u0627\u062d\u0648\u0644 \u06a9\u0648 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u0645\u0646\u0635\u0648\u0628\u06d2 \u06a9\u0627 \u0688\u06be\u0627\u0646\u0686\u06c1 \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-plaintext\">freecodecamp-multi-agent-ai-system\/\n\u251c\u2500\u2500 src\/\n\u2502   \u251c\u2500\u2500 agents\/           # LangGraph agent nodes\n\u2502   \u251c\u2500\u2500 graph\/            # State definition and workflow\n\u2502   \u251c\u2500\u2500 mcp_servers\/      # MCP tool servers\n\u2502   \u251c\u2500\u2500 a2a_services\/     # A2A protocol services and client\n\u2502   \u251c\u2500\u2500 crewai_agent\/     # CrewAI agent served via A2A\n\u2502   \u2514\u2500\u2500 observability\/    # Langfuse setup\n\u251c\u2500\u2500 tests\/                # Unit and evaluation tests\n\u251c\u2500\u2500 study_materials\/\n\u2502   \u2514\u2500\u2500 sample_notes\/     # Markdown files the Explainer reads\n\u251c\u2500\u2500 docs\/\n\u251c\u2500\u2500 data\/                 # SQLite checkpoint DB (created at runtime)\n\u251c\u2500\u2500 main.py\n\u251c\u2500\u2500 Makefile\n\u251c\u2500\u2500 docker-compose.yml    # Langfuse local stack\n\u251c\u2500\u2500 requirements.txt\n\u2514\u2500\u2500 .env.example\n<\/code><\/pre>\n<p>\u062a\u0645\u0627\u0645 <code>src\/<\/code> \u06cc\u06c1 \u0645\u0639\u06cc\u0627\u0631\u06cc \u0627\u0632\u06af\u0631 \u06a9\u06cc \u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>src\/<\/code> \u0627\u062d\u062a\u06cc\u0627\u0637 \u0633\u06d2 \u062f\u0631\u062c \u06c1\u06d2\u06d4 \u06a9\u06c1 <code>pyproject.toml<\/code> \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba <code>src\/<\/code> \u0627\u067e\u0646\u06d2 \u0627\u0632\u06af\u0631 \u06a9\u06d2 \u0631\u0627\u0633\u062a\u06d2 \u067e\u0631 \u062a\u0627\u06a9\u06c1 \u0622\u067e \u06a9\u06d2 \u0679\u06cc\u0633\u0679 \u0627\u0633\u06d2 \u062f\u0631\u0622\u0645\u062f \u06a9\u0631\u0633\u06a9\u06cc\u06ba\u06d4 <code>from graph.state import AgentState<\/code> \u067e\u0627\u062a\u06be \u062c\u0645\u0646\u0627\u0633\u0679\u06a9 \u06a9\u06d2 \u0628\u063a\u06cc\u0631\u06d4<\/p>\n<p>\u0627\u06af\u0644\u06d2 \u0628\u0627\u0628 \u0645\u06cc\u06ba\u060c \u0622\u067e \u0633\u0633\u0679\u0645 \u06a9\u0627 \u067e\u06c1\u0644\u0627 \u062d\u0635\u06c1 \u0628\u0646\u0627\u0626\u06cc\u06ba \u06af\u06d2\u060c \u0627\u06cc\u06a9 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u06af\u0631\u0627\u0641 \u062c\u0648 \u0686\u0627\u0631\u0648\u06ba \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0645\u0631\u0628\u0648\u0637 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0645 \u0627\u06cc\u06a9 \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0631\u06cc\u0627\u0633\u062a \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0634\u0631\u0648\u0639 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0633\u06d2 \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679 \u067e\u0691\u06be\u062a\u06d2 \u0644\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-chapter-2-stateful-orchestration-with-langgraph\">\u0628\u0627\u0628 2: \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0631\u06cc\u0627\u0633\u062a\u06cc \u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0634\u0646<\/h2>\n<p>\u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0645\u0627\u0688\u0644\u0632 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0648\u0631\u06a9 \u0641\u0644\u0648\u0632 \u06a9\u0648 \u06c1\u062f\u0627\u06cc\u062a \u0634\u062f\u06c1 \u06af\u0631\u0627\u0641 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u067e\u06cc\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0646\u0648\u0688\u0632 \u0627\u0632\u06af\u0631 \u06a9\u06d2 \u0627\u0641\u0639\u0627\u0644 \u06c1\u06cc\u06ba\u060c \u06cc\u0639\u0646\u06cc \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648\u0688\u06d4 \u06a9\u0646\u0627\u0631\u06d2 \u0627\u0646 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0631\u0648\u0679\u0646\u06af \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062a\u0645\u0627\u0645 \u0646\u0648\u0688\u0633 \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0627\u0633\u0679\u06cc\u0679 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0633\u06d2 \u067e\u0691\u06be\u062a\u06d2 \u0627\u0648\u0631 \u0644\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u06cc\u06a9 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u062c\u0648 \u062a\u0645\u0627\u0645 \u0646\u0648\u0688\u0633 \u06a9\u06d2 \u0686\u0644\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f SQLite \u0645\u06cc\u06ba \u0631\u06cc\u0627\u0633\u062a \u06a9\u06cc \u0646\u0645\u0627\u0626\u0646\u062f\u06af\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0622\u062e\u0631\u06cc \u062d\u0635\u06c1 \u0648\u06c1 \u06c1\u06d2 \u062c\u0648 \u0627\u0633\u06d2 \u0633\u06c1\u0648\u0644\u062a \u0631\u06cc\u067e\u0631 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0679\u0648\u0644 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u0628\u0648\u0644\u06cc \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0644\u0648\u067e \u0627\u0633 \u0637\u0631\u062d \u0644\u06a9\u06be\u0627 \u06c1\u0648\u0627 \u06c1\u06d2: <code>for<\/code> \u062c\u0633 \u0644\u0645\u062d\u06d2 \u0627\u06cc\u06a9 \u0644\u0648\u067e \u06a9\u0631\u06cc\u0634 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u0648\u06c1 \u0633\u0628 \u06a9\u0686\u06be \u06a9\u06be\u0648 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627\u06d4 \u0686\u0648\u06a9\u06cc\u0627\u06ba \u062d\u0627\u062f\u062b\u0627\u062a \u0633\u06d2 \u0628\u0686 \u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 <code>graph.invoke()<\/code> \u0627\u06af\u0631 \u0622\u067e \u0648\u06c1\u06cc \u0633\u06cc\u0634\u0646 ID \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u06cc\u06c1 \u0628\u0627\u0644\u06a9\u0644 \u0648\u06c1\u06cc\u06ba \u0633\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627 \u062c\u06c1\u0627\u06ba \u0633\u06d2 \u0627\u0633 \u0646\u06d2 \u0686\u06be\u0648\u0691\u0627 \u062a\u06be\u0627\u06d4<\/p>\n<p>\u0627\u0633 \u0628\u0627\u0628 \u0645\u06cc\u06ba\u060c \u06c1\u0645 \u06af\u0631\u0627\u0641 \u0641\u0627\u0624\u0646\u0688\u06cc\u0634\u0646 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062c\u0633 \u0645\u06cc\u06ba \u0686\u0627\u0631\u0648\u06ba \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06cc \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0631\u06cc\u0627\u0633\u062a \u06a9\u06cc \u062a\u0639\u0631\u06cc\u0641\u060c \u067e\u06c1\u0644\u0627 \u0679\u0627\u0633\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u0646\u0648\u0688\u060c \u0627\u0648\u0631 \u06af\u0631\u0627\u0641 \u062c\u0648 \u0627\u0646 \u06a9\u0648 \u062c\u0648\u0691\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-21-the-shared-state\">2.1 \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0631\u06cc\u0627\u0633\u062a<\/h3>\n<p>\u06af\u0631\u0627\u0641 \u0645\u06cc\u06ba \u062a\u0645\u0627\u0645 \u0646\u0648\u0688\u0633 \u06a9\u06cc \u0645\u06a9\u0645\u0644 \u062d\u0627\u0644\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 <code>dict<\/code> \u0627\u06cc\u06a9 \u062c\u0632\u0648\u06cc \u0627\u067e \u0688\u06cc\u0679 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0628\u0634\u0645\u0648\u0644 \u0635\u0631\u0641 \u0628\u062f\u0644\u06cc \u06c1\u0648\u0626\u06cc \u0686\u0627\u0628\u06cc\u0627\u06ba\u06d4 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0627\u0646 \u0627\u067e \u0688\u06cc\u0679\u0633 \u06a9\u0648 \u0645\u062c\u0645\u0648\u0639\u06cc \u062d\u0627\u0644\u062a \u0645\u06cc\u06ba \u0636\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u06af\u0644\u06d2 \u0646\u0648\u0688 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u0648 \u0645\u062d\u0641\u0648\u0638 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0631\u06cc\u0627\u0633\u062a \u06a9\u06cc \u062a\u0639\u0631\u06cc\u0641 <code>src\/graph\/state.py<\/code> \u0686\u0627\u0631 \u0688\u06cc\u0679\u0627 \u06a9\u0644\u0627\u0633\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba \u062c\u0646 \u0645\u06cc\u06ba \u0633\u0679\u0631\u06a9\u0686\u0631\u0688 \u0688\u06cc\u0679\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u067e\u06be\u0631 <code>AgentState<\/code> TypedDict \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u06a9\u06d2 \u0632\u06cc\u0631 \u0627\u0646\u062a\u0638\u0627\u0645:<\/p>\n<pre><code class=\"language-python\"># src\/graph\/state.py\n\nfrom __future__ import annotations\n\nimport json\nfrom dataclasses import dataclass, field, asdict\nfrom typing import Annotated, TypedDict\n\nfrom langchain_core.messages import BaseMessage\nfrom langgraph.graph.message import add_messages\n\n\n@dataclass\nclass Topic:\n    \"\"\"A single topic within the study roadmap.\"\"\"\n    title: str\n    description: str\n    estimated_minutes: int\n    prerequisites: list[str] = field(default_factory=list)\n    # pending \u2192 in_progress \u2192 completed | needs_review\n    status: str = \"pending\"\n\n    def to_dict(self) -> dict:\n        return asdict(self)\n\n    @classmethod\n    def from_dict(cls, data: dict) -> \"Topic\":\n        return cls(\n            title=data[\"title\"],\n            description=data[\"description\"],\n            estimated_minutes=data[\"estimated_minutes\"],\n            prerequisites=data.get(\"prerequisites\", []),\n            status=data.get(\"status\", \"pending\"),\n        )\n\n\n@dataclass\nclass StudyRoadmap:\n    \"\"\"The full study plan produced by the Curriculum Planner.\"\"\"\n    goal: str\n    total_weeks: int\n    topics: list[Topic]\n    weekly_hours: int = 5\n\n    def is_complete(self) -> bool:\n        return all(t.status in (\"completed\", \"needs_review\") for t in self.topics)\n\n\n@dataclass\nclass QuizResult:\n    \"\"\"The complete result of one quiz session on a single topic.\"\"\"\n    topic: str\n    questions: list\n    score: float       # 0.0 to 1.0\n    weak_areas: list[str]\n    timestamp: str = \"\"\n\n    def passed(self) -> bool:\n        return self.score >= 0.5\n\n\nclass AgentState(TypedDict):\n    \"\"\"\n    The shared state for the Learning Accelerator graph.\n\n    Partial updates: when a node returns {\"approved\": True}, LangGraph\n    merges that into the existing state. It does NOT replace the whole dict.\n    Nodes only return the keys they changed.\n\n    The one exception is `messages`: it uses the add_messages reducer,\n    which appends to the list instead of replacing it.\n    \"\"\"\n    messages: Annotated[list[BaseMessage], add_messages]\n    session_id: str\n    goal: str\n    roadmap: StudyRoadmap | None\n    approved: bool\n    current_topic_index: int\n    quiz_results: list[QuizResult]\n    weak_areas: list[str]\n    study_materials_path: str\n    error: str | None\n<\/code><\/pre>\n<p>\u06cc\u06c1\u0627\u06ba \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u06d2 \u0686\u0646\u062f \u0641\u06cc\u0635\u0644\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u0633\u0645\u062c\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p><strong>\u0628\u0627\u0642\u0627\u0639\u062f\u06c1 \u06a9\u0644\u0627\u0633 \u06a9\u06cc\u0648\u06ba \u0627\u0648\u0631 \u0679\u0627\u0626\u067e\u0688\u06a9\u0679 \u06a9\u06cc\u0648\u06ba \u0646\u06c1\u06cc\u06ba\u061f<\/strong> LangGraph \u0627\u06cc\u06a9 dict \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 TypedDict \u0644\u063a\u062a \u06a9\u06cc \u0645\u0637\u0627\u0628\u0642\u062a \u06a9\u0648 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0642\u0633\u0645 \u06a9\u06cc \u062d\u0641\u0627\u0638\u062a \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 (IDE \u063a\u0644\u0637 \u06c1\u062c\u06d2 \u0648\u0627\u0644\u06cc \u06a9\u0644\u06cc\u062f\u0648\u06ba \u06a9\u0648 \u067e\u06a9\u0691\u062a\u0627 \u06c1\u06d2)\u06d4 \u0627\u0633 \u0645\u062e\u0635\u0648\u0635 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06d2 \u06a9\u06cc\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0628\u06c1\u062a\u0631\u06cc\u0646 \u0679\u0648\u0644 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u06a9\u06cc\u0648\u06ba<\/strong> <code>add_messages<\/code> <strong>\u06a9\u0648<\/strong> <code>messages<\/code> <strong>\u0645\u06cc\u062f\u0627\u0646\u061f<\/strong> \u062f\u06cc\u06af\u0631 \u062a\u0645\u0627\u0645 \u0634\u0639\u0628\u0648\u06ba <code>AgentState<\/code> \u0622\u062e\u0631\u06cc \u062a\u062d\u0631\u06cc\u0631 \u062c\u06cc\u062a \u0633\u06cc\u0645\u0646\u0679\u06a9\u0633 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0628 \u062f\u0648 \u0646\u0648\u0688 \u0644\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba: <code>roadmap<\/code>\u062f\u0648\u0633\u0631\u0627 \u062c\u06cc\u062a \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0644\u06cc\u06a9\u0646 \u0628\u0627\u062a \u0686\u06cc\u062a \u06a9\u06d2 \u067e\u06cc\u063a\u0627\u0645\u0627\u062a \u0645\u062c\u0645\u0648\u0639\u06cc \u06c1\u0648\u0646\u06d2 \u0686\u0627\u06c1\u0626\u06cc\u06ba\u06d4 \u06a9\u06c1 <code>add_messages<\/code> \u0631\u06cc\u0688\u0648\u0633\u0631 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u06a9\u0648 \u0641\u06c1\u0631\u0633\u062a \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0646\u0626\u06d2 \u067e\u06cc\u063a\u0627\u0645\u0627\u062a \u0634\u0627\u0645\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u06c1\u062f\u0627\u06cc\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627\u0644\u0648\u06ba \u06a9\u06cc \u0645\u06a9\u0645\u0644 \u06af\u0641\u062a\u06af\u0648 \u06a9\u06cc \u062a\u0627\u0631\u06cc\u062e \u06a9\u0648 \u0645\u062d\u0641\u0648\u0638 \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u06c1\u0645\u06cc\u06ba \u0688\u06cc\u0679\u0627 \u06a9\u0644\u0627\u0633\u0632 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06a9\u06cc\u0648\u06ba \u06c1\u06d2\u061f<\/strong> <code>Topic<\/code><strong>\u060c<\/strong> <code>StudyRoadmap<\/code><strong>\u0627\u0648\u0631<\/strong> <code>QuizResult<\/code><strong>?<\/strong> \u0627\u0633 \u06a9\u06cc \u0648\u062c\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u063a\u0644\u0637\u06cc \u0633\u06d2 \u0686\u0627\u0628\u06cc\u0627\u06ba \u062f\u0627\u062e\u0644 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u0633\u0627\u062e\u062a\u06cc \u0688\u06cc\u0679\u0627 \u06a9\u0648 \u067e\u0691\u06be\u0646\u0627 \u0627\u0648\u0631 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 <code>topic.title<\/code> \u0627\u0679\u06be\u0627\u0646\u0627 <code>AttributeError<\/code> \u0627\u06af\u0631 \u0645\u06cc\u062f\u0627\u0646 \u0645\u0648\u062c\u0648\u062f \u0646\u06c1 \u06c1\u0648 \u062a\u0648 \u0641\u0648\u0631\u0627\u064b\u06d4 <code>topic[\"titl\"]<\/code> \u062e\u0627\u0645\u0648\u0634\u06cc \u0633\u06d2 \u0648\u0627\u067e\u0633 \u0622 \u062c\u0627\u0624 <code>None<\/code>. \u0633\u0679\u0631\u06a9\u0686\u0631\u0688 \u0688\u06cc\u0679\u0627 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062c\u0633\u06d2 \u0645\u062a\u0639\u062f\u062f \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0686\u06be\u0648 \u0644\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0688\u06cc\u0679\u0627 \u06a9\u06cc \u06a9\u0644\u0627\u0633\u06cc\u06ba \u0628\u0627\u0642\u0627\u0639\u062f\u06c1 \u0644\u063a\u0627\u062a \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u062d\u0641\u0648\u0638 \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06a9\u06c1 <code>src\/graph\/state.py<\/code> \u0641\u0627\u0626\u0644 \u0645\u06cc\u06ba \u062a\u06cc\u0646 \u0627\u0641\u0627\u062f\u06cc\u062a \u06a9\u06d2 \u0627\u0641\u0639\u0627\u0644 \u0628\u06be\u06cc \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba \u062c\u0648 \u0627\u06cc\u062c\u0646\u0679 \u0646\u0648\u0688\u0633 \u0645\u062d\u0641\u0648\u0638 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u062d\u0627\u0644\u062a \u06a9\u0648 \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\"># src\/graph\/state.py (continued)\n\ndef initial_state(\n    goal: str,\n    session_id: str,\n    study_materials_path: str = \"study_materials\/sample_notes\",\n) -> dict:\n    \"\"\"Create the initial state for a new study session.\"\"\"\n    return {\n        \"messages\": [],\n        \"session_id\": session_id,\n        \"goal\": goal,\n        \"roadmap\": None,\n        \"approved\": False,\n        \"current_topic_index\": 0,\n        \"quiz_results\": [],\n        \"weak_areas\": [],\n        \"study_materials_path\": study_materials_path,\n        \"error\": None,\n    }\n\n\ndef get_current_topic(state: dict) -> Topic | None:\n    \"\"\"Get the topic currently being studied, or None if done.\"\"\"\n    roadmap = state.get(\"roadmap\")\n    if roadmap is None:\n        return None\n    idx = state.get(\"current_topic_index\", 0)\n    if idx >= len(roadmap.topics):\n        return None\n    return roadmap.topics[idx]\n\n\ndef session_is_complete(state: dict) -> bool:\n    \"\"\"True when all topics have been studied.\"\"\"\n    roadmap = state.get(\"roadmap\")\n    if roadmap is None:\n        return True\n    idx = state.get(\"current_topic_index\", 0)\n    return idx >= len(roadmap.topics)\n<\/code><\/pre>\n<p><code>initial_state()<\/code> \u0627\u0633 \u0637\u0631\u062d \u0645\u06cc\u06ba \u06c1\u0645\u06cc\u0634\u06c1 \u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u0633\u06cc\u0634\u0646 \u0628\u0646\u0627\u062a\u0627 \u06c1\u0648\u06ba\u06d4 \u062f\u0633\u062a\u06cc \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0628\u06be\u06cc \u0628\u06be\u06cc \u0688\u06a9\u0679 \u0646\u06c1 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u0626\u06cc\u06ba \u06a9\u06c1 \u062a\u0645\u0627\u0645 \u0641\u06cc\u0644\u0688\u0632 \u0645\u06cc\u06ba \u062f\u0631\u0633\u062a \u0688\u06cc\u0641\u0627\u0644\u0679 \u0627\u0642\u062f\u0627\u0631 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0645\u0637\u0644\u0648\u0628\u06c1 \u06a9\u0644\u06cc\u062f\u06cc\u06ba \u0646\u0627\u062f\u0627\u0646\u0633\u062a\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u063a\u0627\u0626\u0628 \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-22-the-curriculum-planner-the-first-agent-node\">2.2 \u0646\u0635\u0627\u0628 \u06a9\u0627 \u0645\u0646\u0635\u0648\u0628\u06c1 \u0633\u0627\u0632: \u067e\u06c1\u0644\u0627 \u0627\u06cc\u062c\u0646\u0679 \u0646\u0648\u0688<\/h3>\n<p>\u06a9\u0631\u06cc\u06a9\u0648\u0644\u0645 \u067e\u0644\u0627\u0646\u0631 \u0633\u0633\u0679\u0645 \u06a9\u0627 \u0633\u0628 \u0633\u06d2 \u0622\u0633\u0627\u0646 \u0627\u06cc\u062c\u0646\u0679 \u06c1\u06d2\u060c \u0627\u06cc\u06a9 LLM \u06a9\u0627\u0644\u060c \u0627\u06cc\u06a9 JSON \u062c\u0648\u0627\u0628\u060c \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0688\u06cc\u0679\u0627 \u06a9\u0644\u0627\u0633 \u0622\u0624\u0679 \u067e\u0679 \u06a9\u06d2 \u0633\u0627\u062a\u06be\u06d4 \u06a9\u0648\u0626\u06cc \u0679\u0648\u0644\u0632\u060c \u06a9\u0648\u0626\u06cc \u0644\u0648\u067e\u0633 \u0646\u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0627\u0633 \u067e\u06cc\u0679\u0631\u0646 \u06a9\u0648 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0633 \u067e\u0631 \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679 \u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba: \u0627\u0633\u0679\u06cc\u0679 \u067e\u0691\u06be\u06cc\u06ba\u060c \u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u060c \u0622\u0624\u0679 \u067e\u0679 \u06a9\u0648 \u067e\u0627\u0631\u0633 \u06a9\u0631\u06cc\u06ba\u060c \u062c\u0632\u0648\u06cc \u0627\u0633\u0679\u06cc\u0679 \u0627\u067e \u0688\u06cc\u0679 \u0648\u0627\u067e\u0633 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\"># src\/agents\/curriculum_planner.py\n\nimport json\nimport os\n\nfrom langchain_core.messages import HumanMessage, SystemMessage\nfrom langchain_ollama import ChatOllama\n\nfrom graph.state import StudyRoadmap, Topic\n\nMODEL_NAME = os.getenv(\"OLLAMA_MODEL\", \"qwen2.5:7b\")\nOLLAMA_BASE_URL = os.getenv(\"OLLAMA_BASE_URL\", \"http:\/\/localhost:11434\")\n\nPLANNER_SYSTEM_PROMPT = \"\"\"You are an expert curriculum designer. Your job is to\ncreate a structured study roadmap when given a learning goal.\n\nReturn ONLY valid JSON with no prose, no markdown code fences, no explanation.\nThe JSON must match this exact schema:\n\n{\n  \"goal\": \"the original learning goal exactly as given\",\n  \"total_weeks\": <integer between=\"\" and=\"\">,\n  \"weekly_hours\": <integer between=\"\" and=\"\">,\n  \"topics\": [\n    {\n      \"title\": \"Short topic name (3-6 words)\",\n      \"description\": \"One clear sentence explaining what this topic covers\",\n      \"estimated_minutes\": <integer between=\"\" and=\"\">,\n      \"prerequisites\": [\"title of earlier topic if required, else empty list\"],\n      \"status\": \"pending\"\n    }\n  ]\n}\n\nRules:\n- Order topics from foundational to advanced\n- prerequisites must reference earlier topic titles exactly as written\n- Aim for 4 to 6 topics\n- status must always be \"pending\"\n\"\"\"\n<\/integer><\/integer><\/integer><\/code><\/pre>\n<p>\u06cc\u06c1\u0627\u06ba \u0645\u0627\u0688\u0644 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0646\u06d2 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u062f\u0648 \u0686\u06cc\u0632\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 \u0633\u0628 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 <code>temperature=0.1<\/code>. \u06cc\u06c1 \u0628\u06c1\u062a \u06a9\u0645 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0633\u0627\u062e\u062a\u06cc JSON \u0622\u0624\u0679 \u067e\u0679 \u06a9\u0648 \u0645\u0633\u062a\u0642\u0644 \u0645\u0632\u0627\u062c\u06cc \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u0632\u06cc\u0627\u062f\u06c1 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u0627\u06cc\u0633\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u0645\u062a\u0639\u0627\u0631\u0641 \u06a9\u0631\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 JSON \u06a9\u06cc \u062a\u062c\u0632\u06cc\u06c1 \u06a9\u0648 \u0646\u0627\u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0628\u0627\u0631 \u0628\u0646\u0627 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u062f\u0648\u0633\u0631\u0627 <code>format=\"json\"<\/code>. \u06cc\u06c1 \u0627\u0648\u0644\u0627\u0645\u0627 \u06a9\u0627 JSON \u0645\u0648\u0688 \u06c1\u06d2\u060c \u062c\u0648 \u0627\u06cc\u06a9 \u0642\u06cc\u0627\u0633 \u06a9\u06cc \u0633\u0637\u062d \u06a9\u06cc \u0631\u06a9\u0627\u0648\u0679 \u06c1\u06d2\u06d4 \u0627\u0633 \u0633\u06d2 \u0642\u0637\u0639 \u0646\u0638\u0631 \u06a9\u06c1 \u067e\u0631\u0627\u0645\u067e\u0679 \u06a9\u06cc\u0627 \u067e\u0648\u0686\u06be\u062a\u0627 \u06c1\u06d2\u060c \u0622\u067e \u06a9\u0627 \u0645\u0627\u0688\u0644 \u0627\u06cc\u0633\u0627 \u0622\u0624\u0679 \u067e\u0679 \u0646\u06c1\u06cc\u06ba \u0628\u0646\u0627 \u0633\u06a9\u062a\u0627 \u062c\u0648 \u062f\u0631\u0633\u062a JSON \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0645\u0627\u0688\u0644 \u06a9\u0648 JSON \u06a9\u0648 \u0633\u0633\u0679\u0645 \u067e\u0631\u0627\u0645\u067e\u0679 \u067e\u0631 \u0622\u0624\u0679 \u067e\u0679 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u06a9\u06c1\u0646\u06d2 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0637\u0627\u0642\u062a\u0648\u0631 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\">def build_planner_llm() -> ChatOllama:\n    return ChatOllama(\n        model=MODEL_NAME,\n        base_url=OLLAMA_BASE_URL,\n        temperature=0.1,\n        format=\"json\",\n    )\n<\/code><\/pre>\n<p>\u062a\u062c\u0632\u06cc\u06c1 \u06a9\u0627\u0631 \u06a9\u0648 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u0646\u0648\u0688 \u06a9\u06cc \u0641\u0639\u0627\u0644\u06cc\u062a \u0633\u06d2 \u0627\u0644\u06af \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0622\u067e \u06a9\u0648 LLM \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u0679\u06cc\u0633\u0679 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0645\u0627\u0645 11 \u06cc\u0648\u0646\u0679 \u0679\u06cc\u0633\u0679 <code>tests\/test_curriculum_planner.py<\/code> \u06a9\u0627\u0644 <code>parse_roadmap_json()<\/code> \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a:<\/p>\n<pre><code class=\"language-python\">def parse_roadmap_json(json_string: str) -> StudyRoadmap:\n    \"\"\"Parse the LLM's JSON output into a StudyRoadmap dataclass.\"\"\"\n    try:\n        data = json.loads(json_string)\n    except json.JSONDecodeError as e:\n        raise ValueError(\n            f\"LLM returned invalid JSON.n\"\n            f\"Error: {e}n\"\n            f\"Raw output (first 300 chars): {json_string[:300]}\"\n        )\n\n    required = [\"goal\", \"total_weeks\", \"topics\"]\n    for field in required:\n        if field not in data:\n            raise ValueError(f\"LLM JSON missing required field: '{field}'\")\n\n    if not isinstance(data[\"topics\"], list) or len(data[\"topics\"]) == 0:\n        raise ValueError(\"LLM JSON 'topics' must be a non-empty list\")\n\n    topics = []\n    for i, t in enumerate(data[\"topics\"]):\n        for field in [\"title\", \"description\", \"estimated_minutes\"]:\n            if field not in t:\n                raise ValueError(f\"Topic {i} missing required field: '{field}'\")\n        topics.append(Topic(\n            title=t[\"title\"],\n            description=t[\"description\"],\n            estimated_minutes=int(t[\"estimated_minutes\"]),\n            prerequisites=t.get(\"prerequisites\", []),\n            status=t.get(\"status\", \"pending\"),\n        ))\n\n    return StudyRoadmap(\n        goal=data[\"goal\"],\n        total_weeks=int(data[\"total_weeks\"]),\n        weekly_hours=int(data.get(\"weekly_hours\", 5)),\n        topics=topics,\n    )\n<\/code><\/pre>\n<p>\u0646\u0648\u0688 \u06a9\u06cc \u0641\u0639\u0627\u0644\u06cc\u062a \u062e\u0648\u062f \u0627\u0633 \u0646\u0638\u0627\u0645 \u0645\u06cc\u06ba \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062f\u06c1 \u0627\u06cc\u06a9 \u06c1\u06cc \u067e\u06cc\u0679\u0631\u0646 \u06a9\u06cc \u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\">def curriculum_planner_node(state: dict) -> dict:\n    \"\"\"\n    LangGraph node: Curriculum Planner\n\n    Reads:  state[\"goal\"]\n    Writes: state[\"roadmap\"], state[\"messages\"], state[\"error\"]\n    \"\"\"\n    goal = state.get(\"goal\", \"\").strip()\n    if not goal:\n        return {\"error\": \"No learning goal provided.\"}\n\n    print(f\"n[Curriculum Planner] Building roadmap for: '{goal}'\")\n\n    llm = build_planner_llm()\n    messages = [\n        SystemMessage(content=PLANNER_SYSTEM_PROMPT),\n        HumanMessage(content=f\"Create a study roadmap for: {goal}\"),\n    ]\n\n    print(f\"[Curriculum Planner] Calling {MODEL_NAME}...\")\n    response = llm.invoke(messages)\n\n    try:\n        roadmap = parse_roadmap_json(response.content)\n    except ValueError as e:\n        print(f\"[Curriculum Planner] Parse error: {e}\")\n        return {\n            \"error\": str(e),\n            \"messages\": messages + [response],\n        }\n\n    print(f\"[Curriculum Planner] Created {len(roadmap.topics)} topics\")\n\n    # Return ONLY the keys this node changed\n    return {\n        \"roadmap\": roadmap,\n        \"messages\": messages + [response],\n        \"error\": None,\n    }\n<\/code><\/pre>\n<p>\u0648\u0627\u067e\u0633\u06cc \u06a9\u06cc \u0642\u06cc\u0645\u062a \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4 <code>{\"roadmap\": roadmap, \"messages\": ..., \"error\": None}<\/code>. \u06cc\u06c1 \u0627\u06cc\u06a9 \u0645\u06a9\u0645\u0644 \u0631\u06cc\u0627\u0633\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0627\u0633 \u0646\u0648\u0688 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0686\u06be\u0648\u0646\u06d2 \u0648\u0627\u0644\u06cc \u0635\u0631\u0641 \u062a\u06cc\u0646 \u0686\u0627\u0628\u06cc\u0627\u06ba \u06c1\u06cc\u06ba\u06d4 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0627\u0633\u06d2 \u0645\u0648\u062c\u0648\u062f\u06c1 \u062d\u0627\u0644\u062a \u0645\u06cc\u06ba \u0636\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0628\u0627\u0642\u06cc \u062a\u0645\u0627\u0645 \u0641\u06cc\u0644\u0688\u0632 \u0628\u062f\u0633\u062a\u0648\u0631 \u0628\u0631\u0642\u0631\u0627\u0631 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-23-the-graph-definition\">2.3 \u06af\u0631\u0627\u0641 \u06a9\u06cc \u062a\u0639\u0631\u06cc\u0641<\/h3>\n<p>\u06af\u0631\u0627\u0641 \u06a9\u0646\u06a9\u0634\u0646 \u06c1\u06cc\u06ba\u060c \u0645\u0646\u0637\u0642 \u0646\u06c1\u06cc\u06ba\u06d4 \u062a\u0645\u0627\u0645 \u06a9\u0627\u0631\u0648\u0628\u0627\u0631\u06cc \u0645\u0646\u0637\u0642 \u0627\u06cc\u062c\u0646\u0679 \u0645\u0627\u0688\u06cc\u0648\u0644 \u0645\u06cc\u06ba \u0631\u06c1\u062a\u06cc \u06c1\u06d2\u06d4 <code>src\/graph\/workflow.py<\/code> \u06cc\u06c1 \u0635\u0631\u0641 \u0627\u0633 \u0628\u0627\u062a \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06a9\u0648\u0646 \u0633\u06d2 \u0646\u0648\u0688\u0633 \u0645\u0648\u062c\u0648\u062f \u06c1\u06cc\u06ba\u060c \u0648\u06c1 \u06a9\u06cc\u0633\u06d2 \u062c\u0691\u06d2 \u06c1\u0648\u0626\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0631\u0648\u0679\u0646\u06af \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06cc\u0627 \u0641\u06cc\u0635\u0644\u06d2 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\"># src\/graph\/workflow.py\n\nimport os\nimport sqlite3\nfrom pathlib import Path\n\nfrom langgraph.checkpoint.sqlite import SqliteSaver\nfrom langgraph.graph import END, START, StateGraph\n\nfrom agents.curriculum_planner import curriculum_planner_node\nfrom agents.explainer import explainer_node\nfrom agents.human_approval import human_approval_node\nfrom agents.progress_coach import progress_coach_node\nfrom agents.quiz_generator import quiz_generator_node\nfrom graph.state import AgentState, session_is_complete\n\n\ndef route_after_approval(state: dict) -> str:\n    if state.get(\"approved\", False):\n        return \"explainer\"\n    return \"curriculum_planner\"\n\n\ndef route_after_coach(state: dict) -> str:\n    if session_is_complete(state):\n        return \"end\"\n    return \"explainer\"\n\n\ndef build_graph(\n    db_path: str = \"data\/checkpoints.db\",\n    interrupt_before: list | None = None,\n):\n    Path(\"data\").mkdir(exist_ok=True)\n    if db_path == \"data\/checkpoints.db\":\n        db_path = os.getenv(\"CHECKPOINT_DB\", db_path)\n\n    builder = StateGraph(AgentState)\n\n    # Register all five nodes\n    builder.add_node(\"curriculum_planner\", curriculum_planner_node)\n    builder.add_node(\"human_approval\", human_approval_node)\n    builder.add_node(\"explainer\", explainer_node)\n    builder.add_node(\"quiz_generator\", quiz_generator_node)\n    builder.add_node(\"progress_coach\", progress_coach_node)\n\n    # Static edges\n    builder.add_edge(START, \"curriculum_planner\")\n    builder.add_edge(\"curriculum_planner\", \"human_approval\")\n    builder.add_edge(\"explainer\", \"quiz_generator\")\n    builder.add_edge(\"quiz_generator\", \"progress_coach\")\n\n    # Conditional edges\n    builder.add_conditional_edges(\n        \"human_approval\",\n        route_after_approval,\n        {\"explainer\": \"explainer\", \"curriculum_planner\": \"curriculum_planner\"},\n    )\n    builder.add_conditional_edges(\n        \"progress_coach\",\n        route_after_coach,\n        {\"explainer\": \"explainer\", \"end\": END},\n    )\n\n    # IMPORTANT: create the connection directly, not via context manager.\n    # SqliteSaver.from_conn_string() returns a context manager. If you use\n    # `with SqliteSaver.from_conn_string(...) as checkpointer:`, the connection\n    # closes when the `with` block exits. The graph object lives longer than\n    # build_graph(), so the connection must stay open for the process lifetime.\n    conn = sqlite3.connect(db_path, check_same_thread=False)\n    checkpointer = SqliteSaver(conn)\n\n    return builder.compile(\n        checkpointer=checkpointer,\n        interrupt_before=interrupt_before or [],\n    )\n\n\ngraph = build_graph()\n<\/code><\/pre>\n<h4 id=\"heading-the-sqlitesaver-connection-pattern\"> SqliteSaver \u06a9\u0646\u06a9\u0634\u0646 \u067e\u06cc\u0679\u0631\u0646<\/h4>\n<p>\u06a9\u06c1 <code>check_same_thread=False<\/code> \u0627\u06cc\u06a9 \u062c\u06be\u0646\u0688\u0627 \u062f\u0631\u06a9\u0627\u0631 \u06c1\u06d2\u06d4 SQLite \u06a9\u0627 \u0688\u06cc\u0641\u0627\u0644\u0679 \u0631\u0648\u06cc\u06c1 \u0627\u06cc\u06a9 \u062a\u06be\u0631\u06cc\u0688 \u0645\u06cc\u06ba \u0628\u0646\u0627\u0626\u06d2 \u06af\u0626\u06d2 \u06a9\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u062f\u0648\u0633\u0631\u06d2 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0633\u06d2 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0646\u0648\u0688 \u06a9\u06d2 \u0627\u0641\u0639\u0627\u0644 \u06a9\u0648 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u0637\u0648\u0631 \u067e\u0631 \u062f\u0648\u0633\u0631\u06d2 \u062f\u06be\u0627\u06af\u0648\u06ba \u067e\u0631 \u0686\u0648\u06a9\u06cc\u0627\u06ba \u0644\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u062c\u06be\u0646\u0688\u06d2 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 <code>ProgrammingError: SQLite objects created in a thread can only be used in that same thread<\/code> \u0631\u0646 \u0679\u0627\u0626\u0645 \u067e\u0631\u06d4 \u0686\u0648\u0646\u06a9\u06c1 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u0631\u0627\u0626\u0679 \u06a9\u0648 \u0633\u06cc\u0631\u06cc\u0644\u0627\u0626\u0632 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u06a9\u0648\u0626\u06cc \u06c1\u0645 \u0622\u06c1\u0646\u06af \u062a\u062d\u0631\u06cc\u0631\u06cc \u062a\u0646\u0627\u0632\u0639\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u062c\u06be\u0646\u0688\u0627 \u06cc\u06c1\u0627\u06ba \u0645\u062d\u0641\u0648\u0638 \u06c1\u06d2\u06d4<\/p>\n<p>\u0631\u0648\u0679\u0646\u06af \u0641\u0646\u06a9\u0634\u0646 \u062e\u0627\u0644\u0635 \u0627\u0632\u06af\u0631 \u06c1\u06d2\u06d4 \u06a9\u0648\u0626\u06cc LLM \u06a9\u0627\u0644\u0632 \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 \u0631\u06cc\u0627\u0633\u062a \u0633\u06d2 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u062a\u0627\u0631 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0648\u06c1 \u062a\u0627\u0631 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0627 \u062a\u0639\u06cc\u0646 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06a9\u0648\u0646 \u0633\u0627 \u0646\u0648\u0688 \u0622\u06af\u06d2 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u0646\u0679\u0631\u0648\u0644 \u0641\u0644\u0648 \u0645\u0646\u0637\u0642 \u06a9\u0648 \u067e\u0627\u0626\u062a\u06be\u0648\u0646 \u0645\u06cc\u06ba \u0631\u06a9\u06be\u06cc\u06ba\u060c \u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u0645\u06cc\u06ba \u0646\u06c1\u06cc\u06ba\u06d4 \u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u0631\u0648\u0679\u0646\u06af \u06a9\u06d2 \u0641\u06cc\u0635\u0644\u06d2 \u06af\u0631\u0627\u0641 \u06a9\u06d2 \u06a9\u0646\u0679\u0631\u0648\u0644 \u0641\u0644\u0648 \u0645\u06cc\u06ba \u0639\u062f\u0645 \u0627\u0633\u062a\u062d\u06a9\u0627\u0645 \u06a9\u0648 \u0645\u062a\u0639\u0627\u0631\u0641 \u06a9\u0631\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062c\u0633 \u0633\u06d2 \u0627\u0646 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0627\u0633\u062a\u062f\u0644\u0627\u0644 \u06a9\u0631\u0646\u0627 \u0627\u0648\u0631 \u062c\u0627\u0646\u0686\u0646\u0627 \u0628\u06c1\u062a \u0645\u0634\u06a9\u0644 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u06c1 <code>interrupt_before<\/code> \u067e\u06cc\u0631\u0627\u0645\u06cc\u0679\u0631 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u06cc\u0641\u0627\u0644\u0679 \u0648\u06cc\u0644\u06cc\u0648 \u0627\u06cc\u06a9 \u062e\u0627\u0644\u06cc \u0641\u06c1\u0631\u0633\u062a \u06c1\u06d2\u06d4 \u0679\u0631\u0645\u06cc\u0646\u0644 \u0627\u0646\u0679\u0631\u0641\u06cc\u0633 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>interrupt()<\/code> <em>\u0627\u0646\u062f\u0631<\/em> <code>human_approval_node<\/code> \u062c\u06cc\u0633\u0627 \u06a9\u06c1 \u0622\u067e \u0628\u0627\u0628 5 \u0645\u06cc\u06ba \u062f\u06cc\u06a9\u06be\u06cc\u06ba \u06af\u06d2\u060c \u06c1\u0645 \u0631\u0648\u0688 \u0645\u06cc\u067e \u06a9\u06cc \u0645\u0646\u0638\u0648\u0631\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u0648\u0642\u0641 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0645\u0631\u062a\u0628 \u0648\u0642\u062a \u0645\u06cc\u06ba \u06a9\u0633\u06cc \u0631\u06a9\u0627\u0648\u0679 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p>Streamlit UI \u067e\u0627\u0633 \u06a9\u0631\u06cc\u06ba (\u0628\u0627\u0628 9) <code>interrupt_before=[\"quiz_generator\"]<\/code> \u06a9\u0648\u0626\u0632 \u0646\u0648\u0688 \u06a9\u06d2 \u0686\u0644\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06af\u0631\u0627\u0641 \u06a9\u0648 \u0631\u0648\u06a9\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2: <code>input()<\/code> \u0627\u0633\u06d2 \u06af\u0631\u0627\u0641 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0646\u06c1\u06cc\u06ba \u06a9\u06c1\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u06c1\u06cc \u06af\u0631\u0627\u0641 \u0628\u0644\u0688\u0631 \u062f\u0648\u0646\u0648\u06ba \u0637\u0631\u06cc\u0642\u0648\u06ba \u06a9\u0648 \u0633\u067e\u0648\u0631\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0645\u06a9\u0645\u0644 \u06af\u0631\u0627\u0641 \u062f\u0631\u062c \u0630\u06cc\u0644 \u06c1\u06d2:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/umang.pk\/wp-content\/uploads\/2026\/04\/1777579829_0_LangGraph\u060c-MCP\u060c-\u0627\u0648\u0631-A2A-\u06a9\u0627-\u0627\u0633\u062a\u0639\u0645\u0627\u0644-\u06a9\u0631\u062a\u06d2-\u06c1\u0648\u0626\u06d2-\u0645\u0644\u0679\u06cc-\u0627\u06cc\u062c\u0646\u0679.png\" alt=\"\u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0648\u0631\u06a9 \u0641\u0644\u0648 \u06a9\u0627 \u0641\u0644\u0648 \u0686\u0627\u0631\u0679 \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u06a9\u0627 \u0622\u0631\u0688\u0631 \u062f\u06a9\u06be\u0627 \u0631\u06c1\u0627 \u06c1\u06d2: START curriculum_planner \u0645\u06cc\u06ba \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u067e\u06be\u0631 \u0627\u06cc\u06a9 \u0631\u06a9\u0627\u0648\u0679 \u06a9\u06d2 \u0633\u0627\u062a\u06be human_approval \u062c\u0648 \u0635\u0627\u0631\u0641 \u06a9\u06d2 \u0627\u0646 \u067e\u0679 \u06a9\u0648 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u060c Route_after_approval \u0627\u06cc\u06a9 \u0641\u06cc\u0635\u0644\u06d2 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0688\u0627\u0626\u0645\u0646\u0688 \u0628\u0631\u0627\u0646\u0686\u0646\u06af \u0622\u0641 \u0688\u0627\u0679\u0688 \u0645\u0634\u0631\u0648\u0637 \u06a9\u0646\u0627\u0631\u06d2 \u067e\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 (approved=true \u062c\u0627\u0631\u06cc \u0631\u06c1\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 Approved = loops \u0645\u06cc\u06ba looped in the backprovf \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2 reject \u0644\u0648\u067e \u0645\u06cc\u06ba curriculum_planner)\u06d4 \u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u06a9\u0648\u0626\u0632_\u062c\u0646\u0631\u06cc\u0679\u0631 \u0645\u06cc\u06ba \u0628\u06c1\u062a\u0627 \u06c1\u06d2\u060c \u067e\u06be\u0631: \u067e\u0631\u0648\u06af\u0631\u06cc\u0633_\u06a9\u0648\u0686 \u0645\u06cc\u06ba \u0628\u06c1\u062a\u0627 \u06c1\u06d2\u060c \u0627\u06cc\u06a9 \u0631\u0648\u0679_\u0628\u0639\u062f_\u06a9\u0648\u0686 \u06a9\u0627 \u0641\u06cc\u0635\u0644\u06c1 \u0688\u0627\u0626\u0645\u0646\u0688 \u06a9\u06cc \u0634\u0627\u062e \u0628\u0646\u062f\u06cc \u0648\u0627\u0644\u06d2 \u0645\u0634\u0631\u0648\u0637 \u06a9\u0646\u0627\u0631\u06d2 \u0633\u06d2 \u0628\u0627\u06c1\u0631 \u0646\u06a9\u0644\u062a\u0627 \u06c1\u06d2\u06d4 (\u0645\u0637\u0627\u0644\u0639\u06c1 \u06a9\u06d2 \u0644\u0648\u067e \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631\u060c \u0645\u0632\u06cc\u062f \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u06a9\u06cc \u0637\u0631\u0641 \u0644\u0648\u0679 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u062a\u0645\u0627\u0645 \u062a\u06a9\u0645\u06cc\u0644\u06cc\u06ba END \u06a9\u06cc \u0637\u0631\u0641 \u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4) \u0679\u06be\u0648\u0633 \u062a\u06cc\u0631 \u062c\u0627\u0645\u062f \u06a9\u0646\u0627\u0631\u0648\u06ba \u06a9\u06cc \u0646\u0634\u0627\u0646\u062f\u06c1\u06cc \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0688\u06cc\u0634\u0688 \u062a\u06cc\u0631 \u0645\u0634\u0631\u0648\u0637 \u06a9\u0646\u0627\u0631\u0648\u06ba \u06a9\u06cc \u0646\u0634\u0627\u0646\u062f\u06c1\u06cc \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4\" style=\"display:block;margin:0 auto\" width=\"600\" height=\"400\" loading=\"lazy\" title=\"\"><\/p>\n<p><em>\u062a\u0635\u0648\u06cc\u0631 2. \u0645\u06a9\u0645\u0644 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u06af\u0631\u0627\u0641\u06d4 \u062c\u0627\u0645\u062f \u06a9\u0646\u0627\u0631\u06d2 \u0633\u062e\u062a \u06c1\u06cc\u06ba\u06d4 \u0645\u0634\u0631\u0648\u0637 \u06a9\u0646\u0627\u0631\u0648\u06ba \u06a9\u0648 \u0688\u06cc\u0634\u0688 \u0644\u0627\u0626\u0646\u0648\u06ba \u0633\u06d2 \u0638\u0627\u06c1\u0631 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0631\u0648\u0679\u0646\u06af \u0641\u0646\u06a9\u0634\u0646 \u0631\u0646 \u0679\u0627\u0626\u0645 \u067e\u0631 \u0639\u0645\u0644 \u0645\u06cc\u06ba \u0644\u0627\u0626\u06d2 \u062c\u0627\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0631\u0627\u0633\u062a\u06d2 \u06a9\u0627 \u062a\u0639\u06cc\u0646 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/em><\/p>\n<h3 id=\"heading-24-run-it-and-verify\">2.4 \u0686\u0644\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0627\u06cc\u06a9 \u0628\u0627\u0631 \u062c\u0628 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u0627\u067e\u0646\u06d2 \u0646\u0635\u0627\u0628 \u06a9\u06d2 \u0645\u0646\u0635\u0648\u0628\u06c1 \u0633\u0627\u0632 \u0646\u0648\u0688\u0633 \u0627\u0648\u0631 \u06af\u0631\u0627\u0641\u0633 \u0645\u0648\u062c\u0648\u062f \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u0627\u067e\u0646\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u062e\u062a\u062a\u0627\u0645 \u0633\u06d2 \u0622\u062e\u0631 \u062a\u06a9 \u0679\u06cc\u0633\u0679 \u0686\u0644\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">python main.py \"Learn Python closures and decorators from scratch\"\n<\/code><\/pre>\n<p>\u0622\u067e \u06a9\u0648 \u062f\u0631\u062c \u0630\u06cc\u0644 \u06a9\u0648 \u0686\u06cc\u06a9 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2:<\/p>\n<pre><code class=\"language-plaintext\">============================================================\nLearning Accelerator\nSession ID: a3f1b2c4\nGoal: Learn Python closures and decorators from scratch\n============================================================\n\n[Curriculum Planner] Building roadmap for: 'Learn Python closures...'\n[Curriculum Planner] Calling qwen2.5:7b...\n[Curriculum Planner] Created 5 topics\n\nProposed Study Plan\n============================================================\nGoal: Learn Python closures and decorators from scratch\nDuration: 2 weeks @ 5 hrs\/week\n\n  1. Python Functions Review (45 min)\n     Review function definition, arguments, return values, and scope basics\n  2. Scope and the LEGB Rule (60 min)\n     Understand how Python resolves variable names across nested scopes\n  3. Closures Explained (75 min) (needs: Scope and the LEGB Rule)\n     ...\n<\/code><\/pre>\n<p>\u06af\u0631\u0627\u0641 \u06cc\u06c1\u06cc\u06ba \u0631\u06a9 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u06c1 <code>interrupt()<\/code> \u0627\u0646\u062f\u0631 \u0628\u0644\u0627\u0624 <code>human_approval_node<\/code> \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u0686\u0648\u06a9\u06cc \u06a9\u0648 \u0628\u0686\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u06a9\u0627\u0644\u0631 \u06a9\u0648 \u06a9\u0646\u0679\u0631\u0648\u0644 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0622\u067e \u06a9\u0627 \u0622\u0644\u06c1 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4 \u0632\u0645\u0631\u06c1 <code>yes<\/code> \u062c\u0627\u0631\u06cc \u0631\u06a9\u06be\u06cc\u06ba \u06cc\u0627 <code>no<\/code> \u06a9\u06be\u06cc\u0644\u06cc\u06ba<\/p>\n<p> <strong>\u0686\u0648\u06a9\u06cc:<\/strong> \u0645\u06cc\u0631\u06d2 \u067e\u0627\u0633 \u0631\u06cc\u0627\u0633\u062a\u06cc \u0627\u0633\u062a\u0642\u0627\u0645\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u0679\u0627\u0633\u06a9 \u06af\u0631\u0627\u0641 \u06c1\u06d2\u06d4 \u0633\u0628 \u0633\u06d2 \u0627\u0648\u067e\u0631 \u067e\u0631\u0646\u0679 \u06a9\u0631\u062f\u06c1 \u0633\u06cc\u0634\u0646 ID \u062f\u0631\u062c \u0630\u06cc\u0644 \u062c\u06af\u06c1 \u067e\u0631 \u0645\u062d\u0641\u0648\u0638 \u06c1\u06d2: <code>data\/checkpoints.db<\/code>. \u0627\u06af\u0631 \u0645\u06cc\u06ba \u0627\u0628\u06be\u06cc \u0627\u0633 \u0639\u0645\u0644 \u06a9\u0648 \u0645\u0627\u0631 \u06a9\u0631 \u0686\u0644\u0627 \u062f\u0648\u06ba <code>python main.py --resume a3f1b2c4<\/code>\u0627\u0633\u06d2 \u0645\u0646\u0638\u0648\u0631\u06cc \u06a9\u06d2 \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0645\u0646\u062a\u062e\u0628 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u06a9\u0627\u0645 \u06a9\u0631 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0628 \u067e\u0627\u0631\u0633\u0646\u06af \u0645\u0646\u0637\u0642 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06cc\u0648\u0646\u0679 \u0679\u06cc\u0633\u0679 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">pytest tests\/test_state.py tests\/test_curriculum_planner.py -v\n<\/code><\/pre>\n<p>\u062a\u0648\u0642\u0639: 35 \u0679\u06cc\u0633\u0679\u060c \u0633\u0628 \u067e\u0627\u0633\u060c \u0627\u0648\u0644\u0627\u0645\u06c1 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0679\u06cc\u0633\u0679 \u0648\u0631\u0632\u0634 \u06c1\u06d2\u06d4 <code>parse_roadmap_json()<\/code>\u0627\u0633\u0679\u06cc\u0679 \u0688\u06cc\u0679\u0627 \u06a9\u0644\u0627\u0633\u0632 \u0627\u0648\u0631 \u06cc\u0648\u0679\u06cc\u0644\u06cc\u0679\u06cc \u0641\u0646\u06a9\u0634\u0646\u0632: \u0627\u0635\u0644 LLM \u06a9\u0627\u0644\u0632 \u06a9\u06d2 \u0639\u0644\u0627\u0648\u06c1 \u0633\u0628 \u06a9\u0686\u06be\u06d4<\/p>\n<p>\u06cc\u06c1\u0627\u06ba \u06a9\u0627\u0631\u067e\u0648\u0631\u06cc\u0679 \u067e\u06cc\u0679\u0631\u0646: \u0633\u06cc\u0644\u0632 \u0642\u0627\u0628\u0644 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u0627 \u0646\u0638\u0627\u0645 \u0627\u0633\u06cc \u06af\u0631\u0627\u0641 \u0688\u06be\u0627\u0646\u0686\u06d2 \u06a9\u06cc \u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0646\u0635\u0627\u0628 \u06a9\u06d2 \u0645\u0646\u0635\u0648\u0628\u06c1 \u0633\u0627\u0632 \u0646\u0626\u06d2 \u0633\u06cc\u0644\u0632 \u0646\u0645\u0627\u0626\u0646\u062f\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0622\u0646 \u0628\u0648\u0631\u0688\u0646\u06af \u06a9\u0627 \u0631\u0627\u0633\u062a\u06c1 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0645\u06cc\u0646\u06cc\u062c\u0631\u0632 \u0679\u0631\u06cc\u0646\u0646\u06af \u0634\u0631\u0648\u0639 \u06c1\u0648\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u0633 \u06a9\u06cc \u0645\u0646\u0638\u0648\u0631\u06cc \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0633\u06cc\u06a9\u06be\u0646\u06d2 \u06a9\u0627 \u0637\u0631\u06cc\u0642\u06c1 \u067e\u0631\u0648\u0688\u06a9\u0679 \u06a9\u06d2 \u0639\u0644\u0645\u06cc \u0645\u0648\u0636\u0648\u0639\u0627\u062a \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0631 \u0645\u0648\u0636\u0648\u0639 \u06a9\u06d2 \u0628\u0639\u062f \u06af\u0631\u0627\u0641 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0628 \u0646\u0645\u0627\u0626\u0646\u062f\u06c1 \u062f\u0648\u067e\u06c1\u0631 \u06a9\u06d2 \u06a9\u06be\u0627\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f \u0648\u0627\u067e\u0633 \u0622\u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0646\u0638\u0627\u0645 \u0628\u0627\u0644\u06a9\u0644 \u0648\u06c1\u06cc\u06ba \u0633\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0627\u0633 \u0646\u06d2 \u0686\u06be\u0648\u0691\u0627 \u062a\u06be\u0627\u06d4<\/p>\n<p>\u0627\u06af\u0644\u06d2 \u0628\u0627\u0628 \u0645\u06cc\u06ba\u060c \u06c1\u0645 \u0627\u06cc\u06a9 \u0645\u0627\u0688\u0644 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u06a9\u0627 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0627\u06a9\u06c1 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0645\u0639\u06cc\u0627\u0631\u06cc \u0679\u0648\u0644 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u062d\u0627\u0635\u0644 \u06c1\u0648\u060c \u0627\u0648\u0631 \u067e\u06be\u0631 \u067e\u06c1\u0644\u0627 \u0627\u06cc\u062c\u0646\u0679\u060c \u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u0628\u0646\u0627\u0626\u06cc\u06ba\u060c \u062c\u0648 \u0679\u0648\u0644 \u06a9\u0648 \u0644\u0648\u067e \u0645\u06cc\u06ba \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633 \u0648\u0642\u062a \u062a\u06a9 \u0627\u0639\u0627\u062f\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0628 \u062a\u06a9 \u06a9\u06c1 \u0632\u0645\u06cc\u0646\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0627\u0641\u06cc \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u0645\u0648\u062c\u0648\u062f \u0646\u06c1 \u06c1\u0648\u06d4<\/p>\n<p>\u0648\u0636\u0627\u062d\u062a\u06cc \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0686\u06cc\u0632 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u062a\u062d\u0642\u06cc\u0642\u06cc \u0646\u0648\u0679 \u067e\u0691\u06be \u0644\u06cc\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 \u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u06a9\u0648\u0686 \u06a9\u0648 \u0633\u06cc\u0634\u0646 \u0688\u06cc\u0679\u0627 \u06a9\u0648 \u0630\u062e\u06cc\u0631\u06c1 \u0627\u0648\u0631 \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 \u0627\u06af\u0631\u0686\u06c1 \u062f\u0648\u0646\u0648\u06ba \u067e\u0627\u0626\u062a\u06be\u0648\u0646 \u0641\u0646\u06a9\u0634\u0646\u0632 \u06a9\u0648 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u06a9\u0627\u0644 \u06a9\u0631\u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u06c1\u0645 \u0646\u06d2 \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0641\u0627\u0626\u0644 \u0633\u0633\u0679\u0645 \u0644\u06d2 \u0622\u0624\u0679\u060c \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u0627\u0633\u06a9\u06cc\u0645\u0627 \u0633\u06d2 \u062c\u0648\u0691 \u062f\u06cc\u0627 \u0627\u0648\u0631 \u0645\u062a\u0639\u0644\u0642\u06c1 \u0641\u0646\u06a9\u0634\u0646\u0632 \u06a9\u0648 \u0644\u0627\u06af\u0648 \u06a9\u06cc\u0627\u06d4<\/p>\n<p>\u0645\u0627\u0688\u0644 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u0627\u0646\u06c1\u06cc\u06ba \u0635\u0627\u0641 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0644\u06af \u06a9\u0631\u06a9\u06d2 \u062d\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <em>\u06a9\u06cc\u0627<\/em> \u0622\u067e \u06a9\u0648 \u0635\u0631\u0641 \u0679\u0648\u0644\u0632 \u0633\u0631\u0648\u0631 \u06a9\u0648 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 <em>\u06a9\u0633 \u0637\u0631\u062d<\/em> \u06cc\u06c1 \u062e\u062a\u0645 \u06c1\u0648 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u0628\u06cc\u06a9 \u0627\u06cc\u0646\u0688 \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648\u0688 \u062a\u0628\u062f\u06cc\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0622\u067e \u0627\u06cc\u06a9 \u06c1\u06cc \u0679\u0648\u0644 \u0633\u0631\u0648\u0631 \u06a9\u0648 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u062a\u0639\u06cc\u0646\u0627\u062a \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u06a9\u0633\u06cc \u0628\u06be\u06cc MCP \u0633\u06d2 \u06c1\u0645 \u0622\u06c1\u0646\u06af \u0627\u06cc\u062c\u0646\u0679 (LangGraph\u060c CrewAI\u060c Claude Desktop\u060c \u0648\u063a\u06cc\u0631\u06c1) \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-31-mcps-three-primitives\">3.1 MCP \u06a9\u06d2 \u062a\u06cc\u0646 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0639\u0646\u0627\u0635\u0631<\/h3>\n<p>MCP \u06a9\u06cc \u062a\u06cc\u0646 \u0642\u0633\u0645 \u06a9\u06cc \u0641\u0639\u0627\u0644\u06cc\u062a \u06c1\u06d2 \u062c\u0633\u06d2 \u0633\u0631\u0648\u0631 \u0628\u06d2 \u0646\u0642\u0627\u0628 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2:<\/p>\n<ol>\n<li>\n<p><strong>\u0633\u0627\u0645\u0627\u0646<\/strong> \u0627\u06cc\u06a9 \u0642\u0627\u0628\u0644 \u0639\u0645\u0644 \u0641\u0646\u06a9\u0634\u0646 \u062c\u0633\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u062f\u0644\u0627\u0626\u0644 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>read_study_file(filename)<\/code> \u06cc\u06c1 \u0627\u06cc\u06a9 \u0679\u0648\u0644 \u06c1\u06d2\u06d4 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0646\u0679\u0631\u0648\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0627\u0633\u06d2 \u06a9\u0628 \u0628\u0644\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u06cc\u06c1 \u06a9\u0648\u0646 \u0633\u06d2 \u062f\u0644\u0627\u0626\u0644 \u0644\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u0633\u0631\u0648\u0631 \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u06a9\u0648 \u0633\u0646\u0628\u06be\u0627\u0644\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0648\u0633\u0627\u0626\u0644<\/strong> \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u067e\u0691\u06be\u0627 \u062c\u0627\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0633\u0627\u062e\u062a\u06cc \u0688\u06cc\u0679\u0627\u060c \u062c\u0633 \u06a9\u06cc \u0634\u0646\u0627\u062e\u062a URI \u0633\u06d2 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 <code>notes:\/\/index<\/code> \u06cc\u06c1 \u0627\u06cc\u06a9 \u0648\u0633\u06cc\u0644\u06c1 \u06c1\u06d2\u06d4 \u0627\u0633\u06d2 \u0635\u0631\u0641 \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 HTTP GET \u0627\u06cc\u0646\u0688 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0633\u0648\u0686\u06cc\u06ba\u06d4 \u0633\u0631\u0648\u0631 \u06a9\u0646\u0679\u0631\u0648\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06a9\u0648\u0646 \u0633\u0627 \u0688\u06cc\u0679\u0627 \u062f\u0633\u062a\u06cc\u0627\u0628 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u06cc\u062c\u0646\u0679 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u067e\u0631 \u0627\u0633 \u0688\u06cc\u0679\u0627 \u06a9\u0648 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0641\u0648\u0631\u06cc<\/strong> \u0627\u06cc\u06a9 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0642\u0627\u0628\u0644 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u067e\u0631\u0627\u0645\u067e\u0679 \u0679\u06cc\u0645\u067e\u0644\u06cc\u0679 \u062c\u0648 \u0633\u0631\u0648\u0631 \u06a9\u06d2 \u067e\u0627\u0633 \u06c1\u06d2 \u0627\u0648\u0631 \u062c\u0633 \u06a9\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0646\u0627\u0645 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0633\u0633\u0679\u0645 \u067e\u0631\u0627\u0645\u067e\u0679\u0633 \u06a9\u0627 \u0632\u06cc\u0627\u062f\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627\u060c \u0644\u06cc\u06a9\u0646 \u0627\u0633 \u0635\u0648\u0631\u062a \u0645\u06cc\u06ba \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2 \u062c\u0628 \u0679\u0648\u0644\u0632 \u0633\u0631\u0648\u0631 \u0627\u067e\u0646\u06d2 \u0688\u0648\u0645\u06cc\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0631\u0627\u0645\u067e\u0679 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u0627 \u0645\u0627\u0644\u06a9 \u0628\u0646\u0646\u0627 \u0686\u0627\u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ol>\n<p>\u0627\u06c1\u0645 \u0641\u0631\u0642 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0679\u0648\u0644\u0632 \u06a9\u0627\u0645\u0648\u06ba \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0648\u0633\u0627\u0626\u0644 \u0688\u06cc\u0679\u0627 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 \u062c\u0628 \u0622\u067e \u06a9\u0648 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06d4 <em>\u06a9\u0631\u0648<\/em> \u06a9\u0686\u06be\u060c \u06cc\u06c1 \u0627\u06cc\u06a9 \u0622\u0644\u06c1 \u06c1\u06d2. \u062c\u0628 \u0622\u067e \u06a9\u0648 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06d4 <em>\u067e\u0691\u06be\u06cc\u06ba<\/em> \u06a9\u0686\u06be \u0628\u06be\u06cc \u0633\u0627\u062e\u062a\u06c1 \u06c1\u06d2\u060c \u06cc\u06c1 \u0627\u06cc\u06a9 \u0648\u0633\u06cc\u0644\u06c1 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-mcp-as-a-stable-contract\"> MCP \u0627\u06cc\u06a9 \u0645\u0633\u062a\u062d\u06a9\u0645 \u0645\u0639\u0627\u06c1\u062f\u06c1 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631<\/h4>\n<p>\u0627\u06cc\u0645 \u0633\u06cc \u067e\u06cc \u06a9\u0648 \u0627\u06cc\u062c\u0646\u0679 \u0627\u0648\u0631 \u0679\u0648\u0644 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0627\u06cc\u06a9 \u0645\u0633\u062a\u062d\u06a9\u0645 \u0645\u0639\u0627\u06c1\u062f\u06c1 \u0633\u0645\u062c\u06be\u06cc\u06ba\u06d4 \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0627\u06cc\u062c\u0646\u0679 \u062c\u0627\u0646\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0679\u0648\u0644 \u0628\u0644\u0627\u06cc\u0627 \u062c\u0627 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4 <code>read_study_file<\/code> \u0627\u0648\u0631 <code>filename<\/code> \u062a\u0646\u0627\u0632\u0639\u06c1 \u0627\u06cc\u062c\u0646\u0679 \u06cc\u06c1 \u0646\u06c1\u06cc\u06ba \u062f\u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u06cc\u0627 \u0646\u0641\u0627\u0630 \u0688\u0633\u06a9 \u0633\u06d2 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2\u060c S3 \u0628\u0627\u0644\u0679\u06cc \u0633\u06d2 \u06a9\u06be\u06cc\u0646\u0686\u062a\u0627 \u06c1\u06d2\u060c \u06cc\u0627 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0633\u06d2 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u0642\u062f\u0631 \u06c1\u06d2\u06d4 \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648\u0688 \u06a9\u0648 \u0686\u06be\u0648\u0626\u06d2 \u0628\u063a\u06cc\u0631 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-32-build-the-filesystem-mcp-server\">3.2 \u0641\u0627\u0626\u0644 \u0633\u0633\u0679\u0645 MCP \u0633\u0631\u0648\u0631 \u0628\u0646\u0627\u0646\u0627<\/h3>\n<p>\u0627\u06cc\u06a9 \u0641\u0627\u0626\u0644 \u0633\u0633\u0679\u0645 \u0633\u0631\u0648\u0631 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0645\u0637\u0627\u0644\u0639\u06c1 \u06a9\u06d2 \u0646\u0648\u0679\u0633 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u062a\u06cc\u0646 \u0679\u0648\u0644\u0632 \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0648\u0633\u0627\u0626\u0644 \u06a9\u0648 \u0628\u06d2 \u0646\u0642\u0627\u0628 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\"># src\/mcp_servers\/filesystem_server.py\n\nimport os\nfrom pathlib import Path\nfrom mcp.server.fastmcp import FastMCP\n\nmcp = FastMCP(\"Filesystem Server\")\n\n# Path configured via environment variable\nNOTES_BASE = Path(os.getenv(\"NOTES_PATH\", \"study_materials\/sample_notes\"))\n\n\n@mcp.tool()\ndef list_study_files() -> list[str]:\n    \"\"\"\n    List all available study note files.\n\n    Returns a list of filenames relative to the notes directory.\n    Example: ['closures.md', 'decorators.md', 'python_basics.md']\n\n    Always call this first to discover what materials are available\n    before attempting to read specific files.\n    \"\"\"\n    if not NOTES_BASE.exists():\n        return []\n    return sorted([\n        str(f.relative_to(NOTES_BASE))\n        for f in NOTES_BASE.rglob(\"*.md\")\n    ])\n\n\n@mcp.tool()\ndef read_study_file(filename: str) -> str:\n    \"\"\"\n    Read the full content of a study note file.\n\n    Args:\n        filename: The filename to read, exactly as returned by\n                  list_study_files(). Example: 'closures.md'\n\n    Returns the full text content, or an error string if not found.\n    Never raises. Errors are returned as strings so the agent\n    can handle them gracefully.\n    \"\"\"\n    file_path = NOTES_BASE \/ filename\n\n    # Security: path traversal prevention.\n    # Without this, an agent could call read_study_file(\"..\/..\/.env\")\n    # and expose your API keys. We resolve both paths and verify\n    # the requested file is inside the notes directory.\n    try:\n        resolved = file_path.resolve()\n        resolved.relative_to(NOTES_BASE.resolve())\n    except ValueError:\n        return (\n            f\"Error: path traversal attempt blocked for '{filename}'. \"\n            f\"Only files within the notes directory are accessible.\"\n        )\n\n    if not file_path.exists():\n        available = list_study_files()\n        return f\"Error: '{filename}' not found. Available: {available}\"\n\n    if file_path.suffix != \".md\":\n        return f\"Error: only .md files are accessible, got '{file_path.suffix}'\"\n\n    try:\n        return file_path.read_text(encoding=\"utf-8\")\n    except (PermissionError, OSError) as e:\n        return f\"Error reading '{filename}': {e}\"\n\n\n@mcp.tool()\ndef search_notes(query: str) -> list[dict]:\n    \"\"\"\n    Search across all study notes for a keyword or phrase.\n\n    Args:\n        query: The search term. Case-insensitive substring match.\n\n    Returns a list of matches, each with keys: 'file', 'line_number', 'line'.\n    Maximum 20 results to avoid overwhelming the context window.\n    \"\"\"\n    if not NOTES_BASE.exists():\n        return []\n\n    results = []\n    query_lower = query.lower()\n\n    for file_path in sorted(NOTES_BASE.rglob(\"*.md\")):\n        rel_path = str(file_path.relative_to(NOTES_BASE))\n        try:\n            lines = file_path.read_text(encoding=\"utf-8\").splitlines()\n        except (UnicodeDecodeError, PermissionError, OSError):\n            continue\n\n        for line_num, line in enumerate(lines, 1):\n            if query_lower in line.lower():\n                results.append({\n                    \"file\": rel_path,\n                    \"line_number\": line_num,\n                    \"line\": line.strip(),\n                })\n                if len(results) >= 20:\n                    return results\n\n    return results\n\n\n@mcp.resource(\"notes:\/\/index\")\ndef get_notes_index() -> str:\n    \"\"\"\n    Resource: index of all available study materials with file sizes.\n    URI: notes:\/\/index\n    \"\"\"\n    files = list_study_files()\n    if not files:\n        return \"# Study Materials IndexnnNo study materials found.\"\n\n    lines = [\"# Study Materials Indexn\"]\n    for filename in files:\n        file_path = NOTES_BASE \/ filename\n        try:\n            size_kb = file_path.stat().st_size \/ 1024\n            lines.append(f\"- **{filename}** ({size_kb:.1f} KB)\")\n        except OSError:\n            lines.append(f\"- **{filename}** (size unknown)\")\n    lines.append(f\"nTotal: {len(files)} file(s)\")\n    return \"n\".join(lines)\n\n\nif __name__ == \"__main__\":\n    print(f\"[Filesystem MCP] Starting server\")\n    print(f\"[Filesystem MCP] Serving files from: {NOTES_BASE.resolve()}\")\n    mcp.run()\n<\/code><\/pre>\n<p><code>@mcp.tool()<\/code> \u0627\u0648\u0631 <code>@mcp.resource()<\/code> \u0645\u06a9\u0645\u0644 \u0645\u0631\u0628\u0648\u0637 \u0633\u0637\u062d\u06d4 FastMCP \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0627 \u0646\u0627\u0645 (\u062c\u0648 \u0679\u0648\u0644 \u06a9\u0627 \u0646\u0627\u0645 \u0628\u0646 \u062c\u0627\u062a\u0627 \u06c1\u06d2)\u060c \u062f\u0633\u062a\u0627\u0648\u06cc\u0632 \u06a9\u06cc \u062a\u0627\u0631 (\u062c\u0648 \u0648\u06c1 \u062a\u0641\u0635\u06cc\u0644 \u0628\u0646 \u062c\u0627\u062a\u06cc \u06c1\u06d2 \u062c\u0633\u06d2 LLM \u0627\u0633 \u0679\u0648\u0644 \u06a9\u0648 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0641\u06cc\u0635\u0644\u06c1 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2)\u060c \u0627\u0648\u0631 \u0679\u0627\u0626\u067e \u0627\u06cc\u0646\u0648\u0679\u06cc\u0634\u0646 (\u062c\u0648 \u06a9\u06c1 \u062f\u0644\u06cc\u0644 \u06a9\u0627 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u0628\u0646 \u062c\u0627\u062a\u0627 \u06c1\u06d2) \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0633\u0631\u0648\u0631 \u0627\u0648\u0631 \u0633\u0631\u0648\u0631 \u0633\u06d2 \u0645\u0646\u0633\u0644\u06a9 \u06a9\u0644\u0627\u0626\u0646\u0679 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0645\u06a9\u0645\u0644 \u0645\u0639\u0627\u06c1\u062f\u06c1 \u06c1\u06d2\u06d4<\/p>\n<p>Docstrings \u0642\u0627\u0628\u0644 \u062a\u0648\u062c\u06c1 \u06c1\u06cc\u06ba\u06d4 LLM \u062c\u0648 \u0627\u0646 \u0679\u0648\u0644\u0632 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0648\u06c1 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632 \u06a9\u06cc \u062a\u0627\u0631 \u06a9\u0648 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0637\u06d2 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0679\u0648\u0644 \u06a9\u0648 \u06a9\u0628 \u0627\u0648\u0631 \u06a9\u0646 \u062f\u0644\u0627\u0626\u0644 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4 \u0645\u0628\u06c1\u0645 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u0627\u062a (\u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 &quot;\u0641\u0627\u0626\u0644 \u067e\u0691\u06be\u06cc\u06ba&#8221;) \u0679\u0648\u0644 \u06a9\u06d2 \u063a\u0644\u0637 \u0627\u0646\u062a\u062e\u0627\u0628 \u06a9\u0627 \u0628\u0627\u0639\u062b \u0628\u0646\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0633\u0631\u0648\u0631 \u06a9\u06cc \u0688\u0627\u06a9\u0633\u0679\u0631\u0646\u06af \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648 \u0628\u0627\u0644\u06a9\u0644 \u0628\u062a\u0627\u062a\u06cc \u06c1\u06d2 \u06a9\u06c1 \u06c1\u0631 \u0679\u0648\u0644 \u06a9\u0648 \u06a9\u0628 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062f\u0644\u06cc\u0644 \u06a9\u06cc \u0634\u06a9\u0644 \u06a9\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-33-build-the-memory-mcp-server\">3.3 \u0645\u06cc\u0645\u0648\u0631\u06cc MCP \u0633\u0631\u0648\u0631 \u0628\u0646\u0627\u0646\u0627<\/h3>\n<p>\u0645\u06cc\u0645\u0648\u0631\u06cc \u0633\u0631\u0648\u0631 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648 \u0633\u06cc\u0634\u0646 \u06a9\u06d2 \u062f\u0627\u0626\u0631\u06c1 \u06a9\u0627\u0631 \u0645\u06cc\u06ba \u06a9\u0644\u06cc\u062f\u06cc \u0642\u062f\u0631 \u06a9\u0627 \u0630\u062e\u06cc\u0631\u06c1 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06a9\u0633 \u0645\u0648\u0636\u0648\u0639 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u06d4 \u0622\u06af\u06d2 \u06a9\u06cc\u0627 \u06a9\u0631\u0646\u0627 \u06c1\u06d2 \u0627\u0633 \u06a9\u0627 \u0641\u06cc\u0635\u0644\u06c1 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u062a\u0631\u0642\u06cc \u06a9\u0627 \u06a9\u0648\u0686 \u0646\u0648\u0679 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\"># src\/mcp_servers\/memory_server.py\n\nfrom datetime import datetime, timezone\nfrom mcp.server.fastmcp import FastMCP\n\nmcp = FastMCP(\"Memory Server\")\n\n# In-process store: {session_id: {key: {\"value\": str, \"updated_at\": str}}}\n# For production: replace with Redis or PostgreSQL.\n# The MCP interface stays identical. Only this dict changes.\n_store: dict[str, dict] = {}\n\n\ndef _now_iso() -> str:\n    return datetime.now(timezone.utc).isoformat()\n\n\n@mcp.tool()\ndef memory_set(session_id: str, key: str, value: str) -> str:\n    \"\"\"\n    Store a value in session memory.\n\n    Values are always strings. Use JSON for complex data:\n    memory_set(session_id, 'quiz_scores', json.dumps([0.8, 0.6]))\n\n    Args:\n        session_id: Scopes this data to one study session.\n        key: Descriptive name. Examples: 'explained_topics', 'last_quiz_score'\n        value: String value. Use JSON for lists or dicts.\n    \"\"\"\n    if session_id not in _store:\n        _store[session_id] = {}\n    _store[session_id][key] = {\"value\": value, \"updated_at\": _now_iso()}\n    return f\"Stored '{key}' for session '{session_id}'\"\n\n\n@mcp.tool()\ndef memory_get(session_id: str, key: str) -> str:\n    \"\"\"\n    Retrieve a value from session memory.\n\n    Returns the stored value, or the string \"null\" if the key doesn't exist.\n    Returns \"null\" (not Python None) so the LLM can handle the missing case\n    without type errors.\n    \"\"\"\n    session = _store.get(session_id, {})\n    entry = session.get(key)\n    return \"null\" if entry is None else entry[\"value\"]\n\n\n@mcp.tool()\ndef memory_list_keys(session_id: str) -> list[str]:\n    \"\"\"List all keys stored for a session. Returns [] if none exist.\"\"\"\n    return list(_store.get(session_id, {}).keys())\n\n\n@mcp.tool()\ndef memory_delete(session_id: str, key: str) -> str:\n    \"\"\"Delete a specific key from session memory.\"\"\"\n    session = _store.get(session_id, {})\n    if key in session:\n        del session[key]\n        return f\"Deleted '{key}' from session '{session_id}'\"\n    return f\"Key '{key}' not found in session '{session_id}'\"\n\n\n@mcp.resource(\"notes:\/\/session\/{session_id}\")\ndef get_session_summary(session_id: str) -> str:\n    \"\"\"Full summary of everything stored for a session. URI: notes:\/\/session\/{session_id}\"\"\"\n    session = _store.get(session_id, {})\n    if not session:\n        return f\"# Session Memory: {session_id}nnNo data stored yet.\"\n    lines = [f\"# Session Memory: {session_id}n\"]\n    for key, entry in sorted(session.items()):\n        lines.append(f\"## {key}\")\n        lines.append(f\"- Value: {entry['value']}n\")\n    return \"n\".join(lines)\n\n\nif __name__ == \"__main__\":\n    print(\"[Memory MCP] Starting server\")\n    mcp.run()\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>_store<\/code> \u0688\u06a9\u0679 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u0622\u0633\u0627\u0646 \u06c1\u06d2\u06d4 \u0622\u067e \u067e\u0648\u0631\u06d2 \u0645\u06cc\u0645\u0648\u0631\u06cc \u0633\u0631\u0648\u0631 \u06a9\u0648 Redis \u0628\u06cc\u06a9 \u0627\u06cc\u0646\u0688 \u0633\u06d2 \u0628\u062f\u0644 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0622\u067e \u06a9\u0627 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648\u0688 \u062a\u0628\u062f\u06cc\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u06af\u0627\u06d4 \u0635\u0631\u0641 \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f <code>memory_set<\/code> \u0627\u0648\u0631 <code>memory_get<\/code> \u06a9\u0631\u06d2 \u06af\u0627 \u06cc\u06c1 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u0628\u0627\u0624\u0646\u0688\u0631\u06cc \u06a9\u06cc \u0642\u062f\u0631 \u06c1\u06d2\u06d4<\/p>\n<p>\u0633\u0644\u06cc\u06a9\u0679 \u0627\u06cc\u06a9 \u062a\u0627\u0631 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>\"null\"<\/code> \u0627\u0632\u06af\u0631 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 <code>None<\/code> \u0633\u06d2 <code>memory_get<\/code> \u06cc\u06c1 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u06c1\u06d2\u06d4 \u062c\u0628 <code>ToolMessage<\/code> \u0634\u0627\u0645\u0644 <code>None<\/code>\u06a9\u0686\u06be \u0645\u0627\u0688\u0644 \u0648\u0631\u0698\u0646 \u0627\u0633 \u06a9\u0648 \u0635\u062d\u06cc\u062d \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u06c1\u06cc\u0646\u0688\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0648\u0627\u067e\u0633\u06cc \u06a9\u06d2 \u0631\u0627\u0633\u062a\u06d2 \u0645\u06cc\u06ba <code>\"null\"<\/code> LLM \u06a9\u0648 \u0627\u06cc\u06a9 \u0633\u0679\u0631\u0646\u06af \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0633 \u06a9\u0627 \u0627\u0646\u062f\u0627\u0632\u06c1 \u0627\u0633\u067e\u06cc\u0634\u0644 \u06a9\u06cc\u0633\u0632 \u06a9\u0648 \u0633\u0646\u0628\u06be\u0627\u0644\u06d2 \u0628\u063a\u06cc\u0631 \u0644\u06af\u0627\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 (&quot;\u06a9\u0644\u06cc\u062f \u0627\u0628\u06be\u06cc \u0645\u0648\u062c\u0648\u062f \u0646\u06c1\u06cc\u06ba \u06c1\u06d2&#8221;)\u06d4<\/p>\n<h3 id=\"heading-34-how-agents-use-mcp-tools-the-tool-calling-loop\">3.4 \u0627\u06cc\u062c\u0646\u0679 MCP \u0679\u0648\u0644\u0632 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u06cc\u06ba: \u0679\u0648\u0644 \u06a9\u0627\u0644 \u0644\u0648\u067e<\/h3>\n<p>\u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0627\u06cc\u062c\u0646\u0679 \u0648\u06c1 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0628\u0627\u0628 2 (\u0631\u06cc\u0627\u0633\u062a\u0648\u06ba) \u0627\u0648\u0631 \u0628\u0627\u0628 3 (MCP) \u0633\u06d2 \u0633\u0628 \u06a9\u0686\u06be \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0622\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 LLM \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u0627 \u067e\u06c1\u0644\u0627 \u0627\u06cc\u062c\u0646\u0679 \u0628\u06be\u06cc \u06c1\u06d2\u06d4 \u06cc\u0639\u0646\u06cc\u060c iterate\u060c \u0627\u06cc\u06a9 \u0641\u06cc \u0679\u0648\u0644 \u06a9\u0627\u0644\u060c \u062c\u0628 \u062a\u06a9 \u06a9\u06c1 LLM \u0627\u0633 \u0628\u0627\u062a \u06a9\u0627 \u062a\u0639\u06cc\u0646 \u0646\u06c1 \u06a9\u0631\u06d2 \u06a9\u06c1 \u062a\u0641\u0635\u06cc\u0644 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0627\u0641\u06cc \u0645\u0639\u0644\u0648\u0645\u0627\u062a \u0645\u0648\u062c\u0648\u062f \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0645\u06cc\u06ba <code>src\/agents\/explainer.py<\/code>MCP \u0633\u0631\u0648\u0631 \u0641\u0646\u06a9\u0634\u0646\u0632 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a Python \u0641\u0646\u06a9\u0634\u0646\u0632 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u062f\u0631\u0622\u0645\u062f \u06a9\u06cc\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a LangChain \u0633\u06d2 \u062f\u0631\u0622\u0645\u062f \u06a9\u06cc\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>@tool<\/code> \u0688\u06cc\u06a9\u0648\u0631\u06cc\u0679\u0631:<\/p>\n<pre><code class=\"language-python\"># src\/agents\/explainer.py (setup section)\n\nimport json, os\nfrom langchain_core.messages import AIMessage, HumanMessage, SystemMessage, ToolMessage\nfrom langchain_core.tools import tool\nfrom langchain_ollama import ChatOllama\n\nfrom graph.state import get_current_topic\nfrom mcp_servers.filesystem_server import list_study_files, read_study_file, search_notes\nfrom mcp_servers.memory_server import memory_get, memory_set\n\nMODEL_NAME = os.getenv(\"OLLAMA_MODEL\", \"qwen2.5:7b\")\nOLLAMA_BASE_URL = os.getenv(\"OLLAMA_BASE_URL\", \"http:\/\/localhost:11434\")\n\n\n@tool\ndef tool_list_files() -> list[str]:\n    \"\"\"\n    List all available study note files in the notes directory.\n    Returns filenames like ['closures.md', 'decorators.md'].\n    Call this FIRST to discover what materials exist before reading any file.\n    \"\"\"\n    return list_study_files()\n\n\n@tool\ndef tool_read_file(filename: str) -> str:\n    \"\"\"\n    Read the complete content of a study note file.\n    Args:\n        filename: Exact filename as returned by tool_list_files().\n    Returns the full file text, or an error string if not found.\n    \"\"\"\n    return read_study_file(filename)\n\n\n@tool\ndef tool_search_notes(query: str) -> str:\n    \"\"\"\n    Search across all study notes for a keyword or phrase.\n    Args:\n        query: Search term (case-insensitive). Example: 'nonlocal', 'closure'\n    Returns a JSON string with matching lines and their file locations.\n    \"\"\"\n    results = search_notes(query)\n    if not results:\n        return \"No matches found.\"\n    return json.dumps(results, indent=2)\n\n\n@tool\ndef tool_memory_get(session_id: str, key: str) -> str:\n    \"\"\"\n    Retrieve a value from session memory.\n    Args:\n        session_id: The current session ID (from state).\n        key: The memory key to look up.\n    Returns the stored value, or 'null' if not found.\n    \"\"\"\n    return memory_get(session_id, key)\n\n\n@tool\ndef tool_memory_set(session_id: str, key: str, value: str) -> str:\n    \"\"\"\n    Store a value in session memory for later agents to read.\n    Args:\n        session_id: The current session ID (from state).\n        key: Descriptive key name.\n        value: String value. Use JSON for complex data.\n    \"\"\"\n    return memory_set(session_id, key, value)\n\n\nEXPLAINER_TOOLS = [\n    tool_list_files, tool_read_file, tool_search_notes,\n    tool_memory_get, tool_memory_set,\n]\nTOOL_MAP = {t.name: t for t in EXPLAINER_TOOLS}\n<\/code><\/pre>\n<h4 id=\"heading-direct-import-vs-subprocess-transport\"> \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u062f\u0631\u0622\u0645\u062f \u0628\u0645\u0642\u0627\u0628\u0644\u06c1 \u0630\u06cc\u0644\u06cc \u0639\u0645\u0644 \u0646\u0642\u0644 \u0648 \u062d\u0645\u0644<\/h4>\n<p>\u0627\u0633 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0645\u06cc\u06ba\u060c \u06c1\u0645 MCP \u0679\u0648\u0644 \u06a9\u0648 Python \u0641\u0646\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u0627\u0645\u067e\u0648\u0631\u0679 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0627\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0644\u067e\u06cc\u0679\u062a\u06d2 \u06c1\u06cc\u06ba: <code>@tool<\/code>. \u06cc\u06c1 \u0633\u0628 \u06a9\u0686\u06be \u0627\u06cc\u06a9 \u0639\u0645\u0644 \u0645\u06cc\u06ba \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0631\u0642\u06cc \u0622\u0633\u0627\u0646 \u06c1\u06d2\u060c \u06a9\u0648\u0626\u06cc \u0633\u0628 \u067e\u0631\u0648\u0633\u06cc\u0633 \u0627\u0648\u0648\u0631 \u06c1\u06cc\u0688 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0627\u0648\u0631 \u062c\u0627\u0646\u0686 \u0622\u0633\u0627\u0646 \u06c1\u06d2\u06d4<\/p>\n<p>\u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0645\u0627\u062d\u0648\u0644 \u0645\u06cc\u06ba\u060c MCP \u0633\u0631\u0648\u0631 \u0627\u06cc\u06a9 \u0627\u0644\u06af \u0639\u0645\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0686\u0644\u062a\u0627 \u06c1\u06d2 \u062c\u0648 stdio \u06cc\u0627 HTTP \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0628\u0627\u062a \u0686\u06cc\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0645 \u06c1\u0648 <code>MultiServerMCPClient<\/code> \u0633\u06d2 <code>langchain-mcp-adapters<\/code> \u06a9\u0646\u06cc\u06a9\u0679 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648\u0688 \u062f\u0648\u0646\u0648\u06ba \u0637\u0631\u06cc\u0642\u0648\u06ba \u0645\u06cc\u06ba \u0639\u0645\u0644\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u06cc\u06a9 \u062c\u06cc\u0633\u0627 \u06c1\u06d2\u060c \u0635\u0631\u0641 \u0679\u0648\u0644 \u0631\u06cc\u067e\u0646\u06af \u062a\u0628\u062f\u06cc\u0644 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0633\u0627\u062a\u06be\u06d4<\/p>\n<p>\u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u06a9\u0627 \u0633\u0633\u0679\u0645 \u067e\u0631\u0627\u0645\u067e\u0679 \u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u0648 \u0628\u06be\u06cc \u0628\u062a\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06a9\u0648\u0646 \u0633\u06d2 \u0679\u0648\u0644\u0632 \u062f\u0633\u062a\u06cc\u0627\u0628 \u06c1\u06cc\u06ba\u06d4 <em>\u062a\u0631\u062a\u06cc\u0628 \u0645\u06cc\u06ba \u0627\u0646 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u06cc\u06ba\u06d4<\/em>:<\/p>\n<pre><code class=\"language-python\">EXPLAINER_SYSTEM_PROMPT = \"\"\"You are an expert tutor explaining topics to a student.\n\nYour explanations must be grounded in the student's actual study materials.\nUse the available tools to find and read relevant notes before explaining.\n\nAPPROACH (follow this sequence):\n1. Call tool_list_files() to see what materials are available\n2. Call tool_search_notes(topic) to find which files cover this topic\n3. Call tool_read_file(filename) to read the most relevant file(s)\n4. Check prior context: call tool_memory_get(session_id, 'explained_topics')\n5. Write your explanation based on what you found in the notes\n\nEXPLANATION FORMAT:\n- Start with a real-world analogy (1-2 sentences)\n- State the core concept clearly (2-3 sentences)\n- Show a concrete code example from the student's notes\n- End with one common mistake or gotcha to watch out for\n\nAfter writing the explanation, store what you explained:\n  tool_memory_set(session_id, 'explained_topics', <comma-separated topic=\"\" titles=\"\">)\n\"\"\"\n<\/comma-separated><\/code><\/pre>\n<p>\u0679\u0648\u0644 \u06a9\u0627\u0644 \u0644\u0648\u067e <code>explainer_node<\/code> \u063a\u0648\u0631 \u0633\u06d2 \u0633\u0645\u062c\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06a9\u0644\u06cc\u062f\u06cc \u0645\u06cc\u06a9\u0627\u0646\u0632\u0645 \u06c1\u06cc\u06ba:<\/p>\n<pre><code class=\"language-python\"># src\/agents\/explainer.py (node function)\n\ndef execute_tool_call(tool_call: dict) -> str:\n    \"\"\"Execute a tool call and return the result as a string. Never raises.\"\"\"\n    name = tool_call[\"name\"]\n    args = tool_call[\"args\"]\n    if name not in TOOL_MAP:\n        return f\"Error: unknown tool '{name}'. Available: {list(TOOL_MAP.keys())}\"\n    try:\n        result = TOOL_MAP[name].invoke(args)\n        if isinstance(result, (list, dict)):\n            return json.dumps(result)\n        return str(result)\n    except Exception as e:\n        return f\"Error executing {name}({args}): {type(e).__name__}: {e}\"\n\n\ndef explainer_node(state: dict) -> dict:\n    \"\"\"\n    LangGraph node: Explainer Agent\n\n    Reads:  state[\"roadmap\"], state[\"current_topic_index\"], state[\"session_id\"]\n    Writes: state[\"messages\"], state[\"error\"]\n    \"\"\"\n    topic = get_current_topic(state)\n    if topic is None:\n        return {\"error\": \"No current topic found.\"}\n\n    session_id = state.get(\"session_id\", \"unknown\")\n    print(f\"n[Explainer] Topic: '{topic.title}'\")\n\n    llm = ChatOllama(\n        model=MODEL_NAME,\n        base_url=OLLAMA_BASE_URL,\n        temperature=0.3,\n    ).bind_tools(EXPLAINER_TOOLS)\n\n    messages = [\n        SystemMessage(content=EXPLAINER_SYSTEM_PROMPT),\n        HumanMessage(content=(\n            f\"Please explain this topic to me: '{topic.title}'n\"\n            f\"Context: {topic.description}n\"\n            f\"Session ID for memory calls: {session_id}\"\n        )),\n    ]\n\n    max_iterations = 8\n    final_response = None\n\n    for iteration in range(max_iterations):\n        print(f\"[Explainer] LLM call {iteration + 1}\/{max_iterations}...\")\n        response = llm.invoke(messages)\n        messages.append(response)\n\n        if not response.tool_calls:\n            final_response = response\n            print(f\"[Explainer] Complete after {iteration + 1} LLM call(s)\")\n            break\n\n        print(f\"[Explainer] {len(response.tool_calls)} tool call(s) requested:\")\n        for tool_call in response.tool_calls:\n            print(f\"  \u2192 {tool_call['name']}({tool_call['args']})\")\n            result = execute_tool_call(tool_call)\n            log_result = result[:100] + \"...\" if len(result) > 100 else result\n            print(f\"    \u2190 {log_result}\")\n\n            # The tool_call_id must match the ID the LLM assigned to the request.\n            # Without this, the LLM can't correlate result to request.\n            messages.append(ToolMessage(\n                content=result,\n                tool_call_id=tool_call[\"id\"],\n            ))\n\n    if final_response is None:\n        return {\n            \"messages\": messages,\n            \"error\": f\"Explainer reached max iterations ({max_iterations}).\",\n        }\n\n    print(f\"[Explainer] Explanation: {len(final_response.content)} characters\")\n    return {\"messages\": messages, \"error\": None}\n<\/code><\/pre>\n<p>\u0622\u0626\u06cc\u06d2 \u062f\u06cc\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0627\u06cc\u06a9 \u0631\u0646 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u06a9\u06cc\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u0627\u0644 1:<\/strong> LLM \u06a9\u0648 \u0633\u0633\u0679\u0645 \u067e\u0631\u0627\u0645\u067e\u0679\u0633 \u0627\u0648\u0631 \u0627\u0646\u0633\u0627\u0646\u06cc \u067e\u06cc\u063a\u0627\u0645\u0627\u062a \u0645\u0648\u0635\u0648\u0644 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0646 \u0645\u06cc\u06ba &quot;\u0628\u0646\u062f \u06c1\u0648\u0646\u06d2 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u06cc \u06af\u0626\u06cc&#8221; \u06a9\u06d2 \u0644\u06cc\u06d2 \u0648\u0636\u0627\u062d\u062a \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0679\u0648\u0644 \u06a9\u0627\u0644 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062c\u0648\u0627\u0628 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 <code>tool_list_files()<\/code> \u0627\u0648\u0631 <code>tool_search_notes(\"closure\")<\/code>. \u0627\u0628\u06be\u06cc \u062a\u06a9 \u06a9\u0648\u0626\u06cc \u0645\u062a\u0646 \u06a9\u06cc \u062a\u0641\u0635\u06cc\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0679\u0648\u0644 \u0686\u0644\u0627\u0626\u06cc\u06ba:<\/strong> <code>tool_list_files()<\/code> \u0631\u067e\u0648\u0631\u0679 <code>[\"closures.md\", \"decorators.md\", \"python_basics.md\"]<\/code>. <code>tool_search_notes(\"closure\")<\/code> \u0645\u0645\u0627\u062b\u0644 \u0642\u0637\u0627\u0631\u06cc\u06ba \u06cc\u06c1\u0627\u06ba \u0633\u06d2 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2: <code>closures.md<\/code>. \u062f\u0648\u0646\u0648\u06ba \u0646\u062a\u0627\u0626\u062c \u06a9\u0648 \u067e\u06cc\u063a\u0627\u0645 \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a \u0645\u06cc\u06ba \u0627\u0633 \u0637\u0631\u062d \u0634\u0627\u0645\u0644 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2: <code>ToolMessage<\/code> \u0645\u0645\u0627\u062b\u0644 \u0622\u0628\u062c\u06cc\u06a9\u0679 <code>tool_call_id<\/code>.<\/p>\n<p><strong>\u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u0627\u0644 2:<\/strong> \u0627\u0628 \u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u06d2 \u067e\u0627\u0633 \u0641\u0627\u0626\u0644\u0648\u06ba \u0627\u0648\u0631 \u062a\u0644\u0627\u0634 \u06a9\u06d2 \u0646\u062a\u0627\u0626\u062c \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a \u06c1\u06d2\u06d4 \u06cc\u06c1 \u067e\u0648\u0686\u06be\u062a\u0627 \u06c1\u06d2 <code>tool_read_file(\"closures.md\")<\/code>.<\/p>\n<p><strong>\u0679\u0648\u0644 \u0686\u0644\u0627\u0626\u06cc\u06ba:<\/strong> \u0645\u06a9\u0645\u0644 \u062a\u0641\u0635\u06cc\u0644\u0627\u062a <code>closures.md<\/code> \u0648\u0627\u067e\u0633 \u06a9\u0631 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2. <code>ToolMessage<\/code>.<\/p>\n<p><strong>\u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u0627\u0644 3:<\/strong> \u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u0646\u06d2 \u0646\u0648\u0679 \u067e\u0691\u06be\u0627\u06d4 \u06cc\u06c1 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 <code>tool_memory_set(session_id, \"explained_topics\", \"Closures Explained\")<\/code> \u0646\u0648\u0679 \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u0627\u0633 \u0645\u0648\u0636\u0648\u0639 \u067e\u0631 \u062a\u0648\u062c\u06c1 \u062f\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u0627\u0644 4:<\/strong> \u0645\u062d\u0641\u0648\u0638 \u0634\u062f\u06c1 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u06a9\u06d2 \u0633\u0627\u062a\u06be\u060c LLM \u062d\u062a\u0645\u06cc \u062a\u0641\u0635\u06cc\u0644 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0648\u0627\u0628 \u0645\u06cc\u06ba \u0645\u0632\u06cc\u062f \u0679\u0648\u0644 \u06a9\u0627\u0644\u0632 \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 \u0644\u0648\u067e \u062e\u062a\u0645 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0648\u0636\u0627\u062d\u062a\u06cc\u06ba \u0627\u0633 \u0628\u0627\u062a \u067e\u0631 \u0645\u0628\u0646\u06cc \u06c1\u06cc\u06ba \u06a9\u06c1 \u0627\u0635\u0644 \u0645\u06cc\u06ba \u0622\u067e \u06a9\u06d2 \u0646\u0648\u0679\u0633 \u0645\u06cc\u06ba \u06a9\u06cc\u0627 \u06c1\u06d2\u060c \u0645\u0627\u0688\u0644 \u06a9\u06d2 \u062a\u0631\u0628\u06cc\u062a\u06cc \u0688\u06cc\u0679\u0627 \u067e\u0631 \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06a9\u06c1 <code>tool_call_id<\/code> \u0622\u0646 \u0644\u0627\u0626\u0646 \u0645\u0644\u0627\u067e <code>tool_call_id=tool_call[\"id\"]<\/code> \u06cc\u06c1 \u0642\u0627\u0628\u0644 \u062a\u0648\u062c\u06c1 \u06c1\u06d2\u06d4 \u062c\u0628 LLM \u0679\u0648\u0644 \u06a9\u0627\u0644 \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u0627\u06cc\u06a9 ID \u062a\u0641\u0648\u06cc\u0636 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u06c1 <code>ToolMessage<\/code> \u0622\u067e \u06a9\u0648 \u0648\u06c1\u06cc ID \u0634\u0627\u0645\u0644 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2 \u062a\u0627\u06a9\u06c1 LLM \u0646\u062a\u0627\u0626\u062c \u06a9\u0648 \u0622\u067e \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u0646\u0633\u0644\u06a9 \u06a9\u0631 \u0633\u06a9\u06d2\u06d4 \u0627\u0633 \u06a9\u06d2 \u0628\u063a\u06cc\u0631\u060c \u0688\u0627\u0626\u06cc\u0644\u0627\u06af \u062e\u0631\u0627\u0628 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627 \u0627\u0648\u0631 \u0645\u0627\u0688\u0644 \u0631\u062f\u06cc \u06a9\u06cc \u0679\u0648\u06a9\u0631\u06cc \u06cc\u0627 \u063a\u0644\u0637\u06cc\u0627\u06ba \u067e\u06cc\u062f\u0627 \u06a9\u0631\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u06a9\u06c1 <code>max_iterations = 8<\/code> \u062d\u062f \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u0633\u0631\u06a9\u0679 \u0628\u0631\u06cc\u06a9\u0631 \u06c1\u06d2. \u0627\u06cc\u06a9 \u0645\u0628\u06c1\u0645 \u0645\u0627\u0688\u0644 \u062c\u0648 \u06a9\u0633\u06cc \u0679\u0648\u0644 \u06a9\u0648 \u063a\u06cc\u0631 \u0645\u0639\u06cc\u0646\u06c1 \u0645\u062f\u062a \u062a\u06a9 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0633 \u0648\u0642\u062a \u062a\u06a9 \u0686\u0644\u06d2 \u06af\u0627 \u062c\u0628 \u062a\u06a9 \u06a9\u06c1 \u0679\u0648\u0644 \u062e\u062a\u0645 \u0646\u06c1 \u06c1\u0648 \u062c\u0627\u0626\u06d2\u06d4 \u0627\u06cc\u06a9 \u062c\u0627\u0626\u0632 \u0648\u0636\u0627\u062d\u062a\u06cc \u06a9\u0627\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0622\u0679\u06be \u062a\u06a9\u0631\u0627\u0631 \u06a9\u0627\u0641\u06cc \u06c1\u06cc\u06ba\u06d4 \u062c\u0628 \u06a9\u0648\u0626\u06cc \u0645\u0627\u0688\u0644 \u0627\u067e\u0646\u06cc \u062d\u062f \u062a\u06a9 \u067e\u06c1\u0646\u0686 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u06cc\u06a9 \u062e\u0631\u0627\u0628\u06cc \u06a9\u06cc \u062d\u0627\u0644\u062a \u0634\u0631\u0648\u0639 \u06c1\u0648 \u062c\u0627\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u0633\u0633\u0679\u0645 \u067e\u0631\u0627\u0645\u067e\u0679\u0633 \u06a9\u0648 \u0627\u06cc\u0688\u062c\u0633\u0679 \u06cc\u0627 \u0628\u0691\u06d2 \u0645\u0627\u0688\u0644 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-35-run-the-explainer\">3.5 \u0648\u0636\u0627\u062d\u062a\u06cc \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f<\/h3>\n<p>\u0627\u0634\u0627\u0631\u06c1 \u06a9\u0631\u0646\u06d2 \u067e\u0631\u060c \u0631\u0648\u0688 \u0645\u06cc\u067e \u06a9\u0648 \u0642\u0628\u0648\u0644 \u06a9\u0631\u06cc\u06ba\u060c \u067e\u06be\u0631 \u0679\u0648\u0644 \u06a9\u0627\u0644 \u0644\u0648\u067e \u06a9\u0648 \u0639\u0645\u0644 \u0645\u06cc\u06ba \u062f\u06cc\u06a9\u06be\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">python main.py\n<\/code><\/pre>\n<p>\u0645\u0646\u0638\u0648\u0631\u06cc \u06a9\u06d2 \u0628\u0639\u062f:<\/p>\n<pre><code class=\"language-plaintext\">[Explainer] Topic: 'Python Functions Review'\n[Explainer] LLM call 1\/8...\n  \u2192 tool_list_files({})\n    \u2190 [\"closures.md\", \"decorators.md\", \"python_basics.md\"]\n[Explainer] LLM call 2\/8...\n  \u2192 tool_search_notes({'query': 'functions'})\n    \u2190 [{\"file\": \"python_basics.md\", \"line_number\": 12, \"line\": \"## Functions\"}]\n[Explainer] LLM call 3\/8...\n  \u2192 tool_read_file({'filename': 'python_basics.md'})\n    \u2190 # Python Basicsnn## Variables and Types...\n[Explainer] LLM call 4\/8...\n  \u2192 tool_memory_set({'session_id': 'a3f1b2c4', 'key': 'explained_topics', ...})\n    \u2190 Stored 'explained_topics' for session 'a3f1b2c4'\n[Explainer] LLM call 5\/8...\n[Explainer] Complete after 5 LLM call(s)\n[Explainer] Explanation: 487 characters\n<\/code><\/pre>\n<p>\u062a\u0645\u0627\u0645 \u062a\u06cc\u0631 (<code>\u2192<\/code>) LLM \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06c1 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0631\u062f\u06c1 \u0627\u06cc\u06a9 \u0679\u0648\u0644 \u06a9\u0627\u0644 \u06c1\u06d2\u06d4 \u062a\u0645\u0627\u0645 \u067e\u0686\u06be\u0644\u06d2 \u062a\u06cc\u0631 (<code>\u2190<\/code>) LLM \u06a9\u0648 \u0648\u0627\u067e\u0633 \u06a9\u06cc\u06d2 \u06af\u0626\u06d2 \u0646\u062a\u0627\u0626\u062c \u06c1\u06cc\u06ba\u06d4 \u0644\u0648\u067e LLM \u06a9\u0627\u0644 5 \u067e\u0631 \u062e\u062a\u0645 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0627\u0633 \u062c\u0648\u0627\u0628 \u0645\u06cc\u06ba \u062d\u062a\u0645\u06cc \u062a\u0628\u0635\u0631\u06c1 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0645\u0632\u06cc\u062f \u0679\u0648\u0644 \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u06cc\u06ba \u0646\u06c1\u06cc\u06ba \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<p> <strong>\u0686\u0648\u06a9\u06cc:<\/strong> \u06cc\u06c1 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u06c1 \u0679\u0648\u0644 LLM \u0633\u06d2 \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 MCP \u0633\u0631\u0648\u0631 \u0679\u06cc\u0633\u0679 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">pytest tests\/test_mcp_servers.py -v\n<\/code><\/pre>\n<p>\u067e\u06cc\u0634\u06cc\u0646 \u06af\u0648\u0626\u06cc: 36 \u0679\u06cc\u0633\u0679\u060c \u0633\u0628 \u067e\u0627\u0633\u060c \u0627\u0648\u0644\u0627\u0645\u06c1 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0679\u06cc\u0633\u0679 \u0679\u0648\u0644 \u0641\u0646\u06a9\u0634\u0646\u0632 \u06a9\u0648 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a Python \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06a9\u0648\u0626\u06cc \u0630\u06cc\u0644\u06cc \u0639\u0645\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u0627\u0648\u0631 \u06a9\u0648\u0626\u06cc \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u0627\u0648\u0648\u0631 \u06c1\u06cc\u0688 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0686\u0648\u0646\u06a9\u06c1 \u0679\u0648\u0644 \u06a9\u06cc \u0641\u0639\u0627\u0644\u06cc\u062a \u0633\u0627\u062f\u06c1 Python \u06c1\u06d2\u060c \u06cc\u06c1 \u0679\u0648\u0644 \u062f\u0648 \u0637\u0631\u06cc\u0642\u0648\u06ba \u0645\u06cc\u06ba \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: \u0688\u0627\u0626\u0631\u06cc\u06a9\u0679 Python \u0627\u0645\u067e\u0648\u0631\u0679 \u0627\u0648\u0631 MCP \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644\u06d4<\/p>\n<p>\u06cc\u06c1\u0627\u06ba \u06a9\u0627\u0631\u067e\u0648\u0631\u06cc\u0679 \u06a9\u0646\u06a9\u0634\u0646: \u0627\u06cc\u06a9 \u06a9\u0645\u067e\u0644\u0627\u0626\u0646\u0633 \u0679\u0631\u06cc\u0646\u0646\u06af \u0633\u0633\u0679\u0645 \u062c\u0648 \u0627\u0633\u06cc \u067e\u06cc\u0679\u0631\u0646 \u06a9\u0648 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0633 \u0645\u06cc\u06ba MCP \u0633\u0631\u0648\u0631 \u06c1\u0648\u06af\u0627 \u062c\u0648 \u0627\u0633\u0679\u0688\u06cc \u0646\u0648\u0679 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0631\u06cc\u06af\u0648\u0644\u06cc\u0679\u0631\u06cc \u0645\u0648\u0627\u062f \u06a9\u06cc \u0644\u0627\u0626\u0628\u0631\u06cc\u0631\u06cc \u06a9\u0648 \u0628\u06d2 \u0646\u0642\u0627\u0628 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc\u062c\u0646\u0679\u0633 \u0645\u0648\u0636\u0648\u0639 \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0642\u0627\u0636\u0648\u06ba \u06a9\u0648 \u067e\u0691\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0627\u0635\u0644 \u0631\u06cc\u06af\u0648\u0644\u06cc\u0679\u0631\u06cc \u0645\u062a\u0646 \u0633\u06d2 \u0633\u0631\u0679\u06cc\u0641\u06cc\u06a9\u06cc\u0634\u0646 \u06a9\u06d2 \u062c\u0627\u0626\u0632\u06d2 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0646\u06c1 \u06a9\u06c1 \u0648\u06c1 \u0631\u06cc\u06af\u0648\u0644\u06cc\u0679\u0631\u06cc \u0645\u062a\u0646 \u062c\u0633 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0645\u0627\u0688\u0644 \u0633\u0648\u0686\u062a\u0627 \u06c1\u06d2\u06d4 \u06af\u0631\u0627\u0624\u0646\u0688\u0646\u06af \u06a9\u0644\u06cc\u062f \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06af\u0644\u06d2 \u0628\u0627\u0628 \u0645\u06cc\u06ba\u060c \u0622\u067e \u06a9\u0648\u0626\u0632 \u062c\u0646\u0631\u06cc\u0679\u0631 \u0627\u0648\u0631 \u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u06a9\u0648\u0686 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u060c \u062a\u0645\u0627\u0645 \u0645\u0648\u0636\u0648\u0639\u0627\u062a \u067e\u0631 \u06af\u0631\u0627\u0641 \u06a9\u0648 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0644\u0648\u067e \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0634\u0631\u0648\u0637 \u0631\u0648\u0679\u0646\u06af \u06a9\u0648 \u062c\u0648\u0691\u06cc\u06ba \u06af\u06d2\u060c \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0645\u06a9\u0645\u0644 \u0686\u0627\u0631 \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645 \u06a9\u0648 \u0627\u06cc\u0646\u0688 \u0679\u0648 \u0627\u06cc\u0646\u0688 \u0686\u0644\u0627\u0626\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<h2 id=\"heading-chapter-4-building-the-four-agent-system\">\u0628\u0627\u0628 4: \u0641\u0648\u0631 \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645 \u06a9\u06cc \u062a\u0639\u0645\u06cc\u0631<\/h2>\n<p>\u067e\u06c1\u0644\u06d2 \u062a\u06cc\u0646 \u0627\u0628\u0648\u0627\u0628 \u0645\u06cc\u06ba\u060c \u06c1\u0645 \u0646\u06d2 \u0641\u0627\u0624\u0646\u0688\u06cc\u0634\u0646 \u0628\u0646\u0627\u0626\u06cc: \u0627\u06cc\u06a9 \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0627\u0633\u0679\u06cc\u0679 \u0688\u06cc\u0641\u06cc\u0646\u06cc\u0634\u0646\u060c \u0627\u06cc\u06a9 \u06af\u0631\u0627\u0641 \u062c\u0648 \u06c1\u0631 \u0646\u0648\u0688 \u06a9\u06d2 \u0628\u0639\u062f \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062f\u0648 MCP \u0633\u0631\u0648\u0631\u0632\u060c \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0648\u0636\u0627\u062d\u062a\u06cc \u0627\u06cc\u062c\u0646\u0679 \u062c\u0648 \u0627\u0646 \u0633\u0631\u0648\u0631\u0632 \u06a9\u0648 \u0627\u0635\u0644 \u0646\u0648\u0679\u0648\u06ba \u06a9\u06cc \u0628\u0646\u06cc\u0627\u062f \u067e\u0631 \u0648\u0636\u0627\u062d\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u0627\u06cc\u06a9 LLM \u06c1\u06d2 \u062c\u0648 \u0641\u0627\u0626\u0644\u0648\u06ba \u06a9\u0648 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u0628\u0627\u0628 \u0646\u0638\u0627\u0645 \u06a9\u0648 \u0645\u06a9\u0645\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u0648\u0626\u0632 \u062c\u0646\u0631\u06cc\u0679\u0631 \u0627\u0648\u0631 \u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u06a9\u0648\u0686 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u060c \u062a\u0645\u0627\u0645 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u06af\u0631\u0627\u0641 \u06a9\u0648 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0644\u0648\u067e \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0634\u0631\u0648\u0637 \u0631\u0648\u0679\u0646\u06af \u06a9\u0648 \u062c\u0648\u0691\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0645\u06a9\u0645\u0644 \u0627\u06cc\u0646\u0688 \u0679\u0648 \u0627\u06cc\u0646\u0688 \u0633\u06cc\u0634\u0646 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-41-the-quiz-generator-llm-as-judge\">4.1 \u06a9\u0648\u0626\u0632 \u062c\u0646\u0631\u06cc\u0679\u0631: LLM \u0628\u0637\u0648\u0631 \u062c\u062c<\/h3>\n<p>\u06a9\u0648\u0626\u0632 \u062c\u0646\u0631\u06cc\u0679\u0631 \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba \u0633\u0627\u062e\u062a\u06cc \u0644\u062d\u0627\u0638 \u0633\u06d2 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u062f\u0644\u0686\u0633\u067e \u0627\u06cc\u062c\u0646\u0679 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u0645\u062e\u062a\u0644\u0641 \u0645\u0642\u0627\u0635\u062f \u0627\u0648\u0631 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0644\u06af \u0627\u0644\u06af \u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u0627\u0644\u0632 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0627\u06cc\u06a9 \u0646\u0633\u0644 \u06a9\u06cc \u067e\u06a9\u0627\u0631<\/strong> \u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u06a9\u06d2 \u0622\u0624\u0679 \u067e\u0679 \u0633\u06d2 \u0633\u0648\u0627\u0644\u0627\u062a \u067e\u06cc\u062f\u0627 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 <code>temperature=0.4<\/code> (\u0645\u062a\u0639\u062f\u062f \u0645\u0648\u0636\u0648\u0639\u0627\u062a \u067e\u0631 \u0645\u062a\u0646\u0648\u0639\u060c \u063a\u06cc\u0631 \u062f\u06c1\u0631\u0627\u0626\u06d2 \u062c\u0627\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0633\u0648\u0627\u0644\u0627\u062a \u067e\u06cc\u062f\u0627 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0627\u0641\u06cc \u062a\u062e\u0644\u06cc\u0642\u06cc \u0635\u0644\u0627\u062d\u06cc\u062a) <code>format=\"json\"<\/code> \u062a\u0634\u06a9\u06cc\u0644 \u0634\u062f\u06c1 \u0622\u0624\u0679 \u067e\u0679 \u06a9\u0648 \u0646\u0627\u0641\u0630 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p><strong>\u06af\u0631\u06cc\u0688\u0646\u06af \u06a9\u0627\u0644<\/strong> \u0637\u0644\u0628\u0627\u0621 \u06a9\u06d2 \u062c\u0648\u0627\u0628\u0627\u062a \u06a9\u0627 \u0627\u0646\u062f\u0627\u0632\u06c1 \u0644\u06af\u0627\u0626\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 <code>temperature=0.1<\/code>. \u062a\u062c\u0632\u06cc\u0627\u062a\u06cc \u0627\u0648\u0631 \u0645\u0633\u062a\u0642\u0644\u06d4 \u0627\u06cc\u06a9 \u06c1\u06cc \u062c\u0648\u0627\u0628 \u06a9\u0648 \u062f\u0648 \u0628\u0627\u0631 \u06af\u0631\u06cc\u0688 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0646\u062a\u06cc\u062c\u06d2 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u06c1\u06cc \u0627\u0633\u06a9\u0648\u0631 \u06c1\u0648\u06af\u0627\u06d4 \u067e\u06cc\u062f\u0627 \u06a9\u0631\u062f\u06c1 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u062a\u062e\u0644\u06cc\u0642\u06cc \u062a\u0631\u062a\u06cc\u0628\u0627\u062a \u067e\u0631\u06a9\u06be \u06a9\u06cc \u062a\u0634\u062e\u06cc\u0635 \u06a9\u0648 \u0645\u062a\u0627\u062b\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u0646\u0627\u0645 \u062f\u06cc\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u067e\u06cc\u0679\u0631\u0646 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0627\u06cc\u06a9 \u0648\u0631\u06a9 \u0641\u0644\u0648 \u0645\u06cc\u06ba \u0630\u06cc\u0644\u06cc \u06a9\u0627\u0645 \u06c1\u06cc\u06ba \u062c\u0646 \u06a9\u06d2 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0645\u062e\u062a\u0644\u0641 \u062a\u0642\u0627\u0636\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0644\u06af \u0627\u0644\u06af \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0644\u06af \u0627\u0644\u06af LLM \u06a9\u0627\u0644\u0632 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u062f\u0648\u0646\u0648\u06ba \u06a9\u0627\u0645 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u0646\u06d2 \u0648\u0627\u0644\u06cc \u0627\u06cc\u06a9 \u06a9\u0627\u0644 \u0633\u06d2 \u0628\u06c1\u062a\u0631 \u0646\u062a\u0627\u0626\u062c \u062d\u0627\u0635\u0644 \u06c1\u0648 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\"># src\/agents\/quiz_generator.py\n\nimport json\nimport os\nfrom datetime import datetime, timezone\n\nfrom langchain_core.messages import AIMessage, HumanMessage, SystemMessage\nfrom langchain_ollama import ChatOllama\n\nfrom graph.state import QuizQuestion, QuizResult, get_current_topic\n\nMODEL_NAME = os.getenv(\"OLLAMA_MODEL\", \"qwen2.5:7b\")\nOLLAMA_BASE_URL = os.getenv(\"OLLAMA_BASE_URL\", \"http:\/\/localhost:11434\")\n\nGENERATION_PROMPT = \"\"\"You are a quiz designer for a student learning programming.\n\nGiven a topic and explanation, generate {n} quiz questions that test\ngenuine understanding, not just the ability to repeat memorized phrases.\n\nGood questions require the student to:\n  - Apply a concept to a new situation\n  - Explain WHY something works, not just WHAT it does\n  - Identify edge cases or common mistakes\n  - Compare related concepts\n\nReturn ONLY valid JSON with no prose or markdown:\n{{\n  \"questions\": [\n    {{\n      \"question\": \"Clear, specific question text ending with ?\",\n      \"expected_answer\": \"Model answer in 1-3 sentences\",\n      \"difficulty\": \"easy|medium|hard\"\n    }}\n  ]\n}}\n\nRules:\n  - Include at least one question about a common mistake or gotcha\n  - expected_answer should be concise but complete\n  - Avoid yes\/no questions. Ask for explanation or demonstration\n\"\"\"\n\nGRADING_PROMPT = \"\"\"You are a fair teacher grading a student's answer.\n\nQuestion: {question}\nModel answer: {expected_answer}\nStudent's answer: {student_answer}\n\nGrade the student's answer honestly. Be generous with partial credit:\n  - Fundamentally correct with minor gaps: 0.7-0.9\n  - Correct concept but imprecise: 0.5-0.7\n  - Partially correct: 0.3-0.5\n  - Fundamentally wrong: 0.0-0.2\n\nReturn ONLY valid JSON with no prose or markdown:\n{{\n  \"correct\": true,\n  \"score\": 0.85,\n  \"feedback\": \"One specific sentence of feedback\",\n  \"missing_concept\": \"Key concept missed, or empty string if answer is correct\"\n}}\n\"\"\"\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>generate_questions<\/code> \u0627\u0648\u0631 <code>grade_answer<\/code> \u0641\u0646\u06a9\u0634\u0646 \u0627\u0646 \u062f\u0648\u0646\u0648\u06ba \u06a9\u0627\u0644\u0648\u06ba \u06a9\u0648 \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u0646\u0627\u0641\u0630 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062f\u0648\u0646\u0648\u06ba \u06a9\u0648 \u0633\u0627\u062f\u06c1 Python \u0633\u06d2 \u062f\u0631\u0622\u0645\u062f \u0627\u0648\u0631 \u06a9\u0627\u0644 \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u06af\u0631\u0627\u0641 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0622\u067e \u06a9\u0648 A2A \u0633\u0631\u0648\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062a\u0646\u06c1\u0627\u0626\u06cc \u0645\u06cc\u06ba \u062c\u0627\u0646\u0686 \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u062c\u0633\u06d2 \u0622\u067e \u0628\u0627\u0628 8 \u0645\u06cc\u06ba \u0628\u0646\u0627\u0626\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\">def generate_questions(topic: str, explanation: str, n: int = 3) -> list[dict]:\n    \"\"\"Generate n quiz questions from the Explainer's output.\"\"\"\n    llm = ChatOllama(\n        model=MODEL_NAME,\n        base_url=OLLAMA_BASE_URL,\n        temperature=0.4,\n        format=\"json\",\n    )\n\n    prompt = GENERATION_PROMPT.format(n=n)\n    try:\n        response = llm.invoke([\n            SystemMessage(content=prompt),\n            HumanMessage(content=f\"Topic: {topic}nnExplanation:n{explanation}\"),\n        ])\n        data = json.loads(response.content)\n        questions = data.get(\"questions\", [])\n        if questions and isinstance(questions, list):\n            return questions\n    except Exception as e:\n        print(f\"[Quiz Generator] LLM call failed during question generation: {e}\")\n\n    # Fallback: one generic question\n    return [{\n        \"question\": f\"In your own words, explain the key concept of {topic} and why it matters.\",\n        \"expected_answer\": \"A clear explanation demonstrating conceptual understanding.\",\n        \"difficulty\": \"medium\",\n    }]\n\n\ndef grade_answer(question: str, expected: str, student_answer: str) -> dict:\n    \"\"\"Grade a student's answer using the LLM as judge.\"\"\"\n    llm = ChatOllama(\n        model=MODEL_NAME,\n        base_url=OLLAMA_BASE_URL,\n        temperature=0.1,   # Analytical: grading must be consistent\n        format=\"json\",\n    )\n\n    prompt = GRADING_PROMPT.format(\n        question=question,\n        expected_answer=expected,\n        student_answer=student_answer,\n    )\n\n    try:\n        response = llm.invoke([HumanMessage(content=prompt)])\n        return json.loads(response.content)\n    except Exception as e:\n        print(f\"[Quiz Generator] LLM call failed during grading: {e}\")\n        return {\n            \"correct\": False,\n            \"score\": 0.5,\n            \"feedback\": \"Could not grade automatically. Please review manually.\",\n            \"missing_concept\": \"\",\n        }\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>run_quiz<\/code> \u0641\u0646\u06a9\u0634\u0646 \u0627\u06cc\u06a9 \u0627\u0646\u0679\u0631\u0627\u06cc\u06a9\u0679\u0648 \u0679\u0631\u0645\u06cc\u0646\u0644 \u0633\u06cc\u0634\u0646 \u06a9\u0648 \u0645\u0631\u0628\u0648\u0637 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 <code>generate_questions<\/code>\u06c1\u0631 \u0633\u0648\u0627\u0644 \u06a9\u0648 \u0637\u0644\u0628\u0627\u0621 \u06a9\u06d2 \u0633\u0627\u0645\u0646\u06d2 \u067e\u06cc\u0634 \u06a9\u0631\u06cc\u06ba \u0628\u0630\u0631\u06cc\u0639\u06c1: <code>input()<\/code>\u062c\u06cc\u0633\u06d2 \u06c1\u06cc \u06c1\u0631 \u062c\u0648\u0627\u0628 \u0622\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0633 \u06a9\u06cc \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 <code>QuizResult<\/code>:<\/p>\n<pre><code class=\"language-python\">def run_quiz(topic: str, explanation: str) -> QuizResult:\n    \"\"\"Run an interactive quiz session in the terminal.\"\"\"\n    print(f\"n{'='*60}\")\n    print(f\"Quiz: {topic}\")\n    print(f\"{'='*60}\")\n    print(\"Answer each question in your own words. Press Enter to submit.n\")\n\n    questions_data = generate_questions(topic, explanation, n=3)\n    graded_questions = []\n    total_score = 0.0\n    weak_areas = []\n\n    for i, q_data in enumerate(questions_data, 1):\n        question_text = q_data[\"question\"]\n        expected = q_data[\"expected_answer\"]\n        difficulty = q_data.get(\"difficulty\", \"medium\")\n\n        print(f\"Question {i} [{difficulty}]: {question_text}\")\n        user_answer = input(\"Your answer: \").strip()\n        if not user_answer:\n            user_answer = \"(no answer provided)\"\n\n        print(\"Grading...\")\n        grade = grade_answer(question_text, expected, user_answer)\n\n        score = float(grade.get(\"score\", 0.0))\n        correct = bool(grade.get(\"correct\", False))\n        feedback = grade.get(\"feedback\", \"\")\n        missing = grade.get(\"missing_concept\", \"\")\n\n        total_score += score\n        status = \"\u2713\" if correct else \"\u2717\"\n        print(f\"{status} Score: {score:.0%}. {feedback}n\")\n\n        if missing:\n            weak_areas.append(missing)\n\n        graded_questions.append(QuizQuestion(\n            question=question_text,\n            expected_answer=expected,\n            user_answer=user_answer,\n            correct=correct,\n            feedback=feedback,\n            score=score,\n        ))\n\n    avg_score = total_score \/ len(questions_data) if questions_data else 0.0\n    correct_count = sum(1 for q in graded_questions if q.correct)\n\n    print(f\"{'='*60}\")\n    print(f\"Quiz complete! Score: {avg_score:.0%} ({correct_count}\/{len(graded_questions)} correct)\")\n    if weak_areas:\n        print(f\"Areas to review: {', '.join(set(weak_areas))}\")\n    print(f\"{'='*60}n\")\n\n    return QuizResult(\n        topic=topic,\n        questions=graded_questions,\n        score=avg_score,\n        weak_areas=list(set(weak_areas)),\n        timestamp=datetime.now(timezone.utc).isoformat(),\n    )\n<\/code><\/pre>\n<p>\u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0646\u0648\u0688 \u0645\u06cc\u0633\u062c \u06c1\u0633\u0679\u0631\u06cc \u0633\u06d2 \u0688\u0633\u06a9\u0631\u067e\u0679\u0631 \u06a9\u0627 \u0622\u0624\u0679 \u067e\u0679 \u0646\u06a9\u0627\u0644\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633\u06d2 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>run_quiz<\/code>. \u0627\u0633 \u06a9\u06d2 \u0628\u0639\u062f \u06c1\u0645 \u0646\u062a\u0627\u0626\u062c \u0627\u0648\u0631 \u06a9\u0645\u0632\u0648\u0631 \u0639\u0644\u0627\u0642\u0648\u06ba \u06a9\u0648 \u0631\u06cc\u0627\u0633\u062a\u0648\u06ba \u0645\u06cc\u06ba \u062c\u0645\u0639 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">def quiz_generator_node(state: dict) -> dict:\n    \"\"\"\n    LangGraph node: Quiz Generator\n\n    Reads:  state[\"roadmap\"], state[\"current_topic_index\"], state[\"messages\"]\n    Writes: state[\"quiz_results\"], state[\"weak_areas\"], state[\"error\"]\n    \"\"\"\n    topic = get_current_topic(state)\n    if topic is None:\n        return {\"error\": \"No current topic. Curriculum Planner must run first\"}\n\n    # Extract the Explainer's final response from message history.\n    # The Explainer's output is the last AIMessage that has no tool_calls.\n    # Tool-calling responses have content too, but they also have tool_calls set.\n    from langchain_core.messages import AIMessage\n    messages = state.get(\"messages\", [])\n    explanation = \"\"\n    for msg in reversed(messages):\n        if isinstance(msg, AIMessage) and msg.content and not getattr(msg, \"tool_calls\", None):\n            explanation = msg.content\n            break\n\n    if not explanation:\n        print(\"[Quiz Generator] Warning: no explanation found, generating generic quiz\")\n        explanation = f\"Topic: {topic.title}. {topic.description}\"\n\n    print(f\"n[Quiz Generator] Generating quiz for: '{topic.title}'\")\n    quiz_result = run_quiz(topic.title, explanation)\n\n    existing_results = state.get(\"quiz_results\", [])\n    all_weak_areas = list(set(\n        state.get(\"weak_areas\", []) + quiz_result.weak_areas\n    ))\n\n    return {\n        \"quiz_results\": existing_results + [quiz_result],\n        \"weak_areas\": all_weak_areas,\n        \"error\": None,\n        # Pass state forward explicitly to preserve it across interrupt\/resume\n        \"roadmap\": state.get(\"roadmap\"),\n        \"current_topic_index\": state.get(\"current_topic_index\", 0),\n        \"session_id\": state.get(\"session_id\", \"\"),\n    }\n<\/code><\/pre>\n<h4 id=\"heading-why-quizresults-accumulates-instead-of-replaces\"> \u06a9\u06cc\u0648\u06ba <code>quiz_results<\/code> \u0628\u062f\u0644\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u062c\u0645\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/h4>\n<p>\u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u06a9\u0648\u0686\u0632 \u06a9\u0648 \u06a9\u0648\u0626\u0632 \u06a9\u06d2 \u0645\u0648\u062c\u0648\u062f\u06c1 \u0646\u062a\u0627\u0626\u062c \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06af\u06cc\u06d4 \u0622\u067e \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0633\u06cc\u0634\u0646 \u06a9\u06d2 \u062e\u0644\u0627\u0635\u06d2 \u0645\u06cc\u06ba \u0627\u0646 \u062a\u0645\u0627\u0645 \u0627\u0634\u06cc\u0627\u0621 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06af\u06cc\u06d4 \u0646\u0648\u0688 \u0627\u06cc\u06a9 \u0645\u0648\u062c\u0648\u062f\u06c1 \u0641\u06c1\u0631\u0633\u062a \u06c1\u06d2 (<code>existing_results + [quiz_result]<\/code>) \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u06d4<\/p>\n<p><code>weak_areas<\/code> \u06cc\u06c1 \u0627\u0633\u06cc \u067e\u06cc\u0679\u0631\u0646 \u06a9\u06cc \u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>set(existing + new)<\/code> \u06c1\u0645 \u062a\u0645\u0627\u0645 \u0645\u0648\u0636\u0648\u0639\u0627\u062a \u0645\u06cc\u06ba \u0646\u0642\u0644 \u06a9\u0648 \u06c1\u0679\u0627 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u06a9\u0645\u0632\u0648\u0631 \u0639\u0644\u0627\u0642\u0648\u06ba \u06a9\u06cc \u062d\u062a\u0645\u06cc \u0641\u06c1\u0631\u0633\u062a \u06c1\u0631 \u0627\u0633 \u0686\u06cc\u0632 \u06a9\u0648 \u06cc\u06a9\u062c\u0627 \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u062c\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0637\u0627\u0644\u0628 \u0639\u0644\u0645 \u0646\u06d2 \u0633\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u062c\u062f\u0648\u062c\u06c1\u062f \u06a9\u06cc\u06d4<\/p>\n<h3 id=\"heading-42-the-progress-coach-synthesis-and-routing\">4.2 \u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u06a9\u0648\u0686: \u062a\u0631\u06a9\u06cc\u0628 \u0627\u0648\u0631 \u0631\u0648\u0679\u0646\u06af<\/h3>\n<p>\u0633\u06c1\u0648\u0644\u062a \u06a9\u0648\u0686 \u062a\u0631\u062a\u06cc\u0628 \u0648\u0627\u0631 \u062a\u06cc\u0646 \u06a9\u0627\u0645 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2: \u06a9\u0648\u0626\u0632 \u06a9\u06d2 \u0646\u062a\u0627\u0626\u062c \u06a9\u0627 \u062c\u0627\u0626\u0632\u06c1 \u0644\u06cc\u0646\u0627\u060c \u0637\u0644\u0628\u0627\u0621 \u06a9\u0648 \u0641\u06cc\u0688 \u0628\u06cc\u06a9 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u0646\u0627\u060c \u0627\u0648\u0631 \u0641\u06cc\u0635\u0644\u06c1 \u06a9\u0631\u0646\u0627 \u06a9\u06c1 \u0622\u06af\u06d2 \u06a9\u06cc\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0631\u0648\u0679\u0646\u06af \u06a9\u06d2 \u0641\u06cc\u0635\u0644\u06d2 (\u0627\u06af\u0644\u06d2 \u0645\u0648\u0636\u0648\u0639 \u067e\u0631 \u0648\u0627\u067e\u0633 \u062c\u0627\u0626\u06cc\u06ba \u06cc\u0627 \u0633\u06cc\u0634\u0646 \u062e\u062a\u0645 \u06a9\u0631\u06cc\u06ba) \u0622\u067e \u06a9\u06cc \u0633\u0628 \u0633\u06d2 \u0627\u06c1\u0645 \u0630\u0645\u06c1 \u062f\u0627\u0631\u06cc\u0627\u06ba \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\"># src\/agents\/progress_coach.py\n\nimport json\nimport os\nfrom datetime import datetime, timezone\n\nfrom langchain_core.messages import AIMessage, HumanMessage, SystemMessage\nfrom langchain_ollama import ChatOllama\n\nfrom graph.state import QuizResult, StudyRoadmap, get_latest_quiz_result\nfrom mcp_servers.memory_server import memory_set\n\nMODEL_NAME = os.getenv(\"OLLAMA_MODEL\", \"qwen2.5:7b\")\nOLLAMA_BASE_URL = os.getenv(\"OLLAMA_BASE_URL\", \"http:\/\/localhost:11434\")\nPASS_THRESHOLD = 0.5\n\nCOACHING_PROMPT = \"\"\"You are an encouraging learning coach reviewing a student's quiz results.\n\nProvide a brief, warm coaching message (2-3 sentences max) based on:\n  - The topic studied\n  - Their score (0.0 = 0%, 1.0 = 100%)\n  - Any weak areas identified\n\nReturn ONLY valid JSON:\n{{\n  \"summary\": \"2-3 sentence encouraging summary\",\n  \"encouragement\": \"One short motivational sentence for next steps\"\n}}\n\nBe specific. Reference the topic and any weak areas by name.\nNever be discouraging. A low score means \"more practice needed\", not \"you failed.\"\n\"\"\"\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>get_coaching_message<\/code> \u0641\u0646\u06a9\u0634\u0646 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u06cc\u06a9 LLM \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>temperature=0.4<\/code> \u0627\u0648\u0631 <code>format=\"json\"<\/code>. \u0631\u062f \u0639\u0645\u0644 \u06a9\u06cc \u06af\u0631\u0645\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0686\u06be \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 <code>temperature=0.1<\/code> \u0627\u06af\u0631\u0686\u06c1 \u062a\u06a9\u0646\u06cc\u06a9\u06cc \u0637\u0648\u0631 \u067e\u0631 \u062f\u0631\u0633\u062a \u06c1\u06d2\u060c \u06cc\u06c1 \u062e\u0634\u06a9 \u0631\u0627\u0626\u06d2 \u067e\u06cc\u062f\u0627 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\">def get_coaching_message(topic: str, score: float, weak_areas: list[str]) -> dict:\n    \"\"\"Ask the LLM for a personalised coaching message.\"\"\"\n    llm = ChatOllama(\n        model=MODEL_NAME,\n        base_url=OLLAMA_BASE_URL,\n        temperature=0.4,\n        format=\"json\",\n    )\n    context = {\n        \"topic\":         topic,\n        \"score_percent\": f\"{score:.0%}\",\n        \"weak_areas\":    weak_areas if weak_areas else [\"none identified\"],\n    }\n    try:\n        response = llm.invoke([\n            SystemMessage(content=COACHING_PROMPT),\n            HumanMessage(content=json.dumps(context)),\n        ])\n        return json.loads(response.content)\n    except Exception as e:\n        print(f\"[Progress Coach] LLM call failed: {e}\")\n        return {\n            \"summary\":      f\"You scored {score:.0%} on {topic}. Keep going!\",\n            \"encouragement\": \"Every topic builds on the last.\",\n        }\n<\/code><\/pre>\n<p>\u0646\u0648\u0688 \u06a9\u06d2 \u0627\u0641\u0639\u0627\u0644 \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u0648 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0628\u0627\u0646\u062f\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06a9\u0648\u0626\u0632 \u06a9\u06d2 \u062a\u0627\u0632\u06c1 \u062a\u0631\u06cc\u0646 \u0646\u062a\u0627\u0626\u062c \u067e\u0691\u06be\u06cc\u06ba\u060c \u0631\u0648\u0688 \u0645\u06cc\u067e \u067e\u0631 \u0645\u0648\u0636\u0648\u0639 \u06a9\u06cc \u062d\u06cc\u062b\u06cc\u062a \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u067e\u0646\u06cc \u067e\u06cc\u0634 \u0631\u0641\u062a \u06a9\u0648 MCP \u0645\u06cc\u0645\u0648\u0631\u06cc \u0645\u06cc\u06ba \u0631\u06a9\u06be\u06cc\u06ba\u060c \u062a\u0627\u062b\u0631\u0627\u062a \u067e\u0631\u0646\u0679 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0679\u0627\u067e\u06a9 \u0627\u0646\u0688\u06cc\u06a9\u0633 \u06a9\u0648 \u0627\u06cc\u0688\u0648\u0627\u0646\u0633 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">def progress_coach_node(state: dict) -> dict:\n    \"\"\"\n    LangGraph node: Progress Coach\n\n    Reads:  state[\"quiz_results\"], state[\"roadmap\"],\n            state[\"current_topic_index\"], state[\"session_id\"]\n    Writes: state[\"roadmap\"], state[\"current_topic_index\"],\n            state[\"messages\"], state[\"error\"]\n    \"\"\"\n    latest = get_latest_quiz_result(state)\n    if latest is None:\n        return {\"error\": \"No quiz results. Quiz Generator must run first\"}\n\n    roadmap = state.get(\"roadmap\")\n    if roadmap is None:\n        return {\"error\": \"No roadmap found\"}\n\n    idx = state.get(\"current_topic_index\", 0)\n    session_id = state.get(\"session_id\", \"unknown\")\n    score = latest.score\n\n    print(f\"n[Progress Coach] Topic: '{latest.topic}'\")\n    print(f\"[Progress Coach] Score: {score:.0%}\")\n    if latest.weak_areas:\n        print(f\"[Progress Coach] Weak areas: {', '.join(latest.weak_areas)}\")\n\n    # Get coaching message from LLM\n    coaching = get_coaching_message(latest.topic, score, latest.weak_areas)\n\n    # Update topic status in the roadmap\n    topics = roadmap.get(\"topics\", []) if isinstance(roadmap, dict) else roadmap.topics\n    if idx < len(topics):\n        topic = topics[idx]\n        new_status = \"completed\" if score >= PASS_THRESHOLD else \"needs_review\"\n        if isinstance(topic, dict):\n            topic[\"status\"] = new_status\n        else:\n            topic.status = new_status\n\n    # Advance the topic index\n    next_idx = idx + 1\n    all_done = next_idx >= len(topics)\n\n    # Persist progress to MCP memory\n    memory_set(session_id, f\"progress_topic_{idx}\", json.dumps({\n        \"topic\":      latest.topic,\n        \"score\":      score,\n        \"weak_areas\": latest.weak_areas,\n        \"timestamp\":  datetime.now(timezone.utc).isoformat(),\n    }))\n\n    # Print coaching feedback\n    print(f\"n{'\u2500'*60}\")\n    print(f\"Coach: {coaching['summary']}\")\n    print(f\"{coaching['encouragement']}\")\n\n    if all_done:\n        results = state.get(\"quiz_results\", [])\n        avg = sum(r.score for r in results) \/ max(len(results), 1)\n        print(f\"nSession complete! Average: {avg:.0%}\")\n    else:\n        next_topic = topics[next_idx]\n        next_title = next_topic.get(\"title\") if isinstance(next_topic, dict) else next_topic.title\n        print(f\"nNext topic: '{next_title}'\")\n    print(f\"{'\u2500'*60}n\")\n\n    return {\n        \"roadmap\":              roadmap,\n        \"current_topic_index\":  next_idx,\n        \"messages\":             [AIMessage(content=coaching[\"summary\"])],\n        \"error\":                None,\n    }\n<\/code><\/pre>\n<p>\u0627\u0633 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0633\u0645\u062c\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0648 \u0686\u06cc\u0632\u06cc\u06ba \u06c1\u06cc\u06ba:<\/p>\n<p><strong>\u0627\u0646\u0688\u06cc\u06a9\u0633 \u06a9\u0648 \u0622\u06af\u06d2 \u0628\u0691\u06be\u0627\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0645\u0648\u0636\u0648\u0639 \u06a9\u06cc \u062d\u06cc\u062b\u06cc\u062a \u06a9\u0648 \u06a9\u06cc\u0648\u06ba \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u061f<\/strong> \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0631\u06cc\u0627\u0633\u062a \u0628\u062f\u0644\u062a\u06cc \u06c1\u06d2 (<code>\"pending\"<\/code> \u06a9\u0648 <code>\"completed\"<\/code> \u06cc\u0627 <code>\"needs_review\"<\/code>) \u062f\u0631\u062c \u0630\u06cc\u0644 \u0627\u0648\u0642\u0627\u062a \u0645\u06cc\u06ba \u06c1\u0648\u0646\u0627 \u0636\u0631\u0648\u0631\u06cc \u06c1\u06d2: <code>topics[idx]<\/code>\u0646\u06c1\u06cc\u06ba <code>topics[next_idx]<\/code>. \u0627\u0646\u0688\u06cc\u06a9\u0633 \u0628\u0691\u06be\u062a\u0627 \u06c1\u06d2\u06d4 <em>~ \u0628\u0639\u062f<\/em> \u06c1\u0645 \u0641\u06cc \u0627\u0644\u062d\u0627\u0644 \u0645\u0648\u0636\u0648\u0639 \u06a9\u06cc \u062d\u06cc\u062b\u06cc\u062a \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u0633 \u0622\u0631\u0688\u0631 \u06a9\u0648 \u063a\u0644\u0637 \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u0622\u067e \u06a9\u0648 \u063a\u0644\u0637 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u0646\u0638\u0631 \u0622\u0626\u06cc\u06ba \u06af\u06d2\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0644\u0637\u06cc\u0641 \u0628\u06af \u06c1\u06d2 \u062c\u0633\u06d2 \u06cc\u0627\u062f \u06a9\u0631\u0646\u0627 \u0622\u0633\u0627\u0646 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0633\u06cc\u0634\u0646 \u0627\u0628 \u0628\u06be\u06cc \u0646\u0645\u0627\u06cc\u0627\u06ba \u0637\u0648\u0631 \u067e\u0631 \u0635\u062d\u06cc\u062d \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><strong>MCP \u0645\u06cc\u0645\u0648\u0631\u06cc \u067e\u0631 \u06a9\u06cc\u0648\u06ba \u0644\u06a9\u06be\u06cc\u06ba\u061f<\/strong> \u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u06a9\u0648\u0686 \u06c1\u0631 \u0639\u0646\u0648\u0627\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0646\u062a\u0627\u0626\u062c \u06a9\u0648 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2: <code>memory_set<\/code>. \u06cc\u06c1 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u06a9\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06d2 \u0645\u0639\u0627\u0645\u0644\u0627\u062a \u0645\u06cc\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0628 \u06a9\u0648\u0626\u06cc \u0633\u06cc\u0634\u0646 \u06a9\u0631\u06cc\u0634 \u06cc\u0627 \u062a\u0648\u0642\u0641 \u06a9\u06d2 \u0628\u0639\u062f \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0645\u06cc\u0645\u0648\u0631\u06cc \u0633\u0631\u0648\u0631 \u06a9\u06d2 \u067e\u0627\u0633 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0627 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06a9\u06cc\u0627 \u0627\u062d\u0627\u0637\u06c1 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627 \u0627\u0648\u0631 \u0637\u0644\u0628\u0627\u0621 \u0646\u06d2 \u06a9\u06cc\u0633\u06cc \u06a9\u0627\u0631\u06a9\u0631\u062f\u06af\u06cc \u06a9\u0627 \u0645\u0638\u0627\u06c1\u0631\u06c1 \u06a9\u06cc\u0627\u06d4 \u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06af\u0627\u0646 \u0627\u0633 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u0648 \u0628\u0630\u0631\u06cc\u0639\u06c1 \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba: <code>tool_memory_get<\/code> \u0628\u0639\u062f \u06a9\u06d2 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a\u060c \u0637\u0627\u0644\u0628 \u0639\u0644\u0645 \u06a9\u0648 \u06a9\u0633 \u0686\u06cc\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u0634\u06a9\u0644\u0627\u062a \u06a9\u0627 \u0633\u0627\u0645\u0646\u0627 \u06c1\u06d2 \u0627\u0633 \u067e\u0631 \u0627\u0646\u062d\u0635\u0627\u0631 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0632\u0648\u0631 \u06a9\u0648 \u0627\u06cc\u0688\u062c\u0633\u0679 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-43-wiring-the-complete-graph\">4.3 \u067e\u0648\u0631\u06d2 \u06af\u0631\u0627\u0641 \u06a9\u0648 \u062c\u0648\u0691\u0646\u0627<\/h3>\n<p>\u0627\u06cc\u06a9 \u0628\u0627\u0631 \u062c\u0628 \u062a\u0645\u0627\u0645 \u0686\u0627\u0631 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u06cc \u062a\u0639\u0631\u06cc\u0641 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4 <code>workflow.py<\/code> \u0627\u0633\u06d2 \u0645\u062c\u0645\u0648\u0639\u06cc \u06af\u0631\u0627\u0641 \u0633\u06d2 \u0645\u0631\u0628\u0648\u0637 \u06a9\u0631\u06cc\u06ba\u06d4 \u0648\u0627\u0626\u0631\u0646\u06af \u062e\u0648\u062f \u0633\u0633\u0679\u0645 \u06a9\u06cc \u0645\u062e\u062a\u0635\u0631 \u062a\u0631\u06cc\u0646 \u0641\u0627\u0626\u0644 \u06c1\u06d2\u06d4 \u0627\u0646 \u0645\u06cc\u06ba \u0633\u06d2 \u062a\u0642\u0631\u06cc\u0628\u0627\u064b \u0633\u0628\u06be\u06cc 50 \u0644\u0627\u0626\u0646\u0648\u06ba \u0633\u06d2 \u06a9\u0645 \u06c1\u06cc\u06ba\u06d4 <code>add_node<\/code>\u060c <code>add_edge<\/code>\u0627\u0648\u0631 <code>add_conditional_edges<\/code> \u0641\u0648\u0646 \u06a9\u0627\u0644<\/p>\n<pre><code class=\"language-python\"># src\/graph\/workflow.py\n\nimport os\nimport sqlite3\nfrom pathlib import Path\n\nfrom langgraph.checkpoint.sqlite import SqliteSaver\nfrom langgraph.graph import END, START, StateGraph\n\nfrom agents.curriculum_planner import curriculum_planner_node\nfrom agents.explainer import explainer_node\nfrom agents.human_approval import human_approval_node\nfrom agents.progress_coach import progress_coach_node\nfrom agents.quiz_generator import quiz_generator_node\nfrom graph.state import AgentState, session_is_complete\n\n\ndef route_after_approval(state: dict) -> str:\n    if state.get(\"approved\", False):\n        return \"explainer\"\n    return \"curriculum_planner\"\n\n\ndef route_after_coach(state: dict) -> str:\n    if session_is_complete(state):\n        return \"end\"\n    return \"explainer\"\n\n\ndef build_graph(\n    db_path: str = \"data\/checkpoints.db\",\n    interrupt_before: list | None = None,\n):\n    \"\"\"\n    Build and compile the Learning Accelerator graph.\n\n    Args:\n        db_path:          Path to the SQLite checkpoint database.\n        interrupt_before: Optional list of node names to pause before.\n                          Used by the Streamlit UI to intercept quiz_generator.\n    \"\"\"\n    Path(\"data\").mkdir(exist_ok=True)\n    if db_path == \"data\/checkpoints.db\":\n        db_path = os.getenv(\"CHECKPOINT_DB\", db_path)\n\n    builder = StateGraph(AgentState)\n\n    builder.add_node(\"curriculum_planner\", curriculum_planner_node)\n    builder.add_node(\"human_approval\",     human_approval_node)\n    builder.add_node(\"explainer\",          explainer_node)\n    builder.add_node(\"quiz_generator\",     quiz_generator_node)\n    builder.add_node(\"progress_coach\",     progress_coach_node)\n\n    builder.add_edge(START, \"curriculum_planner\")\n    builder.add_edge(\"curriculum_planner\", \"human_approval\")\n    builder.add_edge(\"explainer\",          \"quiz_generator\")\n    builder.add_edge(\"quiz_generator\",     \"progress_coach\")\n\n    builder.add_conditional_edges(\n        \"human_approval\",\n        route_after_approval,\n        {\"explainer\": \"explainer\", \"curriculum_planner\": \"curriculum_planner\"},\n    )\n    builder.add_conditional_edges(\n        \"progress_coach\",\n        route_after_coach,\n        {\"explainer\": \"explainer\", \"end\": END},\n    )\n\n    # CRITICAL: Create the connection directly. Do NOT use a context manager.\n    # The connection must stay open for the process lifetime.\n    # SqliteSaver requires check_same_thread=False because LangGraph runs\n    # node functions and checkpoint writes on different threads.\n    conn = sqlite3.connect(db_path, check_same_thread=False)\n    checkpointer = SqliteSaver(conn)\n\n    return builder.compile(\n        checkpointer=checkpointer,\n        interrupt_before=interrupt_before or [],\n    )\n\n\ngraph = build_graph()\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>interrupt_before<\/code> \u067e\u06cc\u0631\u0627\u0645\u06cc\u0679\u0631\u0632 \u06cc\u06c1\u0627\u06ba \u0642\u0631\u06cc\u0628 \u0633\u06d2 \u062f\u06cc\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06cc\u06ba\u06d4 \u0679\u0631\u0645\u06cc\u0646\u0644 \u0627\u0646\u0679\u0631\u0641\u06cc\u0633 (<code>main.py<\/code>) \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>interrupt()<\/code> \u0627\u0646\u062f\u0631 <code>human_approval_node<\/code> \u0631\u0648\u0688 \u0645\u06cc\u067e \u06a9\u06cc \u0645\u0646\u0638\u0648\u0631\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u0648\u0642\u0641\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4 \u0646\u06c1\u06cc\u06ba <code>interrupt_before<\/code> \u0622\u067e \u06a9\u0648 \u0627\u0633 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4<\/p>\n<p>Streamlit UI (\u0628\u0627\u0628 9) \u06a9\u0648 \u0645\u062e\u062a\u0644\u0641 \u0642\u0633\u0645 \u06a9\u06d2 \u062a\u0648\u0642\u0641 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 <code>quiz_generator_node<\/code> \u0627\u0633 \u0637\u0631\u062d \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4 <code>input()<\/code> \u0627\u0633\u06d2 \u06af\u0631\u0627\u0641 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0646\u06c1\u06cc\u06ba \u06a9\u06c1\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u06c1 <code>build_graph(interrupt_before=[\"quiz_generator\"])<\/code> \u06a9\u0627\u0644 <code>streamlit_app.py<\/code> UI \u06a9\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u06a9\u0631\u062f\u06c1 \u0627\u06cc\u06a9 \u0627\u0644\u06af \u06af\u0631\u0627\u0641 \u0645\u062b\u0627\u0644 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<p>\u0679\u0631\u0645\u06cc\u0646\u0644 \u06af\u0631\u0627\u0641 \u0627\u0648\u0631 UI \u06af\u0631\u0627\u0641 \u0627\u06cc\u06a9 \u06c1\u06cc \u0628\u0644\u0688\u0631 \u0633\u06d2 \u0645\u0631\u062a\u0628 \u06a9\u06cc\u06d2 \u06af\u0626\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0635\u0631\u0641 \u062a\u0648\u0642\u0641 \u06a9\u0627 \u0646\u0642\u0637\u06c1 \u0645\u062e\u062a\u0644\u0641 \u06c1\u06d2\u06d4<\/p>\n<p>\u0631\u0648\u0679\u0646\u06af \u0641\u0646\u06a9\u0634\u0646 \u062e\u0627\u0644\u0635 \u0627\u0632\u06af\u0631 \u06c1\u06d2 \u062c\u0633 \u0645\u06cc\u06ba \u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u0627\u0644\u0632 \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 <code>route_after_approval<\/code> \u067e\u0691\u06be\u06cc\u06ba <code>state[\"approved\"]<\/code>\u0627\u0646\u0633\u0627\u0646\u06cc \u0645\u0646\u0638\u0648\u0631\u06cc \u06a9\u06d2 \u0646\u0648\u0688\u0633 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0628\u0648\u0644\u06cc\u0646\u06d4 <code>route_after_coach<\/code> \u0641\u0648\u0646 \u06a9\u0627\u0644 <code>session_is_complete(state)<\/code>\u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u0626\u06cc\u06ba \u06a9\u06c1 \u0633\u0628\u062c\u06cc\u06a9\u0679 \u0627\u0646\u0688\u06cc\u06a9\u0633 \u0631\u0648\u0688 \u0645\u06cc\u067e \u0633\u06d2 \u0622\u06af\u06d2 \u0628\u0691\u06be\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0645\u0627\u0645 \u06a9\u0646\u0679\u0631\u0648\u0644 \u0641\u0644\u0648 \u0633\u0679\u0627\u06a9\u0633\u0679\u06a9 LLM \u0622\u0624\u0679 \u067e\u0679 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 deterministic Python \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-44-the-complete-execution-flow\">4.4 \u0645\u062c\u0645\u0648\u0639\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0639\u0645\u0644\u062f\u0631\u0622\u0645\u062f \u06a9\u0627 \u0628\u06c1\u0627\u0624<\/h3>\n<p>\u062c\u0628 \u0622\u067e \u0627\u0633\u06d2 \u0686\u0644\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u062f\u0631\u062c \u0630\u06cc\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2: <code>python main.py \"Learn Python closures\"<\/code> \u0627\u0648\u0631 \u0679\u0627\u0626\u067e \u06a9\u0631\u06cc\u06ba\u06d4 <code>yes<\/code> \u0645\u0646\u0638\u0648\u0631\u06cc \u06a9\u06d2 \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631:<\/p>\n<pre><code class=\"language-plaintext\">START\n  \u2193\ncurriculum_planner_node\n  reads:  state[\"goal\"]\n  writes: state[\"roadmap\"], state[\"messages\"]\n  \u2193\nhuman_approval_node\n  interrupt() pauses here. Waits for user input.\n  user types \"yes\"\n  writes: state[\"approved\"] = True + full state forward\n  \u2193  route_after_approval \u2192 \"explainer\"\nexplainer_node (topic 0)\n  reads:  state[\"roadmap\"], state[\"current_topic_index\"]\n  calls:  tool_list_files, tool_search_notes, tool_read_file\n  writes: state[\"messages\"]\n  \u2193\nquiz_generator_node (topic 0)\n  reads:  state[\"messages\"] (extracts explanation)\n  calls:  run_quiz() \u2192 3 questions, 3 graded answers\n  writes: state[\"quiz_results\"], state[\"weak_areas\"]\n  \u2193\nprogress_coach_node (topic 0)\n  reads:  state[\"quiz_results\"], state[\"roadmap\"]\n  writes: state[\"roadmap\"] (topic 0 status updated)\n          state[\"current_topic_index\"] = 1\n          state[\"messages\"] (coaching message)\n  \u2193  route_after_coach \u2192 \"explainer\" (more topics remain)\nexplainer_node (topic 1)\n  ...\n  \u2193\n  [loop continues until current_topic_index >= len(roadmap.topics)]\n  \u2193  route_after_coach \u2192 \"end\"\nEND\n<\/code><\/pre>\n<p>\u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0686\u0648\u06a9\u06cc\u0627\u06ba \u06c1\u0631 \u0646\u0648\u0688 \u06a9\u06d2 \u0628\u0639\u062f \u0631\u06cc\u0627\u0633\u062a \u06a9\u06cc \u0646\u0645\u0627\u0626\u0646\u062f\u06af\u06cc \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u0639\u0645\u0644 \u0622\u067e\u0633 \u0645\u06cc\u06ba \u0645\u062a\u0635\u0627\u062f\u0645 \u06c1\u0648\u06d4 <code>quiz_generator_node<\/code> \u0627\u0648\u0631 <code>progress_coach_node<\/code>\u0627\u06af\u0644\u0627 <code>graph.invoke(None, config=config)<\/code> \u0627\u0633\u06d2 \u0627\u0633\u06cc \u0633\u06cc\u0634\u0646 ID \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u06af\u0644\u0627 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 <code>progress_coach_node<\/code>. \u06a9\u0648\u0626\u0632 \u06a9\u06d2 \u0646\u062a\u0627\u0626\u062c \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u062c\u0627\u0631\u06cc \u06c1\u0648 \u0686\u06a9\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-45-run-the-complete-system\">4.5 \u067e\u0648\u0631\u06d2 \u0646\u0638\u0627\u0645 \u06a9\u0648 \u0686\u0644\u0627\u0646\u0627<\/h3>\n<p>\u0627\u06af\u0631 \u0686\u0627\u0631\u0648\u06ba \u0646\u0648\u0688\u0633 \u0631\u062c\u0633\u0679\u0631\u0688 \u06c1\u06cc\u06ba:<\/p>\n<pre><code class=\"language-bash\">rm -f data\/checkpoints.db\npython main.py \"Learn Python closures and decorators from scratch\"\n<\/code><\/pre>\n<p>\u0622\u067e \u0645\u0646\u0635\u0648\u0628\u06c1 \u0633\u0627\u0632\u060c \u0645\u0646\u0638\u0648\u0631\u06cc \u06a9\u06d2 \u0627\u0634\u0627\u0631\u06d2\u060c \u0627\u0648\u0631 \u067e\u0648\u0631\u0627 \u0644\u0648\u067e \u062f\u06cc\u06a9\u06be\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<pre><code class=\"language-plaintext\">[Curriculum Planner] Building roadmap for: 'Learn Python closures...'\n[Curriculum Planner] Created roadmap: 5 topics, 4 weeks\n  1. Python Functions (60 min)\n  2. Scopes and Namespaces (45 min)\n  3. Inner Functions (60 min)\n  4. Creating Closures (75 min)\n  5. Decorator Basics (60 min)\n\n[Human Approval] Pausing for roadmap review...\n> yes\n[Human Approval] Roadmap approved. Starting study session.\n\n[Explainer] Topic: 'Python Functions'\n[Explainer] LLM call 1\/8...\n  \u2192 tool_list_files({})\n    \u2190 [\"closures.md\", \"decorators.md\", \"python_basics.md\"]\n[Explainer] LLM call 2\/8...\n  \u2192 tool_read_file({'filename': 'python_basics.md'})\n    \u2190 # Python Basics...\n[Explainer] Complete after 4 LLM call(s)\n[Explainer] Explanation: 1938 characters\n\n[Quiz Generator] Generating quiz for: 'Python Functions'\n\n============================================================\nQuiz: Python Functions\n============================================================\nQuestion 1 [medium]: What is the difference between...\nYour answer: Functions are first-class objects...\nGrading...\n\u2713 Score: 80%. Good explanation of first-class functions.\n\n...\n\n[Progress Coach] Topic: 'Python Functions'\n[Progress Coach] Score: 73%\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nCoach: You have a solid grasp of Python functions, especially...\nKeep building on this foundation as you move into closures!\n\nNext topic: 'Scopes and Namespaces'\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n[Explainer] Topic: 'Scopes and Namespaces'\n...\n<\/code><\/pre>\n<p>\u0644\u0648\u067e \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0628 <code>progress_coach_node<\/code> \u0644\u06a9\u06be\u0646\u0627 <code>current_topic_index = 1<\/code>\u060c <code>route_after_coach<\/code> \u0631\u067e\u0648\u0631\u0679 <code>\"explainer\"<\/code>\u06af\u0631\u0627\u0641 \u06a9\u0627\u0644 <code>explainer_node<\/code> \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u062f\u06c1 \u0627\u0646\u0688\u06cc\u06a9\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u0648\u0626\u06cc \u0628\u06cc\u0631\u0648\u0646\u06cc \u0644\u0648\u067e \u0646\u06c1\u06cc\u06ba\u06d4 <code>main.py<\/code>. \u06af\u0631\u0627\u0641 \u0679\u0648\u067e\u0648\u0644\u0648\u062c\u06cc \u062a\u06a9\u0631\u0627\u0631 \u06a9\u0648 \u0633\u0646\u0628\u06be\u0627\u0644\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p> <strong>\u0686\u0648\u06a9\u06cc:<\/strong> \u067e\u0648\u0631\u06d2 \u0679\u06cc\u0633\u0679 \u0633\u0648\u06cc\u0679 \u06a9\u0648 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">pytest tests\/ -v\n<\/code><\/pre>\n<p>\u0645\u062a\u0648\u0642\u0639: 184 \u0679\u06cc\u0633\u0679 \u0627\u06a9\u0679\u06be\u06d2 \u06a9\u06cc\u06d2 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2 \u0627\u0648\u0631 \u062a\u0634\u062e\u06cc\u0635\u06cc \u0679\u06cc\u0633\u0679 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u063a\u06cc\u0631 \u0645\u0646\u062a\u062e\u0628 \u06c1\u0648 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2\u06d4 \u06cc\u0648\u0646\u0679 \u0679\u06cc\u0633\u0679 \u0627\u0648\u0644\u0627\u0645\u0627 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u06a9\u0648\u0626\u0632 \u0627\u0648\u0631 \u06a9\u0648\u0686 \u0646\u0648\u0688\u0633 \u06a9\u0627 \u0627\u062d\u0627\u0637\u06c1 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">pytest tests\/test_quiz_and_coach.py -v\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u0679\u06cc\u0633\u0679 LLM \u06a9\u0627\u0644 \u06a9\u06cc \u0646\u0642\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0631\u06cc\u0627\u0633\u062a\u06cc \u0645\u0639\u0627\u06c1\u062f\u06d2 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>quiz_results<\/code> \u0635\u062d\u06cc\u062d \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u062c\u0645\u0639 <code>current_topic_index<\/code> \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u0631\u0648\u0679\u0646\u06af \u0641\u0646\u06a9\u0634\u0646 \u062f\u0631\u0633\u062a \u0633\u0679\u0631\u0646\u06af \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06af\u0644\u06d2 \u0628\u0627\u0628 \u0645\u06cc\u06ba\u060c \u06c1\u0645 \u062f\u0648 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u067e\u0631 \u06af\u06c1\u0631\u06cc \u0646\u0638\u0631 \u0688\u0627\u0644\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u0628\u0627\u0628 2 \u06a9\u06d2 \u0628\u0639\u062f \u0633\u06d2 \u062e\u0627\u0645\u0648\u0634\u06cc \u0633\u06d2 \u06a9\u0627\u0645 \u06a9\u0631 \u0631\u06c1\u06cc \u06c1\u06cc\u06ba: \u0631\u06cc\u0627\u0633\u062a \u06a9\u06cc \u0627\u0633\u062a\u0642\u0627\u0645\u062a\u060c \u062c\u0648 \u062a\u0635\u0627\u062f\u0645 \u0633\u06d2 \u0628\u0686 \u062c\u0627\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u0646\u0633\u0627\u0646\u06cc \u0634\u0631\u0627\u06a9\u062a \u062f\u0627\u0631 \u0646\u06af\u0631\u0627\u0646\u06cc\u060c \u062c\u0648 \u0627\u0639\u062a\u0631\u0627\u0641 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06af\u0631\u0627\u0641 \u06a9\u0648 \u0631\u0648\u06a9\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u0635\u0627\u0631\u0641 \u06a9\u06d2 \u062c\u0648\u0627\u0628 \u062f\u06cc\u0646\u06d2 \u067e\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-chapter-5-state-persistence-and-human-oversight\">\u0628\u0627\u0628 5: \u0631\u06cc\u0627\u0633\u062a \u06a9\u06cc \u067e\u0627\u0626\u06cc\u062f\u0627\u0631\u06cc \u0627\u0648\u0631 \u0627\u0646\u0633\u0627\u0646\u06cc \u0646\u06af\u0631\u0627\u0646\u06cc<\/h2>\n<p>\u0628\u0627\u0628 2 \u06a9\u06d2 \u0628\u0639\u062f \u067e\u0633 \u0645\u0646\u0638\u0631 \u0645\u06cc\u06ba \u062f\u0648 \u0645\u0633\u0627\u0626\u0644 \u062e\u0627\u0645\u0648\u0634\u06cc \u0633\u06d2 \u062d\u0644 \u06c1\u0648 \u06af\u0626\u06d2\u06d4 \u0646\u0638\u0627\u0645 \u06a9\u0631\u06cc\u0634\u0648\u06ba \u0633\u06d2 \u0628\u0686 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0646\u0633\u0627\u0646\u06cc \u0641\u06cc\u0635\u0644\u0648\u06ba \u06a9\u0627 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646\u06cc \u0639\u0645\u0644 \u06a9\u0648 \u0631\u0648\u06a9 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0628\u0627\u0628 \u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631 \u062f\u0648\u0646\u0648\u06ba \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0633\u0645\u062c\u06be\u0646\u0627 \u0648\u06c1\u06cc \u06c1\u06d2 \u062c\u0648 \u0688\u06cc\u0645\u0648 \u06a9\u0648 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0633\u0633\u0679\u0645 \u0633\u06d2 \u0627\u0644\u06af \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-51-what-checkpointing-actually-does\">5.1 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679\u0633 \u062f\u0631\u0627\u0635\u0644 \u06a9\u06cc\u0627 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/h3>\n<p>\u062c\u0628 \u0628\u06be\u06cc \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0646\u0648\u0688 \u0645\u06a9\u0645\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u067e\u0648\u0631\u06d2 \u0646\u0648\u0688 \u06a9\u0648 \u0633\u06cc\u0631\u06cc\u0644\u0627\u0626\u0632 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>AgentState<\/code> \u0645\u06cc\u06ba \u0627\u0633\u06d2 SQLite \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u0648\u06ba \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0646\u06cc\u0686\u06d2 \u0644\u06a9\u06be\u062a\u0627 \u06c1\u0648\u06ba\u06d4 <code>thread_id<\/code>. \u0648\u06c1 \u062a\u06be\u0631\u06cc\u0688 \u0622\u0626\u06cc \u0688\u06cc \u0633\u06cc\u0634\u0646 \u0622\u0626\u06cc \u0688\u06cc \u06c1\u06d2 \u062c\u0648 \u0622\u063a\u0627\u0632 \u067e\u0631 \u0628\u0646\u0627\u0626\u06cc \u06af\u0626\u06cc \u062a\u06be\u06cc\u06d4 <code>run_session<\/code>.<\/p>\n<p>\u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06a9\u0627 \u0688\u06be\u0627\u0646\u0686\u06c1 \u0622\u0633\u0627\u0646 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-plaintext\">data\/checkpoints.db\n  \u2514\u2500\u2500 checkpoints table\n        thread_id = \"a3f1b2c4\"   \u2190 your session ID\n        checkpoint blob           \u2190 serialized AgentState after each node\n<\/code><\/pre>\n<p>\u0641\u06cc \u0633\u06cc\u0634\u0646 \u0627\u06cc\u06a9 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679\u0633 \u062c\u0645\u0639 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u06c1\u0631 \u0646\u0648\u0688 \u06a9\u06d2 \u0628\u0639\u062f \u0627\u06cc\u06a9\u06d4 LangGraph \u06c1\u0645\u06cc\u0634\u06c1 \u062a\u0627\u0632\u06c1 \u062a\u0631\u06cc\u0646 \u0645\u0639\u0644\u0648\u0645\u0627\u062a \u0644\u0648\u0688 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0628 \u0622\u067e \u06a9\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>graph.invoke(None, config={\"configurable\": {\"thread_id\": \"a3f1b2c4\"}})<\/code>\u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0627\u0633 \u062a\u06be\u0631\u06cc\u0688 \u0622\u0626\u06cc \u0688\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u062d\u0627\u0644\u06cc\u06c1 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u0648 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0648\u06c1\u0627\u06ba \u0633\u06d2 \u0627\u0646\u062a\u062e\u0627\u0628 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u06c1 <code>get_langfuse_config<\/code> \u0641\u0646\u06a9\u0634\u0646 <code>src\/observability\/langfuse_setup.py<\/code> \u062a\u06be\u0631\u06cc\u0688 \u0622\u0626\u06cc \u0688\u06cc \u06a9\u0648 \u067e\u0627\u0633 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u06cc\u06a9 \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0644\u063a\u062a \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">def get_langfuse_config(session_id: str) -> dict:\n    \"\"\"\n    Build the graph run config with session ID as the checkpoint thread ID.\n\n    The config is passed to graph.invoke() on every call: both the initial\n    invocation and any subsequent resume calls. LangGraph uses the thread_id\n    to find and load the right checkpoint.\n    \"\"\"\n    config = {\n        \"configurable\": {\n            \"thread_id\": session_id,\n        }\n    }\n    # If Langfuse is configured, callbacks are added here (Chapter 6)\n    handler = get_langfuse_handler(session_id)\n    if handler:\n        config[\"callbacks\"] = [handler]\n    return config\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u06a9\u0627 \u0648\u0627\u062d\u062f \u0679\u06a9\u0691\u0627 \u06c1\u06d2 \u062c\u0648 \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u0648 \u062c\u0648\u0691\u062a\u0627 \u06c1\u06d2\u06d4 <code>graph.invoke<\/code> \u0627\u0633\u06cc \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u06d2 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u06cc\u0634\u0646 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<h4 id=\"heading-the-sqlitesaver-connection-pattern\"> SqliteSaver \u06a9\u0646\u06a9\u0634\u0646 \u067e\u06cc\u0679\u0631\u0646<\/h4>\n<p>SqliteSaver \u06a9\u0648 \u062f\u0648 \u0637\u0631\u06cc\u0642\u0648\u06ba \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2: \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u0645\u06cc\u0646\u06cc\u062c\u0631 \u0641\u0627\u0631\u0645 (<code>with SqliteSaver.from_conn_string(...) as checkpointer<\/code>) \u062f\u0631\u062c \u0630\u06cc\u0644 \u0635\u0648\u0631\u062a\u0648\u06ba \u0645\u06cc\u06ba \u06a9\u0646\u06a9\u0634\u0646 \u0628\u0646\u062f \u06a9\u0631\u06cc\u06ba: <code>with<\/code> \u0628\u0644\u0627\u06a9 \u062e\u062a\u0645 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0633\u06d2 <code>graph = build_graph()<\/code> \u06cc\u06c1 \u0645\u0627\u0688\u06cc\u0648\u0644 \u0633\u0637\u062d \u06a9\u06d2 \u0645\u062a\u063a\u06cc\u0631 \u06c1\u06cc\u06ba \u062c\u0648 \u067e\u0648\u0631\u06d2 \u0639\u0645\u0644 \u067e\u0631 \u0644\u0627\u06af\u0648 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>with<\/code> \u0628\u0644\u0627\u06a9 \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0646\u06a9\u0634\u0646 \u0628\u0646\u062f \u06a9\u0631 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 <code>build_graph()<\/code> \u0631\u067e\u0648\u0631\u0679 \u0633\u0628 \u06a9\u0686\u06be \u06a9\u06d2 \u0628\u0639\u062f <code>graph.invoke<\/code> \u0627\u06af\u0631 \u0622\u067e \u0628\u0646\u062f \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u067e\u0631 \u0644\u06a9\u06be\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u06a9\u0627\u0644 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u06cc\u06d4<\/p>\n<p>\u0635\u062d\u06cc\u062d \u0646\u0645\u0648\u0646\u06c1 \u06c1\u06d2\u06d4 <code>conn = sqlite3.connect(db_path, check_same_thread=False)<\/code> \u067e\u06be\u0631 <code>checkpointer = SqliteSaver(conn)<\/code>. \u06a9\u0646\u06a9\u0634\u0646 \u0639\u0645\u0644 \u06a9\u06cc \u0632\u0646\u062f\u06af\u06cc \u0628\u06be\u0631 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u06be\u0644\u0627 \u0631\u06c1\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u06c1 <code>check_same_thread=False<\/code> \u0627\u06cc\u06a9 \u062c\u06be\u0646\u0688\u0627 \u062f\u0631\u06a9\u0627\u0631 \u06c1\u06d2\u06d4 SQLite \u06a9\u0627 \u0688\u06cc\u0641\u0627\u0644\u0679 \u0627\u06cc\u06a9 \u062a\u06be\u0631\u06cc\u0688 \u0645\u06cc\u06ba \u0628\u0646\u0627\u0626\u06d2 \u06af\u0626\u06d2 \u06a9\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u062f\u0648\u0633\u0631\u06d2 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0633\u06d2 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0646\u0648\u0688 \u06a9\u06d2 \u0627\u0641\u0639\u0627\u0644 \u06a9\u0648 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u0637\u0648\u0631 \u067e\u0631 \u062f\u0648\u0633\u0631\u06d2 \u062f\u06be\u0627\u06af\u0648\u06ba \u067e\u0631 \u0686\u0648\u06a9\u06cc\u0627\u06ba \u0644\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u062c\u06be\u0646\u0688\u06d2 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u0622\u067e \u06a9\u0648 \u0645\u0644\u062a\u0627 \u06c1\u06d2: <code>ProgrammingError: SQLite objects created in a thread can only be used in that same thread<\/code> \u0631\u0646 \u0679\u0627\u0626\u0645 \u067e\u0631\u06d4<\/p>\n<h3 id=\"heading-52-the-human-approval-node-interrupt-and-resume\">5.2 \u0627\u0646\u0633\u0627\u0646\u06cc \u0645\u0646\u0638\u0648\u0631\u06cc \u06a9\u06d2 \u0646\u0648\u0688\u0633: \u0645\u0639\u0637\u0644 \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0627\u0646\u0633\u0627\u0646\u06cc \u0645\u0646\u0638\u0648\u0631\u06cc \u0646\u0648\u0688\u0633 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644: <code>interrupt()<\/code> \u0639\u0645\u0644 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u06af\u0631\u0627\u0641 \u06a9\u0648 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u0637\u0631\u062d \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u06c1\u06cc\u0648\u0645\u0646-\u0627\u0646-\u062f\u06cc-\u0644\u0648\u067e \u06a9\u0648 \u0646\u0627\u0641\u0630 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0646\u0648\u0688 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0639\u0645\u0644\u062f\u0631\u0622\u0645\u062f \u0631\u0648\u06a9 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0633 \u06a9\u06cc \u062d\u0627\u0644\u062a \u06a9\u06cc \u062c\u0627\u0646\u0686 \u067e\u0691\u062a\u0627\u0644 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 \u06a9\u0646\u0679\u0631\u0648\u0644 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u0648 \u0648\u0627\u067e\u0633 \u06a9\u0631 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2. \u062c\u0628 \u062f\u0648\u0633\u0631\u0627 \u0641\u0631\u06cc\u0642 \u0628\u0644\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>graph.invoke(Command(resume=value), config=config)<\/code>\u0627\u0633\u06cc \u0646\u0648\u0688 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u062f\u0631\u0633\u062a \u0644\u0627\u0626\u0646 \u067e\u0631 \u0639\u0645\u0644\u062f\u0631\u0622\u0645\u062f \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 <code>interrupt()<\/code> \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0628\u0644\u0627\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627\u06d4 <code>decision<\/code> \u067e\u0631 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba <code>value<\/code>.<\/p>\n<pre><code class=\"language-python\"># src\/agents\/human_approval.py\n\nfrom langgraph.types import interrupt\nfrom graph.state import StudyRoadmap\n\n\ndef human_approval_node(state: dict) -> dict:\n    \"\"\"\n    LangGraph node: Human Approval\n\n    Reads:  state[\"roadmap\"]\n    Writes: state[\"approved\"]: True if approved, False if rejected.\n            Also returns all other state keys explicitly (see note below).\n\n    When approved=False, the conditional edge routes back to the\n    Curriculum Planner to generate a new roadmap.\n    When approved=True, the graph continues to the Explainer.\n    \"\"\"\n    roadmap = state.get(\"roadmap\")\n\n    if roadmap is None:\n        return {\"approved\": True}\n\n    print(f\"n[Human Approval] Pausing for roadmap review...\")\n\n    # interrupt() pauses execution here.\n    # The dict passed to interrupt() is the payload. The caller reads this\n    # to know what to display to the user.\n    # Execution resumes when Command(resume=value) is called by the caller.\n    decision = interrupt({\n        \"type\":   \"roadmap_approval\",\n        \"roadmap\": roadmap,\n        \"prompt\": (\n            \"Does this study plan look good?n\"\n            \"  Type 'yes' to start studyingn\"\n            \"  Type 'no' to generate a different plan\"\n        ),\n    })\n\n    approved = str(decision).lower().strip() in (\"yes\", \"y\", \"ok\", \"approve\")\n\n    if approved:\n        print(f\"[Human Approval] Roadmap approved. Starting study session.\")\n    else:\n        print(f\"[Human Approval] Roadmap rejected. Regenerating...\")\n\n    # LangGraph 1.1.0: after Command(resume=...), the next node receives only\n    # the keys returned by this node. Not the full pre-interrupt checkpoint.\n    # Returning the complete state explicitly ensures downstream agents\n    # (explainer, quiz_generator, progress_coach) receive roadmap, session_id, etc.\n    return {\n        \"approved\":              approved,\n        \"roadmap\":               roadmap,\n        \"goal\":                  state.get(\"goal\", \"\"),\n        \"session_id\":            state.get(\"session_id\", \"\"),\n        \"current_topic_index\":   state.get(\"current_topic_index\", 0),\n        \"quiz_results\":          state.get(\"quiz_results\", []),\n        \"weak_areas\":            state.get(\"weak_areas\", []),\n        \"study_materials_path\":  state.get(\"study_materials_path\",\n                                           \"study_materials\/sample_notes\"),\n        \"error\":                 None,\n    }\n<\/code><\/pre>\n<p>\u0627\u0633 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06d2 \u0646\u0686\u0644\u06d2 \u062d\u0635\u06d2 \u0645\u06cc\u06ba \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 1.1.0 \u06a9\u06cc \u062a\u0641\u0635\u06cc\u0644 \u0627\u0635\u0644 \u0631\u0648\u06cc\u06d2 \u06a9\u06cc \u062f\u0633\u062a\u0627\u0648\u06cc\u0632 \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u062c\u0648 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u0645\u06cc\u06ba \u067e\u06cc\u0634 \u0622\u0626\u06d2 \u06af\u0627\u06d4 <code>Command(resume=...)<\/code>\u0627\u06af\u0644\u06d2 \u0646\u0648\u0688 \u06a9\u06cc \u062d\u0627\u0644\u062a \u0645\u06cc\u06ba \u0635\u0631\u0641 \u0648\u06c1\u06cc \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0645\u062f\u0627\u062e\u0644\u062a \u0634\u062f\u06c1 \u0646\u0648\u0688 \u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0628 \u0646\u0648\u0688 \u0635\u0631\u0641 \u0648\u0627\u067e\u0633 \u0622\u062a\u0627 \u06c1\u06d2\u06d4 <code>{\"approved\": True}<\/code>\u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u0646\u0648\u0688 \u0627\u06cc\u06a9 \u062e\u0627\u0644\u06cc \u062d\u0627\u0644\u062a \u062d\u0627\u0635\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>roadmap<\/code>\u0646\u06c1\u06cc\u06ba <code>session_id<\/code>\u0646\u06c1\u06cc\u06ba <code>current_topic_index<\/code>\u06cc\u06c1 \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u06cc\u06a9 \u063a\u0644\u0637\u06cc \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u06a9\u0648\u0688 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u0628\u06af \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0645\u0639\u0637\u0644\/\u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f LangGraph 1.1.0 \u0645\u06cc\u06ba \u0631\u06cc\u0627\u0633\u062a\u06cc \u067e\u06be\u06cc\u0644\u0627\u0624 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0645\u0639\u0631\u0648\u0641 \u0631\u0648\u06cc\u06c1 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u062d\u0644 \u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631 \u0645\u062c\u0645\u0648\u0639\u06cc \u062d\u0627\u0644\u062a \u06a9\u0648 \u0648\u0627\u067e\u0633 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0688\u0627\u0648\u0646 \u0627\u0633\u0679\u0631\u06cc\u0645 \u0646\u0648\u0688\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0631\u06a9\u0627\u0631 \u062a\u0645\u0627\u0645 \u0627\u0633\u0679\u06cc\u0679 \u06a9\u06cc\u0632 \u06a9\u0648 \u0631\u06cc\u0679\u0631\u0646 \u0688\u06a9\u0634\u0646\u0631\u06cc \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 \u0627\u0646\u0679\u0631\u067e\u0679\/\u0631\u06cc\u0632\u06cc\u0648\u0645 \u0628\u0627\u0624\u0646\u0688\u0631\u06cc \u06a9\u06d2 \u0628\u0639\u062f \u0686\u0644\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0646\u0648\u0688\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u0633\u0627 \u0633\u0644\u0648\u06a9 \u06a9\u06cc\u0627 \u062c\u0627\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2 \u062c\u06cc\u0633\u06d2 \u0648\u06c1 \u0636\u0645 \u0634\u062f\u06c1 \u0686\u0648\u06a9\u06cc \u0633\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0634\u0631\u0648\u0639 \u0633\u06d2 \u06c1\u06cc \u062d\u0627\u0644\u062a \u062d\u0627\u0635\u0644 \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u0648\u06ba\u06d4<\/p>\n<h4 id=\"heading-interrupt-vs-interruptbefore\"> Interrupt() \u0628\u0645\u0642\u0627\u0628\u0644\u06c1 Interrupt_before<\/h4>\n<p>\u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u06af\u0631\u0627\u0641 \u06a9\u0648 \u0631\u0648\u06a9\u0646\u06d2 \u06a9\u06d2 \u062f\u0648 \u0637\u0631\u06cc\u0642\u06d2 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>interrupt_before=[\"node_name\"]<\/code> \u06a9\u0648 <code>builder.compile()<\/code> \u062a\u0648\u0642\u0641 <em>\u067e\u06c1\u0644\u06d2<\/em> \u06cc\u06c1 \u0627\u06cc\u06a9 \u0646\u0627\u0645\u0632\u062f \u0646\u0648\u0688 \u06c1\u06d2 \u0627\u0648\u0631 \u0645\u0631\u062a\u0628 \u0648\u0642\u062a \u067e\u0631 \u0628\u0646\u0627\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 <code>interrupt()<\/code> \u0628\u0644\u0627\u06cc\u0627 <em>\u0627\u0646\u062f\u0631<\/em> \u0627\u06cc\u06a9 \u0646\u0648\u0688 \u06a9\u0648 \u0627\u0633 \u06a9\u06d2 \u0639\u0645\u0644 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0631\u0648\u06a9 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u067e\u06d2 \u0644\u0648\u0688 (\u0627\u06cc\u06a9 \u0644\u063a\u062a \u062c\u0633\u06d2 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u0627 \u06cc\u06c1 \u062c\u0627\u0646\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0635\u0627\u0631\u0641 \u06a9\u0648 \u06a9\u06cc\u0627 \u062f\u06a9\u06be\u0627\u0646\u0627 \u06c1\u06d2) \u067e\u0631 \u0645\u0634\u062a\u0645\u0644 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u0646\u0638\u0627\u0645 <code>interrupt()<\/code> \u0627\u0646\u062f\u0631 <code>human_approval_node<\/code> \u0627\u0633 \u06a9\u06cc \u0648\u062c\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0645\u0646\u0638\u0648\u0631\u06cc \u06a9\u06d2 \u0645\u0631\u062d\u0644\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0631\u0648\u0688 \u0645\u06cc\u067e \u0622\u0628\u062c\u06cc\u06a9\u0679 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u0648 \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u06a9\u06c1 <code>interrupt_before<\/code> \u0646\u0648\u0688 \u0686\u0644\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0646\u0642\u0637\u06c1 \u0646\u0638\u0631 \u0631\u06a9 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0631\u0648\u0688 \u0645\u06cc\u067e \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <em>\u0627\u0646\u062f\u0631<\/em> \u0646\u0648\u0688 \u06a9\u0627 \u067e\u06cc\u0634\u0631\u0648 (<code>curriculum_planner_node<\/code>)\u06d4 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba <code>interrupt()<\/code> \u0646\u0648\u0688\u0633 \u0631\u0648\u0688 \u0645\u06cc\u067e \u062d\u0627\u0635\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0645\u0646\u0638\u0648\u0631\u06cc \u06a9\u0627 \u067e\u06d2 \u0644\u0648\u0688 \u0628\u0646\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u062a\u0648\u0642\u0641 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u06cc\u06c1 \u0633\u0628 \u0635\u062d\u06cc\u062d \u062a\u0631\u062a\u06cc\u0628 \u0645\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p>Streamlit UI \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>build_graph(interrupt_before=[\"quiz_generator\"])<\/code> \u0627\u06cc\u06a9 \u0627\u0648\u0631 \u0648\u062c\u06c1: \u0622\u067e \u06a9\u0648 \u06af\u0631\u0627\u0641 \u06a9\u0648 \u0631\u0648\u06a9\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u0633\u06d2 \u0631\u0648\u06a9\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 <code>quiz_generator_node<\/code> \u0627\u0633 \u0637\u0631\u062d \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4 <code>input()<\/code> \u0627\u0633\u06d2 \u06af\u0631\u0627\u0641 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0646\u06c1\u06cc\u06ba \u06a9\u06c1\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u062f\u0648\u0646\u0648\u06ba \u0645\u06cc\u06a9\u0627\u0646\u0632\u0645 \u0627\u0646 \u06a9\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06d2 \u0645\u0639\u0627\u0645\u0644\u0627\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0648\u0632\u0648\u06ba \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-53-handling-the-interrupt-in-mainpy\">5.3 \u06c1\u06cc\u0646\u0688\u0644\u0646\u06af \u0645\u06cc\u06ba \u062e\u0644\u0644 \u0688\u0627\u0644\u0646\u0627 <code>main.py<\/code><\/h3>\n<p>\u0628\u06be\u06cc\u062c\u0646\u06d2 \u0648\u0627\u0644\u0627 <code>graph.invoke<\/code> \u06c1\u0645\u06cc\u06ba \u0627\u06cc\u0633\u06d2 \u0645\u0639\u0627\u0645\u0644\u0627\u062a \u06a9\u0648 \u0633\u0646\u0628\u06be\u0627\u0644\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u06af\u0631\u0627\u0641 \u0645\u0648\u0642\u0648\u0641 \u06c1\u06d2\u06d4 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0627\u06cc\u06a9 \u062a\u0648\u0642\u0641 \u06a9\u0627 \u0627\u0634\u0627\u0631\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0628\u0634\u0645\u0648\u0644: <code>\"__interrupt__\"<\/code> \u0646\u062a\u06cc\u062c\u06d2 \u0645\u06cc\u06ba \u0688\u06a9\u0679 \u0645\u06cc\u06ba. \u0631\u06a9\u0627\u0648\u0679 \u067e\u06d2 \u0644\u0648\u0688 (\u062c\u0648 \u0688\u06a9\u0679 \u0622\u067e \u0646\u06d2 \u067e\u0627\u0633 \u06a9\u06cc\u0627 \u06c1\u06d2\u06d4 <code>interrupt()<\/code>) \u0645\u06cc\u06ba \u06c1\u06d2\u06d4 <code>result[\"__interrupt__\"][0].value<\/code>.<\/p>\n<pre><code class=\"language-python\"># main.py: the interrupt\/resume loop\n\nfrom langgraph.types import Command\n\nresult = graph.invoke(state, config=config)\n\nwhile \"__interrupt__\" in result:\n    interrupt_payload = result[\"__interrupt__\"][0].value\n    roadmap = interrupt_payload.get(\"roadmap\")\n\n    # Display the roadmap for the user to review\n    if roadmap:\n        print(f\"n{'='*60}\")\n        print(\"Proposed Study Plan\")\n        print(f\"{'='*60}\")\n        print(f\"Goal: {roadmap.goal}\")\n        print(f\"Duration: {roadmap.total_weeks} weeks @ \"\n              f\"{roadmap.weekly_hours} hrs\/weekn\")\n        for i, topic in enumerate(roadmap.topics, 1):\n            prereqs = (f\" (needs: {', '.join(topic.prerequisites)})\"\n                       if topic.prerequisites else \"\")\n            print(f\"  {i}. {topic.title} ({topic.estimated_minutes} min){prereqs}\")\n            print(f\"     {topic.description}\")\n\n    print(f\"n{interrupt_payload.get('prompt', 'Continue?')}\")\n    user_input = input(\"> \").strip()\n\n    # Resume the graph with the user's decision.\n    # Command(resume=value) is how you pass input back to the interrupted node.\n    result = graph.invoke(Command(resume=user_input), config=config)\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>while<\/code> \u0644\u0648\u067e \u0627\u06cc\u0633\u06d2 \u0645\u0639\u0627\u0645\u0644\u0627\u062a \u06a9\u0648 \u0633\u0646\u0628\u06be\u0627\u0644\u062a\u0627 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0631\u0648\u0688 \u0645\u06cc\u067e \u06a9\u0648 \u0645\u0633\u062a\u0631\u062f \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0645\u0646\u0635\u0648\u0628\u06c1 \u0633\u0627\u0632 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u062e\u0644\u06cc\u0642 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0633 \u0633\u06d2 \u0627\u06cc\u06a9 \u0627\u0648\u0631 \u0631\u06a9\u0627\u0648\u0679 \u067e\u06cc\u062f\u0627 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u062c\u0628 \u0635\u0627\u0631\u0641 \u0627\u0646 \u067e\u0679 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 <code>no<\/code>\u06af\u0631\u0627\u0641 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4 <code>curriculum_planner_node<\/code> \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u067e\u06be\u0631\u060c \u06cc\u06c1 \u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u0631\u0648\u0688 \u0645\u06cc\u067e \u0627\u0648\u0631 \u06c1\u0679 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 <code>interrupt()<\/code> \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u067e\u06be\u0631\u060c \u0622\u067e \u06a9\u0648 \u0627\u067e\u0646\u0627 \u0646\u06cc\u0627 \u0645\u0646\u0635\u0648\u0628\u06c1 \u0646\u0638\u0631 \u0622\u0626\u06d2 \u06af\u0627\u06d4 \u0635\u0627\u0631\u0641\u06cc\u0646 \u0627\u0633 \u0648\u0642\u062a \u062a\u06a9 \u0622\u067e\u0679 \u0622\u0624\u0679 \u06a9\u0631\u0646\u0627 \u062c\u0627\u0631\u06cc \u0631\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0628 \u062a\u06a9 \u0648\u06c1 \u0645\u0637\u0645\u0626\u0646 \u0646\u06c1 \u06c1\u0648\u06ba\u06d4 \u0644\u0648\u067e \u0635\u0631\u0641 \u0627\u0633 \u0648\u0642\u062a \u062e\u062a\u0645 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u062c\u0628 \u06af\u0631\u0627\u0641 \u0645\u06a9\u0645\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc \u0631\u06a9\u0627\u0648\u0679 \u06a9\u06d2\u06d4<\/p>\n<p>\u0633\u0627\u062e\u062a \u0679\u06be\u06cc\u06a9 \u0679\u06be\u06cc\u06a9 \u0633\u0645\u062c\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-plaintext\">graph.invoke(initial_state, config)\n  \u2192 runs: curriculum_planner \u2192 human_approval (interrupt() fires)\n  \u2192 returns: {\"__interrupt__\": [...]}  \u2190 caller reads roadmap from here\n\nmain.py shows roadmap, collects \"yes\"\n\ngraph.invoke(Command(resume=\"yes\"), config)\n  \u2192 resumes: human_approval (decision = \"yes\", approved = True)\n  \u2192 continues: explainer \u2192 quiz_generator \u2192 progress_coach \u2192 ... \u2192 END\n  \u2192 returns: final state dict  \u2190 no \"__interrupt__\" key\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>config<\/code> \u0688\u06a9\u0634\u0646\u0631\u06cc <code>thread_id<\/code> \u062f\u0648\u0646\u0648\u06ba \u0627\u06cc\u06a9 \u062c\u06cc\u0633\u06d2 \u06c1\u06cc\u06ba <code>graph.invoke<\/code> \u0641\u0648\u0646 \u06a9\u0627\u0644 \u0627\u0633 \u0637\u0631\u062d \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u06a9\u0648 \u06cc\u06c1 \u0645\u0639\u0644\u0648\u0645 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0646\u0626\u06d2 \u0633\u0631\u06d2 \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0631\u0648\u06a9\u06d2 \u06c1\u0648\u0626\u06d2 \u0646\u0648\u0688 \u0633\u06d2 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0644\u0648\u0688 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-54-resuming-a-crashed-session\">5.4 \u06a9\u0631\u06cc\u0634 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0633\u06cc\u0634\u0646\u0632 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0648\u06c1\u06cc \u0637\u0631\u06cc\u0642\u06c1 \u06a9\u0627\u0631 \u062c\u0648 \u0627\u0639\u062a\u0631\u0627\u0641\u0627\u062a \u06a9\u0648 \u0633\u0646\u0628\u06be\u0627\u0644\u062a\u0627 \u06c1\u06d2 \u062a\u0646\u0627\u0632\u0639\u0627\u062a \u06a9\u06cc \u0628\u062d\u0627\u0644\u06cc \u06a9\u0648 \u0628\u06be\u06cc \u0633\u0646\u0628\u06be\u0627\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0639\u0645\u0644 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u062e\u062a\u0645 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>explainer_node<\/code> \u0627\u0648\u0631 <code>quiz_generator_node<\/code>SQLite \u0686\u0648\u06a9\u06cc\u0648\u06ba \u06a9\u06cc \u0627\u067e\u0646\u06cc \u0645\u062c\u0645\u0648\u0639\u06cc \u062d\u0627\u0644\u062a \u0622\u062e\u0631\u06cc \u0645\u06a9\u0645\u0644 \u0634\u062f\u06c1 \u0646\u0648\u0688 \u06a9\u06cc \u0628\u0646\u06cc\u0627\u062f \u067e\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u0639\u0645\u0644 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633\u06cc \u0639\u0645\u0644 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>thread_id<\/code> \u0627\u0633\u06d2 \u0648\u06c1\u0627\u06ba \u0633\u06d2 \u0627\u0679\u06be\u0627\u0624\u06d4<\/p>\n<p>\u06a9\u06c1 <code>--resume<\/code> \u0627\u06cc\u06a9 \u062c\u06be\u0646\u0688\u0627 \u0644\u06af\u0627\u0626\u06cc\u06ba <code>main.py<\/code> \u0627\u0633 \u06a9\u0648 \u0646\u0627\u0641\u0630 \u06a9\u0631\u06cc\u06ba:<\/p>\n<pre><code class=\"language-python\"># main.py\n\nif __name__ == \"__main__\":\n    import argparse\n\n    parser = argparse.ArgumentParser(description=\"Learning Accelerator\")\n    parser.add_argument(\"goal\", nargs=\"?\",\n                        default=\"Learn Python closures and decorators from scratch\")\n    parser.add_argument(\"--resume\", metavar=\"SESSION_ID\",\n                        help=\"Resume an existing session by ID\")\n    args = parser.parse_args()\n\n    if args.resume:\n        run_session(goal=\"\", session_id=args.resume)\n    else:\n        run_session(goal=args.goal)\n<\/code><\/pre>\n<p>\u0627\u0646\u062f\u0631 <code>run_session<\/code>\u0631\u06cc\u0632\u06cc\u0648\u0645\u06d2 \u0627\u0648\u0631 \u0646\u0626\u06cc \u0634\u0631\u0648\u0639\u0627\u062a \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0628\u0627\u0644\u06a9\u0644 \u0627\u06cc\u06a9 \u0644\u0627\u0626\u0646 \u06a9\u0627 \u0641\u0631\u0642 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\"># For a new session: provide initial state\nstate = initial_state(goal, session_id)\n\n# For a resume: pass None. LangGraph loads from the checkpoint.\nstate = None if is_resume else initial_state(goal, session_id)\n\nresult = graph.invoke(state, config=config)\n<\/code><\/pre>\n<p>\u062c\u0628 <code>state<\/code> \u06c1\u06d2 <code>None<\/code>LangGraph \u062a\u0627\u0632\u06c1 \u062a\u0631\u06cc\u0646 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u0648 \u0644\u0648\u0688 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>thread_id<\/code> \u06a9\u0648 <code>config<\/code> \u06cc\u06c1 \u0622\u062e\u0631\u06cc \u0645\u06a9\u0645\u0644 \u0646\u0648\u0688 \u0633\u06d2 \u062c\u0627\u0631\u06cc \u06c1\u06d2\u06d4 \u0627\u0635\u0644 \u0633\u06cc\u0634\u0646 \u0634\u0631\u0648\u0639 \u06c1\u0648\u0646\u06d2 \u067e\u0631 \u0622\u067e \u06a9\u0648 \u0635\u0631\u0641 \u0633\u06cc\u0634\u0646 ID \u067e\u0631\u0646\u0679 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-bash\"># Original session printed: Session ID: a3f1b2c4\n# Process died mid-session\n\npython main.py --resume a3f1b2c4\n<\/code><\/pre>\n<pre><code class=\"language-plaintext\">============================================================\nLearning Accelerator\nSession ID: a3f1b2c4\nResuming existing session...\n============================================================\n\n[Explainer] Topic: 'Creating Closures'\n...\n<\/code><\/pre>\n<p>\u06af\u0631\u0627\u0641 \u06a9\u0648 \u0627\u06af\u0644\u06d2 \u0646\u0627\u0645\u06a9\u0645\u0644 \u0646\u0648\u0688 \u0633\u06d2 \u0645\u0646\u062a\u062e\u0628 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u0648\u06c1 \u0645\u0648\u0636\u0648\u0639\u0627\u062a \u062c\u0648 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0646\u0627\u0641\u0630 \u06a9\u06cc\u06d2 \u062c\u0627 \u0686\u06a9\u06d2 \u06c1\u06cc\u06ba (\u0628\u0634\u0645\u0648\u0644 \u0648\u0636\u0627\u062d\u062a\u06cc\u06ba\u060c \u06a9\u0648\u0626\u0632 \u06a9\u06d2 \u0646\u062a\u0627\u0626\u062c\u060c \u0627\u0648\u0631 \u06a9\u0648\u0686\u0646\u06af \u067e\u06cc\u063a\u0627\u0645\u0627\u062a) \u0648\u06c1\u06cc \u0631\u06c1\u06cc\u06ba \u06af\u06d2\u06d4 \u0635\u0631\u0641 \u0628\u0627\u0642\u06cc \u06a9\u0627\u0645\u0648\u06ba \u06a9\u0648 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<h3 id=\"heading-55-the-deserialization-detail-you-need-to-know\">5.5 \u0688\u06cc \u0633\u06cc\u0631\u06cc\u0644\u0627\u0626\u0632\u06cc\u0634\u0646 \u06a9\u06cc \u062a\u0641\u0635\u06cc\u0644\u0627\u062a \u062c\u0648 \u0622\u067e \u06a9\u0648 \u062c\u0627\u0646\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4<\/h3>\n<p>\u062c\u0628 LangGraph SQLite \u0633\u06d2 \u0627\u06cc\u06a9 \u0686\u0648\u06a9\u06cc \u0644\u0648\u0688 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u0645\u062d\u0641\u0648\u0638 \u0634\u062f\u06c1 \u062d\u0627\u0644\u062a \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u0632\u06af\u0631 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u0642\u062f\u06cc\u0645 \u0627\u0642\u0633\u0627\u0645 (\u0633\u0679\u0631\u0646\u06af\u060c \u0627\u0646\u0679\u06cc\u062c\u0631\u060c \u0633\u0679\u0631\u0646\u06af\u0632 \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a) \u06a9\u06d2 \u0644\u06cc\u06d2 \u06cc\u06c1 \u0634\u0641\u0627\u0641 \u06c1\u06d2\u06d4 \u062d\u0633\u0628 \u0636\u0631\u0648\u0631\u062a \u0688\u06cc\u0679\u0627 \u06a9\u0644\u0627\u0633\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 (<code>Topic<\/code>\u060c <code>StudyRoadmap<\/code>\u060c <code>QuizResult<\/code>)\u060c LangGraph \u0627\u0646\u062f\u0631\u0648\u0646\u06cc msgpack \u0633\u06cc\u0631\u06cc\u0644\u0627\u0626\u0632\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0688\u06cc\u0679\u0627 \u06a9\u0644\u0627\u0633 \u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0627\u06cc\u06a9 \u0628\u0627\u0642\u0627\u0639\u062f\u06c1 \u0644\u063a\u062a \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0648\u0627\u067e\u0633 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1\u06cc \u0648\u062c\u06c1 \u06c1\u06d2\u06d4 <code>get_current_topic<\/code>\u060c <code>session_is_complete<\/code>\u0627\u0648\u0631 <code>get_latest_quiz_result<\/code> \u06a9\u0648 <code>state.py<\/code> \u062f\u0648\u0646\u0648\u06ba \u062f\u0648\u0646\u0648\u06ba \u0634\u06a9\u0644\u06cc\u06ba \u0633\u0646\u0628\u06be\u0627\u0644\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">def get_current_topic(state: dict) -> Topic | None:\n    roadmap = state.get(\"roadmap\")\n    if roadmap is None:\n        return None\n\n    # After checkpoint deserialization, roadmap may be a dict\n    if isinstance(roadmap, dict):\n        topics_raw = roadmap.get(\"topics\", [])\n    else:\n        topics_raw = roadmap.topics\n\n    idx = state.get(\"current_topic_index\", 0)\n    if idx >= len(topics_raw):\n        return None\n\n    t = topics_raw[idx]\n    # Individual topics may also be dicts after deserialization\n    if isinstance(t, dict):\n        return Topic.from_dict\n    return t\n<\/code><\/pre>\n<p>\u0627\u0648\u0631 \u0648\u062c\u06c1 \u06cc\u06c1 \u06c1\u06d2\u06d4 <code>Topic<\/code>\u060c <code>StudyRoadmap<\/code>\u0627\u0648\u0631 <code>QuizResult<\/code> \u0633\u0628 \u06a9\u06d2 \u067e\u0627\u0633 \u06c1\u06d2 <code>from_dict<\/code> \u06a9\u0644\u0627\u0633 \u06a9\u0627 \u0637\u0631\u06cc\u0642\u06c1\u06d4 \u06cc\u06c1 \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u0633\u06c1\u0648\u0644\u062a \u06a9\u06cc \u0686\u06cc\u0632 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u06cc\u06c1 \u0622\u067e \u06a9\u06d2 \u0631\u06cc\u0632\u06cc\u0648\u0645\u06d2 \u06a9\u06d2 \u0635\u062d\u06cc\u062d \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1\u06cc \u067e\u06cc\u0679\u0631\u0646 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0633\u0633\u0679\u0645 \u067e\u0631 \u0644\u0627\u06af\u0648 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0627\u067e\u0646\u06cc \u0645\u0631\u0636\u06cc \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u0627\u0634\u06cc\u0627\u0621 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u06a9\u06cc \u0631\u06cc\u0627\u0633\u062a \u0645\u06cc\u06ba \u0688\u06cc\u0679\u0627 \u06a9\u0644\u0627\u0633\u0632 \u06cc\u0627 Pydantic \u0645\u0627\u0688\u0644 \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u062a\u0645\u0627\u0645 \u0631\u06cc\u0627\u0633\u062a\u06cc \u0631\u0633\u0627\u0626\u06cc \u06a9\u0627\u0631\u0648\u06ba \u06a9\u0648 \u0644\u0627\u0626\u06cc\u0648 \u0627\u0648\u0631 \u0688\u06cc \u0633\u06cc\u0631\u06cc\u0644\u0627\u0626\u0632\u0688 \u0641\u0627\u0631\u0645\u0632 \u06a9\u0648 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0645\u062a \u0633\u0645\u062c\u06be\u0648 \u06a9\u06c1 \u0642\u0633\u0645 \u0648\u06c1\u06cc \u06c1\u0648\u06af\u06cc \u062c\u0648 \u0622\u067e \u0646\u06d2 \u062f\u0631\u062c \u06a9\u06cc \u06c1\u06d2\u06d4 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06d2 \u0645\u0642\u0627\u0645 \u067e\u0631 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-56-test-session-persistence\">5.6 \u0679\u06cc\u0633\u0679 \u0633\u06cc\u0634\u0646 \u0627\u0633\u062a\u0642\u0627\u0645\u062a<\/h3>\n<p>\u0627\u06cc\u06a9 \u0633\u06cc\u0634\u0646 \u0686\u0644\u0627\u0626\u06cc\u06ba\u060c \u0627\u0633\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0645\u06cc\u06ba \u0686\u06be\u0648\u0691 \u062f\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u0622\u06cc\u0627 \u0622\u067e \u06a9\u0627 \u0631\u06cc\u0632\u06cc\u0648\u0645 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-bash\">rm -f data\/checkpoints.db\npython main.py \"Learn Python closures\"\n<\/code><\/pre>\n<p>\u0622\u067e \u06a9\u06d2 \u062f\u0627\u062e\u0644 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f \u0631\u0648\u0688 \u0645\u06cc\u067e \u0638\u0627\u06c1\u0631 \u06c1\u0648\u06af\u0627\u06d4 <code>yes<\/code>\u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u0648 \u062c\u0628 \u062a\u06a9 \u062a\u0645 \u0627\u0633\u06d2 \u0646\u06c1 \u062f\u06cc\u06a9\u06be\u0648 <code>[Explainer] Complete after N LLM call(s)<\/code>. \u067e\u06be\u0631 <code>Ctrl+C<\/code> \u0639\u0645\u0644 \u06a9\u0648 \u062e\u062a\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0633\u0679\u0627\u0631\u0679 \u0627\u067e \u067e\u0631 \u067e\u0631\u0646\u0679 \u06a9\u06cc \u06af\u0626\u06cc \u0633\u06cc\u0634\u0646 ID \u06a9\u0648 \u0646\u0648\u0679 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u0628 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">python main.py --resume <session-id>\n<\/session-id><\/code><\/pre>\n<p>\u06a9\u0648\u0626\u0632 \u062c\u0646\u0631\u06cc\u0679\u0631 \u0645\u06cc\u06ba \u0633\u06cc\u0634\u0646 \u062c\u0627\u0631\u06cc \u0631\u06c1\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 \u0686\u0648\u0646\u06a9\u06c1 \u0648\u0636\u0627\u062d\u062a \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u06cc \u062c\u0627 \u0686\u06a9\u06cc \u06c1\u06d2\u060c \u0622\u0626\u06cc\u06d2 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u067e\u06c1\u0644\u06d2 \u0645\u0648\u0636\u0648\u0639 \u06a9\u06d2 \u0633\u0648\u0627\u0644 \u06a9\u06cc \u0637\u0631\u0641 \u0622\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p> <strong>\u0686\u0648\u06a9\u06cc:<\/strong> \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u0679\u06cc\u0633\u0679 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">pytest tests\/test_checkpointing.py -v\n<\/code><\/pre>\n<p>\u062a\u0648\u0642\u0639: 20 \u0679\u06cc\u0633\u0679\u060c \u0633\u0628\u06be\u06cc \u067e\u0627\u0633 \u06c1\u0648 \u06af\u0626\u06d2\u06d4 \u06cc\u06c1 \u0679\u06cc\u0633\u0679 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u0631\u0627\u0624\u0646\u0688 \u0679\u0631\u067e \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06cc\u0639\u0646\u06cc\u060c \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u0626\u06cc\u06ba \u06a9\u06c1 \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0631\u06a9\u0627\u0648\u0679 \u067e\u06cc\u062f\u0627 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0633\u06cc\u0634\u0646\u0632 \u06a9\u0648 \u0645\u062a\u0648\u0642\u0639 \u062d\u0627\u0644\u062a \u067e\u06cc\u062f\u0627 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u06cc\u06c1 \u06a9\u06c1 dict-vs-dataclass \u0688\u06cc\u0633\u06cc\u0631\u06cc\u0644\u0627\u0626\u0632\u06cc\u0634\u0646 \u06a9\u0648 \u062f\u0631\u0633\u062a \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0646\u0679\u0631\u067e\u0631\u0627\u0626\u0632 \u06a9\u0646\u06cc\u06a9\u0679: \u0633\u06cc\u0644\u0632 \u0627\u06cc\u0628\u0644\u0645\u0646\u0679 \u067e\u0644\u06cc\u0679 \u0641\u0627\u0631\u0645 \u0645\u06cc\u0646\u06cc\u062c\u0631 \u06a9\u06cc \u0645\u0646\u0638\u0648\u0631\u06cc\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u06c1\u06cc \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u067e\u06cc\u0679\u0631\u0646 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u062c\u0628 \u06a9\u0631\u06cc\u06a9\u0648\u0644\u0645 \u0627\u06cc\u062c\u0646\u0679 \u0646\u0626\u06d2 \u06a9\u0631\u0627\u06cc\u06c1 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u0631\u0628\u06cc\u062a\u06cc \u0645\u0646\u0635\u0648\u0628\u06c1 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06af\u0631\u0627\u0641 \u0631\u06a9 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0645\u0646\u062a\u0638\u0645 \u06a9\u0648 \u0627\u06cc\u06a9 \u0627\u0637\u0644\u0627\u0639 \u0628\u06be\u06cc\u062c\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4 \u0645\u0646\u062a\u0638\u0645\u06cc\u0646 \u0648\u06cc\u0628 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0633\u06d2 \u0645\u0646\u0635\u0648\u0628\u0648\u06ba \u06a9\u0627 \u062c\u0627\u0626\u0632\u06c1 \u0644\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0645\u0646\u0638\u0648\u0631\u06cc \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba \u06cc\u0627 \u0627\u0646 \u0645\u06cc\u06ba \u062a\u0631\u0645\u06cc\u0645 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0646\u06c1\u06cc\u06ba \u062c\u0645\u0639 \u06a9\u0631\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0645\u062a\u0639\u0644\u0642\u06c1 HTTP POST \u06a9\u0627\u0644 <code>graph.invoke(Command(resume=decision), config=config)<\/code>. LangGraph \u06a9\u0648\u0688 \u0679\u0631\u0645\u06cc\u0646\u0644 \u0648\u0631\u0698\u0646 \u06a9\u06cc \u0637\u0631\u062d \u06c1\u06d2\u06d4 \u0635\u0631\u0641 \u0627\u0637\u0644\u0627\u0639 \u06a9\u0627 \u0637\u0631\u06cc\u0642\u06c1 \u06a9\u0627\u0631 \u0627\u0648\u0631 \u0627\u0646 \u067e\u0679 \u062c\u0645\u0639 \u06a9\u0631\u0646\u06d2 \u0645\u06cc\u06ba \u0641\u0631\u0642 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06af\u0644\u0627 \u0628\u0627\u0628 \u0645\u0634\u0627\u06c1\u062f\u06d2 \u06a9\u0627 \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627\u0644\u0632\u060c \u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u0627\u0644\u0632\u060c \u0627\u0648\u0631 \u0679\u0648\u0644 \u0627\u06cc\u06af\u0632\u06cc\u06a9\u06cc\u0648\u0634\u0646\u0632 \u06a9\u0648 \u0633\u0627\u062e\u062a\u06cc \u0646\u0634\u0627\u0646\u0627\u062a \u0645\u06cc\u06ba \u06a9\u06cc\u067e\u0686\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0646 \u0633\u06d2 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u0627\u0648\u0631 \u062a\u0635\u0648\u0631 \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-chapter-6-observability-with-langfuse\">\u0628\u0627\u0628 6: \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u0634\u0627\u06c1\u062f\u06c1<\/h2>\n<p>\u0627\u06cc\u06a9 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645 \u062c\u0648 \u063a\u0644\u0637\u06cc\u0648\u06ba \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u063a\u0644\u0637 \u0622\u0624\u0679 \u067e\u0679 \u067e\u06cc\u062f\u0627 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0633\u06d2 \u06a9\u0631\u06cc\u0634 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0633\u0633\u0679\u0645 \u0633\u06d2 \u0688\u06cc\u0628\u06af \u06a9\u0631\u0646\u0627 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0634\u06a9\u0644 \u06c1\u06d2\u06d4 \u0645\u0639\u06cc\u0627\u0631\u06cc \u0627\u0646\u0641\u0631\u0627\u0633\u0679\u0631\u06a9\u0686\u0631 \u0645\u06cc\u0679\u0631\u06a9\u0633 (CPU\u060c \u0645\u06cc\u0645\u0648\u0631\u06cc\u060c \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0645\u06cc\u06ba \u062a\u0627\u062e\u06cc\u0631\u060c \u0627\u06cc\u0631\u0631 \u0631\u06cc\u0679) \u0622\u067e \u06a9\u0648 \u0628\u062a\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0633\u0633\u0679\u0645 \u0635\u062d\u062a \u0645\u0646\u062f \u06c1\u06d2 \u062c\u0628\u06a9\u06c1 \u0627\u06cc\u062c\u0646\u0679 \u063a\u0644\u0637 \u0627\u0646\u062f\u0627\u0632\u06c1 \u0644\u06af\u0627 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4 \u06c1\u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0645\u062e\u062a\u0644\u0641 \u0642\u0633\u0645 \u06a9\u06d2 \u0645\u0634\u0627\u06c1\u062f\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2 \u062c\u0648 \u0646\u06c1 \u0635\u0631\u0641 \u0627\u0633 \u0628\u0627\u062a \u06a9\u06cc \u06af\u0631\u0641\u062a \u06a9\u0631\u06d2 \u06a9\u06c1 \u0622\u06cc\u0627 \u06a9\u0627\u0644 \u06a9\u06cc \u06af\u0626\u06cc \u062a\u06be\u06cc\u060c \u0628\u0644\u06a9\u06c1 \u0645\u0627\u0688\u0644 \u0646\u06d2 \u06a9\u06cc\u0627 \u0641\u06cc\u0635\u0644\u06c1 \u06a9\u06cc\u0627 \u062a\u06be\u0627 \u0627\u0648\u0631 \u06a9\u06cc\u0648\u06ba \u06a9\u06cc\u0627 \u062a\u06be\u0627\u06d4<\/p>\n<p>\u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u06cc\u06c1 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0645\u0627\u0645 LLM \u06a9\u0627\u0644\u0632\u060c \u062a\u0645\u0627\u0645 \u0679\u0648\u0644 \u06a9\u0627\u0644\u0632\u060c \u0627\u0648\u0631 \u06c1\u0631 \u0642\u062f\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u06a9\u0645\u0644 \u0645\u06cc\u0633\u062c \u06c1\u0633\u0679\u0631\u06cc\u060c \u0679\u0631\u06cc\u06a9 \u0627\u0648\u0631 \u0633\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u06af\u0631\u0648\u067e \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u06a9\u0686\u06be \u063a\u0644\u0637 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u0627\u0633 \u0633\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0679\u0631\u06cc\u0633 \u06a9\u06be\u0648\u0644 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u06c1\u0631 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648 \u06a9\u06cc\u0627 \u0645\u0644\u0627\u060c \u0627\u0633\u06d2 \u06a9\u06cc\u0627 \u06a9\u06c1\u0627 \u06af\u06cc\u0627\u060c \u0627\u0648\u0631 \u0627\u0633 \u0646\u06d2 \u06a9\u06cc\u0627 \u0648\u0627\u067e\u0633 \u06a9\u06cc\u0627\u06d4<\/p>\n<p>\u0627\u0633 \u0628\u0627\u0628 \u0645\u06cc\u06ba\u060c \u0622\u067e \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f \u0627\u0646\u0679\u06cc\u06af\u0631\u06cc\u0634\u0646 \u067e\u0648\u0627\u0626\u0646\u0679 \u0627\u0648\u0631 \u0646\u0627\u0631\u0645\u0644 \u0627\u0646\u062d\u0637\u0627\u0637 \u06a9\u06d2 \u0646\u0645\u0648\u0646\u0648\u06ba \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u067e\u0646\u06d2 \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba Langfuse \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4 \u06cc\u06c1 \u0646\u0638\u0627\u0645 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u06a9\u06d2 \u06a9\u0646\u0641\u06cc\u06af\u0631 \u06a9\u0631\u062f\u06c1 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06cc\u0627 \u0627\u0633 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u06cc\u06a9\u0633\u0627\u06ba \u0637\u0648\u0631 \u067e\u0631 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-61-run-langfuse-locally-with-docker\">6.1 \u0688\u0648\u06a9\u0631 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u0686\u0644\u0627\u0646\u0627<\/h3>\n<p>\u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u0627\u0633 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062e\u0648\u062f \u0645\u06cc\u0632\u0628\u0627\u0646 \u06c1\u06d2\u06d4 \u062a\u0645\u0627\u0645 \u0646\u0634\u0627\u0646\u0627\u062a \u0622\u067e \u06a9\u06d2 \u06a9\u0645\u067e\u06cc\u0648\u0679\u0631 \u067e\u0631 \u0631\u06a9\u06be\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06a9\u0633\u06cc API \u06a9\u0644\u06cc\u062f \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u0627\u0648\u0631 \u0622\u067e \u06a9\u0627 \u0688\u06cc\u0679\u0627 \u06a9\u0628\u06be\u06cc \u0628\u06be\u06cc \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u0648 \u0646\u06c1\u06cc\u06ba \u0686\u06be\u0648\u0691\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u06c1 <code>docker-compose.yml<\/code> \u0631\u06cc\u067e\u0648\u0632\u0679\u0631\u06cc \u0633\u06d2 \u0645\u06a9\u0645\u0644 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u0627\u0633\u0679\u06cc\u06a9 \u0644\u0627\u0646\u0686 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-yaml\"># docker-compose.yml\nservices:\n  langfuse-server:\n    image: langfuse\/langfuse:3\n    depends_on:\n      postgres:\n        condition: service_healthy\n    ports:\n      - \"3000:3000\"\n    environment:\n      DATABASE_URL: postgresql:\/\/postgres:postgres@postgres:5432\/langfuse\n      NEXTAUTH_URL: http:\/\/localhost:3000\n      NEXTAUTH_SECRET: local-dev-secret-change-in-production\n      SALT: local-dev-salt-change-in-production\n      ENCRYPTION_KEY: \"0000000000000000000000000000000000000000000000000000000000000000\"\n      LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES: \"true\"\n      TELEMETRY_ENABLED: \"false\"\n\n  postgres:\n    image: postgres:16-alpine\n    environment:\n      POSTGRES_DB: langfuse\n      POSTGRES_USER: postgres\n      POSTGRES_PASSWORD: postgres\n    volumes:\n      - langfuse_postgres_data:\/var\/lib\/postgresql\/data\n    healthcheck:\n      test: [\"CMD-SHELL\", \"pg_isready -U postgres -d langfuse\"]\n      interval: 5s\n      retries: 10\n\nvolumes:\n  langfuse_postgres_data:\n<\/code><\/pre>\n<p>\u0627\u0633\u0679\u06cc\u06a9 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">docker compose up -d\n<\/code><\/pre>\n<p>\u067e\u0648\u0633\u0679\u06af\u0631\u06cc\u0633 \u0634\u0631\u0648\u0639 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u0642\u0631\u06cc\u0628\u0627\u064b 20 \u0633\u06cc\u06a9\u0646\u0688 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u06cc\u06ba\u06d4 \u067e\u06be\u0631 http:\/\/localhost:3000 \u06a9\u06be\u0648\u0644\u06cc\u06ba\u060c \u0627\u06cc\u06a9 \u0627\u06a9\u0627\u0624\u0646\u0679 \u0628\u0646\u0627\u0626\u06cc\u06ba (\u0645\u0642\u0627\u0645\u06cc\u060c \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba) \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u0628\u0646\u0627\u0626\u06cc\u06ba \u062c\u0633 \u06a9\u0627 \u0646\u0627\u0645 \u06c1\u06d2: <code>learning-accelerator<\/code>.<\/p>\n<p>\u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u0646\u06cc\u0686\u06d2 API \u06a9\u0644\u06cc\u062f \u062f\u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <strong>\u062a\u0631\u062a\u06cc\u0628\u0627\u062a \u2192 API \u06a9\u0644\u06cc\u062f<\/strong>. \u0639\u0648\u0627\u0645\u06cc \u0627\u0648\u0631 \u0646\u062c\u06cc \u062f\u0648\u0646\u0648\u06ba \u0686\u0627\u0628\u06cc\u0627\u06ba \u06a9\u0627\u067e\u06cc \u06a9\u0631\u06cc\u06ba\u06d4 <code>.env<\/code>:<\/p>\n<pre><code class=\"language-bash\">LANGFUSE_PUBLIC_KEY=pk-lf-...\nLANGFUSE_SECRET_KEY=sk-lf-...\nLANGFUSE_HOST=http:\/\/localhost:3000\n<\/code><\/pre>\n<h3 id=\"heading-62-the-observability-module\">6.2 \u0645\u0634\u0627\u06c1\u062f\u0627\u062a\u06cc \u0645\u0627\u0688\u06cc\u0648\u0644<\/h3>\n<p>\u0627\u0646\u0636\u0645\u0627\u0645 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u06c1\u06d2\u06d4 <code>src\/observability\/langfuse_setup.py<\/code>. \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u0645\u06cc\u06ba \u062f\u06cc\u06af\u0631 \u062a\u0645\u0627\u0645 \u0641\u0627\u0626\u0644\u06cc\u06ba \u063a\u06cc\u0631 \u062a\u0628\u062f\u06cc\u0644 \u0634\u062f\u06c1 \u0631\u06c1\u06cc\u06ba\u06d4 \u0627\u06cc\u062c\u0646\u0679 \u0646\u0648\u0688 \u0646\u06c1\u06cc\u06ba \u062c\u0627\u0646\u062a\u0627 \u06a9\u06c1 \u0622\u06cc\u0627 \u0648\u06c1 \u0627\u0633 \u0645\u0627\u0688\u06cc\u0648\u0644 \u0633\u06d2 \u062f\u0631\u0622\u0645\u062f \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u0641\u0646\u06a9\u0634\u0646\u0632 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u06cc\u0627 \u0627\u0633 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u0645\u0634\u0627\u06c1\u062f\u0627\u062a\u06cc \u0686\u0644 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0645\u0634\u0627\u06c1\u062f\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06cc\u06c1 \u0635\u062d\u06cc\u062d \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u06c1\u06d2\u06d4 \u0627\u06cc\u062c\u0646\u0679 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0644\u0627\u06af\u0646\u06af \u06a9\u0627\u0644\u0632 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06a9\u06d2\u060c \u0622\u067e \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06cc \u0645\u0646\u0637\u0642 \u06a9\u0648 \u0645\u0634\u0627\u06c1\u062f\u0627\u062a\u06cc \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0645\u06cc\u06ba \u062c\u0648\u0691 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u06a9\u0648 \u062f\u0648\u0633\u0631\u06d2 \u0679\u0648\u0644 \u0633\u06d2 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0686\u06be\u0648 \u0644\u06cc\u0646\u0627\u06d4 \u06a9\u0627\u0644 \u0628\u06cc\u06a9 \u067e\u06cc\u0679\u0631\u0646 \u06a9\u0627\u0631\u0648\u0628\u0627\u0631\u06cc \u0645\u0646\u0637\u0642 \u0633\u06d2 \u0627\u0633 \u0645\u062c\u0645\u0648\u0639\u06c1 \u06a9\u0648 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u062e\u0627\u0631\u062c \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0645\u0627\u0688\u06cc\u0648\u0644 \u0645\u06cc\u06ba \u0686\u0627\u0631 \u0641\u0646\u06a9\u0634\u0646\u0632 \u06c1\u06cc\u06ba \u062c\u0646 \u0645\u06cc\u06ba \u06cc\u06a9 \u0637\u0631\u0641\u06c1 \u0627\u0646\u062d\u0635\u0627\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2: \u06c1\u0631 \u0627\u06cc\u06a9 \u067e\u0686\u06be\u0644\u06d2 \u067e\u0631 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\"># src\/observability\/langfuse_setup.py\n\nimport os\n\n\ndef _langfuse_configured() -> bool:\n    \"\"\"\n    Check whether Langfuse credentials are present in the environment.\n\n    Returns False if either key is missing or empty. In that case the\n    system runs without observability rather than raising an error.\n    \"\"\"\n    public_key = os.getenv(\"LANGFUSE_PUBLIC_KEY\", \"\").strip()\n    secret_key = os.getenv(\"LANGFUSE_SECRET_KEY\", \"\").strip()\n    return bool(public_key and secret_key)\n<\/code><\/pre>\n<p><code>_langfuse_configured()<\/code> \u06af\u0627\u0631\u0688 \u062f\u06cc\u06af\u0631 \u062a\u0645\u0627\u0645 \u0627\u0641\u0639\u0627\u0644 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u0648\u0626\u06cc \u0627\u0633\u0646\u0627\u062f \u06a9\u0627 \u0645\u0637\u0644\u0628 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0633\u0633\u0679\u0645 \u067e\u06be\u0631 \u0628\u06be\u06cc \u0686\u0644\u06d2 \u06af\u0627\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u062e\u0648\u0628\u0635\u0648\u0631\u062a \u0627\u0646\u062d\u0637\u0627\u0637 \u06a9\u0627 \u0646\u0645\u0648\u0646\u06c1 \u06c1\u06d2\u06d4 \u0645\u0634\u0627\u06c1\u062f\u06c1 \u0627\u06cc\u06a9 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0628\u06c1\u062a\u0631\u06cc \u06c1\u06d2\u060c \u0633\u062e\u062a \u0627\u0646\u062d\u0635\u0627\u0631 \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">def get_langfuse_handler(session_id: str, user_id: str = \"local\"):\n    \"\"\"\n    Create a Langfuse callback handler for a session, or None if not configured.\n\n    The handler is a LangChain CallbackHandler that Langfuse provides.\n    When attached to graph.invoke(), it intercepts every LLM call, tool call,\n    and chain invocation automatically. No changes to agent code required.\n    \"\"\"\n    if not _langfuse_configured():\n        return None\n\n    try:\n        from langfuse.langchain import CallbackHandler\n\n        return CallbackHandler(\n            public_key=os.getenv(\"LANGFUSE_PUBLIC_KEY\"),\n            secret_key=os.getenv(\"LANGFUSE_SECRET_KEY\"),\n            host=os.getenv(\"LANGFUSE_HOST\", \"http:\/\/localhost:3000\"),\n            session_id=session_id,\n            user_id=user_id,\n            tags=[\"learning-accelerator\", \"local-inference\"],\n            metadata={\n                \"model\":     os.getenv(\"OLLAMA_MODEL\", \"qwen2.5:7b\"),\n                \"framework\": \"langgraph\",\n            },\n        )\n    except ImportError:\n        print(\"[Observability] langfuse not installed. Run: pip install langfuse\")\n        return None\n    except Exception as e:\n        print(f\"[Observability] Failed to create handler: {e}\")\n        return None\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>session_id<\/code> \u0645\u0646\u062a\u0642\u0644\u06cc <code>CallbackHandler<\/code> Langfuse UI \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0645\u0637\u0627\u0644\u0639\u0627\u062a\u06cc \u0633\u06cc\u0634\u0646 \u06a9\u06d2 \u062a\u0645\u0627\u0645 \u0646\u0634\u0627\u0646\u0627\u062a \u06a9\u0648 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u06af\u0631\u0648\u067e \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u0633 \u0633\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u0645\u0627\u0645 LLM \u06a9\u0627\u0644\u0632\u060c \u0679\u0648\u0644 \u06a9\u0627\u0644\u0632\u060c \u0627\u0648\u0631 \u0646\u0648\u0688 \u0627\u06cc\u06af\u0632\u06cc\u06a9\u06cc\u0648\u0634\u0646\u0632 \u0633\u0646\u06af\u0644 \u0633\u06cc\u0634\u0646 \u0648\u06cc\u0648 \u06a9\u06d2 \u062a\u062d\u062a \u062f\u06a9\u06be\u0627\u0626\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0622\u067e \u0627\u067e\u0646\u06d2 \u0645\u0642\u0635\u062f \u0645\u06cc\u06ba \u062f\u0627\u062e\u0644 \u06c1\u0648\u0646\u06d2 \u0633\u06d2 \u0644\u06d2 \u06a9\u0631 \u06a9\u0648\u0626\u0632 \u06a9\u06d2 \u062d\u062a\u0645\u06cc \u0646\u062a\u0627\u0626\u062c \u062a\u06a9 \u067e\u0648\u0631\u06d2 \u0627\u0646\u0641\u0631\u0646\u0633 \u0686\u06cc\u0646 \u06a9\u06cc \u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06a9\u06c1 <code>tags<\/code> \u0644\u0633\u0679 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u0645\u06cc\u06ba \u0641\u0644\u0679\u0631 \u0627\u06cc\u0628\u0644 \u0644\u06cc\u0628\u0644\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0645\u062a\u0639\u062f\u062f \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u0686\u0644\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c <code>\"learning-accelerator\"<\/code> \u0622\u067e \u0627\u0633 \u0633\u0633\u0679\u0645 \u0633\u06d2 \u0635\u0631\u0641 \u0646\u0634\u0627\u0646\u0627\u062a \u06a9\u0648 \u0641\u0644\u0679\u0631 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">def get_langfuse_config(\n    session_id: str,\n    user_id: str = \"local\",\n    extra_config: dict | None = None,\n) -> dict:\n    \"\"\"\n    Build the complete LangGraph run config for a session.\n\n    Merges the checkpoint thread_id with the Langfuse callback handler.\n    This is the only function main.py calls. One function, one config dict,\n    everything set up.\n\n    Returns a dict ready to pass as `config` to graph.invoke().\n    \"\"\"\n    config = {\n        \"configurable\": {\"thread_id\": session_id},\n    }\n\n    if extra_config:\n        config.update(extra_config)\n\n    handler = get_langfuse_handler(session_id, user_id)\n    if handler:\n        config[\"callbacks\"] = [handler]\n        print(f\"[Observability] Tracing session {session_id} \u2192 \"\n              f\"{os.getenv('LANGFUSE_HOST', 'http:\/\/localhost:3000')}\")\n    else:\n        print(f\"[Observability] Langfuse not configured. Running without tracing.\")\n\n    return config\n<\/code><\/pre>\n<p><code>get_langfuse_config<\/code> \u062f\u0648\u0646\u0648\u06ba \u062e\u062f\u0634\u0627\u062a \u06a9\u0648 \u0627\u06cc\u06a9 \u0688\u06a9\u0679 \u0645\u06cc\u06ba \u0636\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>thread_id<\/code> \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679\u0646\u06af \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u06cc\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>callbacks<\/code> \u0648\u06c1 \u0641\u06c1\u0631\u0633\u062a \u062c\u0648 LangChain \u0645\u0634\u0627\u06c1\u062f\u0627\u062a\u06cc \u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u0648 \u0631\u0648\u0679 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0646 \u062f\u0648 \u06a9\u0644\u06cc\u062f\u0648\u06ba \u06a9\u06d2 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0631\u06c1\u0646\u06d2 \u06a9\u06cc \u0648\u062c\u0648\u06c1\u0627\u062a \u062f\u0631\u062c \u0630\u06cc\u0644 \u06c1\u06cc\u06ba: <code>graph.invoke(state, config=config)<\/code> \u0631\u0648\u0679\u0646\u06af \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0648\u0631\u06cc \u062a\u0631\u062a\u06cc\u0628 \u06a9\u0648 LangGraph \u067e\u0631 \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>configurable<\/code> \u067e\u0648\u0627\u0626\u0646\u0679\u0631 \u06a9\u0644\u06cc\u062f \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 <code>callbacks<\/code> \u06a9\u0627\u0644 \u0628\u06cc\u06a9 \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba\u06d4 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0646\u0638\u0627\u0645 \u062f\u0648\u0633\u0631\u06d2 \u0645\u06cc\u06ba \u0645\u062f\u0627\u062e\u0644\u062a \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627\u06d4<\/p>\n<pre><code class=\"language-python\">def flush_langfuse() -> None:\n    \"\"\"\n    Flush pending traces before process exit.\n\n    Langfuse sends traces in a background thread. Without this call,\n    the last few seconds of traces may be lost when the process exits.\n    Call this at the end of main.py, after all graph.invoke() calls.\n    \"\"\"\n    if not _langfuse_configured():\n        return\n    try:\n        from langfuse import Langfuse\n        Langfuse().flush()\n    except Exception:\n        pass  # Best-effort. Don't crash on exit.\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>flush<\/code> \u0627\u0635\u0644 \u0645\u06cc\u06ba \u0627\u0633\u06d2 \u0627\u06cc\u06a9 \u0645\u0633\u0626\u0644\u06c1 \u06a9\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 Langfuse \u0628\u06cc\u0686\u0648\u06ba \u06a9\u0627 \u0646\u0634\u0627\u0646 \u0644\u06af\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0646\u06c1\u06cc\u06ba \u063a\u06cc\u0631 \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u0637\u0648\u0631 \u067e\u0631 \u0628\u06be\u06cc\u062c\u062a\u0627 \u06c1\u06d2\u06d4 \u0645\u062e\u062a\u0635\u0631 \u0686\u0644\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0639\u0645\u0644 \u062c\u06cc\u0633\u06d2: <code>python main.py<\/code> \u0622\u067e \u0628\u06cc\u0686 \u0628\u06be\u06cc\u062c\u06d2 \u062c\u0627\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0686\u06be\u0648\u0691 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>flush()<\/code> \u06cc\u06c1 \u0627\u0633 \u0648\u0642\u062a \u062a\u06a9 \u0628\u0644\u0627\u06a9 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0628 \u062a\u06a9 \u06a9\u06c1 \u0642\u0637\u0627\u0631 \u062e\u0627\u0644\u06cc \u0646\u06c1 \u06c1\u0648\u06d4<\/p>\n<h3 id=\"heading-63-the-single-integration-point\">6.3 \u0627\u0646\u0636\u0645\u0627\u0645 \u06a9\u0627 \u0648\u0627\u062d\u062f \u0646\u0642\u0637\u06c1<\/h3>\n<p>\u0645\u0646\u062f\u0631\u062c\u06c1 \u0628\u0627\u0644\u0627 \u062a\u0645\u0627\u0645 <code>main.py<\/code> \u0628\u0627\u0644\u06a9\u0644 \u062f\u0648 \u062c\u06af\u06c1\u0648\u06ba \u067e\u0631:<\/p>\n<pre><code class=\"language-python\"># main.py\n\nfrom observability.langfuse_setup import get_langfuse_config, flush_langfuse\n\ndef run_session(goal: str, session_id: str | None = None) -> None:\n    ...\n    # One function call replaces: {\"configurable\": {\"thread_id\": session_id}}\n    # It returns that same dict, plus callbacks if Langfuse is configured.\n    config = get_langfuse_config(session_id)\n\n    result = graph.invoke(state, config=config)\n    while \"__interrupt__\" in result:\n        ...\n        result = graph.invoke(Command(resume=user_input), config=config)\n\n    print_session_summary(result)\n\n    # Flush before exit\n    flush_langfuse()\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u0645\u06a9\u0645\u0644 \u0627\u0646\u0636\u0645\u0627\u0645 \u06c1\u06d2\u06d4 \u0627\u06cc\u062c\u0646\u0679 \u0641\u0627\u0626\u0644 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u062f\u0631\u0622\u0645\u062f\u0627\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u06a9\u0627\u0644\u06cc\u06ba \u067e\u0648\u0631\u06d2 \u06a9\u0648\u0688 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u062a\u0642\u0633\u06cc\u0645 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0646\u0648\u0688 \u06a9\u06d2 \u0627\u0641\u0639\u0627\u0644 \u0645\u06cc\u06ba \u0645\u0634\u0631\u0648\u0637 \u0686\u06cc\u06a9 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06a9\u0627\u0644 \u0628\u06cc\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 LangChain \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u06cc \u0633\u0637\u062d \u067e\u0631 \u06a9\u0627\u0644\u0648\u06ba \u06a9\u0648 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u0622\u067e \u06a9\u0627 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648\u0688 \u0648\u06c1\u06cc \u0631\u06c1\u06d2 \u06af\u0627\u06d4<\/p>\n<h4 id=\"heading-what-the-callback-system-captures-automatically\"> \u06a9\u0627\u0644 \u0628\u06cc\u06a9 \u0633\u0633\u0679\u0645 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u06a9\u06cc\u0627 \u062d\u0627\u0635\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/h4>\n<p>\u06a9\u06c1 <code>CallbackHandler<\/code> LangChain \u06a9\u06d2 \u06a9\u0627\u0644 \u0628\u06cc\u06a9 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u0633\u06d2 \u062c\u0691\u062a\u0627 \u06c1\u06d2\u06d4 LangChain \u06c1\u0645 \u0622\u06c1\u0646\u06af \u0627\u0634\u06cc\u0627\u0621 (<code>ChatOllama<\/code>\u06a9\u0627\u0644 \u0628\u06cc\u06a9 \u0627\u06cc\u0648\u0646\u0679 \u0627\u0633 \u0648\u0642\u062a \u0641\u0627\u0626\u0631 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0628 \u06a9\u0648\u0626\u06cc \u0679\u0648\u0644 (\u0679\u0648\u0644\u060c \u0686\u06cc\u0646\u060c \u06af\u0631\u0627\u0641 \u0646\u0648\u0688) \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u0634\u0631\u0648\u0639 \u06cc\u0627 \u0645\u06a9\u0645\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u06a9\u0627 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0627\u0633\u06d2 \u067e\u06a9\u0691\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0679\u0631\u06cc\u06a9\u0646\u06af \u0627\u0633\u06a9\u0648\u067e \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u0646\u0638\u0627\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06cc\u06c1 \u0633\u0628 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2\u06d4 <code>llm.invoke()<\/code> \u062a\u0645\u0627\u0645 5 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u060c <code>TOOL_MAP[name].invoke(args)<\/code> \u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u06a9\u06d2 \u0679\u0648\u0644 \u06a9\u0627\u0644 \u0644\u0648\u067e \u0645\u06cc\u06ba\u060c \u06a9\u0627\u0644\u060c \u06c1\u0631 \u0646\u0648\u0688 \u06a9\u06d2 \u0622\u063a\u0627\u0632 \u0627\u0648\u0631 \u0627\u062e\u062a\u062a\u0627\u0645 \u06a9\u0627 \u0648\u0642\u062a\u060c \u0627\u0648\u0631 \u06c1\u0631 \u0645\u0631\u062d\u0644\u06d2 \u06a9\u06cc \u0645\u06a9\u0645\u0644 \u0645\u06cc\u0633\u062c \u06c1\u0633\u0679\u0631\u06cc \u06a9\u06cc\u067e\u0686\u0631 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u060c \u06cc\u06c1 \u0633\u0628 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u06a9\u0648\u0688 \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631\u06d4<\/p>\n<h3 id=\"heading-64-what-you-see-in-the-langfuse-ui\">6.4 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 UI \u06a9\u06cc\u0627 \u062f\u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/h3>\n<p>Langfuse \u062a\u0631\u062a\u06cc\u0628 \u0634\u062f\u06c1 \u0633\u06cc\u0634\u0646 \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-bash\">python main.py \"Learn Python closures\"\n<\/code><\/pre>\n<p>http:\/\/localhost:3000 \u06a9\u06be\u0648\u0644\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633 \u067e\u0631 \u062c\u0627\u0626\u06cc\u06ba: <strong>\u062b\u0628\u0648\u062a<\/strong>. \u0622\u067e \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0633\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0646\u0634\u0627\u0646 \u0646\u0638\u0631 \u0622\u0626\u06d2 \u06af\u0627\u06d4 \u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u067e\u06be\u06cc\u0644\u0627\u0626\u06cc\u06ba:<\/p>\n<pre><code class=\"language-plaintext\">Session: a3f1b2c4\n  \u251c\u2500\u2500 curriculum_planner_node       245ms\n  \u2502     \u2514\u2500\u2500 ChatOllama.invoke       238ms\n  \u2502           input:  \"Create a study roadmap for...\"\n  \u2502           output: {\"goal\": \"Learn Python closures\", \"topics\": [...]}\n  \u2502\n  \u251c\u2500\u2500 human_approval_node           (interrupted, user input collected)\n  \u2502\n  \u251c\u2500\u2500 explainer_node                4,821ms\n  \u2502     \u251c\u2500\u2500 ChatOllama.invoke       312ms   \u2192 tool_list_files()\n  \u2502     \u251c\u2500\u2500 tool_list_files         2ms     \u2190 [\"closures.md\", ...]\n  \u2502     \u251c\u2500\u2500 ChatOllama.invoke       287ms   \u2192 tool_read_file(\"closures.md\")\n  \u2502     \u251c\u2500\u2500 tool_read_file          1ms     \u2190 \"# Python Closuresn...\"\n  \u2502     \u251c\u2500\u2500 ChatOllama.invoke       1,204ms \u2192 (no tool calls. final explanation)\n  \u2502     \u2514\u2500\u2500 tool_memory_set         1ms\n  \u2502\n  \u251c\u2500\u2500 quiz_generator_node           8,342ms\n  \u2502     \u251c\u2500\u2500 ChatOllama.invoke       1,890ms  (question generation)\n  \u2502     \u251c\u2500\u2500 ChatOllama.invoke       892ms    (grading Q1)\n  \u2502     \u251c\u2500\u2500 ChatOllama.invoke       874ms    (grading Q2)\n  \u2502     \u2514\u2500\u2500 ChatOllama.invoke       891ms    (grading Q3)\n  \u2502\n  \u2514\u2500\u2500 progress_coach_node           1,102ms\n        \u2514\u2500\u2500 ChatOllama.invoke       1,088ms\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u0679\u0631\u06cc\u0633 \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u062a\u06cc\u0646 \u0686\u06cc\u0632\u0648\u06ba \u06a9\u0648 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0627\u0646\u0641\u0631\u0627\u0633\u0679\u0631\u06a9\u0686\u0631 \u0645\u06cc\u0679\u0631\u06a9\u0633 \u0638\u0627\u06c1\u0631 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba:<\/p>\n<ol>\n<li>\n<p><strong>\u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06c1 \u062a\u0627\u062e\u06cc\u0631 \u06a9\u0627 \u062a\u062c\u0632\u06cc\u06c1\u06d4<\/strong> \u06a9\u0648\u0626\u0632 \u062c\u0646\u0631\u06cc\u0679\u0631 \u0686\u0627\u0631 LLM \u06a9\u0627\u0644\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 8 \u0633\u06cc\u06a9\u0646\u0688 \u0644\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0628 \u062a\u0627\u062e\u06cc\u0631 \u06a9\u0648 \u0628\u06c1\u062a\u0631 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u060c \u062a\u0648 \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u0648\u0627\u0644\u06cc \u06a9\u0627\u0644\u0632 \u06a9\u0627 \u0645\u0642\u0635\u062f \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0631 \u0627\u06cc\u06a9 ~900ms \u06a9\u06cc \u062a\u06cc\u0646 \u06a9\u0627\u0644\u06cc\u06ba\u060c \u0645\u0645\u06a9\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u0645\u062a\u0648\u0627\u0632\u06cc\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0679\u0648\u0644 \u06a9\u0627\u0644\u0646\u06af \u0622\u0631\u0688\u0631\u06d4<\/strong> \u0627\u06cc\u06a9 \u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u0646\u06d2 \u0628\u0644\u0627\u06cc\u0627\u06d4 <code>tool_list_files<\/code>\u067e\u06be\u0631 <code>tool_read_file<\/code>\u067e\u06be\u0631 \u0645\u06cc\u06ba \u0646\u06d2 \u0627\u0633\u06d2 \u0635\u062d\u06cc\u062d \u062a\u0631\u062a\u06cc\u0628 \u0645\u06cc\u06ba \u0645\u06cc\u0645\u0648\u0631\u06cc \u067e\u0631 \u0644\u06a9\u06be\u0627\u06d4 \u0627\u06af\u0631 \u0648\u06c1 \u063a\u0644\u0637 \u062a\u0631\u062a\u06cc\u0628 \u0645\u06cc\u06ba \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u06a9\u0648\u0688 \u06a9\u0648 \u062f\u06cc\u06a9\u06be\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06cc\u06c1\u0627\u06ba \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u06c1\u0631 \u0645\u0631\u062d\u0644\u06d2 \u067e\u0631 \u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u0627\u0646 \u067e\u0679 \u0627\u0648\u0631 \u0622\u0624\u0679 \u067e\u0679\u06d4<\/strong> \u0627\u06af\u0631 Curriculum Planner \u0627\u06cc\u06a9 \u063a\u0644\u0637 \u0631\u0648\u0688 \u0645\u06cc\u067e \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u06a9\u0648 \u0679\u0631\u06cc\u0633 \u0645\u06cc\u06ba \u062e\u0627\u0645 LLM \u0622\u0624\u0679 \u067e\u0679 \u0646\u0638\u0631 \u0622\u0626\u06d2 \u06af\u0627\u06d4 \u0627\u06af\u0631 \u06af\u0631\u06cc\u0688\u0631 \u0622\u067e \u06a9\u0648 \u063a\u0644\u0637 \u0633\u06a9\u0648\u0631 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u067e \u06a9\u0648 \u06a9\u06cc\u0627 \u0645\u0644\u0627 \u0627\u0648\u0631 \u0622\u067e \u0646\u06d2 \u06a9\u06cc\u0627 \u0648\u0627\u067e\u0633 \u06a9\u06cc\u0627\u06d4<\/p>\n<\/li>\n<\/ol>\n<h3 id=\"heading-65-graceful-degradation\">6.5 \u0645\u06a9\u0631\u0645 \u0627\u0646\u062d\u0637\u0627\u0637<\/h3>\n<p>\u0633\u0633\u0679\u0645 \u06a9\u0648 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06cc\u0627 \u0627\u0633 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u06cc\u06a9\u0633\u0627\u06ba \u0637\u0648\u0631 \u067e\u0631 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u0645\u062a\u063a\u06cc\u0631\u0627\u062a \u0645\u0631\u062a\u0628 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>_langfuse_configured()<\/code> False \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>get_langfuse_config<\/code> \u06cc\u06c1 \u062f\u0631\u062c \u0630\u06cc\u0644 \u06a9\u0645 \u0633\u06d2 \u06a9\u0645 \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>thread_id<\/code>:<\/p>\n<pre><code class=\"language-python\"># Without Langfuse configured\nconfig = get_langfuse_config(\"a3f1b2c4\")\n# Returns: {\"configurable\": {\"thread_id\": \"a3f1b2c4\"}}\n\n# With Langfuse configured\nconfig = get_langfuse_config(\"a3f1b2c4\")\n# Returns: {\"configurable\": {\"thread_id\": \"a3f1b2c4\"},\n#           \"callbacks\": [<callbackhandler>]}\n<\/callbackhandler><\/code><\/pre>\n<p>\u0627\u06cc\u062c\u0646\u0679 \u0646\u0648\u0688\u0633 \u06a9\u0648 \u0627\u0633 \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646 \u06a9\u0627 \u06a9\u0648\u0626\u06cc \u0648\u0631\u0698\u0646 \u0645\u0648\u0635\u0648\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u06af\u0627\u06d4 \u0648\u06c1 \u0635\u0631\u0641 \u0648\u0635\u0648\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba <code>state<\/code>. \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 LangGraph \u0627\u0648\u0631 LangChain \u0627\u0646\u0641\u0631\u0627\u0633\u0679\u0631\u06a9\u0686\u0631 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u06a9\u0627\u0631\u0648\u0628\u0627\u0631\u06cc \u0645\u0646\u0637\u0642 \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1 \u0635\u062d\u06cc\u062d \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u067e\u06cc\u0679\u0631\u0646 \u06c1\u06d2. \u0645\u0634\u0627\u06c1\u062f\u0627\u062a\u06cc \u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u06be\u0627\u0646\u0686\u06c1 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2 \u0627\u0648\u0631 \u062e\u0648\u0628\u0635\u0648\u0631\u062a\u06cc \u0633\u06d2 \u0627\u0646\u062d\u0637\u0627\u0637 \u067e\u0630\u06cc\u0631 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2\u06d4 \u0679\u0631\u06cc\u06a9\u0646\u06af \u0628\u06cc\u06a9 \u0627\u06cc\u0646\u0688 \u0645\u06cc\u06ba \u0628\u0646\u062f\u0634 \u0633\u06d2 \u0622\u067e \u06a9\u06cc \u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u06a9\u0631\u06cc\u0634 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0646\u06cc \u0686\u0627\u06c1\u06cc\u06d2\u06d4<\/p>\n<h3 id=\"heading-66-run-the-observability-tests\">6.6 \u0645\u0634\u0627\u06c1\u062f\u0627\u062a\u06cc \u0679\u06cc\u0633\u0679 \u0686\u0644\u0627\u0646\u0627<\/h3>\n<pre><code class=\"language-bash\">pytest tests\/test_observability.py -v\n<\/code><\/pre>\n<p>\u0645\u062a\u0648\u0642\u0639: 16 \u0679\u06cc\u0633\u0679 \u067e\u0627\u0633 \u06c1\u0648\u0626\u06d2\u060c \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u0633\u0631\u0648\u0631 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0679\u06cc\u0633\u0679 \u06a9\u0627 \u0645\u0630\u0627\u0642 \u0627\u0691\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2: <code>_langfuse_configured<\/code> \u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u06cc\u06ba:<\/p>\n<ul>\n<li>\n<p><code>get_langfuse_config<\/code> \u06c1\u0645\u06cc\u0634\u06c1 \u0634\u0627\u0645\u0644 <code>thread_id<\/code> \u06a9\u0648 <code>configurable<\/code><\/p>\n<\/li>\n<li>\n<p>\u0646\u06c1\u06cc\u06ba <code>callbacks<\/code> \u06a9\u0644\u06cc\u062f \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u0627\u06af\u0631 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u06a9\u0646\u0641\u06cc\u06af\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><code>flush_langfuse<\/code> \u0627\u06af\u0631 \u0627\u0633\u0646\u0627\u062f \u063a\u0627\u0626\u0628 \u06c1\u06cc\u06ba \u062a\u0648 \u06cc\u06c1 \u06a9\u0627\u0645 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u06d2 \u06af\u0627\u06d4<\/p>\n<\/li>\n<li>\n<p><code>get_langfuse_handler<\/code> \u0631\u067e\u0648\u0631\u0679 <code>None<\/code> \u06a9\u0648 <code>ImportError<\/code> \u0627\u0633\u06d2 \u0627\u0679\u06be\u0627\u0626\u06d2 \u0628\u063a\u06cc\u0631<\/p>\n<\/li>\n<\/ul>\n<p>\u0627\u0646 \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0679\u06cc\u0633\u0679 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u0633\u0631\u0648\u0631 \u06a9\u0648 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0627\u0646\u0636\u0645\u0627\u0645 \u06a9\u06cc \u0645\u0646\u0637\u0642\u060c \u06cc\u0639\u0646\u06cc \u0645\u0627\u0688\u06cc\u0648\u0644 \u062a\u0631\u062a\u06cc\u0628 \u0634\u062f\u06c1 \u0627\u0648\u0631 \u063a\u06cc\u0631 \u062a\u0634\u06a9\u06cc\u0644 \u0634\u062f\u06c1 \u062f\u0648\u0646\u0648\u06ba \u062d\u0627\u0644\u062a\u0648\u06ba \u0645\u06cc\u06ba \u0635\u062d\u06cc\u062d \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0646\u0679\u0631\u067e\u0631\u0627\u0626\u0632 \u06a9\u0646\u06cc\u06a9\u0679\u06cc\u0648\u06cc\u0679\u06cc: \u0631\u06cc\u06af\u0648\u0644\u06cc\u0679\u0688 \u0635\u0646\u0639\u062a\u0648\u06ba \u0645\u06cc\u06ba \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645 \u0645\u0634\u0627\u06c1\u062f\u06d2 \u06a9\u0627 \u0627\u062a\u0646\u0627 \u06c1\u06cc \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u062a\u0646\u0627 \u062a\u0639\u0645\u06cc\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u06cc\u0628\u06af\u0646\u06af \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u0679\u0631\u06cc\u0633 \u062a\u0645\u0627\u0645 LLM \u06a9\u0627\u0644\u0632 (\u0627\u0646 \u067e\u0679\u060c \u0622\u0624\u0679 \u067e\u0679\u060c \u0679\u0627\u0626\u0645 \u0627\u0633\u0679\u06cc\u0645\u067e\u060c \u0633\u06cc\u0634\u0646 \u0622\u0626\u06cc \u0688\u06cc) \u06a9\u0627 \u0642\u0627\u0628\u0644 \u0633\u0645\u0627\u0639\u062a \u0631\u06cc\u06a9\u0627\u0631\u0688 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0646\u06c1\u06cc\u06ba \u0631\u06cc\u06af\u0648\u0644\u06cc\u0679\u0631\u06cc \u062c\u0627\u0626\u0632\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u0631\u0622\u0645\u062f \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u0648\u06c1\u06cc \u0679\u0631\u06cc\u0633 \u062c\u0648 \u0622\u067e \u06a9\u0648 \u06a9\u0648\u0626\u0632 \u06a9\u06d2 \u063a\u0644\u0637 \u0627\u0633\u06a9\u0648\u0631\u0632 \u06a9\u0648 \u0688\u06cc\u0628\u06af \u06a9\u0631\u0646\u06d2 \u0645\u06cc\u06ba \u0645\u062f\u062f \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0648\u06c1 \u0622\u0688\u06cc\u0679\u0631\u0632 \u06a9\u0648 \u062f\u06a9\u06be\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0645\u0627\u0688\u0644 \u0646\u06d2 \u06a9\u06cc\u0627 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u06cc\u0627 \u0627\u0648\u0631 \u0627\u0633 \u0646\u06d2 \u06a9\u06cc\u0627 \u062a\u06cc\u0627\u0631 \u06a9\u06cc\u0627\u06d4<\/p>\n<p>\u0627\u06af\u0644\u0627 \u0628\u0627\u0628 \u062e\u0648\u062f\u06a9\u0627\u0631 \u0645\u0639\u06cc\u0627\u0631 \u06a9\u06cc \u062a\u0634\u062e\u06cc\u0635 \u06a9\u0627 \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 DeepEval \u0627\u06cc\u06a9 LLM-\u062c\u062c\u0645\u0646\u0679 \u0679\u06cc\u0633\u0679 \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0627\u06a9\u06c1 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u06d2 \u06a9\u06c1 \u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u06a9\u0627 \u0622\u0624\u0679 \u067e\u0679 \u0646\u0648\u0679\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0648\u0641\u0627\u062f\u0627\u0631 \u06c1\u06d2 \u0627\u0648\u0631 \u06a9\u0648\u0626\u0632 \u062c\u0646\u0631\u06cc\u0679\u0631 \u06a9\u06d2 \u0633\u0648\u0627\u0644\u0627\u062a \u0645\u0648\u0636\u0648\u0639 \u0633\u06d2 \u0645\u062a\u0639\u0644\u0642 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-chapter-7-evaluating-agent-quality-with-deepeval\">\u0628\u0627\u0628 7: \u0688\u06cc\u067e \u0627\u06cc\u0648\u0644 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u0645\u0639\u06cc\u0627\u0631 \u06a9\u0627 \u062c\u0627\u0626\u0632\u06c1<\/h2>\n<p>\u0645\u0634\u0627\u06c1\u062f\u06c1 \u06c1\u0645\u06cc\u06ba \u0628\u062a\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06a9\u06cc\u0627 \u06c1\u0648\u0627 \u06c1\u06d2\u06d4 \u062a\u0634\u062e\u06cc\u0635 \u0622\u067e \u06a9\u0648 \u06cc\u06c1 \u062c\u0627\u0646\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06a9\u06cc\u0627 \u06c1\u0648\u0627 \u0627\u0686\u06be\u0627 \u06c1\u06d2 \u06cc\u0627 \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645 \u062d\u0642\u0627\u0626\u0642 \u0628\u06cc\u0627\u0646 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a\u06cc\u06ba\u060c \u0633\u0648\u0627\u0644\u0627\u062a \u062c\u0648 \u063a\u0644\u0637 \u06c1\u0648\u0646\u06d2 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0631\u06cc\u0679\u0646\u06af\u0632 \u062c\u0648 \u063a\u0644\u0637 \u062c\u0648\u0627\u0628\u0627\u062a \u06a9\u0648 \u062f\u0631\u0633\u062a \u0642\u0631\u0627\u0631 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0633\u0628 \u06a9\u0686\u06be \u063a\u0644\u0637\u06cc \u0633\u06d2 \u067e\u0627\u06a9 \u0645\u06a9\u0645\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u067e\u06cc\u062f\u0627 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u062e\u0627\u0645\u06cc\u0627\u06ba \u0627\u0646\u0641\u0631\u0627\u0633\u0679\u0631\u06a9\u0686\u0631 \u0645\u06cc\u0679\u0631\u06a9\u0633 \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u06cc\u0648\u0646\u0679 \u0679\u06cc\u0633\u0679\u0648\u06ba \u0645\u06cc\u06ba \u0646\u0638\u0631 \u0646\u06c1\u06cc\u06ba \u0622\u062a\u0627\u06d4 \u0627\u0633 \u06a9\u0648 \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0648\u0627\u062d\u062f \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0637\u0631\u06cc\u0642\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u062c\u062c\u0648\u06ba \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u062f\u0648\u0633\u0631\u06d2 LLM \u06a9\u06d2 \u0633\u0627\u062a\u06be LLM \u06a9\u06d2 \u0646\u062a\u0627\u0626\u062c \u06a9\u0627 \u062c\u0627\u0626\u0632\u06c1 \u0644\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u0628\u0627\u0628 \u0645\u06cc\u06ba\u060c \u06c1\u0645 \u062a\u062e\u0635\u06cc\u0635\u0627\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0688\u06cc\u067e \u0627\u06cc\u0648\u0644 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u062e\u0648\u062f\u06a9\u0627\u0631 \u0645\u0639\u06cc\u0627\u0631 \u06a9\u0627 \u062c\u0627\u0626\u0632\u06c1 \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>OllamaJudge<\/code> \u06a9\u0644\u0627\u0633 \u062a\u0645\u0627\u0645 \u062c\u0627\u0626\u0632\u06d2 \u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0686\u0644\u0627\u0626\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1\u0627\u06ba \u06a9\u0648\u0626\u06cc \u06a9\u0644\u0627\u0624\u0688 API \u06a9\u06cc\u0632 \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u06a9\u0648\u0626\u06cc \u0642\u06cc\u0645\u062a \u0641\u06cc \u062a\u0634\u062e\u06cc\u0635 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-71-llm-as-judge-evaluation\">7.1 \u0628\u0637\u0648\u0631 \u062c\u062c \u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u06cc \u062a\u0634\u062e\u06cc\u0635<\/h3>\n<p>LLM-\u062c\u062c\u0645\u0646\u0679 \u0627\u06cc\u06a9 \u0627\u06cc\u0633\u0627 \u0646\u0645\u0648\u0646\u06c1 \u06c1\u06d2 \u062c\u0648 \u0627\u06cc\u06a9 LLM \u06a9\u0627\u0644 \u06a9\u0648 \u062f\u0648\u0633\u0631\u06cc LLM \u06a9\u0627\u0644 \u06a9\u06d2 \u0646\u062a\u0627\u0626\u062c \u06a9\u0627 \u0627\u0646\u062f\u0627\u0632\u06c1 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u06a9\u06cc \u0637\u0631\u0641 \u0633\u06d2 \u067e\u06cc\u062f\u0627 \u06a9\u0631\u062f\u06c1 \u0648\u0636\u0627\u062d\u062a \u06a9\u0648 \u062f\u06cc\u06a9\u06be\u062a\u06d2 \u06c1\u0648\u0626\u06d2\u060c \u062c\u062c \u0645\u0627\u0688\u0644 \u0648\u0636\u0627\u062d\u062a \u0627\u0648\u0631 \u0633\u0648\u0631\u0633 \u0646\u0648\u0679\u0633 \u06a9\u0648 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0633\u0627\u062e\u062a\u06cc \u0633\u0648\u0627\u0644\u0627\u062a \u06a9\u06d2 \u062c\u0648\u0627\u0628\u0627\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 &quot;\u06a9\u06cc\u0627 \u0627\u0633 \u0648\u0636\u0627\u062d\u062a \u06a9\u06d2 \u062a\u0645\u0627\u0645 \u062f\u0639\u0648\u0648\u06ba \u06a9\u06cc \u062a\u0627\u0626\u06cc\u062f \u0646\u0648\u0679\u0648\u06ba \u0633\u06d2 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u061f&#8221;<\/p>\n<p>\u06cc\u06c1 \u0627\u06cc\u06a9 \u06a9\u0627\u0645\u0644 \u062a\u0634\u062e\u06cc\u0635 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u062c\u062c \u06a9\u0627 \u0645\u0627\u0688\u0644 \u0628\u06be\u06cc \u063a\u0644\u0637 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u0644\u06cc\u06a9\u0646 \u0645\u0639\u06cc\u0627\u0631 \u06a9\u06d2 \u062c\u0627\u0626\u0632\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u062c\u0648 \u06cc\u06c1\u0627\u06ba \u0627\u06c1\u0645 \u06c1\u06cc\u06ba (\u06a9\u06cc\u0627 \u0648\u0636\u0627\u062d\u062a\u06cc\u06ba \u062f\u06cc\u0627\u0646\u062a\u062f\u0627\u0631 \u06c1\u06cc\u06ba\u061f \u06a9\u06cc\u0627 \u0633\u0648\u0627\u0644\u0627\u062a \u0645\u062a\u0639\u0644\u0642\u06c1 \u06c1\u06cc\u06ba\u061f \u06a9\u06cc\u0627 \u0627\u0633\u06a9\u0648\u0631\u0646\u06af \u06a9\u0627 \u0639\u0645\u0644 \u0645\u0646\u0635\u0641\u0627\u0646\u06c1 \u06c1\u06d2\u061f)\u060c \u0627\u062d\u062a\u06cc\u0627\u0637 \u0633\u06d2 \u0631\u06c1\u0646\u0645\u0627\u0626\u06cc \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 LLM \u062c\u062c\u0632 \u0627\u0635\u0648\u0644 \u067e\u0631 \u0645\u0628\u0646\u06cc \u06c1\u06cc\u0648\u0631\u0633\u0679\u06a9\u0633 \u06a9\u0648 \u0645\u0633\u062a\u0642\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0628\u06c1\u062a\u0631 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0628\u0691\u06d2 \u067e\u06cc\u0645\u0627\u0646\u06d2 \u067e\u0631 \u0627\u0646\u0633\u0627\u0646\u06cc \u062c\u0627\u0626\u0632\u0648\u06ba \u0633\u06d2 \u06a9\u06c1\u06cc\u06ba \u0632\u06cc\u0627\u062f\u06c1 \u0639\u0645\u0644\u06cc \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>DeepEval \u0627\u06cc\u06a9 \u062a\u0634\u062e\u06cc\u0635\u06cc \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u062c\u062c\u0648\u06ba \u06a9\u06cc \u0641\u0648\u0631\u06cc \u062a\u0634\u06a9\u06cc\u0644\u060c \u0627\u0633\u06a9\u0648\u0631\u0646\u06af \u0631\u0648\u0628\u0631\u06a9\u0633\u060c \u0627\u0648\u0631 \u0645\u06cc\u0679\u0631\u06a9 \u062c\u0645\u0639 \u06a9\u0648 \u0633\u0646\u0628\u06be\u0627\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u0679\u06cc\u0633\u0679 \u06a9\u06cc\u0633\u0632 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u067e\u0646\u06cc \u0645\u0631\u0636\u06cc \u06a9\u06d2 \u0645\u0627\u0688\u0644 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-72-the-ollamajudge-class\">7.2 \u0627\u0648\u0644\u0627\u0645\u0627 \u062c\u062c \u06a9\u0644\u0627\u0633<\/h3>\n<p>\u0688\u06cc\u067e \u0627\u06cc\u0648\u0644 \u0628\u0637\u0648\u0631 \u0688\u06cc\u0641\u0627\u0644\u0679 OpenAI \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0634\u062e\u06cc\u0635 \u06a9\u0648 \u0645\u0642\u0627\u0645\u06cc \u0631\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0630\u06cc\u0644\u06cc \u06a9\u0644\u0627\u0633 \u0644\u06a9\u06be\u06cc\u06ba\u06d4 <code>DeepEvalBaseLLM<\/code> \u0627\u067e\u0646\u06d2 \u0627\u0648\u0644\u0627\u0645\u0627 \u0645\u062b\u0627\u0644 \u0633\u06d2 \u062c\u0691\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\"># tests\/test_eval.py\n\nimport os\nfrom deepeval.models import DeepEvalBaseLLM\nfrom langchain_ollama import ChatOllama\n\n\nclass OllamaJudge(DeepEvalBaseLLM):\n    \"\"\"\n    Custom judge model using local Ollama.\n\n    DeepEval supports custom models via the DeepEvalBaseLLM interface.\n    We wrap ChatOllama to provide synchronous and async generation.\n\n    The judge runs at temperature=0.0 for consistency. The same answer\n    evaluated twice should produce the same score.\n    \"\"\"\n\n    def __init__(self):\n        self.model_name = os.getenv(\"OLLAMA_MODEL\", \"qwen2.5:7b\")\n        self.base_url   = os.getenv(\"OLLAMA_BASE_URL\", \"http:\/\/localhost:11434\")\n\n    def load_model(self):\n        return ChatOllama(\n            model=self.model_name,\n            base_url=self.base_url,\n            temperature=0.0,   # Deterministic for evaluation\n        )\n\n    def generate(self, prompt: str) -> str:\n        return self.load_model().invoke(prompt).content\n\n    async def a_generate(self, prompt: str) -> str:\n        return self.generate(prompt)\n\n    def get_model_name(self) -> str:\n        return f\"ollama\/{self.model_name}\"\n\n\ndef get_judge_model():\n    \"\"\"Return an OllamaJudge, or None if deepeval is not installed.\"\"\"\n    try:\n        return OllamaJudge()\n    except ImportError:\n        return None\n<\/code><\/pre>\n<p><code>temperature=0.0<\/code> \u062c\u062c \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u0627\u0646\u062a\u062e\u0627\u0628 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0622\u067e \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u067e \u06a9\u06cc \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u0645\u0633\u062a\u062d\u06a9\u0645 \u06c1\u0648\u06d4 \u0627\u06cc\u06a9 \u06c1\u06cc \u0679\u06cc\u0633\u0679 \u06a9\u0648 \u062f\u0648 \u0628\u0627\u0631 \u0686\u0644\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u06c1\u06cc \u0633\u06a9\u0648\u0631 \u062d\u0627\u0635\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u0632\u06cc\u0627\u062f\u06c1 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u0627\u062a\u0627\u0631 \u0686\u0691\u06be\u0627\u0624 \u0645\u062a\u0639\u0627\u0631\u0641 \u06a9\u0631\u0648\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0633 \u0633\u06d2 \u06cc\u06c1 \u0628\u062a\u0627\u0646\u0627 \u0645\u0634\u06a9\u0644 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u06cc\u0627 \u0627\u0633\u06a9\u0648\u0631 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u0645\u0639\u06cc\u0627\u0631 \u0645\u06cc\u06ba \u062d\u0642\u06cc\u0642\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc\u0648\u06ba \u06a9\u06cc \u0639\u06a9\u0627\u0633\u06cc \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba \u06cc\u0627 \u0628\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u0646\u0645\u0648\u0646\u06d2 \u0644\u06cc\u0646\u06d2 \u0633\u06d2\u06d4<\/p>\n<h3 id=\"heading-73-the-two-tier-test-strategy\">7.3 \u062f\u0648 \u062f\u0631\u062c\u06d2 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06cc \u062d\u06a9\u0645\u062a \u0639\u0645\u0644\u06cc<\/h3>\n<p>\u0679\u06cc\u0633\u0679 \u0633\u0648\u06cc\u0679 \u0645\u062e\u062a\u0644\u0641 \u0627\u06cc\u06af\u0632\u06cc\u06a9\u06cc\u0648\u0634\u0646 \u067e\u0631\u0648\u0641\u0627\u0626\u0644\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062f\u0648 \u062f\u0631\u062c\u0648\u06ba \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u06cc\u0648\u0646\u0679 \u0679\u06cc\u0633\u0679\u0646\u06af<\/strong> \u06cc\u06c1 \u062a\u06cc\u0632 \u06c1\u06d2\u060c \u0627\u0648\u0644\u0627\u0645\u0627 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0627\u0648\u0631 \u062c\u0628 \u0628\u06be\u06cc \u0622\u067e \u06a9\u0627 \u06a9\u0648\u0688 \u062a\u0628\u062f\u06cc\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0633\u0627\u062e\u062a\u06cc \u0645\u0639\u0627\u06c1\u062f\u06d2 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>generate_questions<\/code> \u06a9\u06cc\u0627 \u0622\u067e \u0635\u062d\u06cc\u062d \u06a9\u0644\u06cc\u062f\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0644\u063a\u0627\u062a \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a \u0648\u0627\u067e\u0633 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u061f \u06a9\u0631\u0648 <code>grade_answer<\/code> \u06c1\u0645\u06cc\u0634\u06c1 \u0627\u06cc\u06a9 \u0688\u06a9\u0679 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>correct<\/code>\u060c <code>score<\/code>\u0627\u0648\u0631 <code>feedback<\/code>? \u06a9\u0631\u0648 <code>get_coaching_message<\/code> \u06c1\u0645\u06cc\u0634\u06c1 \u0648\u0627\u067e\u0633 \u0622\u0648 <code>summary<\/code> \u0627\u0648\u0631 <code>encouragement<\/code>?<\/p>\n<p><strong>\u062a\u0634\u062e\u06cc\u0635 \u0679\u06cc\u0633\u0679<\/strong> \u0648\u06c1 \u0633\u0633\u062a \u06c1\u06cc\u06ba (\u06c1\u0631 \u0627\u06cc\u06a9 30-120 \u0633\u06cc\u06a9\u0646\u0688)\u060c \u0627\u0648\u0644\u0627\u0645\u0627 \u06a9\u0648 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0628\u0691\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc\u0648\u06ba \u06cc\u0627 \u0631\u06cc\u0644\u06cc\u0632 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u062f\u0648\u0691\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0645\u0639\u06cc\u0627\u0631 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06a9\u06cc\u0627 \u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u06a9\u06cc \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u0646\u0648\u0679\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0648\u0641\u0627\u062f\u0627\u0631 \u06c1\u06d2\u061f \u06a9\u06cc\u0627 \u0631\u06cc\u0679\u0631 \u06a9\u06d2 \u0627\u0633\u06a9\u0648\u0631 \u0627\u0635\u0644 \u062c\u0648\u0627\u0628 \u06a9\u06d2 \u0645\u0639\u06cc\u0627\u0631 \u0633\u06d2 \u0645\u0645\u0627\u062b\u0644 \u06c1\u06cc\u06ba\u061f<\/p>\n<p>\u062c\u062f\u0627\u0626\u06cc \u062f\u0648 \u062c\u06af\u06c1\u0648\u06ba \u067e\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u0633\u0628 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 <code>pyproject.toml<\/code> \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba <code>addopts = \"-m 'not eval'\"<\/code> \u062a\u0648 <code>pytest tests\/<\/code> \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0637\u06d2 \u0634\u062f\u06c1 \u0637\u0648\u0631 \u067e\u0631\u060c \u062a\u0634\u062e\u06cc\u0635\u06cc \u0679\u06cc\u0633\u0679 \u06a9\u0648 \u0686\u06be\u0648\u0691 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-toml\">[tool.pytest.ini_options]\npythonpath = [\"src\"]\ntestpaths  = [\"tests\"]\nasyncio_mode = \"auto\"\naddopts    = \"-m 'not eval'\"\nmarkers = [\n    \"unit: fast tests, no external dependencies\",\n    \"eval: slow evaluation tests requiring Ollama (LLM-as-judge)\",\n]\n<\/code><\/pre>\n<p>\u062f\u0648\u0633\u0631\u0627\u060c \u062a\u0645\u0627\u0645 \u062a\u0634\u062e\u06cc\u0635\u06cc \u0679\u06cc\u0633\u0679 \u06a9\u06cc \u06a9\u0644\u0627\u0633\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0641\u0639\u0627\u0644 \u0627\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0633\u062c\u06d2 \u06c1\u0648\u0626\u06d2 \u06c1\u06cc\u06ba: <code>@pytest.mark.eval<\/code>:<\/p>\n<pre><code class=\"language-python\">@pytest.mark.eval\nclass TestExplainerQuality:\n    ...\n<\/code><\/pre>\n<p>\u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631 \u062a\u0634\u062e\u06cc\u0635\u06cc \u0679\u06cc\u0633\u0679 \u0686\u0644\u0627\u0626\u06cc\u06ba:<\/p>\n<pre><code class=\"language-bash\">pytest tests\/test_eval.py -m eval -v -s\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>-s<\/code> \u062c\u06be\u0646\u0688\u0627 \u0622\u0624\u0679 \u067e\u0679 \u06a9\u06cc\u067e\u0686\u0631 \u06a9\u0648 \u063a\u06cc\u0631 \u0641\u0639\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0633 \u0633\u06d2 \u0622\u067e \u0627\u067e\u0646\u06d2 \u0645\u0627\u0688\u0644 \u06a9\u06d2 \u0627\u0633\u06a9\u0648\u0631\u0632 \u0627\u0648\u0631 \u0646\u062a\u0627\u0626\u062c \u06a9\u0648 \u062d\u0642\u06cc\u0642\u06cc \u0648\u0642\u062a \u0645\u06cc\u06ba \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-74-shared-fixtures-in-conftestpy\">7.4 \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0633\u06c1\u0648\u0644\u06cc\u0627\u062a <code>conftest.py<\/code><\/h3>\n<p><code>tests\/conftest.py<\/code> \u062a\u0645\u0627\u0645 \u0679\u06cc\u0633\u0679 \u0641\u0627\u0626\u0644\u0648\u06ba \u0645\u06cc\u06ba \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0641\u06a9\u0633\u0686\u0631 \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\"># tests\/conftest.py\n\nimport sys\nfrom pathlib import Path\nimport pytest\n\nsys.path.insert(0, str(Path(__file__).parent.parent \/ \"src\"))\n\n\ndef pytest_configure(config):\n    \"\"\"Register custom markers so pytest doesn't warn about unknown marks.\"\"\"\n    config.addinivalue_line(\n        \"markers\",\n        \"eval: marks tests requiring Ollama (deselect with -m 'not eval')\"\n    )\n    config.addinivalue_line(\n        \"markers\",\n        \"unit: marks fast tests with no external dependencies\"\n    )\n\n\n@pytest.fixture\ndef sample_roadmap():\n    \"\"\"A minimal StudyRoadmap for use in unit tests.\"\"\"\n    from graph.state import StudyRoadmap, Topic\n    return StudyRoadmap(\n        goal=\"Learn Python closures\",\n        total_weeks=2,\n        topics=[\n            Topic(\n                title=\"Closures Explained\",\n                description=\"Understand how closures capture enclosing scope variables\",\n                estimated_minutes=60,\n            ),\n            Topic(\n                title=\"Practical Closure Patterns\",\n                description=\"Apply closures to real problems: factories, memoisation\",\n                estimated_minutes=45,\n                prerequisites=[\"Closures Explained\"],\n            ),\n        ],\n    )\n\n\n@pytest.fixture\ndef sample_state(sample_roadmap):\n    \"\"\"A minimal AgentState dict for use in unit tests.\"\"\"\n    from graph.state import initial_state\n    state = initial_state(\"Learn Python closures\", \"test-session-001\")\n    state[\"roadmap\"] = sample_roadmap\n    state[\"current_topic_index\"] = 0\n    return state\n\n\n@pytest.fixture\ndef closures_note_content():\n    \"\"\"\n    The content of closures.md, used as retrieval context in faithfulness tests.\n    Falls back to an inline summary if the file doesn't exist.\n    \"\"\"\n    notes_path = (\n        Path(__file__).parent.parent\n        \/ \"study_materials\/sample_notes\/closures.md\"\n    )\n    if notes_path.exists():\n        return notes_path.read_text(encoding=\"utf-8\")\n    return (\n        \"A closure is a nested function that remembers variables from its \"\n        \"enclosing scope even after the enclosing function returns.\"\n    )\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>closures_note_content<\/code> \u0641\u06a9\u0633\u0686\u0631 \u0645\u062e\u0644\u0635\u06cc \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u0644\u0627\u0634 \u06a9\u0627 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u06c1\u06d2\u06d4 \u0688\u06cc\u067e \u0627\u06cc\u0648\u0644 \u06a9\u0627 <code>FaithfulnessMetric<\/code> \u062c\u062c \u0633\u06d2 \u0627\u0633 \u0628\u06cc\u0627\u0646 \u0645\u06cc\u06ba \u06c1\u0631 \u062f\u0639\u0648\u06d2 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u0646\u06d2 \u06a9\u0648 \u06a9\u06c1\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u0627\u06cc\u0633\u06d2 \u062d\u0642\u0627\u0626\u0642 \u062a\u062e\u0644\u06cc\u0642 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0646\u0648\u0679\u0633 \u0645\u06cc\u06ba \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0645\u06cc\u0679\u0631\u06a9\u0633 \u0627\u0633 \u06a9\u0648 \u067e\u06a9\u0691 \u0644\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-75-the-explainer-quality-tests\">7.5 \u0648\u0636\u0627\u062d\u062a\u06cc \u0645\u0639\u06cc\u0627\u0631 \u06a9\u06cc \u062c\u0627\u0646\u0686<\/h3>\n<p>\u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06af\u0627\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u0634\u062e\u06cc\u0635\u06cc \u0679\u06cc\u0633\u0679 \u062f\u0648 \u0633\u0648\u0627\u0644\u0627\u062a \u06a9\u06d2 \u062c\u0648\u0627\u0628\u0627\u062a \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06a9\u06cc\u0627 \u0622\u0624\u0679 \u067e\u0679 \u0622\u067e \u06a9\u06d2 \u0646\u0648\u0679\u0633 \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u06c1\u06d2 \u0627\u0648\u0631 \u0622\u067e \u06a9\u06d2 \u067e\u0648\u0686\u06be\u06d2 \u06af\u0626\u06d2 \u0633\u0648\u0627\u0644 \u0633\u06d2 \u0645\u062a\u0639\u0644\u0642 \u06c1\u06d2\u061f<\/p>\n<pre><code class=\"language-python\"># tests\/test_eval.py\n\ndef run_explainer(topic_title: str, topic_description: str, session_id: str) -> str:\n    \"\"\"Run the Explainer agent and return its final explanation text.\"\"\"\n    from graph.state import StudyRoadmap, Topic, initial_state\n    from agents.explainer import explainer_node\n    from langchain_core.messages import AIMessage\n\n    state = initial_state(f\"Learn {topic_title}\", session_id)\n    state[\"roadmap\"] = StudyRoadmap(\n        goal=f\"Learn {topic_title}\",\n        total_weeks=1,\n        topics=[Topic(topic_title, topic_description, 60)],\n    )\n    state[\"current_topic_index\"] = 0\n\n    result = explainer_node(state)\n\n    # Extract the final response: last AIMessage with no tool_calls\n    for msg in reversed(result.get(\"messages\", [])):\n        if (isinstance(msg, AIMessage) and msg.content\n                and not getattr(msg, \"tool_calls\", None)):\n            return msg.content\n    return \"\"\n\n\n@pytest.mark.eval\nclass TestExplainerQuality:\n\n    FAITHFULNESS_THRESHOLD = 0.6\n    RELEVANCY_THRESHOLD    = 0.6\n\n    @pytest.fixture(autouse=True)\n    def setup(self, closures_note_content):\n        \"\"\"Run the Explainer once, reuse the output across all tests in this class.\"\"\"\n        self.retrieval_context = [closures_note_content]\n        self.explanation = run_explainer(\n            topic_title=\"Closures Explained\",\n            topic_description=\"Understand how closures capture enclosing scope variables\",\n            session_id=\"eval-test-001\",\n        )\n        if not self.explanation:\n            pytest.skip(\"Explainer returned empty output. Check Ollama is running.\")\n\n    def test_explanation_is_faithful_to_notes(self):\n        \"\"\"\n        The explanation should not hallucinate facts not in the source notes.\n\n        FaithfulnessMetric asks the judge: is every claim in the output\n        supported by the retrieval context (the notes)?\n        A low score means the agent is making things up.\n        \"\"\"\n        from deepeval.test_case import LLMTestCase\n        from deepeval.metrics import FaithfulnessMetric\n\n        judge = get_judge_model()\n        if judge is None:\n            pytest.skip(\"Could not initialise judge model\")\n\n        test_case = LLMTestCase(\n            input=\"Explain Python closures\",\n            actual_output=self.explanation,\n            retrieval_context=self.retrieval_context,\n        )\n        metric = FaithfulnessMetric(\n            model=judge,\n            threshold=self.FAITHFULNESS_THRESHOLD,\n            include_reason=True,\n        )\n        metric.measure(test_case)\n\n        print(f\"n[Faithfulness] Score: {metric.score:.3f}\")\n        if hasattr(metric, \"reason\"):\n            print(f\"[Faithfulness] Reason: {metric.reason}\")\n\n        assert metric.score >= self.FAITHFULNESS_THRESHOLD, (\n            f\"Faithfulness {metric.score:.3f} below {self.FAITHFULNESS_THRESHOLD}.n\"\n            f\"The explanation may contain hallucinated facts.n\"\n            f\"Reason: {getattr(metric, 'reason', 'not available')}\"\n        )\n\n    def test_explanation_is_relevant_to_topic(self):\n        \"\"\"The explanation should address what was actually asked.\"\"\"\n        from deepeval.test_case import LLMTestCase\n        from deepeval.metrics import AnswerRelevancyMetric\n\n        judge = get_judge_model()\n        if judge is None:\n            pytest.skip(\"Could not initialise judge model\")\n\n        test_case = LLMTestCase(\n            input=\"Explain Python closures\",\n            actual_output=self.explanation,\n        )\n        metric = AnswerRelevancyMetric(\n            model=judge,\n            threshold=self.RELEVANCY_THRESHOLD,\n        )\n        metric.measure(test_case)\n\n        print(f\"n[Relevancy] Score: {metric.score:.3f}\")\n\n        assert metric.score >= self.RELEVANCY_THRESHOLD, (\n            f\"Relevancy {metric.score:.3f} below {self.RELEVANCY_THRESHOLD}.n\"\n            f\"The explanation may have wandered off-topic.\"\n        )\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>autouse=True<\/code> \u0641\u06a9\u0633\u0686\u0631 <code>TestExplainerQuality<\/code> \u0688\u0633\u06a9\u0631\u067e\u0679\u0631 \u06a9\u0648 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u0686\u0644\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u062f\u0648\u0646\u0648\u06ba \u0679\u06cc\u0633\u0679\u0648\u06ba \u0645\u06cc\u06ba \u0622\u0624\u0679 \u067e\u0679 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u06cc\u06c1 \u062f\u0648 \u0627\u0644\u06af \u0627\u0644\u06af \u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u0627\u0644\u0632 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u06af\u0631\u06cc\u0632 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 (\u0627\u06cc\u06a9 \u0641\u06cc \u0679\u06cc\u0633\u0679) \u062c\u0628 \u0627\u06cc\u06a9 \u06c1\u06cc \u062a\u0641\u0635\u06cc\u0644 \u062f\u0648\u0646\u0648\u06ba \u0645\u06cc\u0679\u0631\u06a9\u0633 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631 \u0633\u06a9\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-76-the-grading-quality-tests\">7.6 \u06af\u0631\u06cc\u0688 \u06a9\u0648\u0627\u0644\u0679\u06cc \u0679\u06cc\u0633\u0679<\/h3>\n<p>\u06cc\u06c1 \u0679\u06cc\u0633\u0679 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0631\u06cc\u0679\u0631 \u06a9\u0627 \u0627\u0633\u06a9\u0648\u0631 \u0627\u0635\u0644 \u062c\u0648\u0627\u0628\u0627\u062a \u06a9\u06d2 \u0645\u0639\u06cc\u0627\u0631 \u0633\u06d2 \u0645\u06cc\u0644 \u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0688\u06cc\u067e \u0627\u06cc\u0648\u0644 \u0645\u06cc\u0679\u0631\u06a9\u0633 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0648\u06c1 \u06a9\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba <code>grade_answer<\/code> \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u0627\u0633\u06a9\u0648\u0631 \u06a9\u06cc \u062d\u062f\u0648\u062f \u067e\u0631 \u0627\u0635\u0631\u0627\u0631 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">@pytest.mark.eval\nclass TestGradingQuality:\n\n    def test_correct_answer_scores_high(self):\n        \"\"\"A clearly correct answer should score >= 0.65.\"\"\"\n        from agents.quiz_generator import grade_answer\n\n        result = grade_answer(\n            question=\"What are the three requirements for a Python closure?\",\n            expected=(\n                \"A closure requires: 1) a nested inner function, \"\n                \"2) the inner function references a variable from the enclosing scope, \"\n                \"3) the enclosing function returns the inner function.\"\n            ),\n            student_answer=(\n                \"You need a nested function that uses variables from the outer \"\n                \"function's scope, and the outer function has to return the inner function.\"\n            ),\n        )\n        print(f\"n[GradeQuality] Correct answer: {result.get('score', 0):.2f}\")\n        assert result.get(\"score\", 0) >= 0.65, (\n            f\"Correct answer scored too low: {result['score']:.2f}n\"\n            f\"Feedback: {result.get('feedback', '')}\"\n        )\n\n    def test_wrong_answer_scores_low(self):\n        \"\"\"A clearly wrong answer should score <= 0.35.\"\"\"\n        from agents.quiz_generator import grade_answer\n\n        result = grade_answer(\n            question=\"What is a Python closure?\",\n            expected=(\n                \"A closure is a nested function that captures and remembers \"\n                \"variables from its enclosing scope after the enclosing function returns.\"\n            ),\n            student_answer=(\n                \"A closure is a class that closes over its attributes \"\n                \"and prevents external access to them.\"\n            ),\n        )\n        print(f\"n[GradeQuality] Wrong answer: {result.get('score', 0):.2f}\")\n        assert result.get(\"score\", 0) <= 0.35, (\n            f\"Wrong answer scored too high: {result['score']:.2f}n\"\n            f\"The grader may be too lenient.\"\n        )\n\n    def test_partial_answer_scores_middle(self):\n        \"\"\"A partially correct answer should score between 0.3 and 0.75.\"\"\"\n        from agents.quiz_generator import grade_answer\n\n        result = grade_answer(\n            question=\"What is late binding in closures and how do you fix it?\",\n            expected=(\n                \"Late binding means closures look up variable values at call time, \"\n                \"not at definition time. Fix: use default argument values \"\n                \"(lambda i=i: i instead of lambda: i).\"\n            ),\n            student_answer=(\n                \"Late binding means the closure uses the variable's current value \"\n                \"when called, not when defined.\"  # Knows what, not how to fix\n            ),\n        )\n        score = result.get(\"score\", 0)\n        print(f\"n[GradeQuality] Partial answer: {score:.2f}\")\n        assert 0.3 <= score <= 0.75, (\n            f\"Partial answer should score 0.3 to 0.75, got {score:.2f}\"\n        )\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u062a\u06cc\u0646\u0648\u06ba \u0679\u06cc\u0633\u0679 \u0645\u0644 \u06a9\u0631 \u0627\u0646\u0634\u0627\u0646\u06a9\u0646 \u06a9\u06cc \u0648\u0634\u0648\u0633\u0646\u06cc\u06cc\u062a\u0627 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06af\u0631\u06cc\u0688\u0631 \u062f\u0631\u0633\u062a \u062c\u0648\u0627\u0628\u0627\u062a \u06a9\u0648 \u0627\u0646\u0639\u0627\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u060c \u063a\u0644\u0637 \u062c\u0648\u0627\u0628\u0627\u062a \u06a9\u0648 \u0633\u0632\u0627 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0645\u0646\u0627\u0633\u0628 \u06c1\u0648\u0646\u06d2 \u067e\u0631 \u062c\u0632\u0648\u06cc \u06a9\u0631\u06cc\u0688\u0679 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0645\u0627\u0688\u0644 \u06a9\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc \u06cc\u0627 \u062a\u06cc\u0632 \u0631\u0641\u062a\u0627\u0631 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u06d2 \u0628\u0639\u062f \u062a\u06cc\u0646\u0648\u06ba \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u06a9\u0648 \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0645\u0639\u0644\u0648\u0645 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627 \u06a9\u06c1 \u06af\u0631\u06cc\u0688\u0631 \u06a9\u0633 \u0633\u0645\u062a \u0686\u0644\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-77-the-coaching-quality-test\">7.7 \u06a9\u0648\u0686\u0646\u06af \u06a9\u0648\u0627\u0644\u0679\u06cc \u0679\u06cc\u0633\u0679<\/h3>\n<p>\u06a9\u0648\u0686\u0646\u06af \u0679\u06cc\u0633\u0679\u0646\u06af \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u06c1\u0645 DeepEval \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>GEval<\/code> \u0645\u06cc\u0679\u0631\u06a9\u060c \u0622\u067e \u06a9\u06d2 \u0627\u067e\u0646\u06d2 \u062a\u0634\u062e\u06cc\u0635\u06cc \u0645\u0639\u06cc\u0627\u0631 \u06a9\u0648 \u0633\u0627\u062f\u06c1 \u0627\u0646\u06af\u0631\u06cc\u0632\u06cc \u0645\u06cc\u06ba \u0644\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0639\u0627\u0644\u0645\u06af\u06cc\u0631 \u062a\u062e\u0645\u06cc\u0646\u06c1 \u0644\u06af\u0627\u0646\u06d2 \u0648\u0627\u0644\u0627:<\/p>\n<pre><code class=\"language-python\">@pytest.mark.eval\nclass TestProgressCoachQuality:\n\n    COACHING_QUALITY_THRESHOLD = 0.6\n\n    def test_coaching_message_is_encouraging_and_specific(self):\n        \"\"\"\n        Coaching messages should be warm, specific, and actionable.\n\n        GEval lets you write evaluation criteria in plain English.\n        The judge scores the output 0.0 to 1.0 against those criteria.\n        \"\"\"\n        from deepeval.test_case import LLMTestCase, LLMTestCaseParams\n        from deepeval.metrics import GEval\n        from agents.progress_coach import get_coaching_message\n\n        judge = get_judge_model()\n        if judge is None:\n            pytest.skip(\"Could not initialise judge model\")\n\n        coaching = get_coaching_message(\n            topic=\"Python Closures\",\n            score=0.67,\n            weak_areas=[\"late binding\", \"nonlocal keyword\"],\n        )\n        coaching_text = (\n            f\"Summary: {coaching.get('summary', '')}n\"\n            f\"Encouragement: {coaching.get('encouragement', '')}\"\n        )\n\n        test_case = LLMTestCase(\n            input=(\n                \"Generate coaching feedback for a student who scored 67% on \"\n                \"Python Closures and struggled with late binding and nonlocal\"\n            ),\n            actual_output=coaching_text,\n        )\n        metric = GEval(\n            name=\"CoachingQuality\",\n            criteria=(\n                \"Evaluate whether this coaching message is: \"\n                \"1) Encouraging without being dishonest about the score, \"\n                \"2) Specific to the topic and weak areas mentioned, \"\n                \"3) Actionable. Gives the student a clear next step. \"\n                \"4) Concise. 2 to 4 sentences total. \"\n                \"A poor message is generic, vague, or condescending.\"\n            ),\n            evaluation_params=[LLMTestCaseParams.ACTUAL_OUTPUT],\n            model=judge,\n            threshold=self.COACHING_QUALITY_THRESHOLD,\n        )\n        metric.measure(test_case)\n\n        print(f\"n[CoachingQuality] Score: {metric.score:.3f}\")\n\n        assert metric.score >= self.COACHING_QUALITY_THRESHOLD, (\n            f\"Coaching quality {metric.score:.3f} below threshold.n\"\n            f\"Message:n{coaching_text}\"\n        )\n<\/code><\/pre>\n<p><code>GEval<\/code> \u06cc\u06c1 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0644\u0686\u06a9\u062f\u0627\u0631 \u0645\u06cc\u0679\u0631\u06a9 \u06c1\u06d2 \u062c\u0648 DeepEval \u067e\u06cc\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0622\u067e \u0633\u0627\u062f\u06c1 \u0632\u0628\u0627\u0646 \u0645\u06cc\u06ba \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \"\u0627\u0686\u06be\u0627\" \u06a9\u06cc\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u062c\u062c \u0627\u0646 \u0645\u0639\u06cc\u0627\u0631\u0627\u062a \u06a9\u06cc \u0628\u0646\u06cc\u0627\u062f \u067e\u0631 \u0622\u067e \u06a9\u0648 \u0627\u0633\u06a9\u0648\u0631 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u0633 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0627\u0633 \u0648\u0642\u062a \u06a9\u0631\u06cc\u06ba \u062c\u0628 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u0645\u0639\u06cc\u0627\u0631\u06cc \u062a\u0642\u0627\u0636\u06d2 \u06c1\u0648\u06ba \u062c\u0646 \u06a9\u0627 \u0641\u0627\u0631\u0645\u0648\u0644\u0648\u06ba \u0645\u06cc\u06ba \u0627\u0638\u06c1\u0627\u0631 \u06a9\u0631\u0646\u0627 \u0645\u0634\u06a9\u0644 \u06c1\u0648 \u0644\u06cc\u06a9\u0646 \u0627\u0644\u0641\u0627\u0638 \u0645\u06cc\u06ba \u0628\u06cc\u0627\u0646 \u06a9\u0631\u0646\u0627 \u0622\u0633\u0627\u0646 \u06c1\u0648\u06d4<\/p>\n<h3 id=\"heading-78-run-the-evaluation-suite\">7.8 \u062a\u0634\u062e\u06cc\u0635\u06cc \u0633\u06cc\u0679 \u0686\u0644\u0627\u0646\u0627<\/h3>\n<p>\u06cc\u0648\u0646\u0679 \u0679\u06cc\u0633\u0679 (\u062a\u06cc\u0632\u060c \u06a9\u0648\u0626\u06cc \u0627\u0648\u0644\u0627\u0645\u06c1 \u0646\u06c1\u06cc\u06ba):<\/p>\n<pre><code class=\"language-bash\">pytest tests\/ -v\n# 184 tests, eval tests automatically excluded\n<\/code><\/pre>\n<p>\u062a\u0634\u062e\u06cc\u0635\u06cc \u0679\u06cc\u0633\u0679 (\u0633\u0633\u062a\u060c \u0627\u0648\u0644\u0627\u0645\u06c1 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2):<\/p>\n<pre><code class=\"language-bash\">pytest tests\/test_eval.py -m eval -v -s\n<\/code><\/pre>\n<p>\u0622\u067e \u0627\u0633 \u0637\u0631\u062d \u0622\u0624\u0679 \u067e\u0679 \u062f\u06cc\u06a9\u06be\u06cc\u06ba \u06af\u06d2:<\/p>\n<pre><code class=\"language-plaintext\">[TestExplainerQuality] Running Explainer for closures topic...\n[TestExplainerQuality] Explanation length: 1,847 chars\n\n[Faithfulness] Score: 0.782 (threshold: 0.600)\n[Faithfulness] Reason: All major claims trace back to the closures.md source material.\nPASSED\n\n[Relevancy] Score: 0.841\nPASSED\n\n[GradeQuality] Correct answer: 0.82\nPASSED\n\n[GradeQuality] Wrong answer: 0.15\nPASSED\n\n[GradeQuality] Partial answer: 0.55\nPASSED\n\n[CoachingQuality] Score: 0.731\nPASSED\n<\/code><\/pre>\n<h4 id=\"heading-setting-thresholds-conservatively\"> \u0642\u062f\u0627\u0645\u062a \u067e\u0633\u0646\u062f\u06cc \u0633\u06d2 \u062d\u062f \u0645\u0642\u0631\u0631 \u06a9\u0631\u06cc\u06ba\u06d4<\/h4>\n<p>\u0645\u0642\u0627\u0645\u06cc 7B \u0645\u0627\u0688\u0644 \u0646\u06d2 \u0645\u062e\u0644\u0635\u06cc \u0627\u0648\u0631 \u0645\u0637\u0627\u0628\u0642\u062a \u06a9\u06d2 \u0627\u0634\u0627\u0631\u06cc\u0648\u06ba \u067e\u0631 0.6 \u0627\u0648\u0631 0.8 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0633\u06a9\u0648\u0631 \u06a9\u06cc\u0627\u06d4 \u06a9\u0644\u0627\u0624\u0688 \u0645\u0627\u0688\u0644\u0632 \u0645\u06cc\u06ba \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 0.8 \u0627\u0648\u0631 0.95 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0633\u06a9\u0648\u0631 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u0633 \u0679\u06cc\u0633\u0679 \u06a9\u06cc \u062d\u062f 0.6 \u067e\u0631 \u0633\u06cc\u0679 \u06a9\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u06d4 \u06cc\u0639\u0646\u06cc \u0645\u0642\u0627\u0645\u06cc \u0645\u0627\u0688\u0644 \u06a9\u0648 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u067e\u0627\u0633 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06cc\u06c1 \u06a9\u0627\u0641\u06cc \u06a9\u0645 \u06c1\u06d2 \u0627\u0648\u0631 \u06a9\u0627\u0631\u06a9\u0631\u062f\u06af\u06cc \u0645\u06cc\u06ba \u0634\u062f\u06cc\u062f \u06af\u0631\u0627\u0648\u0679 \u06a9\u0648 \u067e\u06a9\u0691\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0627\u0641\u06cc \u0632\u06cc\u0627\u062f\u06c1 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0622\u067e \u0633\u062e\u062a \u06a9\u0648\u0627\u0644\u0679\u06cc \u06af\u06cc\u0679 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u0628\u0691\u06d2 \u0645\u0627\u0688\u0644 \u0645\u06cc\u06ba \u0627\u067e \u06af\u0631\u06cc\u0688 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u062d\u062f \u0628\u0691\u06be\u0627\u0626\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u06a9\u0633\u06cc \u0627\u06cc\u0633\u06d2 \u0645\u0627\u0688\u0644 \u067e\u0631 \u0679\u06cc\u0633\u0679 \u0645\u0633\u0644\u0633\u0644 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u0645\u0648\u0636\u0648\u0639\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u0686\u06be\u06d2 \u0646\u062a\u0627\u0626\u062c \u067e\u06cc\u062f\u0627 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u062d\u062f \u06a9\u0648 \u06a9\u0645 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633 \u06a9\u06cc \u0648\u062c\u06c1 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u0646\u0679\u0631\u067e\u0631\u0627\u0626\u0632 \u06a9\u0646\u06cc\u06a9\u0679\u06cc\u0648\u06cc\u0679\u06cc: \u0627\u0633 \u0637\u0631\u062d \u06a9\u06d2 \u0627\u06cc\u0648\u06cc\u0644\u06cc\u0648\u0627\u06cc\u0634\u0646 \u0633\u0648\u06cc\u0679\u0633 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u0645\u0627\u0688\u0644 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u06d2 \u0645\u0633\u0627\u0626\u0644 \u06a9\u0648 \u0645\u0646\u0638\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0627\u06cc\u06a9 \u0637\u0631\u06cc\u0642\u06c1 \u06c1\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0627\u06cc\u06a9 \u0645\u0627\u0688\u0644 \u0648\u0631\u0698\u0646 \u0633\u06d2 \u062f\u0648\u0633\u0631\u06d2 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u062a\u0639\u06cc\u0646\u0627\u062a \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u062a\u0634\u062e\u06cc\u0635\u06cc \u0679\u06cc\u0633\u0679 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0648\u0641\u0627\u062f\u0627\u0631\u06cc \u0627\u06cc\u06a9 \u062d\u062f \u0633\u06d2 \u0646\u06cc\u0686\u06d2 \u0622\u062a\u06cc \u06c1\u06d2 \u062a\u0648\u060c \u0645\u0627\u0688\u0644 \u06a9\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u0641\u0631\u06cc\u0628 \u06a9\u06d2 \u062e\u0637\u0631\u06d2 \u06a9\u0648 \u0645\u062a\u0639\u0627\u0631\u0641 \u06a9\u0631\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0631\u0648\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u06af\u0631\u06cc\u0688\u0631 \u062f\u0631\u0633\u062a \u062c\u0648\u0627\u0628\u0627\u062a \u0628\u06c1\u062a \u06a9\u0645 \u0627\u0633\u06a9\u0648\u0631 \u06a9\u0631\u0646\u0627 \u0634\u0631\u0648\u0639 \u06a9\u0631 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u062d\u062f \u0628\u0691\u06be\u0646\u06d2 \u0633\u06d2 \u0637\u0627\u0644\u0628 \u0639\u0644\u0645 \u06a9\u06d2 \u062a\u062c\u0631\u0628\u06d2 \u067e\u0631 \u0627\u062b\u0631 \u067e\u0691\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0634\u062e\u06cc\u0635\u06cc \u0679\u06cc\u0633\u0679 LLM \u0631\u0648\u06cc\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0631\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0633\u0648\u0679 \u06c1\u06cc\u06ba\u060c \u0627\u0633\u06cc \u0637\u0631\u062d \u062c\u06cc\u0633\u06d2 \u06cc\u0648\u0646\u0679 \u0679\u06cc\u0633\u0679 \u06a9\u0648\u0688 \u0644\u0627\u062c\u06a9 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0631\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0633\u0648\u0679 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06af\u0644\u0627 \u0628\u0627\u0628 A2A \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u067e\u0631\u062a \u06a9\u0627 \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u0648\u0626\u0632 \u062c\u0646\u0631\u06cc\u0679\u0631 \u0627\u06cc\u06a9 \u0627\u0633\u0679\u06cc\u0646\u0688 \u0644\u0648\u0646 \u0633\u0631\u0648\u0633 \u0628\u0646 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0627\u06cc\u062c\u0646\u0679 \u06cc\u0627 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u0627\u0644 \u06a9\u0631\u0633\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 CrewAI \u0627\u06cc\u062c\u0646\u0679 \u0627\u0633 \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba \u062d\u0635\u06c1 \u0644\u06cc\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0628 \u0637\u0644\u0628\u0627\u0621 \u06a9\u0648 \u0627\u0636\u0627\u0641\u06cc \u0645\u062f\u062f \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u062a\u0648 \u062a\u0631\u0642\u06cc \u06a9\u06d2 \u06a9\u0648\u0686\u0632 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06c1 \u062a\u0641\u0648\u06cc\u0636 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-chapter-8-cross-framework-coordination-with-a2a\">\u0628\u0627\u0628 8: A2A \u06a9\u06d2 \u0633\u0627\u062a\u06be \u067e\u0648\u0631\u06d2 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0645\u06cc\u06ba \u06c1\u0645 \u0622\u06c1\u0646\u06af\u06cc\u06d4<\/h2>\n<p>\u0627\u0628 \u062a\u06a9\u060c \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679 Python \u0641\u0646\u06a9\u0634\u0646\u0632 \u06c1\u06cc\u06ba \u062c\u0646\u06c1\u06cc\u06ba LangGraph \u06a9\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0679\u06be\u06cc\u06a9 \u06c1\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0646\u0638\u0627\u0645\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u0648 \u0627\u06cc\u06a9 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0645\u06cc\u06ba \u0631\u06a9\u06be\u0646\u0627 \u0635\u062d\u06cc\u062d \u0627\u0646\u062a\u062e\u0627\u0628 \u06c1\u06d2\u06d4<\/p>\n<p>\u0644\u06cc\u06a9\u0646 \u062d\u0642\u06cc\u0642\u06cc \u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u06be\u0627\u0646\u0686\u06d2 \u06a9\u0648 \u0628\u0639\u0636 \u0627\u0648\u0642\u0627\u062a \u06a9\u0686\u06be \u0645\u062e\u062a\u0644\u0641 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u06cc\u0639\u0646\u06cc\u060c \u0627\u06cc\u062c\u0646\u0679 \u062c\u0648 \u0645\u062e\u062a\u0644\u0641 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u067e\u0631 \u0628\u0646\u0627\u0626\u06d2 \u06af\u0626\u06d2 \u06c1\u06cc\u06ba\u060c \u0645\u062e\u062a\u0644\u0641 \u0679\u06cc\u0645\u0648\u06ba \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06c1 \u062f\u06cc\u06a9\u06be \u0628\u06be\u0627\u0644 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u060c \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u062a\u0639\u06cc\u0646\u0627\u062a \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 HTTP \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06cc \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0686\u06cc\u0632 \u0633\u06d2 \u0628\u0644\u0627\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06cc\u062c\u0646\u0679 \u0633\u06d2 \u0627\u06cc\u062c\u0646\u0679 (A2A) \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u06cc\u06c1 \u0645\u0645\u06a9\u0646 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4 A2A \u0627\u06cc\u06a9 \u06a9\u06be\u0644\u0627 \u0645\u0639\u06cc\u0627\u0631 \u06c1\u06d2 (JSON-RPC 2.0 \u0627\u0648\u0631 HTTP \u067e\u0631 \u0645\u0628\u0646\u06cc) \u062c\u0648 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0627\u0633 \u0628\u0627\u062a \u06a9\u06cc \u062a\u0634\u06c1\u06cc\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0627\u06cc\u06a9 \u0645\u0639\u06cc\u0627\u0631\u06cc \u0637\u0631\u06cc\u0642\u06c1 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0648\u06c1 \u06a9\u06cc\u0627 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u0648\u06ba \u06a9\u06cc \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc\u0648\u06ba \u06a9\u0648 \u0642\u0628\u0648\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0633 \u0633\u06d2 \u0642\u0637\u0639 \u0646\u0638\u0631 \u06a9\u06c1 \u06a9\u0627\u0644\u0631 \u06a9\u0633 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 LangGraph \u0627\u06cc\u062c\u0646\u0679 \u0627\u0648\u0631 \u0627\u06cc\u06a9 CrewAI \u0627\u06cc\u062c\u0646\u0679 \u062c\u0633 \u0646\u06d2 \u06a9\u0628\u06be\u06cc \u0627\u06cc\u06a9 \u062f\u0648\u0633\u0631\u06d2 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0646\u06c1\u06cc\u06ba \u0633\u0646\u0627 \u06c1\u06d2\u060c A2A \u067e\u0631 \u0627\u0633\u06cc \u0637\u0631\u062d \u06c1\u0645 \u0622\u06c1\u0646\u06af\u06cc \u067e\u06cc\u062f\u0627 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0633 \u0637\u0631\u062d \u062f\u0648 REST \u0633\u0631\u0648\u0633\u0632 HTTP \u067e\u0631 \u06c1\u0645 \u0622\u06c1\u0646\u06af \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u0633 \u0628\u0627\u0628 \u0645\u06cc\u06ba\u060c \u0622\u067e \u0627\u067e\u0646\u06d2 \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba \u062f\u0648 A2A \u062e\u062f\u0645\u0627\u062a \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4 \u06a9\u0648\u0626\u0632 \u062c\u0646\u0631\u06cc\u0679\u0631\u060c \u062c\u0648 \u0627\u06cc\u06a9 \u0627\u0633\u0679\u06cc\u0646\u0688 \u0644\u0648\u0646 \u0633\u0631\u0648\u0633 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0633\u0627\u0645\u0646\u06d2 \u0622\u06cc\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 CrewAI Study Buddy\u060c \u062c\u0633 \u06a9\u0648 \u0633\u06c1\u0648\u0644\u062a \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u0648\u0686 \u0627\u0633 \u0648\u0642\u062a \u0637\u0644\u0628 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0628 \u0637\u0644\u0628\u0627\u0621 \u06a9\u0648 \u0648\u0636\u0627\u062d\u062a \u06a9\u06d2 \u0645\u062e\u062a\u0644\u0641 \u0632\u0627\u0648\u06cc\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-81-how-a2a-works\">8.1 A2A \u06a9\u06cc\u0633\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/h3>\n<p>A2A \u0645\u06cc\u06ba \u062a\u06cc\u0646 \u062a\u0635\u0648\u0631\u0627\u062a \u06c1\u06cc\u06ba \u062c\u0648 \u0622\u067e \u06a9\u0648 \u06a9\u0648\u0688 \u0644\u06a9\u06be\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0633\u0645\u062c\u06be\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2:<\/p>\n<p><strong>\u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627\u0631\u0688<\/strong> \u06cc\u06c1 \u0627\u06cc\u06a9 JSON \u062f\u0633\u062a\u0627\u0648\u06cc\u0632 \u06c1\u06d2 \u062c\u0648 . <code>\/.well-known\/agent-card.json<\/code>. \u0628\u06cc\u0627\u0646 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06cc\u0627 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2: \u0627\u0633 \u06a9\u0627 \u0646\u0627\u0645\u060c \u0635\u0644\u0627\u062d\u06cc\u062a\u06cc\u06ba\u060c \u0645\u06c1\u0627\u0631\u062a\u06cc\u06ba\u060c \u0627\u0648\u0631 \u06a9\u0627\u0645 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0645\u0646\u062a\u0642\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u062a\u0645\u0627\u0645 A2A \u06a9\u0644\u0627\u0626\u0646\u0679\u0633 \u067e\u06c1\u0644\u06d2 \u06cc\u06c1 \u062f\u06cc\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062d\u0627\u0635\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u06cc\u0627 \u0627\u06cc\u062c\u0646\u0679 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0648 \u0633\u0646\u0628\u06be\u0627\u0644 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627\u0631\u0688 \u0627\u06cc\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627 \u0639\u0648\u0627\u0645\u06cc API \u0645\u0639\u0627\u06c1\u062f\u06c1 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u062c\u06cc\u0633\u0627 \u06a9\u06c1 REST \u062e\u062f\u0645\u0627\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 OpenAPI \u062a\u0641\u0635\u06cc\u0644\u0627\u062a \u06a9\u06cc \u0637\u0631\u062d \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0627\u067e\u0646\u06cc \u0627\u0633\u0627\u0626\u0646\u0645\u0646\u0679 \u062c\u0645\u0639 \u06a9\u0631\u0648\u0627\u0626\u06cc\u06ba\u06d4<\/strong> \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f \u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u0646\u0642\u0637\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>POST \/tasks\/send<\/code>. \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0627\u06cc\u06a9 \u06a9\u0631\u062f\u0627\u0631 \u06c1\u06d2 (<code>\"user\"<\/code>) \u0627\u0648\u0631 \u062d\u0635\u0648\u06ba \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a (\u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 <code>TextPart<\/code> \u0628\u0634\u0645\u0648\u0644 JSON \u0645\u0648\u0627\u062f)\u06d4 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627\u0645 \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633\u06cc \u0641\u0627\u0631\u0645\u06cc\u0679 \u06a9\u06d2 \u067e\u06cc\u063a\u0627\u0645 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062c\u0648\u0627\u0628 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u06cc \u0622\u0632\u0627\u062f\u06cc<\/strong> \u06cc\u06c1\u06cc \u0628\u0627\u062a \u06c1\u06d2\u06d4 A2A \u0633\u0631\u0648\u0631 \u062a\u0645\u0627\u0645 HTTP \u0627\u0648\u0631 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u0645\u06cc\u06a9\u0627\u0646\u0632\u0645 \u06a9\u0648 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0622\u067e \u06a9\u0627 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648\u0688 \u06c1\u06d2\u06d4 <code>AgentExecutor<\/code> \u0630\u06cc\u0644\u06cc \u0637\u0628\u0642\u06c1: <code>execute()<\/code> \u0648\u06c1 \u0637\u0631\u06cc\u0642\u06c1 \u062c\u0648 \u062a\u062c\u0632\u06cc\u06c1 \u0634\u062f\u06c1 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0648\u0635\u0648\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062c\u0648\u0627\u0628 \u062e\u0627\u0631\u062c \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0648\u06c1 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u062c\u0648 \u0627\u06cc\u06af\u0632\u06cc\u06a9\u06cc\u0648\u0679\u0631\u0632 (LangGraph\u060c CrewAI\u060c \u0648\u063a\u06cc\u0631\u06c1) \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u067e\u0631\u062a \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0635\u0631\u0641 HTTP \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-plaintext\">Caller (any framework)\n  \u2193  GET \/.well-known\/agent-card.json   \u2190 discover capabilities\n  \u2193  POST \/tasks\/send                   \u2190 submit task (JSON-RPC 2.0)\n  \u2191  response with result artifacts\nA2A Server (Starlette + uvicorn)\n  \u2193  calls AgentExecutor.execute()\nYour agent logic (LangGraph \/ CrewAI \/ anything)\n<\/code><\/pre>\n<h3 id=\"heading-82-the-quiz-generator-as-an-a2a-service\">8.2 \u06a9\u0648\u0626\u0632 \u062c\u0646\u0631\u06cc\u0679\u0631 \u0628\u0637\u0648\u0631 A2A \u0633\u0631\u0648\u0633<\/h3>\n<p><code>src\/a2a_services\/quiz_service.py<\/code> \u0644\u06cc\u0628\u0627\u0631\u0679\u0631\u06cc <code>generate_questions<\/code> \u0627\u0648\u0631 <code>grade_answer<\/code> (\u0648\u06c1\u06cc \u0641\u0639\u0627\u0644\u06cc\u062a \u062c\u0648 \u0628\u0627\u0628 4 \u0645\u06cc\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc \u06af\u0626\u06cc \u06c1\u06d2) \u0628\u0637\u0648\u0631 A2A \u0633\u0631\u0648\u0633\u06d4 \u0627\u0633 \u0641\u0639\u0627\u0644\u06cc\u062a \u0645\u06cc\u06ba \u06a9\u0686\u06be \u0628\u06be\u06cc \u0646\u06c1\u06cc\u06ba \u0628\u062f\u0644\u062a\u0627\u06d4<\/p>\n<p><strong>\u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627\u0631\u0688<\/strong> \u067e\u06c1\u0644\u0627:<\/p>\n<pre><code class=\"language-python\"># src\/a2a_services\/quiz_service.py\n\nfrom a2a.types import AgentCapabilities, AgentCard, AgentSkill\n\nQUIZ_SKILL = AgentSkill(\n    id=\"generate_and_grade_quiz\",\n    name=\"Generate and Grade Quiz\",\n    description=(\n        \"Given a topic and optional explanation text, generates quiz questions \"\n        \"that test conceptual understanding. If answers are provided, grades \"\n        \"each answer and returns scores with identified weak areas.\"\n    ),\n    tags=[\"quiz\", \"assessment\", \"education\", \"grading\"],\n    examples=[\n        \"Generate a quiz on Python closures\",\n        \"Grade these answers for a decorators quiz\",\n    ],\n)\n\nQUIZ_AGENT_CARD = AgentCard(\n    name=\"Quiz Generator Service\",\n    description=(\n        \"Generates and grades quizzes using LLM-as-judge. \"\n        \"Framework-agnostic: works with any A2A-compatible agent.\"\n    ),\n    url=\"http:\/\/localhost:9001\/\",\n    version=\"1.0.0\",\n    defaultInputModes=[\"text\"],\n    defaultOutputModes=[\"text\"],\n    capabilities=AgentCapabilities(streaming=False),\n    skills=[QUIZ_SKILL],\n)\n<\/code><\/pre>\n<p>\u0627\u06cc\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627\u0631\u0688 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0641\u0631\u0627\u06c1\u0645 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>GET \/.well-known\/agent-card.json<\/code> \u0622\u067e A2A \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0627\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0646\u06c1\u06cc\u06ba \u0644\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p><strong>AgentExecutor<\/strong> \u0627\u0635\u0644 \u06a9\u0648\u0626\u0632 \u0645\u0646\u0637\u0642 \u067e\u0631 \u0645\u0634\u062a\u0645\u0644 \u06c1\u06d2\u06d4 \u062a\u062c\u0632\u06cc\u06c1 \u0634\u062f\u06c1 A2A \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0648\u0635\u0648\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>generate_questions<\/code> \u0627\u0648\u0631 \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 <code>grade_answer<\/code>\u0646\u062a\u0627\u0626\u062c \u0628\u0631\u0622\u0645\u062f \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">from a2a.server.agent_execution import AgentExecutor, RequestContext\nfrom a2a.server.events import EventQueue\nfrom a2a.types import Message, TextPart\nfrom agents.quiz_generator import generate_questions, grade_answer\n\n\nclass QuizAgentExecutor(AgentExecutor):\n    \"\"\"\n    Handles incoming A2A quiz tasks.\n\n    Request format (JSON in the TextPart):\n    {\n        \"topic\":       \"Python Closures\",\n        \"explanation\": \"A closure is...\",   (optional)\n        \"answers\":     [\"answer 1\", ...]    (optional. omit for questions only)\n    }\n    \"\"\"\n\n    async def execute(\n        self,\n        context: RequestContext,\n        event_queue: EventQueue,\n    ) -> None:\n        # Parse request\n        request_text = \"\"\n        for part in context.current_request.params.message.parts:\n            if isinstance(part, TextPart):\n                request_text += part.text\n\n        try:\n            request_data = json.loads(request_text)\n        except json.JSONDecodeError:\n            request_data = {\"topic\": request_text}\n\n        topic             = request_data.get(\"topic\", \"General Knowledge\")\n        explanation       = request_data.get(\"explanation\", \"\")\n        provided_answers  = request_data.get(\"answers\", [])\n\n        # Generate questions (synchronous blocking call in thread pool)\n        questions_data = await asyncio.to_thread(\n            generate_questions, topic, explanation, 3\n        )\n\n        if not provided_answers:\n            # No answers. Return questions only.\n            result = {\n                \"status\":    \"questions_ready\",\n                \"topic\":     topic,\n                \"questions\": questions_data,\n            }\n        else:\n            # Grade provided answers\n            graded     = []\n            total      = 0.0\n            weak_areas = []\n\n            for q_data, answer in zip(questions_data, provided_answers):\n                grade = await asyncio.to_thread(\n                    grade_answer,\n                    q_data[\"question\"],\n                    q_data[\"expected_answer\"],\n                    answer,\n                )\n                score = float(grade.get(\"score\", 0.0))\n                total += score\n                if grade.get(\"missing_concept\"):\n                    weak_areas.append(grade[\"missing_concept\"])\n                graded.append({\n                    \"question\": q_data[\"question\"],\n                    \"answer\":   answer,\n                    \"score\":    score,\n                    \"correct\":  bool(grade.get(\"correct\", False)),\n                    \"feedback\": grade.get(\"feedback\", \"\"),\n                })\n\n            result = {\n                \"status\":           \"graded\",\n                \"topic\":            topic,\n                \"score\":            total \/ len(questions_data) if questions_data else 0.0,\n                \"questions\":        questions_data,\n                \"graded_questions\": graded,\n                \"weak_areas\":       list(set(weak_areas)),\n            }\n\n        # Emit result. A2A sends this back to the caller.\n        await event_queue.enqueue_event(\n            Message(\n                role=\"agent\",\n                parts=[TextPart(text=json.dumps(result, indent=2))],\n            )\n        )\n\n    async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None:\n        pass\n<\/code><\/pre>\n<p><code>asyncio.to_thread<\/code> \u06c1\u0645 \u0622\u06c1\u0646\u06af \u0644\u067e\u06cc\u0679\u062a\u0627 \u06c1\u06d2\u06d4 <code>generate_questions<\/code> \u0627\u0648\u0631 <code>grade_answer<\/code> \u0641\u0648\u0646 \u06a9\u0627\u0644 A2A \u0627\u06cc\u06af\u0632\u06cc\u06a9\u06cc\u0648\u0679\u0631 \u063a\u06cc\u0631 \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0627\u06cc\u0648\u0646\u0679 \u0644\u0648\u067e \u0645\u06cc\u06ba \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u0628\u0644\u0627\u06a9\u0646\u06af \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u0627 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u0644\u0648\u067e \u06a9\u0648 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062f\u06cc\u06af\u0631 \u062a\u0645\u0627\u0645 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc\u0648\u06ba \u06a9\u0648 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 <code>to_thread<\/code> \u062a\u06be\u0631\u06cc\u0688 \u067e\u0648\u0644 \u067e\u0631 \u0628\u0644\u0627\u06a9\u0646\u06af \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u06cc\u0648\u0646\u0679 \u0644\u0648\u067e \u06a9\u0648 \u0628\u0644\u0627\u06a9 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u0646\u062a\u06cc\u062c\u06c1 \u06a9\u0627 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0633\u0631\u0648\u0631 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba:<\/strong><\/p>\n<pre><code class=\"language-python\">from a2a.server.apps import A2AStarletteApplication\nfrom a2a.server.request_handlers import DefaultRequestHandler\nfrom a2a.server.tasks import InMemoryTaskStore\n\ndef create_quiz_server():\n    handler = DefaultRequestHandler(\n        agent_executor=QuizAgentExecutor(),\n        task_store=InMemoryTaskStore(),\n    )\n    app = A2AStarletteApplication(\n        agent_card=QUIZ_AGENT_CARD,\n        http_handler=handler,\n    )\n    return app.build()\n\nif __name__ == \"__main__\":\n    uvicorn.run(create_quiz_server(), host=\"0.0.0.0\", port=9001, log_level=\"warning\")\n<\/code><\/pre>\n<pre><code class=\"language-bash\">python src\/a2a_services\/quiz_service.py\n# [Quiz A2A Service] Starting on http:\/\/localhost:9001\n# [Quiz A2A Service] Agent Card: http:\/\/localhost:9001\/.well-known\/agent-card.json\n<\/code><\/pre>\n<p>\u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u0626\u06cc\u06ba \u06a9\u06c1 \u06cc\u06c1 \u0686\u0644 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-bash\">curl http:\/\/localhost:9001\/.well-known\/agent-card.json\n<\/code><\/pre>\n<pre><code class=\"language-json\">{\n  \"name\": \"Quiz Generator Service\",\n  \"description\": \"Generates and grades quizzes...\",\n  \"url\": \"http:\/\/localhost:9001\/\",\n  \"skills\": [\n    {\n      \"id\": \"generate_and_grade_quiz\",\n      \"name\": \"Generate and Grade Quiz\"\n    }\n  ]\n}\n<\/code><\/pre>\n<h3 id=\"heading-83-the-a2a-client\">8.3 A2A \u06a9\u0644\u0627\u0626\u0646\u0679<\/h3>\n<p><code>src\/a2a_services\/a2a_client.py<\/code> \u0627\u067e\u0646\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648\u0688 \u0645\u06cc\u06ba HTTP \u0627\u0648\u0631 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u06a9\u06cc \u062a\u0641\u0635\u06cc\u0644\u0627\u062a \u0645\u062d\u0641\u0648\u0638 \u06a9\u0631\u06cc\u06ba\u06d4 \u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u06a9\u0648\u0686 JSON-RPC \u0644\u0641\u0627\u0641\u06d2 \u0646\u06c1\u06cc\u06ba \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 <code>delegate_quiz_task<\/code> \u06c1\u0645 \u0646\u062a\u06cc\u062c\u06c1 \u062e\u06cc\u0632 \u0688\u06a9\u0679 \u0648\u0627\u067e\u0633 \u0644\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\"># src\/a2a_services\/a2a_client.py\n\nimport httpx\nimport json\nimport uuid\n\nQUIZ_SERVICE_URL  = os.getenv(\"QUIZ_SERVICE_URL\",  \"http:\/\/localhost:9001\")\nSTUDY_BUDDY_URL   = os.getenv(\"STUDY_BUDDY_URL\",   \"http:\/\/localhost:9002\")\nDEFAULT_TIMEOUT   = 120.0\n\n\ndef discover_agent(base_url: str) -> dict:\n    \"\"\"Fetch an Agent Card to discover capabilities. Returns {} if unreachable.\"\"\"\n    card_url = f\"{base_url.rstrip('\/')}\/.well-known\/agent-card.json\"\n    try:\n        response = httpx.get(card_url, timeout=5.0)\n        response.raise_for_status()\n        return response.json()\n    except Exception as e:\n        print(f\"[A2A Client] Cannot reach {card_url}: {e}\")\n        return {}\n\n\ndef send_task(\n    base_url: str,\n    message_text: str,\n    task_id: str | None = None,\n    timeout: float = DEFAULT_TIMEOUT,\n) -> dict:\n    \"\"\"\n    Submit a task to an A2A agent via JSON-RPC 2.0.\n\n    The JSON-RPC envelope is what A2A requires. Your caller doesn't\n    need to know about the envelope. It just passes a text payload.\n    Pass an explicit task_id when you need an idempotency key; otherwise\n    a UUID is generated for you.\n    \"\"\"\n    payload = {\n        \"jsonrpc\": \"2.0\",\n        \"id\":      1,\n        \"method\":  \"tasks\/send\",\n        \"params\": {\n            \"id\":      task_id or str(uuid.uuid4()),\n            \"message\": {\n                \"role\":  \"user\",\n                \"parts\": [{\"type\": \"text\", \"text\": message_text}],\n            },\n        },\n    }\n\n    url = f\"{base_url.rstrip('\/')}\/tasks\/send\"\n    try:\n        response = httpx.post(url, json=payload, timeout=timeout)\n        response.raise_for_status()\n        data = response.json()\n\n        # Extract text from the A2A response envelope:\n        # result.artifacts[0].parts[0].text\n        result    = data.get(\"result\", {})\n        artifacts = result.get(\"artifacts\", [])\n        if artifacts:\n            for part in artifacts[0].get(\"parts\", []):\n                if part.get(\"type\") == \"text\":\n                    try:\n                        return json.loads(part[\"text\"])\n                    except json.JSONDecodeError:\n                        return {\"text\": part[\"text\"]}\n\n        # Fallback: check status message\n        status = result.get(\"status\", {})\n        for part in status.get(\"message\", {}).get(\"parts\", []):\n            if part.get(\"type\") == \"text\":\n                try:\n                    return json.loads(part[\"text\"])\n                except json.JSONDecodeError:\n                    return {\"text\": part[\"text\"]}\n\n        return result\n\n    except httpx.TimeoutException:\n        return {\"error\": f\"Service timed out after {timeout}s\"}\n    except httpx.ConnectError:\n        return {\"error\": f\"Cannot connect to {url}\"}\n    except Exception as e:\n        return {\"error\": f\"A2A task failed: {e}\"}\n\n\ndef delegate_quiz_task(\n    topic: str,\n    explanation: str,\n    answers: list[str] | None = None,\n    quiz_service_url: str = QUIZ_SERVICE_URL,\n) -> dict:\n    \"\"\"High-level helper: delegate a quiz task to the Quiz A2A service.\"\"\"\n    payload = json.dumps({\n        \"topic\":       topic,\n        \"explanation\": explanation,\n        \"answers\":     answers or [],\n    })\n    return send_task(quiz_service_url, payload)\n\n\ndef is_quiz_service_available(quiz_service_url: str = QUIZ_SERVICE_URL) -> bool:\n    \"\"\"Quick health check: is the quiz service reachable?\"\"\"\n    return bool(discover_agent(quiz_service_url))\n<\/code><\/pre>\n<p><code>discover_agent<\/code> \u06cc\u06c1 \u06c1\u06cc\u0644\u062a\u06be \u0686\u06cc\u06a9 \u0627\u067e \u06c1\u06d2\u06d4 \u0627\u067e\u0646\u0627 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627\u0631\u0688 \u06cc\u06c1\u0627\u06ba \u0633\u06d2 \u062d\u0627\u0635\u0644 \u06a9\u0631\u06cc\u06ba: <code>\/.well-known\/agent-card.json<\/code> 5 \u0633\u06cc\u06a9\u0646\u0688 \u06a9\u06cc \u0648\u0642\u062a \u06a9\u06cc \u062d\u062f \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u0633\u0631\u0648\u0633 \u0633\u06d2 \u062c\u0691 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u06a9\u0627\u0645 \u06a9\u0648 \u0642\u0628\u0648\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0633\u06c1\u0648\u0644\u062a \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u0648\u0686\u0632 \u0688\u06cc\u0644\u06cc\u06af\u06cc\u0679 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u0633\u06d2 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062c\u0628 \u0648\u0627\u067e\u0633 \u0622\u06cc\u0627 <code>{}<\/code>\u06a9\u0648\u0686 \u067e\u0648\u0631\u0627 \u06a9\u0627\u0645 \u062c\u0645\u0639 \u06a9\u0631\u0627\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u06d2 \u06af\u0627 \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0645\u0642\u0627\u0645\u06cc \u06a9\u0648\u0626\u0632 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0648\u0627\u067e\u0633 \u0622 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<h3 id=\"heading-84-the-crewai-study-buddy\">8.4 CrewAI \u0631\u06cc\u0633\u0631\u0686 \u0628\u0688\u06cc<\/h3>\n<p>Study Buddy \u0628\u0646\u06cc\u0627\u062f\u06cc A2A \u0642\u062f\u0631 \u06a9\u06cc \u062a\u062c\u0648\u06cc\u0632 \u06a9\u0648 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0627\u06cc\u062c\u0646\u0679\u0633 \u0627\u06cc\u06a9 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u067e\u0631 CrewAI \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0628\u0644\u0627 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba \u062c\u0633 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u0646\u06c1\u06cc\u06ba \u062c\u0627\u0646\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><code>src\/crewai_agent\/study_buddy.py<\/code> \u0627\u06cc\u06a9 CrewAI \u0627\u06cc\u062c\u0646\u0679 \u0628\u0646\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633\u06d2 A2A \u0633\u06d2 \u0644\u067e\u06cc\u0679\u06cc\u06ba\u06d4 <code>AgentExecutor<\/code>\u067e\u0648\u0631\u0679 9002 \u067e\u0631 \u067e\u06cc\u0634 \u06a9\u06cc\u0627 \u06af\u06cc\u0627\u06d4 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u06a9\u0648\u0686 CrewAI \u06a9\u0648 \u062f\u0631\u0622\u0645\u062f \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 CrewAI \u0627\u06cc\u062c\u0646\u0679 LangGraph \u062f\u0631\u0622\u0645\u062f \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0635\u0631\u0641 HTTP \u067e\u0631 \u0628\u0627\u062a \u0686\u06cc\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0639\u0645\u0644\u06c1 \u06a9\u06cc \u0637\u0631\u0641:<\/p>\n<pre><code class=\"language-python\"># src\/crewai_agent\/study_buddy.py\n\nfrom crewai import Agent, Crew, LLM, Process, Task\nfrom crewai.tools import BaseTool\n\nMODEL_NAME     = os.getenv(\"OLLAMA_MODEL\", \"qwen2.5:7b\")\nOLLAMA_BASE_URL = os.getenv(\"OLLAMA_BASE_URL\", \"http:\/\/localhost:11434\")\n\n\nclass TopicAnalyserTool(BaseTool):\n    \"\"\"\n    Structures the Study Buddy's approach before generating its response.\n\n    In production this might query a knowledge graph or curriculum database.\n    For the tutorial, it produces structured guidance from the inputs.\n    \"\"\"\n    name:        str = \"topic_analyser\"\n    description: str = (\n        \"Analyse a study topic and weak areas to produce a structured \"\n        \"list of key concepts to focus on.\"\n    )\n    args_schema: type = TopicAnalyserInput\n\n    def _run(self, topic: str, weak_areas: list[str] | None = None) -> str:\n        areas = weak_areas or []\n        return json.dumps({\n            \"topic\":              topic,\n            \"focus_areas\":        areas or [f\"Core concepts of {topic}\"],\n            \"suggested_approach\": f\"Start with fundamentals, then address: {', '.join(areas)}.\",\n            \"study_tip\": (\n                \"Try explaining the concept out loud in your own words. \"\n                \"If you can teach it simply, you understand it.\"\n            ),\n        })\n\n\ndef build_study_buddy_crew(topic: str, explanation: str, weak_areas: list[str]) -> Crew:\n    \"\"\"Build a CrewAI crew for a specific study assistance request.\"\"\"\n    llm = LLM(model=f\"ollama\/{MODEL_NAME}\", base_url=OLLAMA_BASE_URL)\n\n    agent = Agent(\n        role=\"Study Buddy\",\n        goal=(\n            \"Provide clear, encouraging supplementary explanations that help \"\n            \"students understand difficult concepts from a fresh angle.\"\n        ),\n        backstory=(\n            \"You are an experienced tutor who specialises in finding alternative \"\n            \"explanations and analogies that make difficult ideas click.\"\n        ),\n        llm=llm,\n        tools=[TopicAnalyserTool()],\n        verbose=False,\n        allow_delegation=False,\n    )\n\n    weak_text = (\n        f\"The student struggled with: {', '.join(weak_areas)}\"\n        if weak_areas else \"No specific weak areas identified.\"\n    )\n\n    task = Task(\n        description=(\n            f\"A student is studying '{topic}'. They received this explanation:nn\"\n            f\"{explanation[:1000]}nn\"\n            f\"{weak_text}nn\"\n            f\"Use the topic_analyser tool to structure your approach. Then provide:n\"\n            f\"1) A fresh analogy that explains the core concept differentlyn\"\n            f\"2) One concrete example targeting the weak area(s)n\"\n            f\"3) One practical tip for remembering this conceptn\"\n            f\"Keep your response concise and encouraging (150-250 words).\"\n        ),\n        agent=agent,\n        expected_output=(\n            \"A study assistance response with a fresh analogy, \"\n            \"a targeted example, and a memory tip.\"\n        ),\n    )\n\n    return Crew(\n        agents=[agent],\n        tasks=[task],\n        process=Process.sequential,\n        verbose=False,\n    )\n<\/code><\/pre>\n<p>A2A \u0631\u06cc\u067e\u0631 CrewAI \u0679\u06cc\u0645 \u06a9\u0648 A2A \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u0633\u06d2 \u062c\u0648\u0691\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u06c1\u06d2 <code>StudyBuddyExecutor<\/code>\u062c\u06cc\u0633\u0627 \u06a9\u06c1 \u0688\u06be\u0627\u0646\u0686\u06c1 <code>QuizAgentExecutor<\/code>\u0644\u06cc\u06a9\u0646 \u067e\u06be\u0631 \u0645\u062c\u06be\u06d2 \u0627\u06cc\u06a9 \u0641\u0648\u0646 \u0622\u06cc\u0627\u06d4 <code>crew.kickoff()<\/code> \u06a9\u0648\u0626\u0632 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2:<\/p>\n<pre><code class=\"language-python\">class StudyBuddyExecutor(AgentExecutor):\n    \"\"\"\n    Bridges the A2A protocol to CrewAI execution.\n\n    The LangGraph system has no idea this is CrewAI.\n    The CrewAI crew has no idea it's serving an A2A request.\n    \"\"\"\n\n    async def execute(\n        self,\n        context: RequestContext,\n        event_queue: EventQueue,\n    ) -> None:\n        # Parse request\n        request_text = \"\"\n        for part in context.current_request.params.message.parts:\n            if isinstance(part, TextPart):\n                request_text += part.text\n\n        try:\n            request_data = json.loads(request_text)\n        except json.JSONDecodeError:\n            request_data = {\"topic\": request_text}\n\n        topic       = request_data.get(\"topic\", \"General Topic\")\n        explanation = request_data.get(\"explanation\", \"\")\n        weak_areas  = request_data.get(\"weak_areas\", [])\n\n        # CrewAI's kickoff() is synchronous. Run in thread pool\n        # to avoid blocking the async event loop.\n        try:\n            crew        = build_study_buddy_crew(topic, explanation, weak_areas)\n            crew_result = await asyncio.to_thread(crew.kickoff)\n            result_text = crew_result.raw if hasattr(crew_result, \"raw\") else str(crew_result)\n\n            result = {\n                \"source\":     \"crewai_study_buddy\",\n                \"topic\":      topic,\n                \"weak_areas\": weak_areas,\n                \"assistance\": result_text,\n                \"status\":     \"complete\",\n            }\n        except Exception as e:\n            result = {\n                \"source\":     \"crewai_study_buddy\",\n                \"topic\":      topic,\n                \"assistance\": f\"Could not generate supplementary help for '{topic}'.\",\n                \"status\":     \"error\",\n                \"error\":      str(e),\n            }\n\n        await event_queue.enqueue_event(\n            Message(\n                role=\"agent\",\n                parts=[TextPart(text=json.dumps(result, indent=2))],\n            )\n        )\n<\/code><\/pre>\n<p><code>asyncio.to_thread(crew.kickoff)<\/code> \u06cc\u06c1 \u0627\u06cc\u06a9 \u062a\u0646\u0642\u06cc\u062f\u06cc \u0644\u06a9\u06cc\u0631 \u06c1\u06d2\u06d4 \u0639\u0645\u0644\u06c1 \u06a9\u0627 <code>kickoff()<\/code> \u06cc\u06c1 \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u0627\u0648\u0631 \u0645\u0633\u062f\u0648\u062f \u06c1\u06d2\u06d4 \u0645\u0627\u0688\u0644 \u0627\u0648\u0631 \u06a9\u0627\u0645 \u06a9\u06cc \u067e\u06cc\u0686\u06cc\u062f\u06af\u06cc \u067e\u0631 \u0645\u0646\u062d\u0635\u0631 \u06c1\u06d2\u060c \u06cc\u06c1 30 \u0633\u06d2 \u200b\u200b60 \u0633\u06cc\u06a9\u0646\u0688 \u062a\u06a9 \u0686\u0644 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0633\u06d2 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u06a9\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>async<\/code> \u06cc\u06c1 \u0641\u06cc\u0686\u0631 \u067e\u0648\u0631\u06d2 A2A \u0633\u0631\u0648\u0631 \u06a9\u0648 \u0627\u0633 \u0648\u0642\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0646\u062c\u0645\u062f \u06a9\u0631 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0633\u06d2 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u062f\u0648\u0633\u0631\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0648 \u0642\u0628\u0648\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 <code>asyncio.to_thread<\/code> Python \u06a9\u06d2 \u0688\u06cc\u0641\u0627\u0644\u0679 \u062a\u06be\u0631\u06cc\u0688 \u067e\u0648\u0644 \u067e\u0631 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u060c \u0679\u06cc\u0645 \u06a9\u06d2 \u0686\u0644\u0646\u06d2 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u062f\u06cc\u06af\u0631 \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u0648\u06ba \u06a9\u0648 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u0648\u0646\u0679 \u06a9\u06d2 \u0644\u0648\u067e \u06a9\u0648 \u0622\u0632\u0627\u062f \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-85-the-progress-coach-fallback-pattern\">8.5 \u067e\u06cc\u0634 \u0631\u0641\u062a \u06a9\u0648\u0686 \u0641\u0627\u0644 \u0628\u06cc\u06a9 \u067e\u06cc\u0679\u0631\u0646<\/h3>\n<p>\u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u06a9\u0648\u0686 \u0645\u0627\u0688\u06cc\u0648\u0644 A2A \u062e\u062f\u0645\u0627\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0628\u0627\u062a \u0686\u06cc\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0648 \u0645\u062f\u062f\u06af\u0627\u0631 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0631 \u0627\u06cc\u06a9 \u067e\u06c1\u0644\u06d2 \u0628\u06cc\u0631\u0648\u0646\u06cc \u0633\u0631\u0648\u0633 \u06a9\u0648 \u0622\u0632\u0645\u0627\u0626\u06d2 \u06af\u0627 \u0627\u0648\u0631 \u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u062e\u0631\u0627\u0628\u06cc \u067e\u06cc\u0634 \u0622\u062a\u06cc \u06c1\u06d2 \u062a\u0648 \u0645\u0642\u0627\u0645\u06cc \u0688\u06cc\u0641\u0627\u0644\u0679 \u067e\u0631 \u0648\u0627\u067e\u0633 \u0622\u062c\u0627\u0626\u06d2 \u06af\u06cc\u06d4<\/p>\n<p>\u0627\u0633\u0679\u0688\u06cc \u0628\u0688\u06cc \u0627\u0633\u0633\u0679\u0646\u0679 \u0627\u0633 \u0633\u06d2 \u0645\u0646\u0633\u0644\u06a9 \u06c1\u06cc\u06ba: <code>progress_coach_node<\/code> \u062c\u0628 \u0628\u06be\u06cc \u0645\u0648\u0636\u0648\u0639 \u06a9\u0627 \u0633\u06a9\u0648\u0631 \u06af\u0632\u0631\u0646\u06d2 \u06a9\u06cc \u062d\u062f \u0633\u06d2 \u0646\u06cc\u0686\u06d2 \u06c1\u0648 \u062a\u0648 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u0648\u0626\u0632 \u0688\u06cc\u0644\u06cc\u06af\u06cc\u0634\u0646 \u0627\u0633\u0633\u0679\u0646\u0679 \u0627\u0646 \u0642\u0627\u0631\u0626\u06cc\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0627\u0631 \u0639\u0645\u0627\u0631\u062a \u06a9\u06d2 \u0628\u0644\u0627\u06a9 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0648 A2A \u0633\u0631\u0648\u0633 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u06af\u0631\u06cc\u0688\u0646\u06af \u06a9\u0648 \u0627\u0646 \u0644\u0627\u0626\u0646 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0631\u0648\u0679 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0637\u06d2 \u0634\u062f\u06c1 \u0628\u06c1\u0627\u0624 \u06a9\u0648\u0626\u0632 \u062a\u062e\u0644\u06cc\u0642 \u06a9\u0648 \u0633\u0627\u062f\u06af\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0642\u0627\u0645\u06cc \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u062f\u0648\u0646\u0648\u06ba \u0645\u062f\u062f\u06af\u0627\u0631 \u0627\u06cc\u06a9 \u06c1\u06cc \u0633\u0631\u06a9\u0679 \u0628\u0631\u06cc\u06a9\u0631 \u067e\u06cc\u0679\u0631\u0646 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627\u0631\u0688 \u06a9\u06cc \u067e\u06c1\u0644\u06d2 \u062c\u0627\u0646\u0686 \u067e\u0691\u062a\u0627\u0644 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0635\u0644 \u0622\u067e\u0631\u06cc\u0634\u0646 \u06a9\u0627\u0644 \u0645\u062d\u062f\u0648\u062f \u0648\u0642\u062a \u067e\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0635\u0627\u0631\u0641 \u06a9\u0648 \u0628\u06cc\u0631\u0648\u0646\u06cc \u063a\u0644\u0637\u06cc\u0627\u06ba \u0638\u0627\u06c1\u0631 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\"># src\/agents\/progress_coach.py\n\nQUIZ_SERVICE_URL = \"http:\/\/localhost:9001\"\n\ndef try_a2a_quiz_delegation(topic, explanation, answers) -> dict | None:\n    \"\"\"\n    Attempt to delegate quiz grading to the A2A Quiz Service.\n    Returns the grading result, or None on any failure.\n\n    Note: USE_A2A_QUIZ is read at call time, not at module load time.\n    Reading env vars at import time causes test isolation failures.\n    The env var state at import time gets baked in for the process lifetime.\n    \"\"\"\n    use_a2a = os.getenv(\"USE_A2A_QUIZ\", \"true\").lower() == \"true\"\n    if not use_a2a:\n        return None\n\n    try:\n        from a2a_services.a2a_client import delegate_quiz_task, is_quiz_service_available\n\n        if not is_quiz_service_available(QUIZ_SERVICE_URL):\n            print(f\"[Progress Coach] Quiz A2A service unavailable. Using local.\")\n            return None\n\n        print(f\"[Progress Coach] Delegating quiz to A2A: {QUIZ_SERVICE_URL}\")\n        result = delegate_quiz_task(topic=topic, explanation=explanation, answers=answers)\n\n        if \"error\" in result:\n            print(f\"[Progress Coach] A2A failed: {result['error']}\")\n            return None\n\n        return result\n\n    except Exception as e:\n        print(f\"[Progress Coach] A2A error: {e}\")\n        return None\n\n\ndef try_study_buddy_assistance(topic, explanation, weak_areas) -> str | None:\n    \"\"\"\n    Request supplementary help from the CrewAI Study Buddy.\n    Returns assistance text, or None if the service is unavailable.\n    \"\"\"\n    study_buddy_url = os.getenv(\"STUDY_BUDDY_URL\", \"http:\/\/localhost:9002\")\n    use_study_buddy = os.getenv(\"USE_STUDY_BUDDY\", \"true\").lower() == \"true\"\n\n    if not use_study_buddy:\n        return None\n\n    try:\n        from a2a_services.a2a_client import request_study_assistance, is_study_buddy_available\n\n        if not is_study_buddy_available(study_buddy_url):\n            return None\n\n        result = request_study_assistance(\n            topic=topic,\n            explanation=explanation,\n            weak_areas=weak_areas,\n            study_buddy_url=study_buddy_url,\n        )\n\n        if result.get(\"status\") == \"error\" or \"error\" in result:\n            return None\n\n        return result.get(\"assistance\", \"\")\n\n    except Exception as e:\n        return None\n<\/code><\/pre>\n<p>\u067e\u0631 \u062a\u0628\u0635\u0631\u06d2 <code>os.getenv<\/code> \u06a9\u0627\u0644 \u06a9\u0627 \u0648\u0642\u062a \u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06d2\u06d4 \u0645\u0627\u0688\u06cc\u0648\u0644\u0632 \u062f\u0631\u0622\u0645\u062f \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a \u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u0645\u062a\u063a\u06cc\u0631\u0627\u062a \u06a9\u0648 \u067e\u0691\u06be\u0646\u0627 (<code>USE_A2A = os.getenv(\"USE_A2A_QUIZ\", \"true\") == \"true\"<\/code> \u0641\u0627\u0626\u0644 \u06a9\u06d2 \u0627\u0648\u067e\u0631\u06cc \u062d\u0635\u06d2 \u0645\u06cc\u06ba) \u0627\u0646 \u0627\u0642\u062f\u0627\u0631 \u06a9\u0648 \u0628\u06cc\u06a9 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0627\u0633 \u0648\u0642\u062a \u0645\u0648\u062c\u0648\u062f \u062a\u06be\u06cc\u06ba \u062c\u0628 \u0645\u0627\u0688\u06cc\u0648\u0644 \u067e\u06c1\u0644\u06cc \u0628\u0627\u0631 \u062f\u0631\u0622\u0645\u062f \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627\u06d4 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 env var \u0633\u06cc\u0679 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0679\u06cc\u0633\u0679 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc \u0646\u0638\u0631 \u0646\u06c1\u06cc\u06ba \u0622\u0626\u06d2 \u06af\u06cc \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0645\u0627\u0688\u06cc\u0648\u0644 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0686\u0644\u0627\u06cc\u0627 \u062c\u0627 \u0686\u06a9\u0627 \u06c1\u06d2\u06d4 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u067e\u0691\u06be\u0646\u0627 \u06c1\u0631 \u06a9\u0627\u0644 \u067e\u0631 \u0645\u0648\u062c\u0648\u062f\u06c1 \u0642\u062f\u0631 \u06a9\u06cc \u0636\u0645\u0627\u0646\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-86-running-the-full-three-terminal-setup\">8.6 \u062a\u0645\u0627\u0645 3 \u0679\u0631\u0645\u06cc\u0646\u0644 \u0633\u06cc\u0679\u0646\u06af\u0632 \u067e\u0631 \u0639\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0627\u06cc\u06a9 \u0628\u0627\u0631 \u062c\u0628 \u062a\u0645\u0627\u0645 \u062e\u062f\u0645\u0627\u062a \u0627\u067e\u0646\u06cc \u062c\u06af\u06c1 \u067e\u0631 \u0622\u062c\u0627\u0626\u06cc\u06ba \u062a\u0648 \u067e\u0648\u0631\u0627 \u0646\u0638\u0627\u0645 \u062a\u06cc\u0646 \u0679\u0631\u0645\u06cc\u0646\u0644\u0632 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0679\u0631\u0645\u06cc\u0646\u0644 1:<\/strong> \u06a9\u0644\u06cc\u062f\u06cc \u0633\u06cc\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0633\u0631\u0639\u062a \u06a9\u0627\u0631:<\/p>\n<pre><code class=\"language-bash\">source .venv\/bin\/activate\npython main.py \"Learn Python closures\"\n<\/code><\/pre>\n<p><strong>\u0679\u0631\u0645\u06cc\u0646\u0644 2:<\/strong> \u06a9\u0648\u0626\u0632 \u062c\u0646\u0631\u06cc\u0679\u0631 A2A \u062e\u062f\u0645\u0627\u062a:<\/p>\n<pre><code class=\"language-bash\">source .venv\/bin\/activate\npython src\/a2a_services\/quiz_service.py\n<\/code><\/pre>\n<p><strong>\u0679\u0631\u0645\u06cc\u0646\u0644 3:<\/strong> CrewAI \u0631\u06cc\u0633\u0631\u0686 \u0641\u0631\u06cc\u0646\u0688\u0632:<\/p>\n<pre><code class=\"language-bash\">source .venv\/bin\/activate\npython src\/crewai_agent\/study_buddy.py\n<\/code><\/pre>\n<p>\u06cc\u0627 \u0645\u06cc\u06a9 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2:<\/p>\n<pre><code class=\"language-bash\">make services   # Terminals 2 and 3 in background\nmake run        # Terminal 1\n<\/code><\/pre>\n<p>\u062c\u0628 \u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u06a9\u0648\u0686 \u062f\u0648\u0646\u0648\u06ba \u062e\u062f\u0645\u0627\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0686\u0644\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u06a9\u0648 \u062f\u0631\u062c \u0630\u06cc\u0644 \u0646\u0638\u0631 \u0622\u062a\u0627 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-plaintext\">[Progress Coach] Score: 35%\n[Progress Coach] Delegating quiz to A2A: http:\/\/localhost:9001\n[Quiz A2A] Task received: topic=\"Python Functions\", answers_provided=3\n[Quiz A2A] Task complete: status=graded\n[Progress Coach] A2A quiz complete: score=35%\n[Progress Coach] Requesting study assistance from CrewAI Study Buddy...\n[Study Buddy A2A] Request: topic=\"Python Functions\", weak_areas=['first-class functions']\n[Study Buddy A2A] Task complete (287 chars)\n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nCoach: You scored 35% on Python Functions. That's a solid foundation to build on...\n\n&#x1f4da; Study Buddy says:\nThink of functions like variables with superpowers. Just as you can pass a number\nto another function, you can pass a function too...\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n<\/code><\/pre>\n<p>\u0627\u06af\u0631 \u062f\u0648\u0646\u0648\u06ba \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0633\u0631\u0648\u0633 \u0646\u06c1\u06cc\u06ba \u0686\u0644 \u0631\u06c1\u06cc \u06c1\u06d2 \u062a\u0648 \u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u06a9\u0648\u0686 \u062e\u0648\u0628\u0635\u0648\u0631\u062a\u06cc \u0633\u06d2 \u0648\u0627\u067e\u0633 \u0622\u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-plaintext\">[A2A Client] Cannot reach http:\/\/localhost:9001\/.well-known\/agent-card.json: Connection refused\n[Progress Coach] Quiz A2A service unavailable. Using local.\n<\/code><\/pre>\n<p>\u0633\u06cc\u0634\u0646 \u062c\u0627\u0631\u06cc \u06c1\u06d2\u06d4 \u0637\u0627\u0644\u0628 \u0639\u0644\u0645 \u06a9\u0628\u06be\u06cc \u063a\u0644\u0637\u06cc \u0646\u06c1\u06cc\u06ba \u062f\u06cc\u06a9\u06be\u062a\u0627\u06d4<\/p>\n<p> <strong>\u0686\u0648\u06a9\u06cc:<\/strong> A2A \u0679\u06cc\u0633\u0679 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">pytest tests\/test_a2a.py tests\/test_crewai_interop.py -v\n<\/code><\/pre>\n<p>\u0645\u062a\u0648\u0642\u0639: 44 \u0679\u06cc\u0633\u0679\u060c \u0633\u0628\u06be\u06cc \u067e\u0627\u0633 \u06c1\u0648 \u06af\u0626\u06d2\u06d4 \u06cc\u06c1 \u0679\u06cc\u0633\u0679 HTTP \u06a9\u0627\u0644 \u06a9\u0627 \u0645\u0630\u0627\u0642 \u0627\u0691\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062f\u0631\u062c \u0630\u06cc\u0644 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>delegate_quiz_task<\/code> \u062f\u0631\u0633\u062a JSON-RPC \u067e\u06d2 \u0644\u0648\u0688 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 <code>discover_agent<\/code> \u06a9\u0646\u06a9\u0634\u0646 \u06a9\u06cc \u063a\u0644\u0637\u06cc\u0648\u06ba \u06a9\u0648 \u0627\u062d\u0633\u0646 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>build_study_buddy_crew<\/code> \u0645\u0646\u0627\u0633\u0628 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u062a\u0634\u06a9\u06cc\u0644 \u0634\u062f\u06c1 \u0639\u0645\u0644\u06c1 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06cc \u062e\u062f\u0645\u0627\u062a \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0646\u0679\u0631\u067e\u0631\u0627\u0626\u0632 \u06a9\u0646\u06cc\u06a9\u0679\u06cc\u0648\u06cc\u0679\u06cc: A2A \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u0646\u0638\u0627\u0645 \u06a9\u0648 \u062a\u0646\u0638\u06cc\u0645\u06cc \u0633\u0637\u062d \u067e\u0631 \u0642\u0627\u0628\u0644 \u062a\u0631\u062a\u06cc\u0628 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u0679\u06cc\u0645 (LangGraph) \u06a9\u06cc \u0637\u0631\u0641 \u0633\u06d2 \u0628\u0646\u0627\u06cc\u0627 \u06af\u06cc\u0627 \u06a9\u0645\u067e\u0644\u0627\u0626\u0646\u0633 \u0679\u0631\u06cc\u0646\u0646\u06af \u067e\u0644\u06cc\u0679 \u0641\u0627\u0631\u0645 \u062f\u0648\u0633\u0631\u06cc \u0679\u06cc\u0645 (CrewAI \u06cc\u0627 \u06a9\u0648\u0626\u06cc HTTP \u0633\u0631\u0648\u0633) \u06a9\u06cc \u0637\u0631\u0641 \u0633\u06d2 \u0628\u0646\u0627\u0626\u06cc \u06af\u0626\u06cc \u0633\u0631\u0679\u06cc\u0641\u06cc\u06a9\u06cc\u0634\u0646 \u062a\u0635\u062f\u06cc\u0642\u06cc \u0633\u0631\u0648\u0633 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc \u0679\u06cc\u0645 \u06a9\u0648 \u062f\u0648\u0633\u0631\u06cc \u0679\u06cc\u0645 \u06a9\u06cc \u0639\u0645\u0644 \u0622\u0648\u0631\u06cc \u06a9\u06cc \u062a\u0641\u0635\u06cc\u0644\u0627\u062a \u062c\u0627\u0646\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 A2A \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u0627\u06cc\u06a9 \u0645\u0639\u0627\u06c1\u062f\u06c1 \u06c1\u06d2\u06d4 \u062f\u0648\u0646\u0648\u06ba \u0641\u0631\u06cc\u0642 \u0627\u0633 \u06a9\u0627 \u0627\u062d\u062a\u0631\u0627\u0645 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0628\u0627\u0642\u06cc \u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0622\u062e\u0631\u06cc \u0628\u0627\u0628 \u0645\u06cc\u06ba \u067e\u0648\u0631\u06d2 \u0646\u0638\u0627\u0645 \u06a9\u0648 \u0633\u0631\u06d2 \u0633\u06d2 \u0622\u062e\u0631 \u062a\u06a9 \u0686\u0644\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u062f\u06cc\u06a9\u06be\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u060c \u06cc\u06c1 \u062f\u06cc\u06a9\u06be\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0627\u0633\u06d2 \u06a9\u06cc\u0633\u06d2 \u0628\u0691\u06be\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2\u060c \u0627\u0648\u0631 \u06cc\u06c1 \u062f\u06cc\u06a9\u06be\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u0646\u0638\u0627\u0645 \u0622\u06af\u06d2 \u06a9\u06c1\u0627\u06ba \u062c\u0627 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-chapter-9-the-complete-system-and-whats-next\">\u0628\u0627\u0628 9: \u0645\u062c\u0645\u0648\u0639\u06cc \u0646\u0638\u0627\u0645 \u0627\u0648\u0631 \u0627\u06af\u0644\u06d2 \u0627\u0642\u062f\u0627\u0645\u0627\u062a<\/h2>\n<p>\u0633\u0628 \u06a9\u0686\u06be \u0628\u0646\u0627\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u0686\u0627\u0631 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0627\u06cc\u062c\u0646\u0679\u0633 \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0631\u06cc\u0627\u0633\u062a \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0645\u0631\u0628\u0648\u0637 \u06c1\u06cc\u06ba\u060c \u0679\u0648\u0644 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u062f\u0648 MCP \u0633\u0631\u0648\u0631\u0632\u060c \u062f\u0648 A2A \u0633\u0631\u0648\u0633\u0632 \u062c\u0648 \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0639\u0645\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0686\u0644 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u060c \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u06a9\u06cc\u067e\u0686\u0631 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0641\u06cc\u0635\u0644\u06d2 \u06a9\u06cc \u0633\u0637\u062d \u06a9\u06d2 \u0646\u0634\u0627\u0646\u0627\u062a\u060c \u0688\u06cc\u067e \u0627\u06cc\u0648\u0644 \u0686\u0644\u0627\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u0648\u0627\u0644\u0679\u06cc \u06af\u06cc\u0679\u0633\u060c \u0627\u0648\u0631 \u0627\u06cc\u06a9 Streamlit UI \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u0648 \u0628\u063a\u06cc\u0631 \u0679\u0631\u0645\u06cc\u0646\u0644 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1 \u0628\u0627\u0628 \u0627\u06cc\u06a9 \u0639\u0645\u0644\u06cc \u06a9\u062a\u0627\u0628 \u06c1\u06d2\u06d4 \u06a9\u0633 \u0637\u0631\u062d \u062a\u0645\u0627\u0645 \u0679\u06a9\u0691\u06d2 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0641\u0679 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0633\u06cc\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u067e\u06cc\u0645\u0627\u0646\u06c1 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0644\u0631\u0646\u0646\u06af \u0627\u06cc\u06a9\u0633\u0644\u0631\u06cc\u0679\u0631 \u0633\u06d2 \u0622\u06af\u06d2 \u067e\u06cc\u0679\u0631\u0646 \u06a9\u0627 \u0627\u0637\u0644\u0627\u0642 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-91-mainpy-the-entry-point\">9.1 <code>main.py<\/code>: \u0627\u0646\u0679\u0631\u06cc \u067e\u0648\u0627\u0626\u0646\u0679<\/h3>\n<p><code>main.py<\/code> 140 \u0644\u0627\u0626\u0646\u0648\u06ba \u0633\u06d2 \u06a9\u0645\u06d4 \u06cc\u06c1 \u0686\u0627\u0631 \u06a9\u0627\u0645 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2: \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0644\u0648\u0688 \u06a9\u0631\u06cc\u06ba\u060c \u06a9\u0645\u0627\u0646\u0688 \u0644\u0627\u0626\u0646 \u0622\u0631\u06af\u0648\u0645\u0646\u0679\u0633 \u067e\u0631 \u0639\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u0646\u0679\u0631\u067e\u0679\/\u0631\u06cc\u0632\u06cc\u0648\u0645 \u0644\u0648\u067e \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u06af\u0631\u0627\u0641 \u06a9\u0648 \u0686\u0644\u0627\u0626\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0633\u06cc\u0634\u0646 \u06a9\u0627 \u062e\u0644\u0627\u0635\u06c1 \u067e\u0631\u0646\u0679 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u062f\u06cc\u06af\u0631 \u062a\u0645\u0627\u0645 \u0645\u0633\u0627\u0626\u0644 (\u0627\u06cc\u062c\u0646\u0679\u060c \u0679\u0648\u0644\u0632\u060c \u0645\u0634\u0627\u06c1\u062f\u06c1\u060c \u0627\u0633\u062a\u0642\u0627\u0645\u062a) \u0645\u0627\u0688\u06cc\u0648\u0644\u0632 \u0645\u06cc\u06ba \u0633\u0646\u0628\u06be\u0627\u0644\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>main.py<\/code> \u062f\u0631\u0622\u0645\u062f<\/p>\n<pre><code class=\"language-python\"># main.py\n\nimport sys\nimport os\nimport uuid\nfrom pathlib import Path\n\n# Add src\/ to Python path before any project imports\nsys.path.insert(0, str(Path(__file__).parent \/ \"src\"))\n\nfrom dotenv import load_dotenv\nload_dotenv()\n\nfrom graph.workflow import graph\nfrom graph.state import initial_state\nfrom observability.langfuse_setup import get_langfuse_config, flush_langfuse\n\n\ndef run_session(goal: str, session_id: str | None = None) -> None:\n    \"\"\"Run a complete interactive study session with Langfuse tracing.\"\"\"\n    is_resume = session_id is not None\n    if not session_id:\n        session_id = str(uuid.uuid4())[:8]\n\n    # get_langfuse_config() builds the full run config:\n    #   - thread_id for SQLite checkpointing\n    #   - Langfuse callback handler (if LANGFUSE_PUBLIC_KEY is set)\n    config = get_langfuse_config(session_id)\n\n    print(f\"n{'='*60}\")\n    print(f\"Learning Accelerator\")\n    print(f\"Session ID: {session_id}\")\n    if is_resume:\n        print(f\"Resuming existing session...\")\n    else:\n        print(f\"Goal: {goal}\")\n    print(f\"{'='*60}\")\n\n    # For a new session: initial state. For resume: None. LangGraph loads from checkpoint.\n    state = None if is_resume else initial_state(goal, session_id)\n    result = graph.invoke(state, config=config)\n\n    # Interrupt\/resume loop\n    from langgraph.types import Command\n    while \"__interrupt__\" in result:\n        interrupt_payload = result[\"__interrupt__\"][0].value\n        roadmap = interrupt_payload.get(\"roadmap\")\n        if roadmap:\n            # Display roadmap (abbreviated for chapter. See repo for the full version.)\n            print_roadmap(roadmap)\n        print(f\"n{interrupt_payload.get('prompt', 'Continue?')}\")\n        user_input = input(\"> \").strip()\n        result = graph.invoke(Command(resume=user_input), config=config)\n\n    if result.get(\"error\"):\n        print(f\"n[ERROR] {result['error']}\")\n        return\n\n    print_session_summary(result)\n    flush_langfuse()   # Ensure all traces are sent before exit\n\n\nif __name__ == \"__main__\":\n    import argparse\n    parser = argparse.ArgumentParser(description=\"Learning Accelerator\")\n    parser.add_argument(\"goal\", nargs=\"?\",\n                        default=\"Learn Python closures and decorators from scratch\")\n    parser.add_argument(\"--resume\", metavar=\"SESSION_ID\",\n                        help=\"Resume an existing session by ID\")\n    args = parser.parse_args()\n\n    if args.resume:\n        run_session(goal=\"\", session_id=args.resume)\n    else:\n        run_session(goal=args.goal)\n<\/code><\/pre>\n<p>\u0627\u0633 \u0641\u0627\u0626\u0644 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u062a\u06cc\u0646 \u0686\u06cc\u0632\u06cc\u06ba \u0642\u0627\u0628\u0644 \u063a\u0648\u0631 \u06c1\u06cc\u06ba:<\/p>\n<p><strong>\u06af\u0631\u0627\u0641 \u06a9\u0648 \u0645\u0627\u0688\u06cc\u0648\u0644 \u0644\u06cc\u0648\u0644 \u0633\u0646\u06af\u0644\u0679\u0646 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u062f\u0631\u0622\u0645\u062f \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/strong> <code>from graph.workflow import graph<\/code> \u0686\u0644\u0627\u0626\u06cc\u06ba <code>build_graph()<\/code> \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u062f\u0631\u0622\u0645\u062f \u067e\u0631\u06d4 \u0645\u0631\u062a\u0628 \u0634\u062f\u06c1 \u06af\u0631\u0627\u0641 \u067e\u0648\u0631\u06d2 \u0639\u0645\u0644 \u067e\u0631 \u0644\u0627\u06af\u0648 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u0628\u0634\u0645\u0648\u0644 \u0627\u06cc\u06a9 \u06c1\u06cc SqliteSaver \u06a9\u0646\u06a9\u0634\u0646 \u0627\u0648\u0631 \u0648\u06c1\u06cc \u0631\u062c\u0633\u0679\u0631\u0688 \u0646\u0648\u0688\u0633\u06d4<\/p>\n<p>\u06cc\u06c1 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u06c1\u06d2\u06d4 \u0627\u06a9\u062b\u0631\u06cc\u062a <code>graph.invoke<\/code> \u06a9\u0627\u0644\u0632 (\u0627\u0628\u062a\u062f\u0627\u0626\u06cc \u0627\u0648\u0631 \u06a9\u0633\u06cc \u0631\u06a9\u0627\u0648\u0679 \u06a9\u06cc \u0648\u062c\u06c1 \u0633\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u06cc \u06af\u0626\u06cc) \u0633\u0628\u06be\u06cc \u0627\u06cc\u06a9 \u06c1\u06cc \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679\u0631 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u06cc\u06a9 \u06c1\u06cc \u0645\u0631\u062a\u0628 \u06a9\u0631\u062f\u06c1 \u06af\u0631\u0627\u0641 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<p><strong>\u0631\u06cc\u0632\u06cc\u0648\u0645\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u0679\u06cc\u0679\u0633 \u06c1\u06cc\u0646\u0688\u0644\u0646\u06af \u0627\u06cc\u06a9 \u0644\u0627\u0626\u0646 \u06c1\u06d2\u06d4<\/strong> <code>state = None if is_resume else initial_state(...)<\/code>. \u06af\u0632\u0631\u0646\u0627 <code>None<\/code> LangGraph \u06a9\u0648 \u062a\u0627\u0632\u06c1 \u062a\u0631\u06cc\u0646 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u0644\u0648\u0688 \u06a9\u0631\u0646\u06d2 \u06a9\u0648 \u06a9\u06c1\u062a\u0627 \u06c1\u06d2\u06d4 <code>thread_id<\/code> \u06a9\u0648 <code>config<\/code>. \u06cc\u06c1 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u06cc \u0637\u0631\u0641 \u0633\u06d2 \u0645\u06a9\u0645\u0644 \u0631\u06cc\u0632\u06cc\u0648\u0645 \u0645\u06cc\u06a9\u0627\u0646\u0632\u0645 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u06a9\u06c1<\/strong> <code>while<\/code> <strong>\u0644\u0648\u067e \u0645\u0646\u0638\u0648\u0631\u06cc \u0627\u0648\u0631 \u0645\u0633\u062a\u0631\u062f \u062f\u0648\u0646\u0648\u06ba \u06a9\u0648 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/strong> \u062c\u0628 \u0635\u0627\u0631\u0641 \u0627\u0646 \u067e\u0679 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 <code>no<\/code>\u0645\u0634\u0631\u0648\u0637 \u06a9\u0646\u0627\u0631\u0648\u06ba \u06a9\u0648 \u0648\u0627\u067e\u0633 \u0628\u06be\u06cc\u062c \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2: <code>curriculum_planner<\/code>\u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u0631\u0648\u0688 \u0645\u06cc\u067e \u0628\u0646\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u062f\u0648\u0633\u0631\u0627 \u0631\u0648\u0688 \u0645\u06cc\u067e \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4 <code>interrupt()<\/code>. \u0644\u0648\u067e \u0646\u0626\u06d2 \u0631\u0648\u0688 \u0645\u06cc\u067e\u0633 \u06a9\u0648 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u062a\u0627 \u0631\u06c1\u062a\u0627 \u06c1\u06d2 \u062c\u0628 \u062a\u06a9 \u06a9\u06c1 \u0635\u0627\u0631\u0641 \u0627\u0646\u06c1\u06cc\u06ba \u0645\u0646\u0638\u0648\u0631 \u0646\u06c1 \u06a9\u0631 \u062f\u06d2\u06d4<\/p>\n<h3 id=\"heading-92-the-three-terminal-startup\">9.2 3 \u0679\u0631\u0645\u06cc\u0646\u0644 \u0634\u0631\u0648\u0639<\/h3>\n<p>\u067e\u0648\u0631\u06d2 \u0646\u0638\u0627\u0645 \u06a9\u0648 \u0628\u06cc\u06a9 \u0648\u0642\u062a \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0646 \u0639\u0645\u0644 \u062f\u0631\u06a9\u0627\u0631 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06a9\u06c1 <code>Makefile<\/code> \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f \u06a9\u0645\u0627\u0646\u0688 \u06c1\u062f\u0641 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-bash\">make setup      # First time only: create venv and install dependencies\nmake langfuse   # Optional: start self-hosted Langfuse\nmake services   # Start both A2A services in background\nmake run        # Start main application (foreground)\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>services<\/code> \u06c1\u062f\u0641:<\/p>\n<pre><code class=\"language-makefile\">services: stop\n\t@echo \"Starting A2A services...\"\n\t$(PYTHON) src\/a2a_services\/quiz_service.py &\n\t@sleep 1\n\t$(PYTHON) src\/crewai_agent\/study_buddy.py &\n\t@sleep 1\n\t@echo \"\"\n\t@echo \"Services started:\"\n\t@echo \"  Quiz:        http:\/\/localhost:9001\"\n\t@echo \"  Study Buddy: http:\/\/localhost:9002\"\n<\/code><\/pre>\n<p>\u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u0626\u06cc\u06ba \u06a9\u06c1 \u0622\u067e \u06c1\u0631 \u0686\u06cc\u0632 \u0633\u06d2 \u062c\u0691 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">curl http:\/\/localhost:9001\/.well-known\/agent-card.json\ncurl http:\/\/localhost:9002\/.well-known\/agent-card.json\ncurl http:\/\/localhost:3000                   # Langfuse UI\n<\/code><\/pre>\n<h3 id=\"heading-93-a-complete-session-end-to-end\">9.3 \u067e\u0648\u0631\u0627 \u0633\u06cc\u0634\u0646\u060c \u0622\u062e\u0631 \u0633\u06d2 \u0622\u062e\u0631 \u062a\u06a9<\/h3>\n<p>Ollama \u0686\u0644 \u0631\u06c1\u0627 \u06c1\u06d2\u060c A2A \u0633\u0631\u0648\u0633 \u0634\u0631\u0648\u0639 \u06c1\u0648 \u06af\u0626\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 Langfuse \u06a9\u0648 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-bash\">make services\nmake run\n<\/code><\/pre>\n<p>\u06af\u0648\u0644 \u0627\u0646 \u067e\u0679\u060c \u0645\u0646\u0638\u0648\u0631\u06cc \u0627\u0648\u0631 \u0679\u0627\u067e\u06a9 \u0644\u0648\u067e\u0633:<\/p>\n<pre><code class=\"language-plaintext\">============================================================\nLearning Accelerator\nSession ID: 8660e1d6\nGoal: Learn Python closures and decorators from scratch\n============================================================\n\n[Observability] Tracing session 8660e1d6 \u2192 http:\/\/localhost:3000\n\n[Curriculum Planner] Building roadmap for: 'Learn Python closures...'\n[Curriculum Planner] Calling qwen2.5:7b...\n[Curriculum Planner] Created roadmap: 5 topics, 4 weeks\n  1. Python Functions: 60 min\n  2. Scopes and Namespaces (needs: Python Functions): 45 min\n  3. Inner Functions (needs: Scopes and Namespaces): 60 min\n  4. Creating Closures (needs: Inner Functions): 75 min\n  5. Decorator Basics (needs: Creating Closures): 60 min\n\n[Human Approval] Pausing for roadmap review...\n\n============================================================\nProposed Study Plan\n============================================================\nGoal: Learn Python closures and decorators from scratch\nDuration: 4 weeks @ 5 hrs\/week\n\n  1. Python Functions (60 min)\n     Understand how functions are first-class objects in Python.\n  ...\n\nDoes this study plan look good?\n  Type 'yes' to start studying\n  Type 'no' to generate a different plan\n> yes\n\n[Human Approval] Roadmap approved. Starting study session.\n\n[Explainer] Topic: 'Python Functions'\n[Explainer] LLM call 1\/8...\n  \u2192 tool_list_files({})\n    \u2190 [\"closures.md\", \"decorators.md\", \"python_basics.md\"]\n[Explainer] LLM call 2\/8...\n  \u2192 tool_read_file({'filename': 'python_basics.md'})\n    \u2190 # Python Basics...\n[Explainer] Complete after 4 LLM call(s)\n\n[Quiz Generator] Generating quiz for: 'Python Functions'\n[Progress Coach] Delegating quiz to A2A: http:\/\/localhost:9001\n[Quiz A2A] Task received: topic=\"Python Functions\", answers_provided=3\n[Quiz A2A] Task complete: status=graded\n\n[Progress Coach] Score: 67%\n[Progress Coach] Requesting study assistance from CrewAI Study Buddy...\n[Study Buddy A2A] Task complete (287 chars)\n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nCoach: You've got a solid foundation in Python functions...\n\n&#x1f4da; Study Buddy says:\nThink of functions like variables with superpowers...\n\nNext topic: 'Scopes and Namespaces'\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n<\/code><\/pre>\n<p>\u0648\u06c1 \u0648\u0627\u062d\u062f \u0633\u06cc\u0634\u0646 \u0633\u0633\u0679\u0645 \u06a9\u06d2 \u062a\u0645\u0627\u0645 \u0627\u062c\u0632\u0627\u0621 \u06a9\u0648 \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0628\u0634\u0645\u0648\u0644 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0634\u0646\u060c \u0627\u06cc\u0633 \u06a9\u06cc\u0648 \u0627\u06cc\u0644\u0627\u0626\u0679 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679\u0633\u060c \u06c1\u06cc\u0648\u0645\u0646-\u0627\u0646-\u062f\u06cc-\u0644\u0648\u067e \u0627\u0646\u0679\u0631\u067e\u0679\u0633\u060c \u0627\u06cc\u0645 \u0633\u06cc \u067e\u06cc \u0679\u0648\u0644 \u06a9\u0627\u0644\u0632\u060c \u06a9\u0648\u0626\u0632 \u0633\u0631\u0648\u0633 \u0627\u0648\u0631 \u06a9\u0631\u06cc\u0648 \u0627\u06d2 \u0622\u0626\u06cc \u0627\u0633\u0679\u0688\u06cc \u0628\u0688\u06cc \u062f\u0648\u0646\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 A2A \u0648\u0641\u062f\u060c \u0627\u0648\u0631 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u0679\u0631\u06cc\u06a9\u0646\u06af\u06d4 \u0627\u06cc\u06a9 \u0633\u06cc\u0634\u0646 \u06a9\u0627 \u062e\u0644\u0627\u0635\u06c1 \u0622\u062e\u0631 \u0645\u06cc\u06ba \u067e\u0631\u0646\u0679 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0679\u0631\u06cc\u0633 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u0645\u06cc\u06ba \u0633\u06cc\u06a9\u0646\u0688\u0648\u06ba \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<h3 id=\"heading-94-the-streamlit-ui\">9.4 \u0622\u0633\u0627\u0646 UI<\/h3>\n<p>\u0679\u0631\u0645\u06cc\u0646\u0644 \u0627\u0646\u0679\u0631\u0641\u06cc\u0633 \u062a\u0631\u0642\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0648\u0632\u0648\u06ba \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0627\u067e\u0646\u06d2 \u0633\u0633\u0679\u0645 \u06a9\u0648 \u06a9\u0633\u06cc \u0627\u06cc\u0633\u06d2 \u0634\u062e\u0635 \u06a9\u0648 \u062f\u06a9\u06be\u0627\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u0627\u0633\u06d2 \u06c1\u0631 \u0631\u0648\u0632 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0679\u0631\u0645\u06cc\u0646\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u06be\u0648\u0644\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0633\u0633\u0679\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0648\u06cc\u0628 UI \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06af\u06cc\u06d4<\/p>\n<p><code>streamlit_app.py<\/code> \u0627\u067e\u0646\u06d2 \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u06a9\u06cc \u062c\u0691 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u06cc\u06ba\u06d4 \u062a\u0639\u0645\u06cc\u0631\u0627\u062a\u06cc \u067e\u06c1\u0644\u0648 \u0633\u0645\u062c\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06d2\u06d4 <strong>\u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u06a9\u0648\u0688<\/strong> <code>src\/<\/code> <strong>\u06a9\u0648\u0626\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc \u0646\u06c1\u06cc\u06ba<\/strong>. \u0627\u0633\u06cc \u06af\u0631\u0627\u0641 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 <code>main.py<\/code> \u0627\u067e\u0646\u06cc \u0648\u06cc\u0628 \u0627\u06cc\u067e\u0633 \u06a9\u0648 \u0637\u0627\u0642\u062a\u0648\u0631 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 \u0635\u0631\u0641 I\/O \u0645\u06cc\u06a9\u0627\u0646\u0632\u0645 \u0645\u062e\u062a\u0644\u0641 \u06c1\u06d2\u06d4 <code>input()<\/code> \u0627\u0648\u0631 <code>print()<\/code> \u06cc\u06c1 \u0627\u06cc\u06a9 Streamlit \u0648\u06cc\u062c\u06cc\u0679 \u0628\u0646 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0645\u0639\u0637\u0644\/\u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u067e\u06cc\u0679\u0631\u0646 \u0628\u0679\u0646 \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631\u0646\u06d2 \u067e\u0631 \u0627\u0633 \u0637\u0631\u062d \u0628\u0646 \u062c\u0627\u062a\u0627 \u06c1\u06d2: <code>st.session_state<\/code> \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>Streamlit \u06c1\u0631 \u0635\u0627\u0631\u0641 \u06a9\u06d2 \u062a\u0639\u0627\u0645\u0644 \u067e\u0631 \u067e\u0648\u0631\u06cc Python \u0627\u0633\u06a9\u0631\u067e\u0679 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0686\u06cc\u0632 \u062c\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f \u0628\u0627\u0642\u06cc \u0631\u06c1\u0646\u06cc \u0686\u0627\u06c1\u0626\u06d2\u06d4 <code>st.session_state<\/code>Streamlit \u0627\u06cc\u06a9 \u062d\u06a9\u0645 \u06c1\u06d2 \u062c\u0648 \u067e\u06be\u0627\u0646\u0633\u06cc\u0648\u06ba \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0645\u062d\u0641\u0648\u0638 \u06c1\u06d2\u06d4 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0633\u06cc\u0634\u0646 IDs\u060c \u0631\u0646 \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646\u0632\u060c \u0631\u0648\u0688 \u0645\u06cc\u067e\u060c \u0679\u0627\u067e\u06a9 \u0627\u0646\u0688\u06cc\u06a9\u0633\u060c \u0627\u0648\u0631 \u06a9\u0648\u0626\u0632 \u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u0633\u0628 \u06cc\u06c1\u0627\u06ba \u0645\u0648\u062c\u0648\u062f \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06cc\u067e \u0627\u06cc\u06a9 \u0631\u06cc\u0627\u0633\u062a\u06cc \u0645\u0634\u06cc\u0646 \u067e\u0631 \u0645\u0634\u062a\u0645\u0644 \u06c1\u06d2 \u062c\u0633 \u0645\u06cc\u06ba \u067e\u0627\u0646\u0686 \u0627\u0633\u06a9\u0631\u06cc\u0646\u06cc\u06ba \u06c1\u06cc\u06ba (\u0627\u06c1\u062f\u0627\u0641 \u062f\u0631\u062c \u06a9\u0631\u06cc\u06ba\u060c \u0631\u0648\u0688 \u0645\u06cc\u067e \u06a9\u0648 \u0645\u0646\u0638\u0648\u0631 \u06a9\u0631\u06cc\u06ba\u060c \u062a\u0628\u0635\u0631\u06c1\u060c \u06a9\u0648\u0626\u0632\u060c \u0627\u0648\u0631 \u06c1\u0648 \u06af\u06cc\u0627)\u06d4 <code>st.session_state.screen<\/code> \u06c1\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u0644\u0646\u06d2 \u06a9\u0627 \u0641\u06cc\u0635\u0644\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06a9\u06cc\u0627 \u067e\u06cc\u0634 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0622\u0631\u06a9\u06cc\u0679\u06cc\u06a9\u0686\u0631\u0644 \u0634\u06a9\u0646 \u06c1\u06d2 <code>quiz_generator_node<\/code> \u0641\u0648\u0646 \u06a9\u0627\u0644 <code>run_quiz()<\/code> \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 <code>input()<\/code> \u0627\u067e\u0646\u06d2 \u0679\u0631\u0645\u06cc\u0646\u0644 \u0633\u06d2 \u062c\u0648\u0627\u0628\u0627\u062a \u062c\u0645\u0639 \u06a9\u0631\u06cc\u06ba\u06d4 Streamlit \u0633\u06d2 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u067e\u0631\u060c \u0628\u0631\u0627\u0624\u0632\u0631 \u0645\u0646\u062c\u0645\u062f \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0641\u06a9\u0633 \u0627\u0633 \u0637\u0631\u062d \u0627\u06cc\u06a9 \u0645\u0631\u062a\u0628 \u06a9\u0631\u062f\u06c1 UI \u0645\u062e\u0635\u0648\u0635 \u06af\u0631\u0627\u0641 \u06c1\u06d2: <code>interrupt_before=[\"quiz_generator\"]<\/code>:<\/p>\n<pre><code class=\"language-python\"># streamlit_app.py (key excerpt)\n\nfrom graph.workflow import build_graph\nfrom graph.state import initial_state, StudyRoadmap, QuizResult\nfrom agents.quiz_generator import generate_questions, grade_answer\n\n# UI-specific graph: pauses BEFORE quiz_generator so the UI can\n# handle quiz I\/O without input() being called inside the graph.\nui_graph = build_graph(\n    db_path=\"data\/checkpoints_ui.db\",\n    interrupt_before=[\"quiz_generator\"],\n)\n<\/code><\/pre>\n<p>UI \u06a9\u0648\u0626\u0632 \u06a9\u0648 \u062e\u0648\u062f \u06a9\u0627\u0644 \u06a9\u0631\u06a9\u06d2 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>generate_questions<\/code> \u0627\u0648\u0631 <code>grade_answer<\/code> \u062c\u0628 \u06a9\u0648\u0626\u0632 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u0627\u06cc\u067e \u06a9\u06cc \u067e\u0631\u062a \u0645\u06cc\u06ba \u0645\u06a9\u0645\u0644 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2 (\u0627\u06cc\u06a9 \u062c\u06cc\u0633\u06cc \u0641\u0639\u0627\u0644\u06cc\u062a\u060c \u0645\u062e\u062a\u0644\u0641 \u06a9\u0627\u0644\u0631)\u060c \u0627\u06cc\u067e \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06cc \u06c1\u06d2: <code>graph.update_state()<\/code> \u0627\u0646\u062c\u06cc\u06a9\u0634\u0646 <code>QuizResult<\/code> \u062c\u06cc\u0633\u06d2 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u067e\u0631 \u0648\u0627\u067e\u0633 \u062c\u0627\u0646\u0627 <code>quiz_generator_node<\/code> \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u06a9\u0648\u0686 \u06a9\u0648 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06af\u0631\u0627\u0641 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">def advance_after_quiz(quiz_result: QuizResult):\n    \"\"\"After UI-handled quiz completes, inject result and resume graph.\"\"\"\n    config = st.session_state.graph_config\n\n    # Tell LangGraph quiz_generator has already run with this result\n    ui_graph.update_state(\n        config,\n        {\n            \"quiz_results\":        existing + [quiz_result],\n            \"weak_areas\":          all_weak,\n            \"roadmap\":             st.session_state.roadmap,\n            \"current_topic_index\": st.session_state.current_topic_index,\n        },\n        as_node=\"quiz_generator\",\n    )\n\n    # Resume. Runs progress_coach, then either explainer (next topic) or END.\n    # Because interrupt_before=[\"quiz_generator\"], if a next topic exists\n    # the graph pauses again before its quiz_generator.\n    result = ui_graph.invoke(None, config=config)\n<\/code><\/pre>\n<p>\u06cc\u0627\u062f \u0631\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u067e\u06cc\u0679\u0631\u0646 \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba: <code>graph.update_state(config, values, as_node=...)<\/code> \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u0648 \u0627\u0633 \u0637\u0631\u062d \u067e\u06cc\u0686 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u062c\u06cc\u0633\u06d2 \u06a9\u0633\u06cc \u0645\u062e\u0635\u0648\u0635 \u0646\u0648\u0688 \u0646\u06d2 \u0627\u0633 \u0642\u062f\u0631 \u06a9\u0648 \u067e\u06cc\u062f\u0627 \u06a9\u06cc\u0627 \u06c1\u0648\u06d4 \u06cc\u06c1 \u06af\u0631\u0627\u0641 \u06a9\u06d2 \u0628\u0627\u06c1\u0631 \u0686\u0644\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u0648\u0688 \u06a9\u06d2 \u0646\u062a\u0627\u0626\u062c \u06a9\u0648 \u06af\u0631\u0627\u0641 \u06a9\u06d2 \u0627\u0633\u0679\u06cc\u0679 \u0641\u0644\u0648 \u0645\u06cc\u06ba \u062f\u0627\u062e\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0627\u06cc\u06a9 \u0637\u0631\u06cc\u0642\u06c1 \u06c1\u06d2\u06d4<\/p>\n<p>\u0686\u0644\u0627\u0626\u06cc\u06ba:<\/p>\n<pre><code class=\"language-bash\">make streamlit\n# or: streamlit run streamlit_app.py\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/umang.pk\/wp-content\/uploads\/2026\/04\/1777579829_572_LangGraph\u060c-MCP\u060c-\u0627\u0648\u0631-A2A-\u06a9\u0627-\u0627\u0633\u062a\u0639\u0645\u0627\u0644-\u06a9\u0631\u062a\u06d2-\u06c1\u0648\u0626\u06d2-\u0645\u0644\u0679\u06cc-\u0627\u06cc\u062c\u0646\u0679.png\" alt=\"Streamlit \u0648\u06cc\u0628 \u0627\u0646\u0679\u0631\u0641\u06cc\u0633 \u06a9\u0627 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u0634\u0627\u0679 \u062c\u0633 \u0645\u06cc\u06ba \u0644\u0631\u0646\u0646\u06af \u0627\u06cc\u06a9\u0633\u0644\u0631\u06cc\u0679\u0631 \u06a9\u06d2 \u0631\u0648\u0688 \u0645\u06cc\u067e \u06a9\u06cc \u0645\u0646\u0638\u0648\u0631\u06cc \u06a9\u06cc \u0627\u0633\u06a9\u0631\u06cc\u0646 \u062f\u06a9\u06be\u0627\u0626\u06cc \u062f\u06d2 \u0631\u06c1\u06cc \u06c1\u06d2: \u0644\u0631\u0646\u0646\u06af \u0627\u06cc\u06a9\u0633\u0644\u0631\u06cc\u0679\u0631 \u0622\u0626\u0679\u0645 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0628\u0627\u0626\u06cc\u06ba \u0637\u0631\u0641 \u0644\u06cc\u0628\u0644 \u0644\u06af\u0627 \u06c1\u0648\u0627 \u0646\u06cc\u0648\u06cc\u06af\u06cc\u0634\u0646\u060c \u0627\u0648\u0631 \u06af\u0631\u06cc\u062c\u0648\u06cc\u0634\u0646 \u06a9\u06cc\u067e \u0679\u0627\u0626\u0679\u0644 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u0631\u06a9\u0632\u06cc \u0645\u0648\u0627\u062f \u06a9\u0627 \u0639\u0644\u0627\u0642\u06c1\u06d4 \" style=\"display:block;margin:0 auto\" width=\"600\" height=\"400\" loading=\"lazy\" Learning a &quot;Proposed Study section listing the goal &quot;Learn Python closures and decorators from duration &quot;4 weeks 5 followed by five numbered topic cards (Python Scopes Inner Creating Decorator each with estimated one-sentence prerequisite two buttons at bottom labeled &quot;Approve start &quot;Generate different title=\"\"><\/p>\n<p><em>\u0634\u06a9\u0644 3\u06d4 \u0627\u0633\u0679\u0631\u06cc\u0645 \u0644\u0627\u0626\u0679 \u0648\u06cc\u0628 \u0627\u0646\u0679\u0631\u0641\u06cc\u0633\u06d4 \u0648\u06c1\u06cc \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u06a9\u0648\u0688\u060c \u0648\u06c1\u06cc MCP \u0633\u0631\u0648\u0631\u060c \u0648\u06c1\u06cc A2A \u0633\u0631\u0648\u0633\u06d4 \u062f\u06cc\u06af\u0631 I\/O<\/em><\/p>\n<p>\u0628\u0631\u0627\u0624\u0632\u0631 http:\/\/localhost:8501 \u067e\u0631 \u06a9\u06be\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u0622\u067e \u0648\u06cc\u0628 UI \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u0633\u06cc \u0646\u0638\u0627\u0645 \u06a9\u0648 \u062d\u0627\u0635\u0644 \u06a9\u0631\u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0679\u0627\u0631\u06af\u0679 \u0627\u0646 \u067e\u0679 \u0641\u0627\u0631\u0645 \u0645\u06cc\u06ba \u06c1\u0648\u06af\u0627 \u0631\u0648\u0688 \u0645\u06cc\u067e \u06a9\u06cc \u0645\u0646\u0638\u0648\u0631\u06cc \u06a9\u06d2 \u062f\u0648 \u0628\u0679\u0646 \u06c1\u0648\u06ba \u06af\u06d2\u06d4 \u062a\u0641\u0635\u06cc\u0644 \u06a9\u0648 \u0641\u0627\u0631\u0645\u06cc\u0679 \u0634\u062f\u06c1 \u0645\u0627\u0631\u06a9 \u0688\u0627\u0624\u0646 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u067e\u06cc\u0634 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u0648\u0626\u0632 \u0633\u0648\u0627\u0644\u0627\u062a \u0627\u06cc\u06a9 \u0648\u0642\u062a \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u062c\u0648\u0627\u0628 \u06a9\u06d2 \u0645\u06cc\u062f\u0627\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06a9\u0648\u0686 \u06a9\u06cc \u0631\u0627\u0626\u06d2 \u0627\u06af\u0644\u06d2 \u0645\u0648\u0636\u0648\u0639 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0645\u0639\u0644\u0648\u0645\u0627\u062a\u06cc \u062e\u0627\u0646\u06d2 \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0633\u06cc\u0634\u0646 \u0645\u06a9\u0645\u0644 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u0633\u0645\u0631\u06cc \u0627\u0633\u06a9\u0631\u06cc\u0646 \u06c1\u0631 \u0645\u0648\u0636\u0648\u0639 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0622\u067e \u06a9\u0627 \u0633\u06a9\u0648\u0631 \u0627\u0648\u0631 \u0679\u0631\u0645\u06cc\u0646\u0644 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u06cc\u0634\u0646 ID \u062f\u06a9\u06be\u0627\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-the-streamlit-sessionstate-pattern\"> \u0627\u0633\u0679\u0631\u06cc\u0645\u0644\u06cc\u0679 <code>session_state<\/code> \u067e\u06cc\u0679\u0631\u0646<\/h4>\n<p>Streamlit \u06c1\u0631 \u0635\u0627\u0631\u0641 \u06a9\u06d2 \u062a\u0639\u0627\u0645\u0644 \u067e\u0631 \u067e\u0648\u0631\u06cc \u0627\u0633\u06a9\u0631\u067e\u0679 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0631 \u0648\u06c1 \u0686\u06cc\u0632 \u062c\u0633 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0632\u0646\u062f\u06c1 \u0631\u06c1\u0646\u0627 \u06c1\u06d2\u06d4 <code>st.session_state<\/code>\u0627\u06cc\u06a9 \u0644\u063a\u062a \u062c\u0648 Streamlit \u0631\u0646\u0632 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u062a\u06cc \u06c1\u06d2\u06d4 \u0644\u06cc\u0646\u06af\u0631\u0627\u0641 <code>session_id<\/code> \u0627\u0648\u0631 <code>graph_config<\/code> \u062a\u0645 \u062f\u0648\u0646\u0648\u06ba \u0648\u06c1\u0627\u06ba \u062c\u0627\u0624\u06d4 \u06cc\u06c1\u06cc \u062d\u0627\u0644 \u0645\u0648\u062c\u0648\u062f\u06c1 \u0627\u0633\u06a9\u0631\u06cc\u0646\u060c \u0631\u0648\u0688 \u0645\u06cc\u067e\u060c \u0645\u0648\u062c\u0648\u062f\u06c1 \u0633\u0648\u0627\u0644\u0627\u062a \u06a9\u0627 \u0627\u0634\u0627\u0631\u06cc\u06c1\u060c \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f \u062c\u0648\u0627\u0628\u0627\u062a\u060c \u0627\u0648\u0631 \u062a\u06a9\u0645\u06cc\u0644\u06cc \u0641\u06c1\u0631\u0633\u062a\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u06be\u06cc \u06c1\u06d2\u06d4 <code>QuizResult<\/code> \u0627\u0634\u06cc\u0627\u0621<\/p>\n<p>\u0627\u06cc\u067e\u0633 \u0645\u0624\u062b\u0631 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0631\u06cc\u0627\u0633\u062a\u06cc \u0645\u0634\u06cc\u0646\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 <code>st.session_state.screen<\/code> \u0627\u0633 \u0628\u0627\u062a \u06a9\u0627 \u062a\u0639\u06cc\u0646 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0628\u0679\u0646 \u06a9\u06d2 \u06a9\u0644\u06a9 \u06a9\u06d2 \u062c\u0648\u0627\u0628 \u0645\u06cc\u06ba \u06a9\u06cc\u0627 \u0631\u06cc\u0646\u0688\u0631\u0646\u06af \u0627\u0648\u0631 \u0627\u0633\u0679\u06cc\u0679 \u0645\u0634\u06cc\u0646 \u0679\u0631\u0627\u0646\u0632\u06cc\u0634\u0646 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u0641\u0631\u0633\u0679 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0627 \u06a9\u0627\u0631\u0646\u0627\u0645\u06c1 \u06c1\u06d2\u06d4 \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0679\u0631\u0645\u06cc\u0646\u0644 UI\u060c \u0627\u06cc\u06a9 \u0648\u06cc\u0628 UI \u06c1\u06d2\u060c \u062c\u0633 \u06a9\u06d2 \u0628\u0639\u062f React \u0641\u0631\u0646\u0679 \u0627\u06cc\u0646\u0688\u060c \u0627\u06cc\u06a9 Slack bot\u060c \u06cc\u0627 iOS \u0627\u06cc\u067e \u0634\u0627\u0645\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0622\u067e\u0634\u0646 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u0633 \u0645\u06cc\u06ba LangGraph \u06a9\u0648\u0688 \u06c1\u06d2\u06d4 <code>src\/<\/code> \u06cc\u06c1 \u0627\u0646 \u0633\u0628 \u0633\u06d2 \u0645\u062a\u0627\u062b\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-95-the-project-structure-final\">9.5 \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u06a9\u0627 \u0688\u06be\u0627\u0646\u0686\u06c1\u060c \u062d\u062a\u0645\u06cc<\/h3>\n<p>\u0633\u0628 \u06a9\u0686\u06be \u0628\u0646\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u0630\u062e\u06cc\u0631\u06c1 \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628 \u0627\u0633 \u0637\u0631\u062d \u0646\u0638\u0631 \u0622\u062a\u06cc \u06c1\u06d2:<\/p>\n<pre><code class=\"language-plaintext\">freecodecamp-multi-agent-ai-system\/\n\u251c\u2500\u2500 src\/\n\u2502   \u251c\u2500\u2500 agents\/\n\u2502   \u2502   \u251c\u2500\u2500 curriculum_planner.py   # JSON roadmap generation\n\u2502   \u2502   \u251c\u2500\u2500 explainer.py             # MCP tool-calling loop\n\u2502   \u2502   \u251c\u2500\u2500 quiz_generator.py        # Two-call pattern + grading\n\u2502   \u2502   \u251c\u2500\u2500 progress_coach.py        # Synthesis + A2A delegation\n\u2502   \u2502   \u2514\u2500\u2500 human_approval.py        # interrupt() \/ Command resume\n\u2502   \u251c\u2500\u2500 graph\/\n\u2502   \u2502   \u251c\u2500\u2500 state.py                 # AgentState + 4 dataclasses\n\u2502   \u2502   \u2514\u2500\u2500 workflow.py              # StateGraph definition\n\u2502   \u251c\u2500\u2500 mcp_servers\/\n\u2502   \u2502   \u251c\u2500\u2500 filesystem_server.py     # Tools: list, read, search\n\u2502   \u2502   \u2514\u2500\u2500 memory_server.py         # Tools: get, set, delete, list\n\u2502   \u251c\u2500\u2500 a2a_services\/\n\u2502   \u2502   \u251c\u2500\u2500 quiz_service.py          # Quiz agent on :9001\n\u2502   \u2502   \u2514\u2500\u2500 a2a_client.py            # JSON-RPC client + discovery\n\u2502   \u251c\u2500\u2500 crewai_agent\/\n\u2502   \u2502   \u2514\u2500\u2500 study_buddy.py           # CrewAI agent on :9002\n\u2502   \u2514\u2500\u2500 observability\/\n\u2502       \u2514\u2500\u2500 langfuse_setup.py        # Callback handler + config\n\u251c\u2500\u2500 tests\/                           # 182 unit + 12 eval tests\n\u251c\u2500\u2500 study_materials\/sample_notes\/    # Explainer's source content\n\u251c\u2500\u2500 docs\/                            # ARCHITECTURE.md, MODEL_SELECTION.md\n\u251c\u2500\u2500 data\/                            # SQLite checkpoints (created at runtime)\n\u251c\u2500\u2500 main.py                          # Terminal entry point\n\u251c\u2500\u2500 streamlit_app.py                 # Web UI entry point\n\u251c\u2500\u2500 Makefile                         # One-command targets\n\u251c\u2500\u2500 docker-compose.yml               # Self-hosted Langfuse\n\u251c\u2500\u2500 requirements.txt                 # Pinned versions\n\u2514\u2500\u2500 pyproject.toml                   # pythonpath + pytest config\n<\/code><\/pre>\n<h3 id=\"heading-96-extending-the-system\">9.6 \u0633\u0633\u0679\u0645 \u06a9\u06cc \u062a\u0648\u0633\u06cc\u0639<\/h3>\n<p>\u06cc\u06c1 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u0645\u0648\u062c\u0648\u062f\u06c1 \u06a9\u0648\u0688 \u06a9\u0648 \u0686\u06be\u0648\u0626\u06d2 \u0628\u063a\u06cc\u0631 \u0645\u062a\u0639\u062f\u062f \u0633\u0645\u062a\u0648\u06ba \u0645\u06cc\u06ba \u062a\u0648\u0633\u06cc\u0639 \u06a9\u06cc \u062d\u0645\u0627\u06cc\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u0627\u06cc\u062c\u0646\u0679 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0646\u0648\u0688 \u0641\u0646\u06a9\u0634\u0646 \u0644\u06a9\u06be\u06cc\u06ba\u06d4 <code>src\/agents\/your_agent.py<\/code>. \u0631\u062c\u0633\u0679\u0631 \u06a9\u0631\u06cc\u06ba\u06d4 <code>workflow.py<\/code> \u06a9\u06d2 \u0633\u0627\u062a\u06be <code>builder.add_node(\"your_agent\", your_agent_node)<\/code>. \u0645\u0648\u062c\u0648\u062f\u06c1 \u0646\u0648\u0688\u0633 \u0633\u06d2 \u062c\u0691\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u0646\u0627\u0631\u0648\u06ba \u06a9\u0648 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u0628\u0627\u0642\u06cc \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679 \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc \u06a9\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06d2 \u0631\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0648\u06c1 \u0627\u06cc\u06a9 \u062f\u0648\u0633\u0631\u06d2 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0646\u06c1\u06cc\u06ba \u062c\u0627\u0646\u062a\u06d2\u06d4 \u0648\u06c1 \u0635\u0631\u0641 \u0631\u06cc\u0627\u0633\u062a \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u062c\u0627\u0646\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p><strong>\u0627\u0646\u0641\u0631\u0646\u0633 \u0628\u06cc\u06a9 \u0627\u06cc\u0646\u0688 \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>ChatOllama<\/code> \u0627\u0634\u0627\u0631\u06c1 \u06a9\u06cc\u0627 <code>OLLAMA_BASE_URL<\/code>. \u0627\u0633 \u06cc\u0648 \u0622\u0631 \u0627\u06cc\u0644 \u06a9\u0648 LiteLLM \u06af\u06cc\u0679 \u0648\u06d2 \u067e\u0631 \u0633\u06cc\u0679 \u06a9\u0631\u0646\u0627 (\u0633\u0627\u0645\u0646\u06d2 \u0645\u06cc\u06ba \u0627\u0648\u0644\u0627\u0645\u0627 \u06a9\u0627 API \u0628\u0648\u0644\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0648\u067e\u0646 \u0627\u06d2 \u0622\u0626\u06cc\u060c \u0627\u06cc\u0646\u062a\u06be\u0631\u0648\u067e\u06a9\u060c \u06cc\u0627 \u062f\u0648\u0633\u0631\u06d2 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0646\u0646\u062f\u06af\u0627\u0646 \u06a9\u0648 \u067e\u06cc\u0686\u06be\u06d2 \u06a9\u06cc \u0637\u0631\u0641 \u0644\u06d2 \u062c\u0627\u062a\u0627 \u06c1\u06d2) \u0686\u0627\u0631\u0648\u06ba \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc \u06a9\u0648\u0688 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644\u06cc \u06a9\u06d2 \u0646\u0626\u06d2 \u0628\u06cc\u06a9 \u0627\u06cc\u0646\u0688 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631 \u062f\u06d2 \u06af\u0627\u06d4 API \u0627\u06cc\u06a9 \u0645\u0639\u0627\u06c1\u062f\u06c1 \u06c1\u06d2\u06d4<\/p>\n<p><strong>MCP \u0679\u0648\u0644\u0632 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0627\u0636\u0627\u0641\u06c1 <code>@mcp.tool()<\/code> \u0641\u0646\u06a9\u0634\u0646 <code>filesystem_server.py<\/code> \u06cc\u0627 <code>memory_server.py<\/code>. \u0627\u0633\u06d2 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>@tool<\/code> \u0631\u06cc\u067e\u0631 <code>explainer.py<\/code> \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba <code>EXPLAINER_TOOLS<\/code>. \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627 \u0633\u0633\u0679\u0645 \u067e\u0631\u0627\u0645\u067e\u0679 LLM \u06a9\u0648 \u0628\u062a\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0646\u06cc\u0627 \u0679\u0648\u0644 \u06a9\u0628 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4 \u06a9\u0633\u06cc \u062f\u0648\u0633\u0631\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0646\u0626\u06cc A2A \u0633\u0631\u0648\u0633 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0630\u06cc\u0644 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u0645\u0627\u0688\u06cc\u0648\u0644 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 <code>a2a_services\/<\/code> \u0627\u06af\u0644\u0627 <code>quiz_service.py<\/code> \u067e\u06cc\u0679\u0631\u0646: \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627\u0631\u0688\u060c \u0627\u06cc\u06af\u0632\u06cc\u06a9\u06cc\u0648\u0679\u0631 \u0633\u0628 \u06a9\u0644\u0627\u0633\u060c \u06cc\u0648\u0648\u06cc\u06a9\u0648\u0631\u0646 \u0633\u0631\u0648\u0631\u06d4 \u06a9\u0644\u0627\u0626\u0646\u0679 \u06a9\u06cc \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>a2a_client.py<\/code>. \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0627\u06cc\u062c\u0646\u0679 \u062c\u0633 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648 \u0627\u0633\u06d2 \u06a9\u0644\u0627\u0626\u0646\u0679 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062e\u062f\u0645\u0627\u062a \u0627\u0644\u06af \u0627\u0644\u06af \u0639\u0645\u0644 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0628\u0646\u06cc\u0627\u062f\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0633\u06d2 \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u062a\u0639\u06cc\u0646\u0627\u062a\u060c \u0627\u0633\u06a9\u06cc\u0644\u060c \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u06cc \u062c\u0627 \u0633\u06a9\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<p><strong>\u0627\u067e\u0646\u06cc \u0631\u06cc\u0627\u0633\u062a \u06a9\u0648 PostgreSQL \u0645\u06cc\u06ba \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u062a\u0628\u062f\u06cc\u0644\u06cc <code>SqliteSaver<\/code> \u06a9\u06d2 \u0633\u0627\u062a\u06be <code>PostgresSaver<\/code> \u06a9\u0648 <code>workflow.py<\/code>. \u06a9\u0646\u06a9\u0634\u0646 \u0633\u0679\u0631\u0646\u06af \u06a9\u0648 \u0627\u067e\u0646\u06cc \u067e\u0648\u0633\u0679\u06af\u0631\u06cc\u0633 \u0645\u062b\u0627\u0644 \u067e\u0631 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u0648\u0631 \u06a9\u0686\u06be \u0646\u06c1\u06cc\u06ba \u0628\u062f\u0644\u062a\u0627\u06d4 LangGraph \u06a9\u0627 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u0627\u0646\u0679\u0631\u0641\u06cc\u0633 \u0628\u06cc\u06a9 \u0627\u06cc\u0646\u0688 \u0627\u06cc\u06af\u0646\u0648\u0633\u0679\u06a9 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0627\u067e\u0646\u06cc A2A \u0633\u0631\u0648\u0633 \u0645\u06cc\u06ba \u062a\u0635\u062f\u06cc\u0642 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u067e\u06cc\u06a9 <code>create_quiz_server()<\/code>\u062a\u0648\u062b\u06cc\u0642 \u0645\u0688\u0644 \u0648\u06cc\u0626\u0631 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0633\u0679\u0627\u0631\u0644\u06cc\u0679 \u0627\u06cc\u067e\u06d4 A2A \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u0627\u0633 \u06a9\u06cc \u062d\u0645\u0627\u06cc\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627\u0631\u0688 \u0627\u06cc\u06a9 \u062a\u0635\u062f\u06cc\u0642\u06cc \u0627\u0633\u06a9\u06cc\u0645 \u06a9\u0627 \u0627\u0639\u0644\u0627\u0646 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u06a9\u0644\u0627\u0626\u0646\u0679 \u0627\u067e\u0646\u06d2 \u0627\u0633\u0646\u0627\u062f \u06a9\u0648 \u0627\u06cc\u06a9\u0634\u0646 \u0644\u0641\u0627\u0641\u06d2 \u0645\u06cc\u06ba \u067e\u0627\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u06d2 \u0628\u0627\u06c1\u0631 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u06a9\u06cc \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc\u0648\u06ba \u0645\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4<\/p>\n<p>\u0627\u0646 \u0645\u06cc\u06ba \u0633\u06d2 \u06c1\u0631 \u0627\u06cc\u06a9 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u06cc \u0627\u06cc\u06a9 \u0645\u062e\u0635\u0648\u0635 \u067e\u0631\u062a \u06a9\u0648 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0633\u06cc \u06a9\u0648 \u0628\u06be\u06cc \u0646\u06cc\u0686\u06d2 \u06a9\u06cc \u062a\u06c1\u0648\u06ba \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0644\u06a9\u06be\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p> <strong>\u0686\u0648\u06a9\u06cc:<\/strong> \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u06d2 \u0686\u0644\u0646\u06d2 \u06a9\u06d2 \u0633\u0627\u062a\u06be\u060c \u067e\u0648\u0631\u0627 \u0679\u06cc\u0633\u0679 \u0633\u0648\u06cc\u0679 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">make services\npytest tests\/ -v\n# 184 tests, eval tests skipped by default\n<\/code><\/pre>\n<p>\u0627\u0633 \u06a9\u06d2 \u0628\u0639\u062f \u06c1\u0645 Ollama \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u062a\u0634\u062e\u06cc\u0635\u06cc \u0679\u06cc\u0633\u0679 \u0686\u0644\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">pytest tests\/test_eval.py -m eval -s -v\n# 12 eval tests: checks quality, faithfulness, grading calibration\n<\/code><\/pre>\n<p>\u0622\u062e\u0631 \u0645\u06cc\u06ba\u060c \u067e\u0648\u0631\u06d2 \u0646\u0638\u0627\u0645 \u06a9\u0648 \u062f\u0633\u062a\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0686\u0644\u0627\u0626\u06cc\u06ba.<\/p>\n<pre><code class=\"language-bash\">make run\n# Follow the prompts, complete a session\n# Check Langfuse UI for the trace\n<\/code><\/pre>\n<p>\u062a\u0635\u062f\u06cc\u0642 \u06a9\u06d2 \u062a\u06cc\u0646\u0648\u06ba \u0645\u0631\u0627\u062d\u0644 \u06af\u0632\u0631 \u0686\u06a9\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0646\u0638\u0627\u0645 \u0645\u06a9\u0645\u0644 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-97-five-extensions-ordered-by-effort\">9.7 \u06a9\u0648\u0634\u0634 \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc \u06af\u0626\u06cc \u067e\u0627\u0646\u0686 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646\u0632<\/h3>\n<p>\u0622\u067e\u0631\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u0686\u0627\u0631 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u0646\u0638\u0627\u0645 \u06c1\u06cc\u06ba. \u06cc\u06c1 \u0645\u0634\u06a9\u0644 \u062d\u0635\u06c1 \u06c1\u06d2\u06d4 \u0628\u0627\u0642\u06cc \u0627\u0646\u06a9\u0631\u06cc\u0645\u0646\u0679\u0644 \u06c1\u06cc\u06ba\u06d4 \u0646\u06cc\u0686\u06d2 \u06a9\u06cc \u06c1\u0631 \u0633\u0645\u062a \u0627\u06cc\u06a9 \u0642\u062f\u0631\u062a\u06cc \u0627\u06af\u0644\u0627 \u0645\u0631\u062d\u0644\u06c1 \u06c1\u06d2\u060c \u062f\u0648\u0628\u0627\u0631\u06c1 \u0644\u06a9\u06be\u0646\u0627 \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<h4 id=\"heading-1-swap-the-inference-backend-to-a-managed-gateway-under-an-hour-of-work\">1. \u0627\u067e\u0646\u06d2 \u0627\u0646\u0641\u0631\u0646\u0633 \u0628\u06cc\u06a9 \u0627\u06cc\u0646\u0688 \u06a9\u0648 \u0627\u06cc\u06a9 \u0645\u0646\u0638\u0645 \u06af\u06cc\u0679 \u0648\u06d2 (\u06a9\u0627\u0645 \u06a9\u06d2 \u0627\u06cc\u06a9 \u06af\u06be\u0646\u0679\u06d2 \u0633\u06d2 \u06a9\u0645) \u067e\u0631 \u0633\u0648\u0626\u0686 \u06a9\u0631\u06cc\u06ba\u06d4<\/h4>\n<p>\u0633\u0633\u0679\u0645 \u06a9\u06d2 \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba: <code>ChatOllama<\/code> \u0627\u0634\u0627\u0631\u06c1 \u06a9\u06cc\u0627 <code>OLLAMA_BASE_URL<\/code>. \u0627\u0633 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u0627\u0633 URL \u06a9\u0648 LiteLLM \u06af\u06cc\u0679 \u0648\u06d2 \u067e\u0631 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u06d4 LiteLLM \u0633\u0627\u0645\u0646\u06d2 \u067e\u0631 \u0627\u0648\u0644\u0627\u0645\u0627 \u06a9\u0627 API \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 OpenAI\u060c Anthropic\u060c Together\u060c \u06cc\u0627 \u067e\u0686\u06be\u0644\u06d2 \u062d\u0635\u06d2 \u067e\u0631 \u062f\u0648\u0633\u0631\u06d2 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0646\u0646\u062f\u06af\u0627\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0631\u0648\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0686\u0627\u0631\u0648\u06ba \u0627\u06cc\u062c\u0646\u0679\u0633 \u0627\u06cc\u06a9 \u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u0645\u062a\u063a\u06cc\u0631 \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06a9\u06d2 \u0646\u0626\u06d2 \u067e\u0633\u062f\u06cc\u062f \u067e\u0631 \u0633\u0648\u0626\u0686 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06c1\u0645 \u0641\u0627\u0644 \u0628\u06cc\u06a9 \u0631\u0648\u0679\u0646\u06af \u06a9\u0648 \u0627\u0633\u06cc \u0646\u0642\u0637\u06c1 \u0646\u0638\u0631 \u0633\u06d2 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 GPT-4 \u06a9\u0648 \u0622\u0632\u0645\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 LiteLLM \u06a9\u0648 \u06a9\u0646\u0641\u06cc\u06af\u0631 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u06af\u0631 \u0648\u06c1 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u0648\u0627\u067e\u0633 Claude \u067e\u0631 \u062c\u0627\u0626\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0627\u06af\u0631 \u062f\u0648\u0646\u0648\u06ba \u0646\u06cc\u0686\u06d2 \u06c1\u0648\u06ba \u062a\u0648 \u0645\u0642\u0627\u0645\u06cc \u0645\u0627\u0688\u0644 \u067e\u0631 \u0648\u0627\u067e\u0633 \u062c\u0627\u0626\u06cc\u06ba\u06d4 \u0622\u067e \u06a9\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648\u0688 \u06a9\u0648 \u0627\u0646\u062f\u0627\u0632\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u06c1\u0648 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-2-add-an-authentication-layer-to-the-a2a-services-a-few-hours-of-work\">2. \u0627\u067e\u0646\u06cc A2A \u0633\u0631\u0648\u0633 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u062a\u0635\u062f\u06cc\u0642\u06cc \u067e\u0631\u062a \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba (\u06a9\u0686\u06be \u06af\u06be\u0646\u0679\u06d2 \u0644\u06af\u062a\u06d2 \u06c1\u06cc\u06ba)\u06d4<\/h4>\n<p>\u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627\u0631\u0688 \u062a\u0635\u062f\u06cc\u0642\u06cc \u0627\u0633\u06a9\u06cc\u0645\u0648\u06ba \u06a9\u0627 \u0627\u0639\u0644\u0627\u0646 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 A2A \u06a9\u06cc \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u06cc\u0626\u0631\u0631 \u0679\u0648\u06a9\u0646 \u06cc\u0627 mTLS \u0633\u0631\u0679\u06cc\u0641\u06a9\u06cc\u0679 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u067e\u06cc\u06a9 <code>create_quiz_server()<\/code>\u0627\u067e\u0646\u06cc Starlette \u0627\u06cc\u067e \u06a9\u0648 FastAPI \u06a9\u06d2 \u0645\u0648\u0627\u0641\u0642 \u062a\u0635\u062f\u06cc\u0642\u06cc \u0645\u0688\u0644 \u0648\u06cc\u0626\u0631 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u06d4 <code>a2a_client.py<\/code> \u0627\u06cc\u06a9\u0634\u0646 \u0644\u0641\u0627\u0641\u06d2 \u0645\u06cc\u06ba \u0627\u0633\u0646\u0627\u062f \u06a9\u0648 \u067e\u0627\u0633 \u06a9\u0631\u0646\u0627 \u0633\u0631\u0648\u0633 \u06a9\u0648 \u0645\u062d\u0641\u0648\u0638 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0628 \u0628\u06be\u0631\u0648\u0633\u06c1 \u0645\u0646\u062f \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u0633\u06d2 \u0628\u0627\u06c1\u0631 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>A2A \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u0633 \u06a9\u06cc \u062d\u0645\u0627\u06cc\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0628\u06cc\u0626\u0631\u0631 \u0679\u0648\u06a9\u0646 HTTP \u0645\u06cc\u06ba \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>Authorization<\/code> \u062f\u06cc\u06af\u0631 REST \u062e\u062f\u0645\u0627\u062a \u06a9\u06cc \u0637\u0631\u062d\u060c \u06cc\u06c1 \u0627\u06cc\u06a9 \u06c1\u06cc\u0688\u0631 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-3-migrate-sqlite-checkpointing-to-postgresql-half-a-day-including-testing\">3. SQLite \u0686\u0648\u06a9\u06cc\u0648\u06ba \u06a9\u0648 PostgreSQL \u0645\u06cc\u06ba \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba (\u0679\u06cc\u0633\u0679\u0646\u06af \u0633\u0645\u06cc\u062a \u0622\u062f\u06be\u0627 \u062f\u0646 \u0644\u06af\u062a\u0627 \u06c1\u06d2)\u06d4<\/h4>\n<p>\u062a\u0628\u062f\u06cc\u0644\u06cc <code>SqliteSaver<\/code> \u06a9\u06d2 \u0633\u0627\u062a\u06be <code>PostgresSaver<\/code> \u06a9\u0648 <code>workflow.py<\/code>. \u06a9\u0646\u06a9\u0634\u0646 \u0633\u0679\u0631\u0646\u06af \u06a9\u0648 \u0627\u067e\u0646\u06cc \u067e\u0648\u0633\u0679\u06af\u0631\u06cc\u0633 \u0645\u062b\u0627\u0644 \u067e\u0631 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u06d4 LangGraph \u06a9\u0627 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u0627\u0646\u0679\u0631\u0641\u06cc\u0633 \u0628\u06cc\u06a9 \u0627\u06cc\u0646\u0688 \u0627\u06cc\u06af\u0646\u0648\u0633\u0679\u06a9 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u06a9\u062b\u06cc\u0631 \u0645\u062b\u0627\u0644\u06cc \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06c1\u0645 \u06c1\u06d2\u06d4 SQLite \u0627\u06cc\u06a9 \u06c1\u06cc \u0639\u0645\u0644 \u0645\u06cc\u06ba \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0628\u06a9\u06c1 PostgreSQL \u0645\u062a\u0639\u062f\u062f \u0645\u062b\u0627\u0644\u0648\u06ba \u06a9\u0648 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 <code>main.py<\/code> (\u06cc\u0627 Streamlit \u0627\u06cc\u067e\u0633) \u06a9\u0627 \u0645\u0648\u0627\u0632\u0646\u06c1 \u0627\u06cc\u06a9 \u06c1\u06cc \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u0627\u0633\u0679\u0648\u0631 \u0633\u06d2 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u0633\u06cc\u0634\u0646 \u0645\u062b\u0627\u0644 \u06a9\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06c1\u0648\u0646\u06d2 \u067e\u0631 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06c1\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633\u06d2 \u062a\u0645\u0627\u0645 \u0645\u062b\u0627\u0644\u0648\u06ba \u0645\u06cc\u06ba \u0645\u0646\u062a\u062e\u0628 \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-4-add-streaming-responses-a-day-or-two-of-work\">4. \u0627\u06cc\u06a9 \u0633\u0644\u0633\u0644\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u0627 \u062c\u0648\u0627\u0628 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba (\u06a9\u0627\u0645 \u06a9\u06d2 \u0627\u06cc\u06a9 \u06cc\u0627 \u062f\u0648 \u062f\u0646)\u06d4<\/h4>\n<p>\u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0633\u067e\u0648\u0631\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>graph.astream()<\/code> \u0627\u06cc\u062c\u0646\u0679 \u0646\u0648\u0688\u0633 \u0633\u06d2 \u0679\u0648\u06a9\u0646 \u0644\u06cc\u0648\u0644 \u0627\u0633\u0679\u0631\u06cc\u0645\u0646\u06af \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4 \u0627\u0633\u0679\u0631\u06cc\u0645\u0632 \u06a9\u0648 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0627\u0648\u0631 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062f\u06c1 \u062a\u0641\u0635\u06cc\u0644 \u067e\u06cc\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 Streamlit UI \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u06d4 \u0645\u06a9\u0645\u0644 \u062c\u0648\u0627\u0628 \u06a9\u06d2 \u0644\u06cc\u06d2 3-4 \u0633\u06cc\u06a9\u0646\u0688 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u0635\u0627\u0631\u0641\u06cc\u0646 500ms \u06a9\u06d2 \u0628\u0639\u062f \u0622\u0624\u0679 \u067e\u0679 \u0627\u0633\u0679\u0627\u0631\u0679 \u062f\u06cc\u06a9\u06be\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<p>\u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0648\u06c1 \u0627\u06cc\u062c\u0646\u0679 \u06c1\u06d2 \u062c\u0648 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0641\u0627\u0626\u062f\u06c1 \u0627\u0679\u06be\u0627\u062a\u0627 \u06c1\u06d2\u06d4 1,500-2,500 \u062d\u0631\u0648\u0641 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a\u06cc\u06ba \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0633\u0645\u062c\u06be\u06cc \u062c\u0627\u0646\u06d2 \u0648\u0627\u0644\u06cc \u062a\u0627\u062e\u06cc\u0631 \u0645\u06cc\u06ba \u0628\u06c1\u062a\u0631\u06cc \u0646\u0645\u0627\u06cc\u0627\u06ba \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-5-build-a-mobile-friendly-frontend-a-week-of-focused-work\">5. \u0645\u0648\u0628\u0627\u0626\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0648\u0633\u062a\u0627\u0646\u06c1 \u0641\u0631\u0646\u0679 \u0627\u06cc\u0646\u0688 \u0628\u0646\u0627\u0646\u0627 (\u0627\u06cc\u06a9 \u06c1\u0641\u062a\u06c1 \u06a9\u0627 \u06af\u06c1\u0631\u0627 \u06a9\u0627\u0645)<\/h4>\n<p>\u0627\u067e\u0646\u06d2 Streamlit UI \u06a9\u0648 \u0627\u06cc\u06a9 React \u06cc\u0627 Next.js \u0641\u0631\u0646\u0679 \u0627\u06cc\u0646\u0688 \u0633\u06d2 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba \u062c\u0648 \u0622\u067e \u06a9\u06d2 \u06af\u0631\u0627\u0641 \u06a9\u06d2 \u0627\u0631\u062f \u06af\u0631\u062f FastAPI \u0631\u06cc\u067e\u0631 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0631\u06cc\u067e\u0631 \u0648\u06c1\u06cc \u067e\u0627\u0646\u0686 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u0641\u0644\u0648\u0632 \u06a9\u0648 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u06cc\u0633\u06d2 REST \u0627\u06cc\u0646\u0688 \u067e\u0648\u0627\u0626\u0646\u0679: \u0627\u06c1\u062f\u0627\u0641 \u062f\u0631\u062c \u06a9\u0631\u06cc\u06ba\u060c \u0631\u0648\u0688 \u0645\u06cc\u067e \u06a9\u0648 \u0645\u0646\u0638\u0648\u0631 \u06a9\u0631\u06cc\u06ba\u060c \u062a\u0628\u0635\u0631\u06d2\u060c \u06a9\u0648\u0626\u0632\u060c \u0627\u0648\u0631 \u0645\u06a9\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u06a9\u0648\u0688 \u06c1\u06d2\u06d4 <code>src\/<\/code> \u06cc\u06c1 \u0628\u0627\u0644\u06a9\u0644 \u0646\u06c1\u06cc\u06ba \u0628\u062f\u0644\u062a\u0627\u06d4 \u06a9\u0648\u0626\u0632 \u06a9\u0627 \u0645\u062c\u0645\u0648\u0639\u06c1 \u0627\u0648\u0631 \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u0627 \u067e\u06cc\u0679\u0631\u0646 \u0648\u06c1\u06cc \u0631\u06c1\u06d2 \u06af\u0627 \u062c\u06cc\u0633\u0627 \u06a9\u06c1 Streamlit \u0627\u06cc\u067e \u0641\u06cc \u0627\u0644\u062d\u0627\u0644 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 API \u0645\u0639\u0627\u06c1\u062f\u06c1 \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-plaintext\">POST \/api\/sessions                     \u2192 create session, return session_id + roadmap\nPOST \/api\/sessions\/:id\/approval        \u2192 body: {\"approved\": true\/false}\nGET  \/api\/sessions\/:id\/current         \u2192 current topic, explanation, questions\nPOST \/api\/sessions\/:id\/answer          \u2192 submit one quiz answer, get graded response\nGET  \/api\/sessions\/:id\/summary         \u2192 final summary when complete\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u0648\u06c1 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u06c1\u06d2 \u062c\u0633\u06d2 \u0644\u0631\u0646\u0646\u06af \u0627\u06cc\u06a9\u0633\u0644\u0631\u06cc\u0679\u0631 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0631\u06d2 \u06af\u0627 \u0627\u06af\u0631 \u06cc\u06c1 \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u067e\u0631\u0648\u0688\u06a9\u0679 \u0628\u0646 \u062c\u0627\u0626\u06d2\u06d4 \u06af\u0631\u0627\u0641 \u0628\u06cc\u06a9 \u0627\u06cc\u0646\u0688 \u067e\u0631 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u0641\u0631\u0646\u0679 \u0627\u06cc\u0646\u0688 \u0627\u06cc\u06a9 \u067e\u062a\u0644\u0627 \u06a9\u0644\u0627\u0626\u0646\u0679 \u06c1\u06d2\u06d4 \u0636\u0645\u06cc\u0645\u06c1 C \u0645\u06cc\u06ba \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u0628\u0691\u06be\u0627\u0646\u06d2 \u06a9\u06cc \u0686\u06cc\u06a9 \u0644\u0633\u0679 \u0644\u0627\u06af\u0648 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-98-production-hardening\">9.8 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u06a9\u0648 \u0645\u0636\u0628\u0648\u0637 \u0628\u0646\u0627\u0626\u06cc\u06ba<\/h3>\n<p>\u0644\u06a9\u06be\u0627 \u06c1\u0648\u0627 \u0633\u0633\u0679\u0645 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0644\u06cc\u0648\u0644 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u060c \u063a\u0644\u0637\u06cc\u0648\u06ba \u06a9\u0648 \u0627\u062d\u0633\u0646 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u062a\u0645\u0627\u0645 \u062a\u0635\u0648\u0631\u0627\u062a \u06a9\u0648 \u0635\u062d\u06cc\u062d \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u0646\u0679\u0631\u067e\u0631\u0627\u0626\u0632 \u067e\u06cc\u0645\u0627\u0646\u06d2 \u067e\u0631 \u06c1\u0632\u0627\u0631\u0648\u06ba \u0633\u0627\u062a\u06be\u06cc \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u06cc \u062e\u062f\u0645\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0627\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u0628\u0627\u062a \u067e\u0631 \u0645\u0646\u062d\u0635\u0631 \u06c1\u06d2 \u06a9\u06c1 \u06c1\u0631 \u0634\u06d2 \u06a9\u0648 \u06a9\u062a\u0646\u06d2 \u06a9\u0627\u0645 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u060c \u062a\u0628\u062f\u06cc\u0644\u06cc\u0648\u06ba \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06c1\u0648 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba:<\/p>\n<p><strong>\u0634\u0631\u062d \u06a9\u06cc \u062d\u062f \u0641\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u06d4<\/strong> \u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0679\u0631 \u06a9\u06cc \u0633\u0637\u062d \u067e\u0631 \u0646\u0627\u0641\u0630 \u06a9\u0631\u062f\u06c1 \u0641\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0679\u0648\u06a9\u0646 \u0628\u062c\u0679 \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0633\u062e\u062a \u067e\u0627\u0628\u0646\u062f\u06cc\u0627\u06ba \u06c1\u06cc\u06ba\u060c \u06c1\u062f\u0627\u06cc\u0627\u062a \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0641\u06cc \u0627\u06cc\u062c\u0646\u0679 \u067e\u0627\u0646\u0686 \u0679\u0648\u0644 \u06a9\u0627\u0644\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0686\u0627\u0631 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627 \u0646\u0638\u0627\u0645 \u0641\u06cc \u0635\u0627\u0631\u0641 \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u067e\u0631 20 LLM \u06a9\u0627\u0644\u0632 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u06c1\u06d2\u06d4 \u067e\u06cc\u0645\u0627\u0646\u06d2 \u067e\u0631\u060c \u0644\u0627\u06af\u062a \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u0646\u062c\u06cc\u0646\u0626\u0631\u0646\u06af \u06a9\u0627 \u0645\u0633\u0626\u0644\u06c1 \u0628\u0646 \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4 LiteLLM \u06af\u06cc\u0679 \u0648\u06d2 \u0627\u0633\u06d2 \u0622\u0633\u0627\u0646 \u0628\u0646\u0627 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u0622\u067e \u0641\u06cc \u0633\u06cc\u0634\u0646 \u0627\u067e\u0646\u06d2 \u0627\u062e\u0631\u0627\u062c\u0627\u062a \u06a9\u0648 \u0679\u0631\u06cc\u06a9 \u06a9\u0631\u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u062d\u062f\u0648\u062f \u06a9\u0627 \u0627\u0637\u0644\u0627\u0642 \u06a9\u0631\u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p><strong>\u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u06c1\u062c\u0631\u062a \u06a9\u06cc \u062d\u0641\u0627\u0638\u062a\u06d4<\/strong> \u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0648\u0631\u0698\u0646 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u06cc\u06ba\u06d4 <code>AgentState<\/code> \u062e\u0627\u06a9\u06c1 \u062c\u0628 \u0622\u067e \u0633\u0633\u0679\u0645 \u06a9\u0627 \u0646\u06cc\u0627 \u0648\u0631\u0698\u0646 \u062a\u0639\u06cc\u0646\u0627\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u062c\u0627\u0631\u06cc \u0648\u0631\u06a9 \u0641\u0644\u0648 \u062c\u0648 \u067e\u0631\u0627\u0646\u06d2 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba \u0646\u0626\u06d2 \u06a9\u0648\u0688 \u06a9\u0648 \u0688\u06cc \u0633\u06cc\u0631\u06cc\u0644\u0627\u0626\u0632 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4 \u0627\u06af\u0631 \u0641\u06cc\u0644\u0688\u0632 \u06a9\u0648 \u0634\u0627\u0645\u0644 \u06cc\u0627 \u06c1\u0679\u0627 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0648\u0631\u06a9 \u0641\u0644\u0648 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0645\u06cc\u06ba \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u0641\u0627\u0631\u0645\u06cc\u0679 \u06a9\u0648 \u0639\u0648\u0627\u0645\u06cc API \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0633\u0645\u062c\u06be\u06cc\u06ba\u06d4 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0637\u06d2 \u0634\u062f\u06c1 \u0627\u0642\u062f\u0627\u0631 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0646\u0626\u06d2 \u0641\u06cc\u0644\u0688\u0632 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u060c \u06c1\u0679\u0627\u0626\u06d2 \u06af\u0626\u06d2 \u0641\u06cc\u0644\u0688\u0632 \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0631\u06cc\u0644\u06cc\u0632 \u0633\u0627\u0626\u06cc\u06a9\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062d\u0630\u0641 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0641\u0631\u0633\u0648\u062f\u06c1 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0627\u067e\u0646\u06cc \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u06d2 \u062d\u0635\u06d2 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u0645\u0646\u062a\u0642\u0644\u06cc \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p><strong>\u06a9\u0648\u0644\u0688 \u06c1\u06cc\u0646\u0688\u0644\u0646\u06af \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0627\u0639\u0644\u06cc \u0645\u0627\u0688\u0644 \u06a9\u06d2 \u0648\u0632\u0646 \u0627\u0648\u0631 \u0627\u0646\u062d\u0635\u0627\u0631 \u0648\u0627\u0644\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0646\u0679\u06cc\u0646\u0631\u0632 \u06a9\u0648 \u06a9\u0648\u0644\u0688 \u0627\u0633\u0679\u0627\u0631\u0679 \u06c1\u0648\u0646\u06d2 \u0645\u06cc\u06ba 30 \u0633\u06d2 \u200b\u200b60 \u0633\u06cc\u06a9\u0646\u0688 \u0644\u06af \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06cc \u0634\u0631\u062d \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06a9\u06d2 \u0634\u0631\u0648\u0639 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0627\u06cc\u06a9 \u0645\u0646\u0679 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u0646\u06c1\u06cc\u06ba \u062f\u06d2 \u0633\u06a9\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u0645\u062a\u0628\u0627\u062f\u0644 \u0631\u0627\u0633\u062a\u06c1 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u0631\u06cc\u06ba \u062c\u0648 \u06a9\u0646\u0679\u06cc\u0646\u0631\u0632 \u06a9\u06d2 \u06af\u0631\u0645 \u062a\u0627\u0644\u0627\u0628 \u06a9\u0648 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be \u06a9\u0631 \u06cc\u0627 \u0627\u06cc\u06a9 \u0622\u0633\u0627\u0646\u060c \u062a\u06cc\u0632 \u0628\u06cc\u06a9 \u0627\u067e \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06a9\u06d2 \u06a9\u0648\u0644\u0688 \u0627\u0633\u0679\u0627\u0631\u0679 \u0645\u06cc\u06ba \u062a\u0627\u062e\u06cc\u0631 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u0648\u0626\u06cc \u062a\u06cc\u0633\u0631\u0627 \u0622\u067e\u0634\u0646 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0633\u0631\u062f\u06cc \u0634\u0631\u0648\u0639 \u0646\u06c1 \u06c1\u0648\u0646\u06d2 \u06a9\u0627 \u0628\u06c1\u0627\u0646\u06c1 \u0646\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p><strong>\u067e\u06cc\u0645\u0627\u0646\u06d2 \u067e\u0631 \u0645\u0634\u0627\u06c1\u062f\u06c1\u06d4<\/strong> \u0645\u0642\u0627\u0645\u06cc \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u062a\u0631\u0642\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u06a9\u06cc \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0645\u0646\u0638\u0645 \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u06cc\u0627 \u0627\u0633\u06cc \u0637\u0631\u062d \u06a9\u06d2 \u062a\u0642\u0633\u06cc\u0645 \u0634\u062f\u06c1 \u0679\u0631\u06cc\u0633\u0646\u06af \u0628\u06cc\u06a9 \u0627\u06cc\u0646\u0688 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u062c\u0648 \u0631\u0648\u0632\u0627\u0646\u06c1 \u0644\u0627\u06a9\u06be\u0648\u06ba \u0646\u0634\u0627\u0646\u0627\u062a \u06a9\u0648 \u0633\u0646\u0628\u06be\u0627\u0644 \u0633\u06a9\u06d2\u06d4<\/p>\n<p>\u0641\u06cc\u0635\u0644\u06c1 \u06a9\u06cc \u0633\u0637\u062d \u0633\u06d2 \u0628\u0627\u062e\u0628\u0631 \u0631\u06c1\u0646\u06d2 \u06a9\u06cc \u0622\u067e \u06a9\u0648 \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 \u0635\u0631\u0641 \u0627\u0646\u0641\u0631\u0627\u0633\u0679\u0631\u06a9\u0686\u0631 \u0645\u06cc\u0679\u0631\u06a9\u0633 \u0622\u067e \u06a9\u0648 \u06cc\u06c1 \u0646\u06c1\u06cc\u06ba \u0628\u062a\u0627\u062a\u06d2 \u06a9\u06c1 \u0622\u067e \u06a9\u06d2 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0627\u0646\u0641\u0631\u0646\u0633 \u0686\u06cc\u0646 \u0645\u06cc\u06ba \u06a9\u06cc\u0627 \u063a\u0644\u0637 \u06c1\u06d2\u06d4 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0645\u06cc\u06ba \u062a\u0627\u062e\u06cc\u0631 \u0627\u0633 \u0648\u0642\u062a \u062a\u06a9 \u0679\u06be\u06cc\u06a9 \u06c1\u0648\u0633\u06a9\u062a\u06cc \u06c1\u06d2 \u062c\u0628 \u062a\u06a9 \u06a9\u06c1 \u0645\u0627\u0688\u0644 \u063a\u0644\u0637 \u062c\u0648\u0627\u0628\u0627\u062a \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><strong>CI \u06a9\u06cc \u062a\u0634\u062e\u06cc\u0635\u06d4<\/strong> \u0628\u0627\u0628 7 \u0645\u06cc\u06ba DeepEval \u0679\u06cc\u0633\u0679 \u0622\u067e \u06a9\u06cc \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u06d2 \u062d\u0635\u06d2 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0686\u0644\u0627\u0626\u06d2 \u062c\u0627\u0626\u06cc\u06ba\u06d4 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0646\u06cc\u0627 \u0645\u0627\u0688\u0644\u060c \u067e\u0631\u0627\u0645\u067e\u0679\u060c \u06cc\u0627 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc \u062a\u0634\u062e\u06cc\u0635 \u06a9\u06d2 \u0645\u06a9\u0645\u0644 \u0645\u062c\u0645\u0648\u0639\u06c1 \u06a9\u0648 \u0645\u062a\u062d\u0631\u06a9 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0648\u0641\u0627\u062f\u0627\u0631\u06cc \u0627\u06cc\u06a9 \u062d\u062f \u0633\u06d2 \u0646\u06cc\u0686\u06d2 \u0622\u062a\u06cc \u06c1\u06d2 \u062a\u0648 \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u0645\u0633\u062f\u0648\u062f \u06c1\u0648\u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 LLM \u0631\u0648\u06cc\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0631\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0633\u0648\u06cc\u0679 \u06c1\u06d2\u060c \u0645\u0639\u06cc\u0627\u0631 \u0645\u06cc\u06ba \u0628\u062a\u062f\u0631\u06cc\u062c \u06a9\u0645\u06cc \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u0627\u0646\u0634\u0648\u0631\u0646\u0633\u06d4<\/p>\n<p><strong>\u0645\u0648\u0627\u062f \u06a9\u06cc \u062d\u0641\u0627\u0638\u062a\u06d4<\/strong> \u0627\u06cc\u062c\u0646\u0679 \u0622\u0624\u0679 \u067e\u0679 \u06a9\u0648 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06cc\u0627 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0633\u0633\u0679\u0645 \u062a\u06a9 \u067e\u06c1\u0646\u0686\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0645\u0648\u0627\u062f \u06a9\u06d2 \u0641\u0644\u0679\u0631\u0632 \u06a9\u0648 \u067e\u0627\u0633 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 \u0627\u06af\u0631\u0686\u06c1 \u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u0622\u067e \u06a9\u06d2 \u0646\u0648\u0679\u0633 \u067e\u0631 \u0645\u0628\u0646\u06cc \u06c1\u06d2\u060c LLM \u067e\u06be\u0631 \u0628\u06be\u06cc \u0641\u0631\u06cc\u0628 \u06cc\u0627 \u0645\u0648\u0627\u062f \u067e\u06cc\u062f\u0627 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0627\u0633 \u06a9\u06cc \u067e\u0627\u0644\u06cc\u0633\u06cc\u0648\u06ba \u06a9\u06cc \u062e\u0644\u0627\u0641 \u0648\u0631\u0632\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0645\u0627\u062d\u0648\u0644 \u0645\u06cc\u06ba \u062c\u06c1\u0627\u06ba \u0622\u0624\u0679 \u067e\u0679 \u06a9\u06d2 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u062a\u06a9 \u067e\u06c1\u0646\u0686\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u06a9\u06cc \u062a\u0648\u062b\u06cc\u0642 \u06a9\u06cc \u067e\u0631\u062a \u0627\u0648\u0631 \u0645\u0648\u0627\u062f \u06a9\u0627 \u0641\u0644\u0679\u0631 \u06cc\u0627 \u063a\u0644\u0637 \u0622\u0624\u0679 \u067e\u0679 \u06a9\u06d2 \u0646\u062a\u0627\u0626\u062c \u0627\u06c1\u0645 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u06cc\u06c1 \u0635\u0627\u0631\u0641 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0646\u0627\u0642\u0627\u0628\u0644\u0650 \u0645\u0630\u0627\u06a9\u0631\u0627\u062a \u06c1\u06d2\u06d4<\/p>\n<p>\u0636\u0645\u06cc\u0645\u06c1 C \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0645\u06a9\u0645\u0644 \u0633\u062e\u062a\u06cc \u0686\u06cc\u06a9 \u0644\u0633\u0679 \u0634\u0627\u0645\u0644 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-99-where-the-ecosystem-is-going-in-2026\">9.9 2026 \u0645\u06cc\u06ba \u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u0646\u0638\u0627\u0645 \u06a9\u06c1\u0627\u06ba \u062c\u0627\u0626\u06d2 \u06af\u0627\u061f<\/h3>\n<p>\u0645\u062a\u0639\u062f\u062f \u0631\u062c\u062d\u0627\u0646\u0627\u062a \u0646\u0626\u06d2 \u0633\u0631\u06d2 \u0633\u06d2 \u062a\u0634\u06a9\u06cc\u0644 \u062f\u06d2 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u06a9\u0633 \u0637\u0631\u062d \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645\u0632 \u0628\u0646\u0627\u0626\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u062c\u0628 \u0622\u067e \u0627\u067e\u0646\u06d2 \u0627\u06af\u0644\u06d2 \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u06a9\u06cc \u0645\u0646\u0635\u0648\u0628\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u062f\u0648\u0646\u0648\u06ba \u067e\u0631 \u062a\u0648\u062c\u06c1 \u062f\u06cc\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h4 id=\"heading-protocol-consolidation\">\u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u0627\u0646\u0636\u0645\u0627\u0645<\/h4>\n<p>MCP \u0627\u0648\u0631 A2A \u062f\u0648\u0646\u0648\u06ba \u0646\u06d2 2025 \u0645\u06cc\u06ba v1.0 \u0648\u0636\u0627\u062d\u062a\u06cc\u06ba \u062c\u0627\u0631\u06cc \u06a9\u06cc\u06ba\u06d4 Google\u060c Anthropic\u060c Salesforce\u060c SAP \u0627\u0648\u0631 \u062f\u0631\u062c\u0646\u0648\u06ba \u062f\u06cc\u06af\u0631 \u062f\u06a9\u0627\u0646\u062f\u0627\u0631\u0648\u06ba \u0646\u06d2 \u062f\u0633\u062a\u062e\u0637 \u06a9\u06cc\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627 \u062f\u0648\u0631 \u0627\u0633\u06cc \u0645\u0639\u06cc\u0627\u0631\u06cc \u06a9\u0627\u0631\u06cc \u06a9\u06d2 \u0639\u0645\u0644 \u06a9\u06cc \u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631 \u0631\u06c1\u0627 \u06c1\u06d2 \u062c\u0648 REST \u0646\u06d2 \u0648\u06cc\u0628 \u0633\u0631\u0648\u0633\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u06cc\u0627 \u062a\u06be\u0627\u06d4 \u06cc\u06c1 \u067e\u06c1\u0644\u06d2 \u062a\u0648 \u06af\u0646\u062f\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u067e\u06be\u0631 \u0628\u0627\u0642\u06cc \u0633\u0628 \u06a9\u0686\u06be \u0648\u0627\u0636\u062d \u0641\u0627\u062a\u062d\u0648\u06ba \u0645\u06cc\u06ba \u0628\u062f\u0644 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0622\u067e \u06a9\u06d2 \u06a9\u0627\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633 \u06a9\u0627 \u06a9\u06cc\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2: MCP \u0645\u06cc\u06ba \u0679\u0648\u0644 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u06a9\u0648 \u0645\u0639\u06cc\u0627\u0631\u06cc \u0628\u0646\u0627\u0646\u0627 \u0627\u0648\u0631 A2A \u0645\u06cc\u06ba \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648\u0622\u0631\u0688\u06cc\u0646\u06cc\u0634\u0646 \u0627\u0628 \u06a9\u0645 \u062e\u0637\u0631\u06c1 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u062a\u06cc\u0646 \u0633\u0627\u0644 \u0628\u0639\u062f \u0628\u06be\u06cc \u0646\u0627\u0641\u0630 \u0631\u06c1\u06cc\u06ba \u06af\u06d2\u06d4 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u0627 \u0627\u0646\u062a\u062e\u0627\u0628 \u0622\u06af\u06d2 \u067e\u06cc\u0686\u06be\u06d2 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<h4 id=\"heading-local-first-infrastructure\">\u0645\u0642\u0627\u0645\u06cc-\u067e\u06c1\u0644\u0627 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u06be\u0627\u0646\u0686\u06c1<\/h4>\n<p>\u0645\u0642\u0627\u0645\u06cc \u0627\u0648\u0631 \u06a9\u0644\u0627\u0624\u0688 \u0627\u0646\u0641\u0631\u0646\u0633 \u06a9\u06d2 \u0645\u0639\u06cc\u0627\u0631 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0641\u0631\u0642 \u06a9\u0645 \u06c1\u0648\u062a\u0627 \u062c\u0627 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4 \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u0633\u0627\u0644 \u067e\u06c1\u0644\u06d2\u060c \u0645\u0642\u0627\u0645\u06cc 7B \u0645\u0627\u0688\u0644 \u067e\u0631 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645 \u0686\u0644\u0627\u0646\u0627 \u0627\u06cc\u06a9 \u0688\u06cc\u0645\u0648 \u062a\u06be\u0627\u060c \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0679\u0648\u0644 \u0646\u06c1\u06cc\u06ba\u06d4 \u0641\u06cc \u0627\u0644\u062d\u0627\u0644\u060c Qwen 2.5 \u067e\u06cc\u0631\u0627\u0645\u06cc\u0679\u0631\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be 7-32B \u06c1\u06cc\u0646\u0688\u0644 \u0679\u0648\u0644 \u06a9\u0627\u0644\u0632 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0648\u0631\u06a9 \u0641\u0644\u0648 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0627\u0641\u06cc \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u06c1\u06d2\u06d4<\/p>\n<p>\u0645\u0642\u0627\u0645\u06cc \u062a\u062e\u0645\u06cc\u0646\u06c1 \u06a9\u06cc \u0631\u0627\u0632\u062f\u0627\u0631\u06cc\u060c \u0642\u06cc\u0645\u062a\u060c \u0627\u0648\u0631 \u062a\u0627\u062e\u06cc\u0631 \u06a9\u06d2 \u0641\u0648\u0627\u0626\u062f \u0627\u06c1\u0645 \u06c1\u06cc\u06ba\u06d4 \u06a9\u0686\u06be \u0635\u0646\u0639\u062a\u06cc\u06ba \u0628\u06cc\u0631\u0648\u0646\u06cc APIs \u06a9\u0648 \u0688\u06cc\u0679\u0627 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u0646\u06c1\u06cc\u06ba \u062f\u06cc\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0627\u06cc\u06a9 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u062c\u0648 \u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u0686\u06be\u06cc \u0637\u0631\u062d \u0633\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u06cc\u06a9 \u0645\u0646\u0638\u0645 \u06af\u06cc\u0679 \u0648\u06d2 \u067e\u0631 \u0628\u06be\u06cc \u0627\u0686\u06be\u0627 \u06a9\u0627\u0645 \u06a9\u0631\u06d2 \u06af\u0627\u06d4 \u0627\u06cc\u06a9 \u0645\u062e\u0635\u0648\u0635 \u06a9\u0644\u0627\u0624\u0688 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0646\u0646\u062f\u06c1 \u06a9\u06cc \u0635\u0644\u0627\u062d\u06cc\u062a\u0648\u06ba \u06a9\u06d2 \u0627\u0631\u062f \u06af\u0631\u062f \u0628\u0646\u0627\u0626\u06d2 \u06af\u0626\u06d2 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631\u0627\u062a \u06a9\u0648 \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u0646\u0627 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0634\u06a9\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-longer-context-narrower-agents\">\u0644\u0645\u0628\u0627 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642\u060c \u062a\u0646\u06af \u0627\u06cc\u062c\u0646\u0679<\/h4>\n<p>\u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u06a9\u06cc \u06a9\u06be\u0691\u06a9\u06cc \u0628\u0691\u06be\u062a\u06cc \u062c\u0627\u0631\u06c1\u06cc \u06c1\u06d2\u06d4 \u0641\u06cc \u0627\u0644\u062d\u0627\u0644\u060c \u0645\u062a\u0639\u062f\u062f \u062a\u062c\u0627\u0631\u062a\u06cc \u0645\u0627\u0688\u0644\u0632 \u0645\u06cc\u06ba 1 \u0645\u0644\u06cc\u0646 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0679\u0648\u06a9\u0646 \u062f\u0633\u062a\u06cc\u0627\u0628 \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645\u0632 \u06a9\u0627 \u0645\u0639\u0627\u0645\u0644\u06c1 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0627\u06cc\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u067e\u0648\u0631\u06cc \u0628\u0627\u062a \u0686\u06cc\u062a \u0627\u0648\u0631 \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u062f\u0644\u06cc\u0644 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06a9\u0627\u0645 \u06a9\u0648 \u06a9\u06cc\u0648\u06ba \u062a\u0642\u0633\u06cc\u0645 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2\u061f<\/p>\n<p>\u062c\u0648\u0627\u0628 \u0628\u062f\u0644 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0627\u0628 \u0635\u0631\u0641 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u0648\u0646\u0688\u0648 \u06a9\u06d2 \u0627\u0646\u062a\u0638\u0627\u0645 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06cc\u06c1 \u062a\u062e\u0635\u0635\u060c \u063a\u0644\u0637\u06cc \u06a9\u06cc \u062a\u0646\u06c1\u0627\u0626\u06cc\u060c \u0627\u0648\u0631 \u0622\u0632\u0627\u062f \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u06a9\u06cc \u0648\u062c\u0648\u06c1\u0627\u062a \u067e\u0631 \u0628\u0627\u0628 1 \u0645\u06cc\u06ba \u0628\u062d\u062b \u06a9\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u06d4 \u062c\u06cc\u0633\u06d2 \u062c\u06cc\u0633\u06d2 \u0633\u0646\u06af\u0644 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06cc \u0635\u0644\u0627\u062d\u06cc\u062a\u06cc\u06ba \u0628\u0691\u06be \u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u060c \"\u06a9\u06cc\u0627 \u06cc\u06c1 \u0645\u0633\u0626\u0644\u06c1 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06cc \u0636\u0645\u0627\u0646\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\" \u06a9\u0627 \u0628\u0627\u0631 \u0628\u0691\u06be \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645 \u0628\u0646\u0627\u0646\u06d2 \u0648\u0627\u0644\u06cc \u0628\u06c1\u062a \u0633\u06cc \u0679\u06cc\u0645\u06cc\u06ba \u0622\u062c \u0627\u06cc\u06a9 \u06c1\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0627\u0648\u0631 \u0628\u06c1\u062a\u0631 \u0679\u0648\u0644\u0632 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0648\u06c1\u06cc \u0646\u062a\u0627\u0626\u062c \u062d\u0627\u0635\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u0633 \u06c1\u06cc\u0646\u0688 \u0628\u06a9 \u06a9\u06d2 \u0646\u0645\u0648\u0646\u06d2 \u0627\u0628 \u0628\u06be\u06cc \u0644\u0627\u06af\u0648 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0633\u0648\u0627\u0644 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0622\u067e \u06a9\u0648 \u0627\u0646 \u062a\u06a9 \u06a9\u0628 \u067e\u06c1\u0646\u0686\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2\u061f<\/p>\n<h3 id=\"heading-910-where-to-apply-these-patterns\">9.10 \u0627\u0646 \u0646\u0645\u0648\u0646\u0648\u06ba \u06a9\u0648 \u06a9\u06c1\u0627\u06ba \u0644\u0627\u06af\u0648 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4<\/h3>\n<p>\u0644\u0631\u0646\u0646\u06af \u0627\u06cc\u06a9\u0633\u0644\u0631\u06cc\u0679\u0631 \u062a\u0639\u0644\u06cc\u0645\u06cc \u06af\u0627\u0691\u06cc\u0627\u06ba \u06c1\u06cc\u06ba\u06d4 \u067e\u06cc\u0679\u0631\u0646 \u0646\u06cc\u0686\u06d2 \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba. \u06cc\u06c1 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0646\u0638\u0627\u0645 \u0622\u062c \u0627\u0633 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h4 id=\"heading-1-sales-enablement\">1. \u0633\u06cc\u0644\u0632 \u0627\u06cc\u06a9\u0679\u06cc\u0648\u06cc\u0634\u0646<\/h4>\n<p>\u0646\u0635\u0627\u0628 \u06a9\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u0646\u0626\u06d2 \u0633\u06cc\u0644\u0632 \u0646\u0645\u0627\u0626\u0646\u062f\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0622\u0646 \u0628\u0648\u0631\u0688\u0646\u06af \u06a9\u0627 \u0631\u0627\u0633\u062a\u06c1 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0645\u0648\u0627\u062f \u06a9\u06d2 \u0627\u06cc\u062c\u0646\u0679 MCP \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u0645\u0639\u0644\u0648\u0645\u0627\u062a \u06a9\u06cc \u0628\u0646\u06cc\u0627\u062f \u0645\u06cc\u06ba \u0645\u0635\u0646\u0648\u0639\u0627\u062a \u06a9\u06cc \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u06a9\u0648 \u0628\u06cc\u0627\u0646 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062a\u0634\u062e\u06cc\u0635\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0641\u06c1\u0645 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u0627\u06cc\u062c\u0646\u0679 \u0645\u062a\u0639\u062f\u062f \u067e\u0631\u0648\u0688\u06a9\u0679 \u0627\u06cc\u0631\u06cc\u0627\u0632 \u0645\u06cc\u06ba \u0633\u0631\u0679\u06cc\u0641\u06cc\u06a9\u06cc\u0634\u0646 \u06a9\u0648 \u0679\u0631\u06cc\u06a9 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062a\u0631\u0628\u06cc\u062a \u0634\u0631\u0648\u0639 \u06c1\u0648\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0645\u0646\u062a\u0638\u0645\u06cc\u0646 \u0646\u0635\u0627\u0628 \u06a9\u0648 \u0627\u0646\u0633\u0627\u0646\u0648\u06ba \u0633\u06d2 \u0645\u0646\u0633\u0644\u06a9 \u06af\u06cc\u0679 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0645\u0646\u0638\u0648\u0631 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h4 id=\"heading-2-compliance-training\">2. \u0642\u0627\u0646\u0648\u0646 \u06a9\u06cc \u062a\u0639\u0645\u06cc\u0644 \u06a9\u06cc \u062a\u0631\u0628\u06cc\u062a<\/h4>\n<p>HIPAA\u060c SOX\u060c \u0627\u0648\u0631 GDPR \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u0648\u0645\u06cc\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u062e\u0635\u0648\u0635 \u0646\u0635\u0627\u0628 \u06a9\u0627 \u0627\u06cc\u062c\u0646\u0679\u06d4 MCP \u0633\u0631\u0648\u0631 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u062d\u0642\u06cc\u0642\u06cc \u0631\u06cc\u06af\u0648\u0644\u06cc\u0679\u0631\u06cc \u0645\u062a\u0646 \u067e\u0631 \u0645\u0628\u0646\u06cc \u0645\u0648\u0627\u062f \u06a9\u0627 \u0627\u06cc\u062c\u0646\u0679 (\u0645\u0627\u0688\u0644 \u06a9\u0627 \u062a\u0631\u0628\u06cc\u062a\u06cc \u0688\u06cc\u0679\u0627 \u0646\u06c1\u06cc\u06ba)\u06d4 \u0632\u06cc\u0627\u062f\u06c1 \u0633\u062e\u062a \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u06cc \u062d\u062f \u0627\u0648\u0631 \u0622\u0688\u0679 \u0644\u0627\u06af\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0631\u06cc\u0679\u0646\u06af \u0627\u06cc\u062c\u0646\u0679 \u062c\u0648 \u0631\u06cc\u06af\u0648\u0644\u06cc\u0679\u0631\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u0631\u0622\u0645\u062f \u06a9\u06cc\u06d2 \u062c\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062a\u0631\u0628\u06cc\u062a \u062a\u0641\u0648\u06cc\u0636 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc\u0648\u0645\u0646-\u0627\u0646-\u062f\u06cc-\u0644\u0648\u067e \u06af\u06cc\u0679 \u0642\u0627\u0646\u0648\u0646\u06cc \u062c\u0627\u0626\u0632\u06c1 \u06a9\u0627 \u0645\u0631\u062d\u0644\u06c1 \u0628\u0646 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-3-customer-support\">3. \u06a9\u0633\u0679\u0645\u0631 \u0633\u067e\u0648\u0631\u0679<\/h4>\n<p>\u0627\u06cc\u06a9 \u0631\u06cc\u0633\u067e\u0634\u0646\u0633\u0679 \u0679\u06a9\u0679\u0648\u06ba \u06a9\u0648 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06d2 \u06af\u0627\u06d4 \u062a\u062d\u0642\u06cc\u0642\u06cc \u0627\u06cc\u062c\u0646\u0679 MCP \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0646\u0627\u0644\u062c \u0628\u06cc\u0633 \u0645\u0636\u0627\u0645\u06cc\u0646 \u067e\u0691\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0688\u0631\u0627\u0641\u0679\u0631 \u062c\u0648\u0627\u0628 \u0644\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0627\u0626\u0632\u06c1 \u0644\u06cc\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u067e\u0627\u0644\u06cc\u0633\u06cc \u06a9\u06cc \u062a\u0639\u0645\u06cc\u0644 \u0686\u06cc\u06a9 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 A2A \u067e\u0631\u062a Salesforce \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 ServiceNow \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0627\u067e\u0646\u06cc \u0645\u0631\u0636\u06cc \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 LangGraph \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u06cc \u06c1\u06d2\u06d4 \u06cc\u0639\u0646\u06cc \u062d\u0633\u0628 \u0636\u0631\u0648\u0631\u062a \u0627\u0646\u0636\u0645\u0627\u0645 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u0633\u0633\u0679\u0645\u0632 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646\u06d4<\/p>\n<h4 id=\"heading-4-engineering-onboarding\">4. \u0627\u0646\u062c\u06cc\u0646\u0626\u0631\u0646\u06af \u0622\u0646 \u0628\u0648\u0631\u0688\u0646\u06af<\/h4>\n<p>\u06a9\u0648\u0688\u0628\u06cc\u0633 \u0627\u06cc\u062c\u0646\u0679 \u0622\u067e \u06a9\u06d2 \u0630\u062e\u06cc\u0631\u06d2 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0646\u0626\u06d2 \u0645\u0644\u0627\u0632\u0645\u06cc\u0646 \u06a9\u06cc \u0631\u06c1\u0646\u0645\u0627\u0626\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0679\u0648\u0644\u0646\u06af \u0627\u06cc\u062c\u0646\u0679 \u062a\u0631\u0642\u06cc \u06a9\u06d2 \u0645\u0627\u062d\u0648\u0644 \u06a9\u0648 \u0628\u06cc\u0627\u0646 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0627\u0626\u0632\u06c1 \u0644\u06cc\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648\u0688\u0646\u06af \u06a9\u06d2 \u0645\u0639\u06cc\u0627\u0631\u0627\u062a \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0633\u0648\u0627\u0644\u0627\u062a \u06a9\u06d2 \u062c\u0648\u0627\u0628\u0627\u062a \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0648\u06c1 \u0633\u0628 \u0627\u0635\u0644 \u06a9\u0648\u0688\u0628\u06cc\u0633 \u0627\u0648\u0631 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u0627\u062a \u067e\u0631 \u0645\u0628\u0646\u06cc \u06c1\u06cc\u06ba\u060c MCP \u0633\u0631\u0648\u0631 \u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u0630\u062e\u06cc\u0631\u06c1 \u06a9\u06cc \u0637\u0631\u0641 \u0627\u0634\u0627\u0631\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0645\u0634\u062a\u0631\u06a9\u06c1 \u062f\u06be\u0627\u06af\u06c1: \u0627\u0646 \u0645\u06cc\u06ba \u0633\u06d2 \u06c1\u0631 \u0627\u06cc\u06a9 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0622\u0631\u06a9\u06cc\u0679\u06cc\u06a9\u0686\u0631\u0644 \u0645\u0627\u0631\u06a9\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0645\u062e\u062a\u0644\u0641 \u0630\u06cc\u0644\u06cc \u06a9\u0627\u0645\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u062e\u062a\u0644\u0641 \u0679\u0648\u0644\u0632\u06d4 \u0627\u06cc\u0644 \u0627\u06cc\u0644 \u0627\u06cc\u0645 \u06a9\u0627\u0644 \u06a9\u06d2 \u0645\u062e\u062a\u0644\u0641 \u0646\u0645\u0648\u0646\u06d2\u06d4 \u0627\u06cc\u06a9 \u062a\u062e\u0635\u0635 \u062c\u0648 \u0627\u06cc\u06a9 \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0627\u06cc\u062c\u0646\u0679 \u0633\u06d2 \u0633\u0645\u062c\u06be\u0648\u062a\u06c1 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u0641\u0627\u0644\u0679 \u0622\u0626\u0633\u0648\u0644\u06cc\u0634\u0646 \u06a9\u06cc \u0636\u0631\u0648\u0631\u06cc\u0627\u062a\u06d4<\/p>\n<p>\u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0648 \u0627\u0633 \u06a9\u06cc \u0646\u06cc\u0627\u067e\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0646\u062a\u062e\u0628 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627\u06d4 \u0627\u0646 \u06a9\u0627 \u0627\u0646\u062a\u062e\u0627\u0628 \u0627\u0633 \u0644\u06cc\u06d2 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06a9\u06c1 \u0648\u06c1 \u0645\u0633\u0627\u0626\u0644 \u06a9\u06cc \u0627\u0642\u0633\u0627\u0645 \u0633\u06d2 \u0645\u0645\u0627\u062b\u0644 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-911-what-to-build-next\">9.11 \u0622\u06af\u06d2 \u06a9\u06cc\u0627 \u0628\u0646\u0627\u0646\u0627 \u06c1\u06d2\u06d4<\/h3>\n<p>\u06c1\u0644\u06a9\u06cc \u0633\u06d2 \u0644\u06d2 \u06a9\u0631 \u0633\u0628 \u0633\u06d2 \u0628\u0691\u06cc \u0644\u0641\u0679\u0648\u06ba \u062a\u06a9\u060c \u06cc\u06c1\u0627\u06ba \u06a9\u0686\u06be \u062a\u062c\u0627\u0648\u06cc\u0632 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0627\u0646\u06c1\u06cc\u06ba \u06a9\u06c1\u0627\u06ba \u0644\u06d2 \u062c\u0627\u0646\u0627 \u06c1\u06d2\u06d4<\/p>\n<ol>\n<li>\n<p><strong>\u0627\u067e\u0646\u06d2 \u0627\u06cc\u0645 \u0633\u06cc \u067e\u06cc \u0679\u0648\u0644\u0632 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0627\u067e\u0646\u06cc \u0646\u0648\u0679\u0633 \u0688\u0627\u0626\u0631\u06a9\u0679\u0631\u06cc \u0645\u06cc\u06ba \u0641\u0627\u0626\u0644 \u0633\u0633\u0679\u0645 \u0633\u0631\u0648\u0631 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u06cc\u06a9 MCP \u0633\u0631\u0648\u0631 \u0644\u06a9\u06be\u06cc\u06ba \u062c\u0648 \u0622\u067e \u06a9\u06d2 \u067e\u0633\u0646\u062f\u06cc\u062f\u06c1 \u0639\u0644\u0645\u06cc \u0630\u0631\u0627\u0626\u0639 \u0633\u06d2 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: \u062a\u0635\u0648\u0631\u060c \u0633\u0646\u06af\u0645\u060c \u0627\u0648\u0631 \u0679\u06cc\u0645 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u06cc \u0633\u0627\u0626\u0679\u0633\u06d4 \u0679\u0648\u0644 \u06a9\u0627\u0644 \u0644\u0648\u067e \u0627\u0633\u06cc \u0637\u0631\u062d \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0635\u0631\u0641 \u0633\u0631\u0648\u0631 \u06a9\u06d2 \u0646\u0641\u0627\u0630 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644\u06cc \u0622\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0646\u0635\u0627\u0628 \u06a9\u06cc \u0634\u0627\u062e\u06cc\u06ba \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4<\/strong> \u0644\u0631\u0646\u0646\u06af \u0627\u06cc\u06a9\u0633\u0644\u0631\u06cc\u0679\u0631 \u0627\u06cc\u06a9 \u067e\u0631\u0648\u06af\u0631\u0627\u0645\u0646\u06af \u0645\u0648\u0636\u0648\u0639 \u06a9\u0648 \u0641\u0631\u0636 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u067e\u0646\u0627 \u067e\u0631\u0627\u0645\u067e\u0679 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>curriculum_planner.py<\/code> \u0622\u067e \u06a9\u06d2 \u0688\u0648\u0645\u06cc\u0646 \u0645\u06cc\u06ba: \u0637\u0628\u06cc \u062a\u0639\u0644\u06cc\u0645\u060c \u0632\u0628\u0627\u0646 \u0633\u06cc\u06a9\u06be\u0646\u0627\u060c \u0642\u0627\u0646\u0648\u0646\u06cc \u062a\u0631\u0628\u06cc\u062a\u06d4 \u06af\u0631\u0627\u0641 \u06a9\u0627 \u0688\u06be\u0627\u0646\u0686\u06c1 \u0648\u06c1\u06cc \u0631\u06c1\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be\u06cc \u062a\u062c\u0632\u06cc\u0627\u062a\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4<\/strong> \u06c1\u0645 \u0627\u06cc\u06a9 \u0686\u06be\u0679\u0627 \u0627\u06cc\u062c\u0646\u0679 \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u0648\u0642\u062a\u0627\u064b \u0641\u0648\u0642\u062a\u0627\u064b \u0686\u0644\u062a\u0627 \u06c1\u06d2 (\u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0637\u06d2 \u0634\u062f\u06c1 \u06af\u0631\u0627\u0641 \u0646\u06c1\u06cc\u06ba) \u0627\u0648\u0631 \u0633\u06cc\u0634\u0646\u0648\u06ba \u0645\u06cc\u06ba \u0633\u06cc\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0646\u0645\u0648\u0646\u0648\u06ba \u06a9\u0627 \u062e\u0644\u0627\u0635\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633\u060c \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u0679\u0631\u06cc\u0633\u060c \u0627\u0648\u0631 MCP \u0645\u06cc\u0645\u0648\u0631\u06cc \u0633\u06d2 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0641\u062a\u06c1 \u0648\u0627\u0631 \u067e\u06cc\u0634\u0631\u0641\u062a \u06a9\u06cc \u0631\u067e\u0648\u0631\u0679 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0632\u0628\u0631\u062f\u0633\u062a \u062a\u0648\u0633\u06cc\u0639 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0645\u0648\u062c\u0648\u062f\u06c1 \u06a9\u0648\u0688 \u0645\u06cc\u06ba \u062a\u0631\u0645\u06cc\u0645 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u0633\u0633\u0679\u0645 \u06a9\u06d2 \u062a\u0645\u0627\u0645 \u062d\u0635\u0648\u06ba \u06a9\u0648 \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0627\u067e\u0646\u06cc \u06c1\u06cc\u0646\u0688 \u0628\u06a9 \u0628\u0646\u0627\u0626\u06cc\u06ba:<\/strong> \u0627\u0646 \u0646\u0645\u0648\u0646\u0648\u06ba \u06a9\u0648 \u0645\u0636\u0628\u0648\u0637 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0628\u06c1\u062a\u0631\u06cc\u0646 \u0637\u0631\u06cc\u0642\u06c1 \u0627\u0646\u06c1\u06cc\u06ba \u0633\u06a9\u06be\u0627\u0646\u0627 \u06c1\u06d2\u06d4 \u0645\u062e\u062a\u0644\u0641 \u0645\u0633\u0627\u0626\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u062e\u062a\u0644\u0641 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645 \u0628\u0646\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u062c\u0648 \u06a9\u0686\u06be \u0622\u067e \u0633\u06cc\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0633\u06d2 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u0646\u0641\u0631\u0627\u0633\u0679\u0631\u06a9\u0686\u0631 \u067e\u06cc\u0679\u0631\u0646 (\u0679\u0648\u0644\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 MCP\u060c \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648\u0622\u0631\u0688\u06cc\u0646\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 A2A\u060c \u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 LangGraph\u060c \u0644\u0686\u06a9 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0686\u0648\u06a9\u06cc\u0627\u06ba\u060c LLM-\u062c\u062c \u0628\u0631\u0627\u0626\u06d2 \u062a\u0634\u062e\u06cc\u0635) \u062a\u0645\u0627\u0645 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u0645\u0633\u0627\u0626\u0644 \u067e\u0631 \u0644\u0627\u06af\u0648 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06a9\u0686\u06be \u0627\u06cc\u062c\u0646\u0679 \u0627\u0648\u0631 \u0627\u0648\u0632\u0627\u0631 \u0628\u062f\u0644 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ol>\n<h2 id=\"heading-conclusion\">\u0646\u062a\u06cc\u062c\u06c1<\/h2>\n<p>\u0622\u067e \u0646\u06d2 \u0627\u0633 \u06c1\u06cc\u0646\u0688 \u0628\u06a9 \u06a9\u0627 \u0622\u063a\u0627\u0632 \u0627\u06cc\u06a9 \u0633\u0648\u0627\u0644 \u0633\u06d2 \u06a9\u06cc\u0627\u06d4 \u06a9\u06cc\u0627 \u0622\u067e \u06a9\u0627 \u0645\u0633\u0626\u0644\u06c1 \u062f\u0631\u062d\u0642\u06cc\u0642\u062a \u0645\u062a\u0639\u062f\u062f \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u061f \u0627\u0633 \u0633\u0648\u0627\u0644 \u0646\u06d2 \u0628\u0627\u0642\u06cc \u0627\u0646\u062c\u06cc\u0646\u0626\u0631\u0646\u06af \u06a9\u0648 \u0627\u06cc\u0645\u0627\u0646\u062f\u0627\u0631 \u0631\u06a9\u06be\u0627\u06d4<\/p>\n<p>\u0644\u0631\u0646\u0646\u06af \u0627\u06cc\u06a9\u0633\u0644\u0631\u06cc\u0679\u0631 \u0645\u06cc\u06ba \u06c1\u0631 \u0627\u06cc\u062c\u0646\u0679 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0648\u06c1 \u062c\u0648 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0648\u06c1 \u062f\u0648\u0633\u0631\u06d2 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u0633\u06d2 \u0628\u0627\u0644\u06a9\u0644 \u0645\u062e\u062a\u0644\u0641 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0645\u062e\u062a\u0644\u0641 \u0679\u0648\u0644\u0632\u060c \u0645\u062e\u062a\u0644\u0641 LLM \u06a9\u0627\u0644 \u067e\u06cc\u0679\u0631\u0646\u060c \u0645\u062e\u062a\u0644\u0641 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a\u060c \u0645\u062e\u062a\u0644\u0641 \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u0637\u0631\u06cc\u0642\u06d2\u06d4<\/p>\n<p>\u06c1\u0645 \u0646\u06d2 \u0627\u06cc\u06a9 \u06a9\u062b\u06cc\u0631 \u0627\u06cc\u062c\u0646\u0679 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0627 \u0627\u0646\u062a\u062e\u0627\u0628 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627\u06d4 \u0645\u06cc\u06ba \u0646\u06d2 \u0627\u0633 \u06a9\u0627 \u0627\u0646\u062a\u062e\u0627\u0628 \u06a9\u06cc\u0627 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0645\u062c\u06be\u06d2 \u0645\u0633\u0626\u0644\u06c1 \u0641\u0627\u0631\u0645 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u0641\u06cc\u0635\u0644\u06d2 \u0633\u06d2 \u0627\u0648\u067e\u0631 \u06a9\u06cc \u062a\u0645\u0627\u0645 \u062a\u06a9\u0646\u06cc\u06a9\u06cc \u062a\u06c1\u0648\u06ba \u0646\u06d2 \u0627\u0646\u06c1\u06cc \u0627\u0635\u0648\u0644\u0648\u06ba \u067e\u0631 \u0639\u0645\u0644 \u06a9\u06cc\u0627\u06d4<\/p>\n<ul>\n<li>\n<p>\u0686\u0648\u0646\u06a9\u06c1 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0633\u0633\u0679\u0645 \u06a9\u0631\u06cc\u0634 \u06c1\u0648\u0646\u06d2 \u067e\u0631 \u062d\u0627\u0644\u062a \u0646\u06c1\u06cc\u06ba \u06a9\u06be\u0648 \u0633\u06a9\u062a\u06d2\u060c \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0631\u06cc\u0627\u0633\u062a \u067e\u0631 \u0645\u0628\u0646\u06cc \u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0634\u0646 \u0627\u0648\u0631 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u06cc \u0635\u0644\u0627\u062d\u06cc\u062a\u06cc\u06ba \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u06a9\u0633\u06cc \u062e\u0627\u0635 \u0639\u0645\u0644 \u0633\u06d2 \u0645\u0646\u0633\u0644\u06a9 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2\u060c MCP \u0645\u0639\u06cc\u0627\u0631\u06cc \u0679\u0648\u0644 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc\u06d4<\/p>\n<\/li>\n<li>\n<p>A2A \u0646\u06d2 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u06c1\u0645 \u0622\u06c1\u0646\u06af\u06cc \u06a9\u0648 \u0641\u0639\u0627\u0644 \u06a9\u06cc\u0627\u060c \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u062d\u0642\u06cc\u0642\u06cc \u062f\u0646\u06cc\u0627 \u06a9\u0627 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u06be\u0627\u0646\u0686\u06c1 \u0628\u0639\u0636 \u0627\u0648\u0642\u0627\u062a \u0645\u062a\u0639\u062f\u062f \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u067e\u0631 \u067e\u06be\u06cc\u0644\u0627 \u06c1\u0648\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0686\u0648\u0646\u06a9\u06c1 \u0627\u0646\u0641\u0631\u0627\u0633\u0679\u0631\u06a9\u0686\u0631 \u0645\u06cc\u0679\u0631\u06a9\u0633 \u0627\u06a9\u06cc\u0644\u06d2 \u06cc\u06c1 \u0646\u06c1\u06cc\u06ba \u0628\u062a\u0627 \u0633\u06a9\u062a\u0627 \u06a9\u06c1 \u0622\u06cc\u0627 \u06a9\u0648\u0626\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0635\u062d\u06cc\u062d \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0627\u0633\u062a\u062f\u0644\u0627\u0644 \u06a9\u0631 \u0631\u06c1\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u0646\u06d2 \u0641\u06cc\u0635\u0644\u06d2 \u06a9\u06cc \u0633\u0637\u062d \u06a9\u06d2 \u0646\u0634\u0627\u0646\u0627\u062a \u062d\u0627\u0635\u0644 \u06a9\u0631 \u0644\u06cc\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>DeepEval \u0646\u06d2 \u06a9\u0648\u0627\u0644\u0679\u06cc \u06af\u06cc\u0679 \u0644\u0627\u06af\u0648 \u06a9\u06cc\u0627 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 LLM \u0646\u062a\u0627\u0626\u062c \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0648\u0627\u062d\u062f \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0637\u0631\u06cc\u0642\u06c1 \u0648\u0627\u0636\u062d \u0645\u0639\u06cc\u0627\u0631 \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u0641\u06cc\u0635\u0644\u06c1 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0627\u06cc\u06a9 \u0627\u0648\u0631 LLM \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>Streamlit UI \u0646\u06d2 \u0638\u0627\u06c1\u0631 \u06a9\u06cc\u0627 \u06a9\u06c1 LangGraph \u06a9\u0648\u0688 I\/O-agnostic \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06cc\u06c1\u06cc \u06af\u0631\u0627\u0641 \u0679\u0631\u0645\u06cc\u0646\u0644 \u0633\u06cc\u0634\u0646\u0632 \u0627\u0648\u0631 \u0648\u06cc\u0628 \u0627\u06cc\u067e\u0633 \u06a9\u0648 \u0633\u067e\u0648\u0631\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u0627\u0646 \u0633\u0628 \u06a9\u06d2 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0627\u0646\u062c\u06cc\u0646\u0626\u0631\u0646\u06af \u0627\u0635\u0648\u0644 \u0648\u06c1\u06cc \u06c1\u06cc\u06ba \u062c\u0648 \u0622\u06af\u06d2 \u0628\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06cc\u06ba\u06d4 <strong>\u0627\u0686\u06be\u06cc \u0637\u0631\u062d \u0633\u06d2 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u0631\u062f\u06c1 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba \u062a\u0645\u0627\u0645 \u062d\u062f\u0648\u062f \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u06c1\u06cc\u06ba\u060c \u0627\u06cc\u0633\u0648\u0633\u06cc \u0627\u06cc\u0634\u0646\u0632 \u0646\u06c1\u06cc\u06ba\u06d4<\/strong>.<\/p>\n<p>\u0627\u06cc\u062c\u0646\u0679 TypedDict \u0645\u0639\u0627\u06c1\u062f\u0648\u06ba \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0631\u06cc\u0627\u0633\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0628\u0627\u062a \u0686\u06cc\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u06cc\u062c\u0646\u0679 MCP \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0679\u0648\u0644\u0632 \u0633\u06d2 \u0628\u0627\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u06cc\u062c\u0646\u0679 A2A \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0627\u06cc\u06a9 \u062f\u0648\u0633\u0631\u06d2 \u0633\u06d2 \u0628\u0627\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u06cc\u062c\u0646\u0679 \u0644\u06cc\u0646\u06af \u0686\u06cc\u0646 \u06a9\u0627\u0644 \u0628\u06cc\u06a9\u0633 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0645\u0634\u0627\u06c1\u062f\u06d2 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0628\u0627\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06c1\u0631 \u0628\u0627\u0624\u0646\u0688\u0631\u06cc \u06a9\u0648 \u0628\u0642\u06cc\u06c1 \u062d\u062f\u0648\u062f \u06a9\u0648 \u0686\u06be\u0648\u0626\u06d2 \u0628\u063a\u06cc\u0631 \u062a\u0628\u062f\u06cc\u0644\u060c \u062a\u0628\u062f\u06cc\u0644 \u06cc\u0627 \u0628\u0691\u06be\u0627\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0648\u06c1\u06cc \u06c1\u06d2 \u062c\u0648 \u0633\u0633\u0679\u0645 \u06a9\u06cc \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u06a9\u0627 \u062f\u0631\u062c\u06c1 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0634\u062f\u06c1 \u0645\u062e\u0635\u0648\u0635 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0628\u0644\u06a9\u06c1 \u0627\u0646 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u0648 \u0648\u0627\u0636\u062d \u0627\u0646\u0679\u0631\u0641\u06cc\u0633 \u06a9\u06d2 \u067e\u06cc\u0686\u06be\u06d2 \u0631\u06a9\u06be\u0646\u06d2 \u06a9\u0627 \u0646\u0638\u0645 \u0648 \u0636\u0628\u0637 \u06c1\u06d2\u06d4<\/p>\n<p>\u062c\u0648 \u0628\u06be\u06cc \u0622\u067e \u0622\u06af\u06d2 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0633 \u0627\u0635\u0648\u0644 \u06a9\u0648 \u0630\u06c1\u0646 \u0645\u06cc\u06ba \u0631\u06a9\u06be\u06cc\u06ba\u06d4 \u0645\u0627\u0688\u0644 \u0628\u062f\u0644 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0628\u062f\u0644 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u062f\u0648\u0631 \u0645\u06cc\u06ba \u06a9\u0686\u06be \u0679\u0648\u0644\u0632 \u0627\u0633 \u0634\u0631\u062d \u0633\u06d2 \u062a\u06cc\u0627\u0631 \u06c1\u0648\u06ba \u06af\u06d2 \u062c\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u0648\u0626\u06cc \u06c1\u06cc\u0646\u0688 \u0628\u06a9 \u0646\u06c1\u06cc\u06ba \u0631\u06a9\u06be \u0633\u06a9\u062a\u06cc\u06d4 \u0627\u0686\u06be\u06d2 \u062a\u0639\u0645\u06cc\u0631\u0627\u062a\u06cc \u0641\u06cc\u0635\u0644\u06d2 \u0627\u0646 \u0633\u0628 \u06a9\u0648 \u067e\u06cc\u0686\u06be\u06d2 \u0686\u06be\u0648\u0691 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u0633 \u06c1\u06cc\u0646\u0688 \u0628\u06a9 \u06a9\u0627 \u0645\u06a9\u0645\u0644 \u06a9\u0648\u0688 github.com\/sandeepmb\/freecodecamp-multi-agent-ai-system \u067e\u0631 \u062f\u0633\u062a\u06cc\u0627\u0628 \u06c1\u06d2\u06d4 \u06a9\u0644\u0648\u0646\u060c \u062f\u0648\u0691\u0646\u0627\u060c \u06a9\u0627\u0646\u0679\u0627\u060c \u067e\u06cc\u0645\u0627\u0646\u06c1\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0627\u0646 \u0646\u0645\u0648\u0646\u0648\u06ba \u06a9\u06cc \u0628\u0646\u06cc\u0627\u062f \u067e\u0631 \u06a9\u0648\u0626\u06cc \u062f\u0644\u0686\u0633\u067e \u0686\u06cc\u0632 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0645\u06cc\u06ba \u0648\u0627\u0642\u0639\u06cc \u0627\u0633 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0633\u0646\u0646\u0627 \u0686\u0627\u06c1\u0648\u06ba \u06af\u0627\u06d4<\/p>\n<p>\u0627\u0628 \u062c\u0627\u0624 \u06a9\u0686\u06be \u0628\u0646\u0627 \u0644\u0648\u06d4<\/p>\n<h2 id=\"heading-appendix-a-framework-comparison\">\u0636\u0645\u06cc\u0645\u06c1 A: \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u0627 \u0645\u0648\u0627\u0632\u0646\u06c1<\/h2>\n<p>\u0627\u0633 \u06c1\u06cc\u0646\u0688 \u0628\u06a9 \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0627\u0648\u0631 \u062c\u06c1\u0627\u06ba \u06c1\u0631 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0645\u0646\u0627\u0633\u0628 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u062c\u062f\u0648\u0644 2026 \u06a9\u06d2 \u0627\u0648\u0627\u0626\u0644 \u062a\u06a9 \u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u0646\u0638\u0627\u0645 \u06a9\u06cc \u062d\u0627\u0644\u062a \u06a9\u0648 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0645\u062e\u0635\u0648\u0635 \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u062a\u0628\u062f\u06cc\u0644 \u06c1\u0648 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06cc\u06d4 \u0645\u0642\u0635\u062f\u06cc \u0642\u06cc\u0627\u0633\u0627\u062a \u0645\u0633\u062a\u062d\u06a9\u0645 \u0631\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<table>\n<thead>\n<tr>\n<th>\u06a9\u0646\u06a9\u0627\u0644<\/th>\n<th>\u06cc\u06c1 \u06a9\u06cc\u0627 \u06c1\u06d2<\/th>\n<th>\u0645\u06cc\u06ba \u0627\u0633\u06d2 \u06a9\u0628 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0648\u06ba\u061f<\/th>\n<th>\u0627\u06af\u0631 \u0622\u067e \u0627\u0633\u06d2 \u0686\u06be\u0648\u0691 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>\u0644\u06cc\u0646\u06af\u0631\u0627\u0641<\/strong><\/td>\n<td>\u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679\u0633\u060c \u0645\u0634\u0631\u0648\u0637 \u0631\u0648\u0679\u0646\u06af\u060c \u0627\u0648\u0631 \u0628\u0646\u06cc\u0627\u062f\u06cc HITL \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0633\u0679\u06cc\u0679\u0641\u0648\u0644 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627 \u06af\u0631\u0627\u0641<\/td>\n<td>\u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0648\u0631\u06a9 \u0641\u0644\u0648 \u062c\u06c1\u0627\u06ba \u0631\u06cc\u0627\u0633\u062a\u06cc \u0627\u0633\u062a\u0642\u0627\u0645\u062a \u0627\u0648\u0631 \u062a\u0639\u06cc\u06cc\u0646\u0627\u062a\u06cc \u0631\u0648\u0679\u0646\u06af \u0627\u06c1\u0645 \u06c1\u06cc\u06ba\u06d4<\/td>\n<td>\u0633\u0627\u062f\u06c1 \u0648\u0627\u062d\u062f \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627 \u06a9\u0627\u0645 \u062c\u0633 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u0631\u06cc\u0627\u0633\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/td>\n<\/tr>\n<tr>\n<td><strong>\u0639\u0645\u0644\u06c1 AI<\/strong><\/td>\n<td>\u0627\u0639\u0644\u0627\u0646\u0627\u062a\u06cc \u0679\u06cc\u0645\u0648\u06ba \u0627\u0648\u0631 \u06a9\u0627\u0645\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u0631\u062f\u0627\u0631 \u067e\u0631 \u0645\u0628\u0646\u06cc \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9<\/td>\n<td>\u06a9\u0631\u062f\u0627\u0631 \u067e\u0631 \u0645\u0628\u0646\u06cc \u0627\u06cc\u062c\u0646\u0679 \u062a\u0639\u0627\u0648\u0646 \u06a9\u06cc \u062a\u06cc\u0632 \u0631\u0641\u062a\u0627\u0631 \u067e\u0631\u0648\u0679\u0648 \u0679\u0627\u0626\u067e\u0646\u06af\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0627 \u0645\u0639\u0627\u0645\u0644\u06c1 \u06c1\u06d2 \u062c\u0648 \u0642\u062f\u0631\u062a\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0641\u0644\u0627\u0626\u0679 \u0627\u0679\u06cc\u0646\u0688\u0646\u0679 \u0627\u0633\u062a\u0639\u0627\u0631\u06c1 \u067e\u0631 \u0641\u0679 \u0628\u06cc\u0679\u06be\u062a\u0627 \u06c1\u06d2\u06d4<\/td>\n<td>\u067e\u06cc\u0686\u06cc\u062f\u06c1 \u0628\u0631\u0627\u0646\u0686\u0646\u06af \u0645\u0646\u0637\u0642 \u06cc\u0627 \u062d\u0633\u0628 \u0636\u0631\u0648\u0631\u062a \u06a9\u0646\u0679\u0631\u0648\u0644 \u0641\u0644\u0648\u06d4 \u0639\u0645\u0644\u06c1 \u062a\u062c\u0631\u06cc\u062f \u0631\u0627\u0633\u062a\u06d2 \u0645\u06cc\u06ba \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2.<\/td>\n<\/tr>\n<tr>\n<td><strong>\u062e\u0648\u062f \u06a9\u0627\u0631 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u067e\u06cc\u062f\u0627<\/strong><\/td>\n<td>\u06af\u0631\u0648\u067e \u0686\u06cc\u0679 \u06a9\u06d2 \u0646\u0645\u0648\u0646\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u0627\u0626\u06cc\u06a9\u0631\u0648\u0633\u0627\u0641\u0679 \u06a9\u0627 \u0645\u06a9\u0627\u0644\u0645\u0627\u062a\u06cc \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9<\/td>\n<td>\u062a\u062d\u0642\u06cc\u0642\u06cc \u0627\u0648\u0631 \u062a\u062d\u0642\u06cc\u0642\u06cc \u06a9\u0627\u0645\u06d4 \u0628\u0627\u062a \u0686\u06cc\u062a \u06a9\u06d2 \u0646\u0645\u0648\u0646\u0648\u06ba \u067e\u0631 \u0645\u0628\u0646\u06cc \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0645\u0646\u0638\u0631\u0646\u0627\u0645\u06d2\u06d4<\/td>\n<td>\u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0646\u0638\u0627\u0645 \u062c\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u062e\u062a \u06a9\u0646\u0679\u0631\u0648\u0644 \u06a9\u06d2 \u0628\u06c1\u0627\u0624 \u0627\u0648\u0631 \u0648\u0627\u0636\u062d \u0631\u06cc\u0627\u0633\u062a\u06cc \u0627\u0646\u062a\u0638\u0627\u0645 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/td>\n<\/tr>\n<tr>\n<td><strong>\u0644\u0627\u0645\u0627 \u0627\u0646\u0688\u06cc\u06a9\u0633<\/strong><\/td>\n<td>RAG - \u0637\u0627\u0642\u062a\u0648\u0631 \u0688\u06cc\u0679\u0627 \u0627\u06a9\u0679\u06be\u0627 \u06a9\u0631\u0646\u06d2 \u0627\u0648\u0631 \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u06a9\u06cc \u0635\u0644\u0627\u062d\u06cc\u062a\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u067e\u06c1\u0644\u0627 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9<\/td>\n<td>\u0633\u0633\u0679\u0645 \u062c\u06c1\u0627\u06ba \u063a\u06cc\u0631 \u0633\u0627\u062e\u062a\u06c1 \u0688\u06cc\u0679\u0627 \u06a9\u06cc \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u0627\u06cc\u06a9 \u0627\u06c1\u0645 \u0645\u0633\u0626\u0644\u06c1 \u06c1\u06d2\u06d4<\/td>\n<td>\u062e\u0627\u0644\u0635 \u0627\u06cc\u062c\u0646\u0679 \u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0634\u0646\u06d4 \u0622\u067e \u0634\u0627\u06cc\u062f LangGraph \u06cc\u0627 \u0627\u0633 \u0633\u06d2 \u0645\u0644\u062a\u06cc \u062c\u0644\u062a\u06cc \u06a9\u0648\u0626\u06cc \u0686\u06cc\u0632 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4<\/td>\n<\/tr>\n<tr>\n<td><strong>\u0644\u06cc\u0646\u06af \u0686\u06cc\u0646<\/strong><\/td>\n<td>LLM \u0627\u06cc\u067e \u06a9\u06d2 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0627\u0635\u0648\u0644\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0648\u0633\u06cc\u0639 \u0679\u0648\u0644 \u06a9\u0679\u06d4 \u0648\u06c1 \u0628\u0646\u06cc\u0627\u062f \u062c\u0633 \u067e\u0631 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0628\u06cc\u0679\u06be\u0627 \u06c1\u06d2\u06d4<\/td>\n<td>\u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0646\u0686\u0644\u06d2 \u062f\u0631\u062c\u06d2 \u06a9\u06d2 \u0628\u0644\u0688\u0646\u06af \u0628\u0644\u0627\u06a9\u0633 (\u067e\u0631\u0627\u0645\u067e\u0679\u0633\u060c \u0622\u0624\u0679 \u067e\u0679 \u067e\u0627\u0631\u0633\u0631\u060c \u0686\u06cc\u0646\u0632)<\/td>\n<td>\u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0634\u0646 \u062e\u0648\u062f\u06d4 \u06af\u0631\u0627\u0641 \u067e\u0631 \u0645\u0628\u0646\u06cc \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/td>\n<\/tr>\n<tr>\n<td><strong>\u0627\u06cc\u0645 \u0633\u06cc \u067e\u06cc<\/strong> (\u06a9\u0648\u0688)<\/td>\n<td>\u0645\u0627\u0688\u0644 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644\u06d4 \u0645\u0639\u06cc\u0627\u0631\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0679\u0648\u0644 \u0627\u0646\u0679\u0631\u0641\u06cc\u0633<\/td>\n<td>\u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0627\u06cc\u0633\u0627 \u0646\u0638\u0627\u0645 \u062c\u06c1\u0627\u06ba \u0679\u0648\u0644 \u06a9\u0627 \u0646\u0641\u0627\u0630 \u0644\u0627\u0632\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0642\u0627\u0628\u0644 \u062a\u0628\u0627\u062f\u0644\u06c1 \u0627\u0648\u0631 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0645\u06cc\u06ba \u062f\u0648\u0628\u0627\u0631\u06c1 \u0642\u0627\u0628\u0644 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06c1\u0648\u06d4<\/td>\n<td>Python \u0641\u0646\u06a9\u0634\u0646\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0648\u0646 \u0622\u0641 \u0627\u0646\u0679\u0631\u0646\u0644 \u0679\u0648\u0644 \u0679\u06be\u06cc\u06a9 \u0633\u06d2 \u06a9\u0627\u0645 \u06a9\u0631 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4<\/td>\n<\/tr>\n<tr>\n<td><strong>A2A<\/strong> (\u06a9\u0648\u0688)<\/td>\n<td>\u0627\u06cc\u062c\u0646\u0679 \u0633\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644\u06d4 HTTP \u067e\u0631 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0645\u06cc\u06ba \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0648\u0622\u0631\u0688\u06cc\u0646\u06cc\u0634\u0646<\/td>\n<td>\u062a\u0645\u0627\u0645 \u0679\u06cc\u0645\u0648\u06ba \u06cc\u0627 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0645\u06cc\u06ba \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0645\u0631\u0628\u0648\u0637 \u06a9\u0631\u06cc\u06ba\u061b \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u06a9\u0648 \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u062a\u0639\u06cc\u0646\u0627\u062a \u06a9\u0631\u06cc\u06ba\u06d4<\/td>\n<td>\u06cc\u06c1 \u0645\u0636\u0628\u0648\u0637\u06cc \u0633\u06d2 \u062c\u0648\u0691\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u06cc\u062c\u0646\u0679 \u06c1\u06cc\u06ba \u062c\u0648 \u06c1\u0645\u06cc\u0634\u06c1 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u062a\u0639\u06cc\u0646\u0627\u062a \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0627\u0644\u0632 \u0622\u0633\u0627\u0646 \u06c1\u06cc\u06ba\u06d4<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0679\u0631 \u06a9\u06d2 \u0627\u0646\u062a\u062e\u0627\u0628 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0646\u06af\u0648\u0679\u06be\u06d2 \u06a9\u0627 \u0627\u0635\u0648\u0644 \u06c1\u06d2: \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u06a9\u06cc \u0637\u0627\u0642\u062a\u06cc\u06ba (\u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679\u0633\u060c \u0628\u0631\u06cc\u06a9\/\u0631\u06cc\u0632\u06cc\u0648\u0645\u060c \u0648\u0627\u0636\u062d \u0631\u06cc\u0627\u0633\u062a\u06cc \u0645\u0639\u0627\u06c1\u062f\u06d2) \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0636\u0631\u0648\u0631\u06cc \u06c1\u06cc\u06ba\u06d4 \u062c\u0628 \u06a9\u0631\u062f\u0627\u0631 \u067e\u0631 \u0645\u0628\u0646\u06cc \u0627\u0633\u062a\u0639\u0627\u0631\u06d2 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0648 \u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631 \u0646\u0642\u0634\u06c1 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 CrewAI \u0628\u06c1\u062a \u0627\u0686\u06be\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0622\u0679\u0648\u062c\u06cc\u0646 \u06a9\u0627 \u06af\u0631\u0648\u067e \u0686\u06cc\u0679 \u067e\u06cc\u0679\u0631\u0646 \u062a\u062d\u0642\u06cc\u0642 \u0627\u0648\u0631 \u062a\u0644\u0627\u0634 \u06a9\u06d2 \u06a9\u0627\u0645\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u062e\u062a \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u06a9\u0646\u0679\u0631\u0648\u0644 \u0641\u0644\u0648 \u0633\u06d2 \u0628\u06c1\u062a\u0631 \u06c1\u06d2\u06d4<\/p>\n<p>\u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u06cc \u062a\u0631\u062c\u06cc\u062d\u0627\u062a \u06a9\u0648 \u0645\u0633\u0626\u0644\u06c1 \u06a9\u06cc \u0627\u0642\u0633\u0627\u0645 \u06a9\u0648 \u0627\u0648\u0648\u0631 \u0631\u0627\u0626\u06cc\u0688 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u0646\u06c1 \u062f\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0622\u067e \u06a9\u0627 \u0645\u0633\u0626\u0644\u06c1 \u06af\u0631\u0627\u0641 \u06c1\u06d2 \u062a\u0648 \u0644\u06cc\u0646\u06af \u06af\u0631\u0627\u0641 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0645\u0633\u0626\u0644\u06c1 \u06af\u0641\u062a\u06af\u0648 \u06a9\u0627 \u06c1\u06d2\u060c \u062a\u0648 AutoGen \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>MCP \u0627\u0648\u0631 A2A \u0627\u0646 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u0627 \u0645\u0642\u0627\u0628\u0644\u06c1 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0648\u06c1 \u0630\u06cc\u0644 \u0645\u06cc\u06ba \u0627\u0646\u0636\u0645\u0627\u0645 \u06a9\u06cc \u067e\u0631\u062a\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 LangGraph \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u0628\u0646\u0627\u0626\u06cc\u06ba\u060c \u0627\u0633\u06d2 A2A \u0633\u0631\u0648\u0633 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u0648\u0631 MCP \u06a9\u0648 \u0628\u0637\u0648\u0631 \u0679\u0648\u0644 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0634\u0646 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0633\u06d2 \u0642\u0637\u0639 \u0646\u0638\u0631 \u0622\u067e \u062c\u0648 \u0628\u06be\u06cc \u0627\u0646\u062a\u062e\u0627\u0628 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0622\u067e \u0627\u0646 \u062a\u06cc\u0646\u0648\u06ba \u06a9\u0648 \u0645\u06a9\u0633 \u0627\u0648\u0631 \u0645\u06cc\u0686 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-appendix-b-model-selection-guide\">\u0636\u0645\u06cc\u0645\u06c1 B: \u0645\u0627\u0688\u0644 \u0633\u0644\u06cc\u06a9\u0634\u0646 \u06af\u0627\u0626\u06cc\u0688<\/h2>\n<p>\u0627\u0633 \u0646\u0638\u0627\u0645 \u0645\u06cc\u06ba \u062a\u0645\u0627\u0645 \u0627\u06cc\u062c\u0646\u0679 \u0645\u0642\u0627\u0645\u06cc \u062a\u062e\u0645\u06cc\u0646\u06c1 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0648\u0644\u0627\u0645\u0627 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0645\u0627\u0688\u0644 \u06a9\u0627 \u0627\u0646\u062a\u062e\u0627\u0628 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0627 \u062a\u0639\u06cc\u0646 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u06cc\u0627 \u0679\u0648\u0644 \u06a9\u0627\u0644\u0632 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 7B \u067e\u06cc\u0631\u0627\u0645\u06cc\u0679\u0631\u0632 \u0648\u0627\u0644\u06d2 \u0645\u0627\u0688\u0644 \u063a\u0644\u0637 JSON \u0627\u0648\u0631 \u0679\u0648\u0644 \u06a9\u06d2 \u0646\u0627\u0645\u0648\u06ba \u06a9\u0648 \u0627\u0633 \u0645\u0642\u0627\u0645 \u062a\u06a9 \u067e\u06c1\u0646\u0686\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-recommendations-by-vram\">VRAM \u0633\u06d2 \u0633\u0641\u0627\u0631\u0634\u0627\u062a<\/h3>\n<table>\n<thead>\n<tr>\n<th>VRAM<\/th>\n<th>\u0645\u0627\u0688\u0644<\/th>\n<th>\u067e\u0644 \u06a9\u0645\u0627\u0646\u0688<\/th>\n<th>\u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u06c1\u062a\u0631\u06cc\u0646 \u0645\u0648\u0632\u0648\u06ba \u06c1\u06d2\u06d4<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>8 \u062c\u06cc \u0628\u06cc<\/td>\n<td><code>qwen2.5:7b<\/code><\/td>\n<td><code>ollama pull qwen2.5:7b<\/code><\/td>\n<td>\u06cc\u0648\u0646\u06cc\u0648\u0631\u0633\u0644 \u0627\u0648\u0631 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0679\u0648\u0644 \u06a9\u0627\u0644\u0646\u06af<\/td>\n<\/tr>\n<tr>\n<td>8 \u062c\u06cc \u0628\u06cc<\/td>\n<td><code>qwen3:8b<\/code><\/td>\n<td><code>ollama pull qwen3:8b<\/code><\/td>\n<td>\u0628\u06c1\u062a\u0631 \u0627\u0646\u062f\u0627\u0632\u06c1\u060c \u0648\u06c1\u06cc VRAM \u06a9\u0644\u0627\u0633<\/td>\n<\/tr>\n<tr>\n<td>24 \u062c\u06cc \u0628\u06cc<\/td>\n<td><code>qwen2.5-coder:32b<\/code><\/td>\n<td><code>ollama pull qwen2.5-coder:32b<\/code><\/td>\n<td>\u0627\u0633\u06d2 \u0627\u0633 \u062f\u0631\u062c\u06d2 \u06a9\u0627 \u0628\u06c1\u062a\u0631\u06cc\u0646 \u0679\u0648\u0644 \u06a9\u06c1\u06cc\u06ba\u06d4<\/td>\n<\/tr>\n<tr>\n<td>24 \u062c\u06cc \u0628\u06cc<\/td>\n<td><code>qwen3:32b<\/code><\/td>\n<td><code>ollama pull qwen3:32b<\/code><\/td>\n<td>\u0627\u0633 \u06a9\u0644\u0627\u0633 \u0645\u06cc\u06ba \u0645\u062c\u0645\u0648\u0639\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0628\u06c1\u062a\u0631\u06cc\u0646<\/td>\n<\/tr>\n<tr>\n<td>\u0635\u0631\u0641 \u0633\u06cc \u067e\u06cc \u06cc\u0648<\/td>\n<td><code>qwen2.5:7b<\/code> (Q4_K_M)<\/td>\n<td><code>ollama pull qwen2.5:7b<\/code><\/td>\n<td>\u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c 5 \u0633\u06d2 10 \u06af\u0646\u0627 \u0633\u0633\u062a<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>macOS \u067e\u0631<\/strong> Apple Silicon \u0645\u0631\u0628\u0648\u0637 \u0645\u06cc\u0645\u0648\u0631\u06cc CPU \u0627\u0648\u0631 GPU \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0645\u0634\u062a\u0631\u06a9 \u06c1\u06d2\u06d4 16 \u062c\u06cc \u0628\u06cc \u0645\u0631\u0628\u0648\u0637 \u0645\u06cc\u0645\u0648\u0631\u06cc \u0645\u06cc\u06a9 \u0645\u0627\u0688\u0644 \u062a\u0642\u0631\u06cc\u0628\u0627\u064b 8 \u062c\u06cc \u0628\u06cc \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0622\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u06cc\u067e\u0644 \u0645\u06cc\u0646\u0648 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba \u2192 \u0627\u0633 \u0645\u06cc\u06a9 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u2192 \u0686\u067e \u0645\u0639\u0644\u0648\u0645\u0627\u062a\u06d4<\/p>\n<p><strong>\u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0645 \u0627\u0632 \u06a9\u0645 \u0642\u0627\u0628\u0644 \u0639\u0645\u0644 \u062f\u0631\u062c\u06d2: 7B \u067e\u06cc\u0631\u0627\u0645\u06cc\u0679\u0631\u0632\u06d4<\/strong> \u0630\u06cc\u0644\u06cc 7B \u0645\u0627\u0688\u0644 \u0686\u06cc\u0679 \u06a9\u0648 \u0627\u0686\u06be\u06cc \u0637\u0631\u062d \u0633\u06d2 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0642\u0627\u0628\u0644 \u0628\u06be\u0631\u0648\u0633\u06c1 \u0679\u0648\u0644 \u06a9\u0627\u0644\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 JSON \u0641\u0627\u0631\u0645\u06cc\u0679 \u06a9\u06cc \u0628\u06c1\u062a \u0633\u0627\u0631\u06cc \u063a\u0644\u0637\u06cc\u0627\u06ba \u067e\u06cc\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u06c1 <code>format=\"json\"<\/code> \u0639\u0644\u0627\u0645\u06c1 \u06a9\u06cc \u0645\u062c\u0628\u0648\u0631\u06cc\u0627\u06ba \u0645\u062f\u062f \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u062f\u0631\u0633\u062a JSON \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0646\u0641\u0631\u0646\u0633 \u0679\u0627\u0626\u0645 \u06a9\u06cc \u0636\u0645\u0627\u0646\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u0644\u06cc\u06a9\u0646 \u0645\u0627\u0688\u0644 \u0627\u0628\u06be\u06cc \u0628\u06be\u06cc \u062a\u06cc\u0627\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 <em>\u0645\u0639\u0646\u06cc \u062e\u06cc\u0632<\/em> JSON \u0642\u0627\u0628\u0644 \u062a\u062c\u0632\u06cc\u06c1 JSON \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u06cc\u0631\u0627\u0645\u06cc\u0679\u0631 \u06a9\u06cc \u06af\u0646\u062a\u06cc 7 \u0628\u0644\u06cc\u0646 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u062f\u0631\u06a9\u0627\u0631 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-temperature-settings-used-in-this-system\">\u0627\u0633 \u0646\u0638\u0627\u0645 \u0645\u06cc\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06cc \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628\u0627\u062a<\/h3>\n<p>\u06cc\u06c1 \u0648\u06c1 \u062a\u0631\u062a\u06cc\u0628\u0627\u062a \u06c1\u06cc\u06ba \u062c\u0648 \u06c1\u0631 \u0627\u06cc\u062c\u0646\u0679 \u067e\u0631 \u0644\u0627\u06af\u0648 \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0627\u0633\u06d2 \u06a9\u0628\u06be\u06cc \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0646\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4 <code>temperature > 0.5<\/code> \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062c\u0648 \u0633\u0627\u062e\u062a\u06cc JSON \u0622\u0624\u0679 \u067e\u0679 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u062c\u0632\u06cc\u06c1 \u0646\u0627\u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0628\u0627\u0631 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\"># Structured output: Curriculum Planner, Quiz Generator grading\nChatOllama(temperature=0.1, format=\"json\")\n\n# Tool-calling loop: Explainer\nChatOllama(temperature=0.3)\n\n# Creative generation: Quiz Generator questions, Progress Coach\nChatOllama(temperature=0.4, format=\"json\")\n\n# Deterministic evaluation: DeepEval OllamaJudge\nChatOllama(temperature=0.0)\n<\/code><\/pre>\n<p><strong>\u0645\u062e\u062a\u0644\u0641 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u06a9\u06cc\u0648\u06ba \u0627\u06c1\u0645 \u06c1\u06cc\u06ba:<\/strong> \u0627\u06cc\u06a9 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f \u0627\u06cc\u062c\u0646\u0679 \u06c1\u0631 \u0627\u0633 \u0686\u06cc\u0632 \u0633\u06d2 \u0633\u0645\u062c\u06be\u0648\u062a\u06c1 \u06a9\u0631\u06d2 \u06af\u0627 \u062c\u0648 \u0627\u0633\u06d2 \u0633\u0646\u0628\u06be\u0627\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u0633\u0627\u062e\u062a\u06cc JSON \u0645\u0646\u0635\u0648\u0628\u0648\u06ba \u06a9\u0648 \u0645\u0633\u062a\u0642\u0644 \u0645\u0632\u0627\u062c\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 0.1 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u062a\u062e\u0644\u06cc\u0642\u06cc \u0633\u0648\u0627\u0644\u0627\u062a \u06a9\u06cc \u062a\u062e\u0644\u06cc\u0642 \u062a\u0646\u0648\u0639 \u06a9\u06d2 \u0644\u06cc\u06d2 0.4 \u06a9\u0627 \u0641\u0627\u0626\u062f\u06c1 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u0645\u0646\u0635\u0641\u0627\u0646\u06c1 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 0.1 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4<\/p>\n<p>\u062c\u0628 \u0627\u06cc\u06a9 \u0627\u06cc\u062c\u0646\u0679 \u062a\u06cc\u0646\u0648\u06ba \u06a9\u0627\u0645 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 <code>temperature=0.25<\/code>\u0645\u0646\u0635\u0648\u0628\u06c1 \u0628\u0646\u062f\u06cc \u062a\u062c\u0632\u06cc\u06c1 \u06a9\u06cc \u063a\u0644\u0637\u06cc\u0627\u06ba \u067e\u06cc\u062f\u0627 \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u0633\u0648\u0627\u0644 \u067e\u06cc\u062f\u0627 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0628\u0627\u0631 \u0628\u0627\u0631 \u0633\u0648\u0627\u0644\u0627\u062a \u067e\u06cc\u062f\u0627 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0645\u062e\u062a\u0644\u0641 \u062f\u0631\u062c\u06c1 \u062d\u0631\u0627\u0631\u062a \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0633\u06d2 \u0645\u062a\u0639\u062f\u062f \u0627\u06cc\u062c\u0646\u0679\u0648\u06ba \u0645\u06cc\u06ba \u062a\u0642\u0633\u06cc\u0645 \u06a9\u0631\u0646\u0627 \u0627\u0633 \u0646\u0638\u0627\u0645 \u06a9\u06d2 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0627 \u0627\u06cc\u06a9 \u0627\u06c1\u0645 \u062c\u0648\u0627\u0632 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-switching-models\">\u0633\u0648\u0626\u0686\u0646\u06af \u0645\u0627\u0688\u0644<\/h3>\n<p>\u062a\u0628\u062f\u06cc\u0644\u06cc <code>OLLAMA_MODEL<\/code> \u06a9\u0648 <code>.env<\/code>. \u06a9\u0648\u0688 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644\u06cc \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-bash\"># .env\nOLLAMA_MODEL=qwen2.5-coder:32b\nOLLAMA_BASE_URL=http:\/\/localhost:11434\n<\/code><\/pre>\n<p>\u067e\u06be\u0631 \u0645\u0627\u0688\u0644 \u062f\u0631\u0622\u0645\u062f \u06a9\u0631\u06cc\u06ba \u0627\u06af\u0631 \u0622\u067e \u0646\u06d2 \u062f\u0631\u062c \u0630\u06cc\u0644 \u06a9\u0627\u0645 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-bash\">ollama pull qwen2.5-coder:32b\n<\/code><\/pre>\n<p>\u0686\u0627\u0631\u0648\u06ba \u0627\u06cc\u062c\u0646\u0679 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0646\u0626\u06d2 \u0645\u0627\u0688\u0644 \u06a9\u0648 \u0627\u067e\u0646\u06cc \u0627\u06af\u0644\u06cc \u062f\u0648\u0691 \u0645\u06cc\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-eval-test-thresholds-by-model\">\u0645\u0627\u0688\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u062e\u0635\u0648\u0635 \u062c\u0627\u0646\u0686 \u06a9\u06cc \u062d\u062f<\/h3>\n<p>\u062f\u06c1\u0644\u06cc\u0632 <code>tests\/test_eval.py<\/code> 7B \u0645\u0627\u0688\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 0.6 \u067e\u0631 \u06a9\u06cc\u0644\u06cc\u0628\u0631\u06cc\u0679 \u06a9\u06cc\u0627 \u06af\u06cc\u0627\u06d4 \u0628\u0691\u06d2 \u0645\u0627\u0688\u0644\u0632 \u0645\u06cc\u06ba \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 \u0632\u06cc\u0627\u062f\u06c1 \u0627\u0633\u06a9\u0648\u0631 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0627\u067e \u06af\u0631\u06cc\u0688 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0633\u062e\u062a \u06a9\u0648\u0627\u0644\u0679\u06cc \u06af\u06cc\u0679 \u0631\u06a9\u06be\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631\u06cc\u06ba:<\/p>\n<table>\n<thead>\n<tr>\n<th>\u0645\u0627\u0688\u0644 \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc<\/th>\n<th>\u0648\u0641\u0627\u062f\u0627\u0631\u06cc<\/th>\n<th>\u0645\u0637\u0627\u0628\u0642\u062a<\/th>\n<th>\u0633\u0648\u0627\u0644 \u06a9\u0627 \u0645\u0639\u06cc\u0627\u0631<\/th>\n<th>\u0645\u06cc\u0645\u0648<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>7-8B \u0645\u0642\u0627\u0645\u06cc<\/td>\n<td>0.65-0.80<\/td>\n<td>0.70-0.85<\/td>\n<td>0.65-0.80<\/td>\n<td>0.6 \u06a9\u06cc \u0688\u06cc\u0641\u0627\u0644\u0679 \u062d\u062f<\/td>\n<\/tr>\n<tr>\n<td>32B \u0645\u0642\u0627\u0645\u06cc<\/td>\n<td>0.80-0.90<\/td>\n<td>0.85-0.95<\/td>\n<td>0.80-0.90<\/td>\n<td>\u0622\u067e \u062d\u062f \u06a9\u0648 0.75 \u062a\u06a9 \u0628\u0691\u06be\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/td>\n<\/tr>\n<tr>\n<td>GPT-4 \/ \u06a9\u0644\u0627\u0688<\/td>\n<td>0.85-0.98<\/td>\n<td>0.90-0.98<\/td>\n<td>0.85-0.95<\/td>\n<td>\u0622\u067e \u062d\u062f \u06a9\u0648 0.85 \u062a\u06a9 \u0628\u0691\u06be\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u0627\u067e\u0646\u06cc \u062d\u062f \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0639\u0627\u0645 \u0633\u06a9\u0648\u0631 \u0633\u06d2 \u062a\u0642\u0631\u06cc\u0628\u0627\u064b 10% \u06a9\u0645 \u067e\u0631 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0627\u067e\u0646\u06d2 \u0639\u0627\u0645 \u0627\u0633\u06a9\u0648\u0631 \u06a9\u06d2 \u0628\u06c1\u062a \u0642\u0631\u06cc\u0628 \u067e\u06c1\u0646\u0686 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u06a9\u0627 \u0627\u0645\u062a\u062d\u0627\u0646 \u063a\u06cc\u0631 \u0645\u0633\u062a\u062d\u06a9\u0645 \u06c1\u0648\u06af\u0627\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0628\u06c1\u062a \u062f\u0648\u0631 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2 \u062a\u0648 \u0622\u067e \u0631\u062c\u0639\u062a \u0633\u06d2 \u0645\u062d\u0631\u0648\u0645 \u06c1\u0648\u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<h2 id=\"heading-appendix-c-production-hardening-checklist\">\u0636\u0645\u06cc\u0645\u06c1 C: \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u0628\u0691\u06be\u0627\u0646\u06d2 \u06a9\u06cc \u0686\u06cc\u06a9 \u0644\u0633\u0679<\/h2>\n<p>\u0644\u06a9\u06be\u0627 \u06c1\u0648\u0627 \u0633\u0633\u0679\u0645 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0644\u06cc\u0648\u0644 \u06c1\u06d2\u06d4 \u067e\u06cc\u0645\u0627\u0646\u06d2 \u067e\u0631 \u062a\u0639\u06cc\u0646\u0627\u062a \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u0633 \u0686\u06cc\u06a9 \u0644\u0633\u0679 \u06a9\u0627 \u062c\u0627\u0626\u0632\u06c1 \u0644\u06cc\u06ba\u06d4 \u06c1\u0631 \u0622\u0626\u0679\u0645 \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u0645\u0648\u0688 \u067e\u0631 \u0646\u0642\u0634\u06c1 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u06a9\u06cc \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-orchestration-and-state\">\u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0634\u0646 \u0627\u0648\u0631 \u0631\u06cc\u0627\u0633\u062a\u06cc\u06ba\u06d4<\/h3>\n<ul>\n<li>\n<p>[ ] <strong>SQLite \u06a9\u0648 PostgreSQL \u0633\u06d2 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u0627<\/strong> \u0686\u0648\u06a9\u06cc\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4 SQLite \u0627\u06cc\u06a9 \u06c1\u06cc \u0639\u0645\u0644 \u0645\u06cc\u06ba \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0645\u062a\u0639\u062f\u062f \u0645\u062b\u0627\u0644\u0648\u06ba \u06a9\u06cc \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0648\u0633\u0679\u06af\u0631\u06cc\u0633 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0648\u0631\u0698\u0646 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> <code>AgentState<\/code> <strong>\u062e\u0627\u06a9\u06c1<\/strong> \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0637\u06d2 \u0634\u062f\u06c1 \u0627\u0642\u062f\u0627\u0631 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u0641\u06cc\u0644\u0688 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u062d\u0630\u0641 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u0627\u067e\u0646\u06d2 \u0631\u06cc\u0644\u06cc\u0632 \u0633\u0627\u0626\u06cc\u06a9\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06c1\u0679\u0627\u0626\u06d2 \u06af\u0626\u06d2 \u0641\u06cc\u0644\u0688\u0632 \u06a9\u0627 \u0645\u0632\u06cc\u062f \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0646\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0627\u0633\u06a9\u06cc\u0645\u0627 \u0645\u0646\u062a\u0642\u0644\u06cc \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0622\u067e \u06a9\u06cc \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u06d2 \u062d\u0635\u06d2 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631\u06d4 \u062c\u0627\u0631\u06cc \u0648\u0631\u06a9 \u0641\u0644\u0648 \u06a9\u0648 \u0631\u0648\u0644\u0646\u06af \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc\u0648\u06ba \u06a9\u06d2 \u0628\u0639\u062f \u0628\u06be\u06cc \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u0627 \u062c\u0627\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0627\u06cc\u06a9 \u0648\u0627\u0636\u062d \u0679\u0627\u0626\u0645 \u0622\u0624\u0679 \u0628\u062c\u0679 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u06c1\u0631 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0679\u0631 \u0633\u06d2 \u062a\u0645\u0627\u0645 \u0688\u0627\u0624\u0646 \u0627\u0633\u0679\u0631\u06cc\u0645 \u0633\u0631\u0648\u0633\u0632 \u062a\u06a9 \u0679\u0627\u0626\u0645 \u0622\u0624\u0679 \u06a9\u0627 \u067e\u0631\u0686\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0633\u0631\u06a9\u0679 \u0628\u0631\u06cc\u06a9\u0631 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u062a\u0645\u0627\u0645 \u0628\u06cc\u0631\u0648\u0646\u06cc \u0633\u0631\u0648\u0633 \u06a9\u0627\u0644\u0632 (LLM API\u060c A2A \u0633\u0631\u0648\u0633\u060c MCP \u0633\u0631\u0648\u0631) \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u06cc\u06ba \u0637\u0648\u0641\u0627\u0646 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u062f\u0628\u0627\u0624 \u06a9\u0648 \u0628\u0691\u06be\u0627 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"heading-inference-and-cost\">\u062a\u062e\u0645\u06cc\u0646\u06c1 \u0627\u0648\u0631 \u0644\u0627\u06af\u062a<\/h3>\n<ul>\n<li>\n<p>[ ] <strong>\u0627\u0646\u0641\u0631\u0646\u0633 \u06af\u06cc\u0679 \u0648\u06d2 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0631\u0648\u0679\u0646\u06af<\/strong> (LiteLLM \u06cc\u0627 \u0627\u0633 \u0633\u06d2 \u0645\u0644\u062a\u06cc \u062c\u0644\u062a\u06cc) \u0645\u06cc\u06ba \u0634\u0631\u062d \u0645\u062d\u062f\u0648\u062f\u060c \u0645\u0627\u0688\u0644 \u0645\u062a\u0628\u0627\u062f\u0644\u060c \u0627\u0648\u0631 \u0644\u0627\u06af\u062a \u0641\u06cc \u0633\u06cc\u0634\u0646 \u0679\u0631\u06cc\u06a9\u0646\u06af \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0641\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0679\u0648\u06a9\u0646 \u0628\u062c\u0679 \u0646\u0627\u0641\u0630 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0679\u0631 \u06a9\u06cc \u0633\u0637\u062d \u067e\u0631\u06d4 \u06cc\u06c1 \u0633\u062e\u062a \u067e\u0627\u0628\u0646\u062f\u06cc\u0627\u06ba \u06c1\u06cc\u06ba\u060c \u06c1\u062f\u0627\u06cc\u0627\u062a \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0679\u0648\u067e\u06cc<\/strong> <code>max_iterations<\/code> \u06c1\u0631 \u0679\u0648\u0644 \u06a9\u0627\u0644 \u0644\u0648\u067e \u0645\u06cc\u06ba\u06d4 \u0648\u0636\u0627\u062d\u062a \u06a9\u0646\u0646\u062f\u06c1 \u06c1\u06d2\u06d4 <code>max_iterations=8<\/code>. \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u0626\u06cc\u06ba \u06a9\u06c1 \u06c1\u0631 \u0627\u06cc\u062c\u0646\u0679 \u06a9\u06cc \u062d\u062f\u0648\u062f \u0627\u06cc\u06a9 \u062c\u06cc\u0633\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0641\u06cc \u0633\u06cc\u0634\u0646 \u0644\u0627\u06af\u062a \u06a9\u06cc \u0646\u06af\u0631\u0627\u0646\u06cc \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u062c\u0628 \u0633\u06cc\u0634\u0646 \u0628\u062c\u0679 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u06c1\u0648\u06ba \u062a\u0648 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u0628\u06be\u06cc\u062c\u06cc\u06ba\u06d4 \u062f\u0648\u0633\u0631\u06cc \u0635\u0648\u0631\u062a \u0645\u06cc\u06ba\u060c \u0627\u06cc\u06a9 \u0627\u0644\u062c\u06be\u0646 \u0627\u06cc\u062c\u0646\u0679 \u062e\u0648\u062f \u06a9\u0648 \u063a\u06cc\u0631 \u0645\u0639\u06cc\u0646\u06c1 \u0645\u062f\u062a \u062a\u06a9 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2.<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"heading-observability\">\u0645\u0634\u0627\u06c1\u062f\u06c1<\/h3>\n<ul>\n<li>\n<p>[ ] <strong>\u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u06a9\u0648 \u0645\u0646\u0638\u0645 \u06cc\u0627 \u0627\u0646\u062a\u06c1\u0627\u0626\u06cc \u062f\u0633\u062a\u06cc\u0627\u0628 \u0633\u06cc\u0644\u0641 \u06c1\u0648\u0633\u0679\u0646\u06af \u0645\u06cc\u06ba \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0645\u0642\u0627\u0645\u06cc \u0644\u06cc\u0646\u06af \u0641\u06cc\u0648\u0632 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0679\u0631\u06cc\u0633 \u0648\u0627\u0644\u06cc\u0648\u0645 \u062a\u06a9 \u062a\u0648\u0633\u06cc\u0639 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0633\u06cc\u0634\u0646 \u0644\u06cc\u0648\u0644 \u0679\u0631\u06cc\u0633 \u06a9\u06cc\u067e\u0686\u0631<\/strong> \u0622\u067e \u0633\u0679\u0631\u06a9\u0686\u0631\u0688 \u0679\u06cc\u06af\u0632 (\u06cc\u0648\u0632\u0631 \u0622\u0626\u06cc \u0688\u06cc\u060c \u0641\u06cc\u0686\u0631 \u0641\u0644\u06cc\u06af\u060c \u0645\u0627\u0688\u0644 \u0648\u0631\u0698\u0646) \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06a9\u06d2 \u0641\u0644\u0679\u0631 \u0627\u0648\u0631 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631\u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0627\u0637\u0644\u0627\u0639 \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628\u0627\u062a<\/strong> \u062e\u0631\u0627\u0628\u06cc \u06a9\u06cc \u0634\u0631\u062d\u0648\u06ba \u0645\u06cc\u06ba \u0627\u0636\u0627\u0641\u06d2\u060c \u0679\u0648\u06a9\u0646 \u06a9\u06cc \u0644\u0627\u06af\u062a \u0645\u06cc\u06ba \u0627\u0636\u0627\u0641\u06d2\u060c \u0627\u0648\u0631 \u062a\u0627\u062e\u06cc\u0631 \u0633\u06d2 \u0631\u06cc\u06af\u0631\u06cc\u0634\u0646\u0632 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u062c\u0627\u0646\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0646\u0645\u0648\u0646\u06c1 \u0679\u0631\u06cc\u06a9\u0646\u06af<\/strong> \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u0645\u06cc\u06ba. 100% \u0633\u06cc\u0645\u067e\u0644\u0646\u06af \u0645\u06c1\u0646\u06af\u0627 \u06c1\u06d2\u06d4 \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631\u060c \u063a\u0644\u0637\u06cc \u06a9\u0648 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u067e\u06a9\u0691\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 10 \u0633\u06d2 20 \u0641\u06cc\u0635\u062f \u0646\u0645\u0648\u0646\u06d2 \u06a9\u0627\u0641\u06cc \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0688\u06cc\u0679\u0627 \u06af\u0648\u062f\u0627\u0645 \u0645\u06cc\u06ba \u0679\u0631\u06cc\u0633 \u0628\u0631\u0622\u0645\u062f \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0637\u0648\u06cc\u0644 \u0645\u062f\u062a\u06cc \u062a\u062c\u0632\u06cc\u06c1 \u0627\u0648\u0631 \u0631\u06cc\u06af\u0648\u0644\u06cc\u0679\u0631\u06cc \u0622\u0688\u0679 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0648\u0642\u0641\u06d2 \u0648\u0642\u0641\u06d2 \u0633\u06d2 \u06a9\u0627\u0631\u06a9\u0631\u062f\u06af\u06cc \u06a9\u0627 \u0645\u0638\u0627\u06c1\u0631\u06c1 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"heading-evaluation-and-quality\">\u062a\u0634\u062e\u06cc\u0635 \u0627\u0648\u0631 \u0645\u0639\u06cc\u0627\u0631<\/h3>\n<ul>\n<li>\n<p>[ ] <strong>CI \u067e\u0631 \u0627\u06cc\u06a9 \u062a\u0634\u062e\u06cc\u0635\u06cc \u0633\u0648\u0679 \u0686\u0644\u0627\u0646\u0627<\/strong> \u06c1\u0631 \u0628\u0627\u0631 \u062c\u0628 \u0622\u067e \u062a\u0639\u06cc\u0646\u0627\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u06cc\u0633\u06cc \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc\u0648\u06ba \u06a9\u0648 \u0645\u0633\u062f\u0648\u062f \u06a9\u0631\u06cc\u06ba \u062c\u0648 \u0645\u0639\u06cc\u0627\u0631 \u06a9\u06cc \u062d\u062f \u06a9\u0648 \u067e\u0648\u0631\u0627 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0631\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0679\u06cc\u0633\u0679 \u0633\u06cc\u0679\u0633 \u06a9\u0648 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u06cc\u06ba<\/strong> \u0627\u0686\u06be\u06d2 \u0627\u0646 \u067e\u0679 \u0627\u0648\u0631 \u0645\u062a\u0648\u0642\u0639 \u0622\u0624\u0679 \u067e\u0679\u0633 \u06a9\u0648 \u062c\u0627\u0646\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0645\u0627\u0688\u0644 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644\u06cc \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u0633\u06d2 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0648\u0642\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u0639\u06cc\u0627\u0631 \u06a9\u06d2 \u0645\u06cc\u0679\u0631\u06a9\u0633 \u06a9\u0648 \u0679\u0631\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0628\u062a\u062f\u0631\u06cc\u062c \u0628\u0691\u06be\u0646\u06d2 \u06a9\u0648 \u067e\u06a9\u0691\u0646\u0627 \u0627\u0686\u0627\u0646\u06a9 \u0631\u062c\u0639\u062a \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0634\u06a9\u0644 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0627\u0646\u0633\u0627\u0646\u06cc \u062c\u0627\u0626\u0632\u06d2 \u06a9\u06d2 \u0646\u0645\u0648\u0646\u06d2 \u0644\u06cc\u06ba\u06d4<\/strong> \u0632\u06cc\u0627\u062f\u06c1 \u062e\u0637\u0631\u06d2 \u0648\u0627\u0644\u06d2 \u0641\u06cc\u0635\u0644\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4 \u06cc\u06c1 \u062a\u0645\u0627\u0645 \u0622\u0624\u0679 \u067e\u0679 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u06cc\u06c1 \u0634\u0645\u0627\u0631\u06cc\u0627\u062a\u06cc \u0644\u062d\u0627\u0638 \u0633\u06d2 \u0627\u06c1\u0645 \u0646\u0645\u0648\u0646\u06c1 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"heading-security\">\u0633\u06cc\u06a9\u0648\u0631\u0679\u06cc<\/h3>\n<ul>\n<li>\n<p>[ ] <strong>\u0627\u067e\u0646\u06cc A2A \u0633\u0631\u0648\u0633 \u0645\u06cc\u06ba \u062a\u0635\u062f\u06cc\u0642 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0622\u067e \u06a9\u06d2 \u0645\u0627\u062d\u0648\u0644 \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u0628\u06cc\u0626\u0631\u0631 \u0679\u0648\u06a9\u0646\u060c mTLS\u060c \u06cc\u0627 OAuth\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0622\u0688\u0679 MCP \u0679\u0648\u0644 \u067e\u0631 \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f<\/strong> \u067e\u0627\u062a\u06be \u0646\u06cc\u0648\u06cc\u06af\u06cc\u0634\u0646\u060c \u0627\u0646\u062c\u06cc\u06a9\u0634\u0646\u060c \u0627\u0648\u0631 \u0627\u0633\u062a\u062d\u0642\u0627\u0642 \u0645\u06cc\u06ba \u0627\u0636\u0627\u0641\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4 \u06a9\u06c1 <code>read_study_file<\/code> \u0627\u0633 \u0646\u0638\u0627\u0645 \u06a9\u0627 \u06a9\u0627\u0645 \u067e\u06cc\u0679\u0631\u0646 \u062f\u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>LLM \u0627\u0646 \u067e\u0679 \u06a9\u0648 \u062d\u0630\u0641 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u062c\u0648 \u0628\u06be\u06cc \u0645\u0627\u0688\u0644 \u062f\u06cc\u06a9\u06be\u062a\u0627 \u06c1\u06d2 \u0648\u06c1 \u0627\u0633 \u06a9\u06d2 \u0631\u0648\u06cc\u06d2 \u06a9\u0648 \u0645\u062a\u0627\u062b\u0631 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u0628\u0634\u0645\u0648\u0644 \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u0634\u062f\u06c1 \u0645\u0648\u0627\u062f \u0633\u06d2 \u0628\u0627\u0644\u0648\u0627\u0633\u0637\u06c1 \u0627\u0634\u0627\u0631\u06d2 \u062f\u0627\u062e\u0644 \u06a9\u0631\u0646\u0627\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0633\u0679\u0631\u06a9\u0686\u0631\u0688 \u0622\u0624\u0679 \u067e\u0679 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642<\/strong> \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0633\u0633\u0679\u0645\u0632 \u067e\u0631 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u062f\u06cc\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u06a9\u06cc \u062a\u0648\u062b\u06cc\u0642\u060c \u067e\u0627\u0644\u06cc\u0633\u06cc \u06a9\u06d2 \u0642\u0648\u0627\u0639\u062f\u060c \u0627\u0648\u0631 \u062d\u0641\u0627\u0638\u062a\u06cc \u0641\u0644\u0679\u0631\u0632\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u063a\u06cc\u0631 \u062a\u0628\u062f\u06cc\u0644 \u0634\u062f\u06c1 \u0622\u0688\u0679 \u0644\u0627\u06af\u0632 \u06a9\u0648 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u06cc\u06ba<\/strong> \u062a\u0645\u0627\u0645 \u0641\u06cc\u0635\u0644\u06d2 \u062c\u0648 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0633\u0631\u06af\u0631\u0645\u06cc\u0648\u06ba \u06a9\u0627 \u0628\u0627\u0639\u062b \u0628\u0646\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0631\u06cc\u06af\u0648\u0644\u06cc\u0679\u0688 \u0635\u0646\u0639\u062a\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0636\u0631\u0648\u0631\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u06c1\u06cc\u0648\u0645\u0646 \u0627\u0646 \u062f\u06cc \u0644\u0648\u067e \u062a\u06be\u0631\u06cc\u0634\u0648\u0644\u0688\u0632 \u06a9\u0648 \u0646\u0627\u0641\u0630 \u06a9\u0631\u0646\u0627<\/strong> \u0627\u0639\u0644\u06cc \u062e\u0637\u0631\u06d2 \u0648\u0627\u0644\u06d2 \u0631\u0648\u06cc\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4 \u06a9\u0645 \u062e\u0637\u0631\u0627\u062a \u06a9\u0648 \u062e\u0648\u062f \u06a9\u0627\u0631 \u0628\u0646\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u0632\u06cc\u0627\u062f\u06c1 \u062e\u0637\u0631\u0627\u062a \u06a9\u0648 \u0628\u0691\u06be\u0627 \u062f\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0627\u0633\u0646\u0627\u062f\u06cc \u06af\u0631\u062f\u0634<\/strong> API \u06a9\u06cc\u0632\u060c \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06a9\u0646\u06a9\u0634\u0646\u0632\u060c \u0627\u0648\u0631 \u0633\u0631\u0648\u0633 \u0679\u0648\u06a9\u0646\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"heading-reliability-and-failure-modes\">\u0648\u0634\u0648\u0633\u0646\u06cc\u06cc\u062a\u0627 \u0627\u0648\u0631 \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u0637\u0631\u06cc\u0642\u0648\u06ba<\/h3>\n<ul>\n<li>\n<p>[ ] <strong>\u0645\u062a\u0628\u0627\u062f\u0644 \u0631\u0627\u0633\u062a\u06d2 \u06a9\u0627 \u0688\u06cc\u0632\u0627\u0626\u0646<\/strong> \u062a\u0645\u0627\u0645 \u0628\u06cc\u0631\u0648\u0646\u06cc \u0627\u0646\u062d\u0635\u0627\u0631 \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4 \u0627\u0633 \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba \u067e\u0631\u0648\u06af\u0631\u06cc\u0633 \u06a9\u0648\u0686 \u06a9\u0627 A2A \u0641\u0627\u0644 \u0628\u06cc\u06a9 \u067e\u06cc\u0679\u0631\u0646 \u0627\u06cc\u06a9 \u0627\u06cc\u0633\u0627 \u0645\u0627\u0688\u0644 \u06c1\u06d2 \u062c\u0648 \u0633\u0631\u0648\u0633 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0646\u0627\u06a9\u0627\u0645\u06cc \u067e\u0631 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0648\u0627\u067e\u0633 \u0622\u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u06a9\u0648\u0644\u0688 \u06c1\u06cc\u0646\u0688\u0644\u0646\u06af \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0646\u0679\u06cc\u0646\u0631\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4 \u06af\u0631\u0645 \u062a\u0627\u0644\u0627\u0628 \u06cc\u0627 \u0642\u0627\u0628\u0644 \u0642\u0628\u0648\u0644 \u0645\u062a\u0628\u0627\u062f\u0644\u06d4 \u06a9\u0646\u0679\u06cc\u0646\u0631 \u0634\u0631\u0648\u0639 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 60 \u0633\u06cc\u06a9\u0646\u0688 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u06af\u0631\u06cc\u0632 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0645\u0648\u0627\u062f \u06a9\u06d2 \u0641\u0644\u0679\u0631\u0632 \u06a9\u0648 \u0644\u0627\u06af\u0648 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0627\u06cc\u062c\u0646\u0679 \u0622\u0624\u0679 \u067e\u0679 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba\u06d4 \u06af\u0631\u0627\u0624\u0646\u0688 \u0627\u0646 \u067e\u0679 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06c1\u06cc\u0644\u0648\u0633\u06cc\u0646\u06cc\u0634\u0646 \u0628\u06be\u06cc \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0635\u062d\u062a \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628\u0627\u062a<\/strong> \u062a\u0645\u0627\u0645 \u062e\u062f\u0645\u0627\u062a \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4 A2A \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627\u0631\u0688 \u06c1\u06cc\u0644\u062a\u06be \u0627\u06cc\u0646\u0688 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u06a9\u0644\u0627\u0626\u0646\u0679 \u06a9\u0646\u06cc\u06a9\u0679\u06cc\u0648\u06cc\u0679\u06cc \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u06d2 \u062d\u0627\u0635\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u062e\u0648\u0628\u0635\u0648\u0631\u062a \u06c1\u0631\u0627\u0633 \u06a9\u06cc \u062c\u0627\u0646\u0686<\/strong> \u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631\u06d4 \u0627\u06cc\u06a9 \u0648\u0642\u062a \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0627\u06cc\u06a9 \u0633\u0631\u0648\u0633\u0632 \u0628\u0646\u062f \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u0622\u06cc\u0627 \u0688\u06cc\u0641\u0627\u0644\u0679 \u0627\u06cc\u067e \u062c\u0648\u0627\u0628 \u062f\u06cc\u0646\u0627 \u062c\u0627\u0631\u06cc \u0631\u06a9\u06be\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"heading-governance\">\u062d\u06a9\u0645\u0631\u0627\u0646\u06cc<\/h3>\n<ul>\n<li>\n<p>[ ] <strong>\u0627\u06cc\u062c\u0646\u0679 \u06a9\u06cc \u062a\u0645\u0627\u0645 \u0630\u0645\u06c1 \u062f\u0627\u0631\u06cc\u0648\u06ba \u06a9\u0648 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u06a9\u0648\u0646 \u0633\u06d2 \u0679\u0648\u0644\u0632 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u06a9\u0646 \u062d\u0627\u0644\u062a\u0648\u06ba \u06a9\u0648 \u067e\u0691\u06be\u0627 \u0627\u0648\u0631 \u0644\u06a9\u06be\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u063a\u0644\u0637\u06cc \u06a9\u06d2 \u06a9\u0648\u0646 \u0633\u06d2 \u0637\u0631\u06cc\u0642\u0648\u06ba \u06a9\u06cc \u062a\u0648\u0642\u0639 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0641\u0648\u0631\u06cc \u0648\u0631\u0698\u0646 \u0631\u062c\u0633\u0679\u0631\u06cc \u06a9\u0648 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u06cc\u06ba<\/strong> \u06cc\u06c1 \u06af\u0679 \u06a9\u0645\u0679 \u0633\u06d2 \u0645\u0646\u0633\u0644\u06a9 \u06c1\u06d2\u06d4 \u0645\u0639\u0644\u0648\u0645 \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u062c\u0628 \u0645\u0633\u0626\u0644\u06c1 \u067e\u06cc\u0634 \u0622\u06cc\u0627 \u062a\u0648 \u06a9\u0648\u0646 \u0633\u06d2 \u0627\u0634\u0627\u0631\u06d2 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u062a\u06be\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0645\u0627\u0688\u0644 \u0627\u067e \u06af\u0631\u06cc\u0688 \u06a9\u0627 \u062c\u0627\u0626\u0632\u06c1 \u0644\u06cc\u06ba \u0627\u0648\u0631 \u0645\u0646\u0638\u0648\u0631 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0645\u0627\u0688\u0644 \u0648\u0631\u0698\u0646 \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0622\u0624\u0679 \u067e\u0679 \u0631\u0648\u06cc\u06d2 \u06a9\u0648 \u0627\u0646 \u0637\u0631\u06cc\u0642\u0648\u06ba \u0633\u06d2 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0628\u06c1\u0627\u0648 \u06a9\u06d2 \u0645\u0641\u0631\u0648\u0636\u0648\u06ba \u06a9\u0648 \u062a\u0648\u0691 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>[ ] <strong>\u0631\u0648\u0644 \u0628\u06cc\u06a9 \u0637\u0631\u06cc\u0642\u06c1 \u06a9\u0627\u0631 \u0642\u0627\u0626\u0645 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u06a9\u0648\u0688 \u0627\u0648\u0631 \u0645\u0627\u0688\u0644 \u062f\u0648\u0646\u0648\u06ba \u062a\u0628\u062f\u06cc\u0644\u06cc\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4 \u062e\u0631\u0627\u0628 \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u06a9\u0648 \u0648\u0627\u067e\u0633 \u0644\u0627\u0646\u06d2 \u0645\u06cc\u06ba \u0645\u0646\u0679 \u0644\u06af\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u06af\u06be\u0646\u0679\u06d2 \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u06cc\u06c1 \u0627\u06cc\u06a9 \u0645\u06a9\u0645\u0644 \u0641\u06c1\u0631\u0633\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0627\u0633 \u0645\u06cc\u06ba \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u0637\u0631\u06cc\u0642\u0648\u06ba \u06a9\u0627 \u0627\u062d\u0627\u0637\u06c1 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2 \u062c\u0648 \u0645\u0644\u0679\u06cc \u0627\u06cc\u062c\u0646\u0679 \u0633\u0633\u0679\u0645 \u06a9\u06cc \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc\u0648\u06ba \u0645\u06cc\u06ba \u062d\u0642\u06cc\u0642\u062a \u067e\u0633\u0646\u062f\u0627\u0646\u06c1 \u06c1\u06cc\u06ba\u06d4 \u0627\u067e\u0646\u06cc \u067e\u06c1\u0644\u06cc \u0639\u0648\u0627\u0645\u06cc \u0631\u06cc\u0644\u06cc\u0632 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u0633 \u06a9\u0627 \u062c\u0627\u0626\u0632\u06c1 \u0644\u06cc\u06ba \u0627\u0648\u0631 \u062c\u06cc\u0633\u06d2 \u062c\u06cc\u0633\u06d2 \u0646\u0638\u0627\u0645 \u062a\u06cc\u0627\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0633\u06c1 \u0645\u0627\u06c1\u06cc \u0645\u06cc\u06ba \u0627\u0633 \u06a9\u0627 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062c\u0627\u0626\u0632\u06c1 \u0644\u06cc\u06ba\u06d4<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u06a9\u0633\u06cc \u0633\u0648\u0627\u0644 \u06a9\u0627 \u062c\u0648\u0627\u0628 \u062f\u06cc\u0646\u06d2 \u06cc\u0627 \u062a\u0644\u0627\u0634 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f AI \u0627\u06cc\u062c\u0646\u0679 \u0628\u0646\u0627\u0646\u0627 \u0627\u06cc\u06a9 \u062d\u0644 \u0634\u062f\u06c1 \u0645\u0633\u0626\u0644\u06c1 \u06c1\u06d2\u06d4 \u0686\u0646\u062f \u0633\u0628\u0642 \u0627\u0648\u0631 \u0686\u0646\u062f \u06af\u06be\u0646\u0679\u0648\u06ba \u06a9\u06d2 \u06a9\u0627\u0645 \u06a9\u06d2 \u0633\u0627\u062a\u06be\u060c \u0622\u067e \u0627\u067e\u0646\u06d2 \u0645\u0642\u0635\u062f \u062a\u06a9 \u067e\u06c1\u0646\u0686 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062c\u0648 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0633\u0628\u0642 \u0686\u06be\u0648\u0691\u062a\u06d2 \u06c1\u06cc\u06ba \u0648\u06c1 \u0627\u0646\u062c\u06cc\u0646\u0626\u0631\u0646\u06af \u06a9\u06cc \u067e\u0631\u062a \u06c1\u06d2 \u062c\u0648 \u0627\u06af\u0644\u06cc \u0622\u062a\u06cc \u06c1\u06d2\u06d4 \u06cc\u0639\u0646\u06cc \u0648\u06c1 \u062d\u0635\u06c1 [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":23299,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[1],"tags":[],"class_list":["post-23298","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/23298","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/comments?post=23298"}],"version-history":[{"count":1,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/23298\/revisions"}],"predecessor-version":[{"id":23300,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/23298\/revisions\/23300"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/media\/23299"}],"wp:attachment":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/media?parent=23298"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/categories?post=23298"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/tags?post=23298"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}