{"id":468585,"date":"2025-07-25T15:07:48","date_gmt":"2025-07-25T15:07:48","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=468585"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=468585","title":{"rendered":"<span>\u041f\u0438\u0448\u0435\u043c \u0430\u0433\u0435\u043d\u0442\u0430 \u043d\u0430 Kotlin: KOSMOS<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0437\u0430\u0432\u0430\u043b\u0435\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f\u043c\u0438 \u043d\u0430 \u041f\u0438\u0442\u043e\u043d\u0435, \u043d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f\u043c\u0438 \u043d\u0430 \u0441\u0432\u043e\u0451\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435. \u0414\u043b\u044f \u043c\u0435\u043d\u044f \u044d\u0442\u043e Kotlin.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442, \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u043a \u0432\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0435 \u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0430\u0433\u0435\u043d\u0442\u043e\u0432. \u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0432 \u043e\u043d\u043e\u0433\u043e \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e, \u0432\u044b \u043f\u043e\u0439\u043c\u0435\u0442\u0435, \u0447\u0442\u043e \u0437\u0430\u0434\u0430\u0447\u0430 \u0438\u0437 \u0441\u0435\u0431\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442.<\/p>\n<p>\u0421\u0442\u0430\u0442\u044c\u044f \u043e\u0431\u0435\u0449\u0430\u0435\u0442 \u0441\u043e\u0431\u043b\u044e\u0434\u0430\u0442\u044c \u0434\u0432\u0430 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430, \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0449\u0438\u0445 \u0432\u043e\u0441\u043f\u0440\u0438\u044f\u0442\u0438\u0435:<\/p>\n<ul>\n<li>\n<p>\u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043e\u0442 \u0447\u0430\u0441\u0442\u043d\u043e\u0433\u043e \u043a \u043e\u0431\u0449\u0435\u043c\u0443, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043b\u0435\u0433\u0447\u0435 \u0432\u043e\u0441\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u044b, \u0447\u0435\u043c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044e.<\/p>\n<\/li>\n<li>\n<p>\u0411\u044b\u0441\u0442\u0440\u0430\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0441\u0432\u044f\u0437\u044c, \u043a\u0430\u043a \u0441 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Read%E2%80%93eval%E2%80%93print_loop\" rel=\"noopener noreferrer nofollow\">REPL<\/a>.<\/p>\n<\/li>\n<\/ul>\n<p>\u0410\u0433\u0435\u043d\u0442\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043b\u0435\u0433\u043a\u043e \u0431\u044b\u043b\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u043b\u0435\u0436\u0430\u0449\u0443\u044e \u0432 \u043e\u0441\u043d\u043e\u0432\u0435 LLM. \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 REST API \u0432 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438 \u0441 SDK, \u043f\u043e\u0449\u0443\u043f\u0430\u0435\u043c \u0413\u0438\u0433\u0430\u0447\u0430\u0442 \u0438 Anthropic.<\/p>\n<p>\u0410\u0445 \u0434\u0430, \ud83e\ude90 <abbr class=\"habraabbr\" title=\"K otlin O pen S ynthetic M ind O rbiting S ystem\" data-title=\"&lt;p&gt;&lt;strong&gt;K&lt;\/strong&gt;otlin &lt;strong&gt;O&lt;\/strong&gt;pen &lt;strong&gt;S&lt;\/strong&gt;ynthetic &lt;strong&gt;M&lt;\/strong&gt;ind &lt;strong&gt;O&lt;\/strong&gt;rbiting &lt;strong&gt;S&lt;\/strong&gt;ystem&lt;\/p&gt;&lt;p&gt;&lt;\/p&gt;\" data-abbr=\"KOSMOS\">KOSMOS<\/abbr> \u2014 \u0430\u043a\u0440\u043e\u043d\u0438\u043c.<\/p>\n<h3>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435<\/h3>\n<ol>\n<li>\n<p><a href=\"#what_is_agent\" rel=\"noopener noreferrer nofollow\"><strong>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0430\u0433\u0435\u043d\u0442<\/strong><\/a><br \/>&#8212; <a href=\"#how_agent_works\" rel=\"noopener noreferrer nofollow\">\u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0430\u0433\u0435\u043d\u0442\u044b: \u043f\u0440\u0438\u043c\u0435\u0440 \u0432 \u0447\u0430\u0442\u0435<\/a><br \/>&#8212; <a href=\"#how_agent_api_works\" rel=\"noopener noreferrer nofollow\">\u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0430\u0433\u0435\u043d\u0442\u044b: \u043f\u0440\u0438\u043c\u0435\u0440 \u0441 API<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#writing_functions\" rel=\"noopener noreferrer nofollow\"><strong>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0430\u0433\u0435\u043d\u0442\u0430<\/strong><\/a><br \/>&#8212; <a href=\"#fn_contract\" rel=\"noopener noreferrer nofollow\">\u041a\u043e\u043d\u0442\u0440\u0430\u043a\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/a><br \/>&#8212; <a href=\"#list_files\" rel=\"noopener noreferrer nofollow\">\u041f\u0438\u0448\u0435\u043c \u043f\u0435\u0440\u0432\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u2014 ListFiles<\/a><br \/>&#8212; <a href=\"#read_file\" rel=\"noopener noreferrer nofollow\">\u041f\u0438\u0448\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0447\u0442\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430<\/a><br \/>&#8212; <a href=\"#other_functions\" rel=\"noopener noreferrer nofollow\">\u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439<\/a><br \/>&#8212; <a href=\"#security\" rel=\"noopener noreferrer nofollow\">\u0417\u0430\u0431\u043e\u0442\u0438\u043c\u0441\u044f \u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#giga_agent_impl\" rel=\"noopener noreferrer nofollow\"><strong>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u0433\u0435\u043d\u0442\u0430 \u0441 \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u043e\u043c<\/strong><\/a><br \/>&#8212; <a href=\"#parrot_agent\" rel=\"noopener noreferrer nofollow\">\u0427\u0430\u0442 \u0441 \u0430\u0433\u0435\u043d\u0442\u043e\u043c-\u043f\u043e\u043f\u0443\u0433\u0430\u0435\u043c<\/a><br \/>&#8212; <a href=\"#giga_rest_token\" rel=\"noopener noreferrer nofollow\">\u0413\u0438\u0433\u0430\u0447\u0430\u0442 \u043f\u043e REST API. \u0417\u0430\u043f\u0440\u043e\u0441 \u0442\u043e\u043a\u0435\u043d\u0430<\/a><br \/>&#8212; <a href=\"#giga_rest_llm\" rel=\"noopener noreferrer nofollow\">\u0413\u0438\u0433\u0430\u0447\u0430\u0442 \u043f\u043e REST API. \u041e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 LLM<\/a><br \/>&#8212; <a href=\"#giga_fn_setup\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/a><br \/>&#8212; <a href=\"#giga_agent_impl_code\" rel=\"noopener noreferrer nofollow\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u0433\u0435\u043d\u0442\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#anthropic_agent\" rel=\"noopener noreferrer nofollow\"><strong>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u0433\u0435\u043d\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 Anthropic SDK<\/strong><\/a><br \/>&#8212; <a href=\"#anthropic_agent_setup\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430<\/a><br \/>&#8212; <a href=\"#anthropic_agent_tools_and_agent\" rel=\"noopener noreferrer nofollow\">\u0410\u0434\u0430\u043f\u0442\u0435\u0440 \u043d\u0430\u0434 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 \u0438 \u0430\u0433\u0435\u043d\u0442<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#what_next\" rel=\"noopener noreferrer nofollow\"><strong>\u0427\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435?<\/strong><\/a><\/p>\n<\/li>\n<\/ol>\n<p><a class=\"anchor\" name=\"what_is_agent\" id=\"what_is_agent\"><\/a><\/p>\n<h2>1. \u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0430\u0433\u0435\u043d\u0442<\/h2>\n<p>\u0415\u0441\u043b\u0438 \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442\u044c LLM \u0443\u043c\u043d\u043e\u0436\u0438\u0442\u044c 2 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0447\u0438\u0441\u043b\u0430, \u043e\u043d\u0430 \u043e\u0448\u0438\u0431\u0435\u0442\u0441\u044f. \u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u2014 \u0434\u0430\u0442\u044c \u0435\u0439 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440. LLM \u0441 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u2014 \u044d\u0442\u043e \u0443\u0436\u0435 \u0430\u0433\u0435\u043d\u0442.<\/p>\n<p>\u0412 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0430\u0433\u0435\u043d\u0442 \u2014 \u044d\u0442\u043e \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u0430\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0430\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 LLM \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c.<\/p>\n<p>\u041f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0435 \u0430\u0433\u0435\u043d\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u0438\u043c\u0435\u0442\u044c \u0434\u043e\u043b\u0433\u043e\u0441\u0440\u043e\u0447\u043d\u0443\u044e \u043f\u0430\u043c\u044f\u0442\u044c (\u0432\u0435\u043a\u0442\u043e\u0440\u043d\u0430\u044f \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, <a href=\"https:\/\/habr.com\/ru\/companies\/raft\/articles\/791034\/\" rel=\"noopener noreferrer nofollow\">RAG<\/a>), \u0445\u0438\u0442\u0440\u044b\u0435 \u043f\u0440\u043e\u043c\u043f\u0442\u044b \u0434\u043b\u044f \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0438 \u0438 \u0441\u0430\u043c\u043e\u043a\u0440\u0438\u0442\u0438\u043a\u0438.<\/p>\n<pre><code class=\"cpp\">                              \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510                               \u2502    Short-term mem    \u2502                               \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524                               \u2502    Long-term mem     \u2502                               \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b2\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518                                           \u2502                                   \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510                                   \u2502    Memory     \u2502                                   \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b2\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518                                           \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510                     \u2502 \u2502   Calendar()      \u2502                     \u2502 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524                     \u2502 \u2502   Calculator()    \u2502                     \u2502 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524                     \u2502 \u2502 CodeInterpreter() \u2502    \u250c\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\u2510 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25c0\u2500\u2500\u2500\u2500\u2502              Agent                \u2502 \u2502     Search()      \u2502    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524                          \u2502 \u2502      ...more      \u2502                          \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518                          \u2502                                                \u2502                                          \u250c\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2510                                          \u2502 Planning  \u2502                                          \u2514\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2518                                                \u2502                                       \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510                                       \u2502 Reflection \u2502 Self-crit \u2502                                       \u2502 Chain-of-thoughts      \u2502                                       \u2502 Subgoal-decomposition  \u2502                                       \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 <\/code><\/pre>\n<p><a class=\"anchor\" name=\"how_agent_works\" id=\"how_agent_works\"><\/a><\/p>\n<h3>\u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0430\u0433\u0435\u043d\u0442\u044b: \u043f\u0440\u0438\u043c\u0435\u0440 \u0432 \u0447\u0430\u0442\u0435<\/h3>\n<p>\u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u043b\u044e\u0431\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u0432\u0430\u043c LLM-\u0447\u0430\u0442 \u0438 \u043d\u0430\u043f\u0438\u0448\u0438\u0442\u0435:<\/p>\n<pre><code class=\"markdown\">\u0415\u0441\u043b\u0438 \u044f \u043f\u043e\u043f\u0440\u043e\u0448\u0443 \u0441\u043b\u043e\u0436\u0438\u0442\u044c \u0434\u0432\u0430 \u0447\u0438\u0441\u043b\u0430, \u0442\u044b \u043c\u043e\u0436\u0435\u0448\u044c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043b\u044c\u043ay\u043b\u044f\u0442\u043e\u0440.  \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043f\u0438\u0448\u0438: ```json {     \"n1\": number1,     \"n2\": number2,     \"operation\": \"+\" } ``` \u0418 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0448\u044c \u043e\u0442\u0432\u0435\u0442. \u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u043b\u043e\u0436\u0438 22 \u0438 33<\/code><\/pre>\n<p>Json \u043e\u0431\u044a\u0435\u043a\u0442 \u0438 \u0435\u0433\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u2014 \u044d\u0442\u043e tool (\u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u0445 Anthropic, OpenAI, Deepseek) \u0438\u043b\u0438 <a href=\"https:\/\/developers.sber.ru\/docs\/ru\/gigachat\/guides\/function-calling#rabota-s-sobstvennymi-funktsiyami\" rel=\"noopener noreferrer nofollow\">\u0444\u0443\u043d\u043a\u0446\u0438\u044f<\/a> (\u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u0445 \u0413\u0438\u0433\u0430\u0447\u0430\u0442). \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u00ab\u0442\u0443\u043b\u044b\u00bb \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438. \u0422\u0435\u043a\u0441\u0442\u043e\u043c \u0432\u044b\u0448\u0435 \u043c\u044b \u0434\u0430\u043b\u0438 \u043f\u043e\u043d\u044f\u0442\u044c LLM, \u0447\u0442\u043e \u0443 \u043d\u0435\u0435 \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u00ab\u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440\u00bb.<\/p>\n<p>\u042f \u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b \u0441 Deepseek, Qwen, ChatGpt, \u0413\u0438\u0433\u0430\u0447\u0430\u0442 \u2014 \u0432\u0441\u0435 \u043e\u0442\u0432\u0435\u0442\u0438\u043b\u0438:<\/p>\n<pre><code class=\"json\">{     \"n1\": 22,     \"n2\": 33,     \"operation\": \"+\" }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043b\u0435\u0433\u043a\u043e \u043f\u0430\u0440\u0441\u0438\u0442\u0441\u044f. \u0412\u0441\u0435 \u0447\u0442\u043e \u043d\u0430\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u2014 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u043d\u0430 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440\u0435 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u00ab55\u00bb \u0432 \u0447\u0430\u0442. LLM \u043e\u0442\u0432\u0435\u0442\u0438\u0442 \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435:<\/p>\n<blockquote>\n<p>\u0421\u0443\u043c\u043c\u0430 \u0447\u0438\u0441\u0435\u043b 22 \u0438 33 \u0440\u0430\u0432\u043d\u0430 55. \ud83d\ude0a<\/p>\n<\/blockquote>\n<p><a class=\"anchor\" name=\"how_agent_api_works\" id=\"how_agent_api_works\"><\/a><\/p>\n<h3>\u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0430\u0433\u0435\u043d\u0442\u044b: \u043f\u0440\u0438\u043c\u0435\u0440 \u0441 API<\/h3>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u0440\u0438\u0442\u0432\u043e\u0440\u0438\u0442\u044c\u0441\u044f \u0430\u0433\u0435\u043d\u0442\u043e\u043c: \u0441\u0430\u043c\u0438 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c LLM.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0437\u0430\u0432\u0435\u0441\u0442\u0438 \u0430\u043a\u043a\u0430\u0443\u043d\u0442 <a href=\"https:\/\/developers.sber.ru\/portal\/products\/gigachat-api\" rel=\"noopener noreferrer nofollow\">\u0413\u0438\u0433\u0430\u0447\u0430\u0442\u0430<\/a>, \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043b\u044e\u0447 \u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\">export GIGA_KEY=\u043a\u043b\u044e\u0447<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441\u0438\u043c \u0442\u043e\u043a\u0435\u043d, \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0445\u0432\u0430\u0442\u0438\u0442 \u043d\u0430 30 \u043c\u0438\u043d\u0443\u0442:<\/p>\n<pre><code class=\"bash\">curl -L -X POST 'https:\/\/ngw.devices.sberbank.ru:9443\/api\/v2\/oauth' \\ -H 'Content-Type: application\/x-www-form-urlencoded' \\ -H 'Accept: application\/json' \\ -H 'RqUID: 9aa1df35-33f6-43fc-b92e-1e61384c8660' \\ -H \"Authorization: Basic $GIGA_KEY\" \\ --data-urlencode 'scope=GIGACHAT_API_PERS' <\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441 \u043e\u0448\u0438\u0431\u043a\u0430\u043c\u0438 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0444\u043b\u0430\u0433 <code>-k<\/code> \u0438\u043b\u0438 \u043f\u0440\u043e\u043f\u0438\u0448\u0438\u0442\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044b \u0421\u0431\u0435\u0440\u0430 \u043f\u043e <a href=\"https:\/\/www.sberbank.com\/ru\/certificates\" rel=\"noopener noreferrer nofollow\">\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438<\/a>.<\/p>\n<p>\u0412 \u043e\u0442\u0432\u0435\u0442 \u043f\u0440\u0438\u0434\u0435\u0442 \u0442\u043e\u043a\u0435\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u043e\u0436\u0435 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\">export GIGA_TOKEN=token<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f (\u0434\u0435\u0442\u0430\u043b\u0438 \u0432 <a href=\"https:\/\/developers.sber.ru\/docs\/ru\/gigachat\/api\/reference\/rest\/post-chat\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>).<\/p>\n<p>\u0417\u0430\u0434\u0430\u0434\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441 \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u0438\u0435 \u0444\u0430\u0439\u043b\u044b \u043b\u0435\u0436\u0430\u0442 \u0432 \u043a\u043e\u0434\u043e\u0432\u043e\u0439 \u0431\u0430\u0437\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (\u043d\u0430\u043c \u043a\u0430\u043a \u0430\u0433\u0435\u043d\u0442\u0443 \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438):<\/p>\n<pre><code class=\"bash\">curl -L 'https:\/\/gigachat.devices.sberbank.ru\/api\/v1\/chat\/completions' \\ -H 'Content-Type: application\/json' \\ -H 'Accept: application\/json' \\ -H \"Authorization: Bearer $GIGA_TOKEN\" \\ -d '{   \"model\": \"GigaChat-Max\",   \"messages\": [     {       \"role\": \"system\",       \"content\": \"\u0422\u044b \u2014 \u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043d\u0442, \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0449\u0438\u0439 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434\"     },     {       \"role\": \"user\",       \"content\": \"\u0427\u0442\u043e \u043b\u0435\u0436\u0438\u0442 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430?\"     }   ],   \"function_call\": \"auto\",   \"functions\": [     {         \"name\": \"ListFiles\",         \"description\": \"\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c ls \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043f\u043e \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443 \u043f\u0443\u0442\u0438. \u0422\u043e\u0447\u043a\u0430 (.) \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043f\u0430\u043f\u043a\u0443\",         \"parameters\": {             \"type\": \"object\",             \"properties\": {                 \"path\": {                 \"type\": \"string\",                 \"description\": \"\u041f\u0443\u0442\u044c \u043a \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438, \u0444\u0430\u0439\u043b\u044b \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u043a\u0430\u0436\u0435\u043c\"              }            }         }     }   ] }'<\/code><\/pre>\n<p>\u041c\u044b \u0443\u043a\u0430\u0437\u0430\u043b\u0438, \u0447\u0442\u043e \u0443 LLM \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u00abListFiles\u00bb, \u0442\u0440\u0435\u0431\u0443\u044e\u0449\u0430\u044f <code>path<\/code> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430, \u0438 \u0441\u043f\u0440\u043e\u0441\u0438\u043b\u0438, \u0447\u0442\u043e \u043b\u0435\u0436\u0438\u0442 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0412 \u043e\u0442\u0432\u0435\u0442 \u0413\u0438\u0433\u0430\u0447\u0430\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 <code>function_call<\/code>.<\/p>\n<pre><code class=\"json\">{   \"choices\": [     {       \"message\": {         \"content\": \"\",         \"role\": \"assistant\",         \"function_call\": {           \"name\": \"ListFiles\",           \"arguments\": {             \"path\": \".\"           }         },         \"functions_state_id\": \"e379e132-2cf8-4ce1-8545-c9c94cbebb1b\"       },       \"index\": 0,       \"finish_reason\": \"function_call\"     }   ],   \"created\": 1752855939,   \"model\": \"GigaChat-Max:2.0.28.2\",   \"object\": \"chat.completion\",   \"usage\": {     \"prompt_tokens\": 88,     \"completion_tokens\": 23,     \"total_tokens\": 111,     \"precached_prompt_tokens\": 3   } }<\/code><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 messages. \u041e\u0436\u0438\u0434\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0442\u0432\u0435\u0442, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 \u044d\u0442\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u0435. \u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u0435\u0440\u043d\u0443\u0432\u0448\u0438\u0439\u0441\u044f <code>functions_state_id<\/code>:<\/p>\n<pre><code class=\"bash\">curl -L 'https:\/\/gigachat.devices.sberbank.ru\/api\/v1\/chat\/completions' \\ -H 'Content-Type: application\/json' \\ -H 'Accept: application\/json' \\ -H \"Authorization: Bearer $GIGA_TOKEN\" \\ -d '{   \"model\": \"GigaChat-Max\",   \"messages\": [     {       \"role\": \"system\",       \"content\": \"\u0422\u044b \u2014 \u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043d\u0442, \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0449\u0438\u0439 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434\"     },     {       \"role\": \"user\",       \"content\": \"\u0427\u0442\u043e \u043b\u0435\u0436\u0438\u0442 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430?\"     },     {       \"role\":\"assistant\",       \"content\":          \"{\\\"name\\\": \\\"ListFiles\\\", \\\"arguments\\\": {\\\"path\\\": \\\".\\\"}} \",       \"functions_state_id\": \"e379e132-2cf8-4ce1-8545-c9c94cbebb1b\"     },     {       \"role\": \"function\",       \"content\": \"[\\\"README.md\\\", \\\"src\/\\\", \\\"src\/main.kt\/\\\"]\",       \"name\": \"ListFiles\"      }   ],   \"function_call\": \"auto\",   \"functions\": [     {         \"name\": \"ListFiles\",         \"description\": \"\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c ls \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043f\u043e \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443 \u043f\u0443\u0442\u0438. \u0422\u043e\u0447\u043a\u0430 (.) \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043f\u0430\u043f\u043a\u0443\",         \"parameters\": {             \"type\": \"object\",             \"properties\": {                 \"path\": {                 \"type\": \"string\",                 \"description\": \"\u041f\u0443\u0442\u044c \u043a \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438, \u0444\u0430\u0439\u043b\u044b \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u043a\u0430\u0436\u0435\u043c\"              }            }         }     }   ] }' <\/code><\/pre>\n<p>\u041e\u0442\u0432\u0435\u0442 \u043f\u0440\u0438\u0448\u0435\u043b, \u043a\u0430\u043a \u043c\u044b \u0438 \u043e\u0436\u0438\u0434\u0430\u043b\u0438: \u0413\u0438\u0433\u0430\u0447\u0430\u0442, \u043e\u0441\u043d\u043e\u0432\u044b\u0432\u0430\u044f\u0441\u044c \u043d\u0430 \u0432\u044b\u0437\u043e\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043e\u0442\u0432\u0435\u0442\u0438\u043b \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441 \u043f\u0440\u043e \u0444\u0430\u0439\u043b\u044b \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438.<\/p>\n<pre><code class=\"json\">{   \"choices\": [     {       \"message\": {         \"content\": \"\u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b:\\n- README.md\\n- src\/\\n- src\/main.kt\",         \"role\": \"assistant\",         \"functions_state_id\": \"de68b8a0-c2c7-448b-af8b-8a1b652fccd5\"       },       \"index\": 0,       \"finish_reason\": \"stop\"     }   ],   \"created\": 1752856961,   \"model\": \"GigaChat-Max:2.0.28.2\",   \"object\": \"chat.completion\",   \"usage\": {     \"prompt_tokens\": 150,     \"completion_tokens\": 26,     \"total_tokens\": 176,     \"precached_prompt_tokens\": 3   } } <\/code><\/pre>\n<p><a class=\"anchor\" name=\"writing_functions\" id=\"writing_functions\"><\/a><\/p>\n<h2>2. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0430\u0433\u0435\u043d\u0442\u0430<\/h2>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u2014 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 (\u0442\u0443\u043b\u044b), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u0430\u0433\u0435\u043d\u0442y \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043c\u0438\u0440\u043e\u043c.<\/p>\n<p>\u041f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435, \u0433\u0434\u0435 \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Kotlin \u043a\u043e\u0434. \u041c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 Kotlin-\u043f\u0440\u043e\u0435\u043a\u0442 \u0432 Intellij IDEA \u0438\u043b\u0438 \u0432\u0437\u044f\u0442\u044c \u0441\u043a\u0435\u043b\u0435\u0442 \u0438\u0437 \u043c\u043e\u0435\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f <a href=\"https:\/\/github.com\/D00mch\/ko-agent\/tree\/skeleton\" rel=\"noopener noreferrer nofollow\">KOSMOS-agent<\/a>.<\/p>\n<pre><code class=\"bash\">tree -I '.*|.git' --prune . \u251c\u2500\u2500 gradle... \u251c\u2500\u2500 gradle.properties \u251c\u2500\u2500 gradlew \u251c\u2500\u2500 settings.gradle.kts \u251c\u2500\u2500 build.gradle.kts \u2514\u2500\u2500 src  \u00a0\u00a0 \u251c\u2500\u2500 main  \u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 kotlin  \u00a0\u00a0 \u2502\u00a0\u00a0     \u251c\u2500\u2500 Main.kt  \u00a0\u00a0 \u2502\u00a0\u00a0     \u2514\u2500\u2500 tool  \u00a0\u00a0 \u2502\u00a0\u00a0         \u251c\u2500\u2500 files  \u00a0\u00a0 \u2502\u00a0\u00a0         \u2502\u00a0\u00a0 \u2514\u2500\u2500 ToolListFiles.kt  \u00a0\u00a0 \u2502\u00a0\u00a0         \u2514\u2500\u2500 ToolSetup.kt  \u00a0\u00a0 \u2514\u2500\u2500 test  \u00a0\u00a0     \u251c\u2500\u2500 kotlin  \u00a0\u00a0     \u2502\u00a0\u00a0 \u2514\u2500\u2500 tool  \u00a0\u00a0     \u2502\u00a0\u00a0     \u2514\u2500\u2500 ToolTest.kt  \u00a0\u00a0     \u2514\u2500\u2500 resources  \u00a0\u00a0         \u251c\u2500\u2500 directory  \u00a0\u00a0         \u2502\u00a0\u00a0 \u2514\u2500\u2500 file.txt  \u00a0\u00a0         \u2514\u2500\u2500 test.txt<\/code><\/pre>\n<p>\u0418\u0437 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u044b \u0432 build.gradle:<\/p>\n<pre><code class=\"kotlin\">dependencies {     implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.Coroutines}\")     testImplementation(kotlin(\"test\")) }<\/code><\/pre>\n<p><a class=\"anchor\" name=\"fn_contract\" id=\"fn_contract\"><\/a><\/p>\n<h3>\u041a\u043e\u043d\u0442\u0440\u0430\u043a\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u0443, \u043c\u044b \u0434\u0443\u043c\u0430\u043b\u0438 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c \u0435\u0435 \u0447\u0430\u0442\u0443 \u0438 \u043a\u0430\u043a\u043e\u0439 \u0430\u043b\u0438\u0430\u0441 \u0435\u0439 \u0434\u0430\u0442\u044c. \u0422\u0430\u043a \u0447\u0442\u043e \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0438\u043c\u044f, \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438 \u0441\u0430\u043c\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f:<\/p>\n<pre><code class=\"kotlin\">interface ToolSetup&lt;input&gt; {     val name: String     val description: String     operator fun invoke(input: Input): String }<\/code><\/pre>\n<p>\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0430\u0433\u0435\u043d\u0442\u0443 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0438 \u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u0423 <code>ListFiles<\/code> \u0435\u0441\u0442\u044c <code>path<\/code>. \u041e\u0442\u043b\u043e\u0436\u0438\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u043d\u0430 \u043f\u043e\u0442\u043e\u043c.<\/p>\n<p>\u0414\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0430\u0433\u0435\u043d\u0442\u0430-\u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a\u0430 \u0432 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043a\u043e\u0434\u0430 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n<ul>\n<li>\n<p>\u0427\u0442\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 (<code>echo<\/code>)<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 (<code>ls<\/code>)<\/p>\n<\/li>\n<li>\n<p>\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 (<code>sed -e<\/code>)<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 (<code>&gt;&gt;<\/code>)<\/p>\n<\/li>\n<li>\n<p>\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 (<code>rm<\/code>)<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0438\u0441\u043a \u0442\u0435\u043a\u0441\u0442\u0430 \u0432 \u0444\u0430\u0439\u043b\u0435 (<code>find<\/code>)<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u043e\u0441\u0442\u043e \u0434\u0430\u0442\u044c \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b \u043c\u044b \u043d\u0435 \u0445\u043e\u0442\u0438\u043c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c. \u0421\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u0430 \u0441 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u043e\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443.<\/p>\n<p><a class=\"anchor\" name=\"list_files\" id=\"list_files\"><\/a><\/p>\n<h3>\u041f\u0438\u0448\u0435\u043c \u043f\u0435\u0440\u0432\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u2014 ListFiles<\/h3>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c <code>ListFiles<\/code>, \u043a\u0430\u043a \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f API \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u0430:<\/p>\n<pre><code class=\"kotlin\">object ToolListFiles : ToolSetup {     override val name = \"ListFiles\"     override val description = \"Runs bash ls command at a given path. Dot (.) means current directory\"      override fun invoke(input: Input): String {         TODO()     }      data class Input(val path: String = \".\") }<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u043c\u044b \u0434\u0430\u043b\u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c. \u0421\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e LLM \u043b\u0443\u0447\u0448\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0441 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u0438\u043c\u0438 \u043f\u0440\u043e\u043c\u043f\u0442\u0430\u043c\u0438. \u041f\u043e\u0447\u0435\u043c\u0443 \u0442\u0430\u043a? \u041d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f, \u0438 \u043f\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u0438\u0439 \u044d\u043a\u043e\u043d\u043e\u043c\u043d\u0435\u0435 (\u043d\u0435\u0442 \u043f\u0430\u0434\u0435\u0436\u0435\u0439 ).<\/p>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430.<\/p>\n<pre><code class=\"kotlin\">@Test fun `test ToolListFiles`() {     val input = ToolListFiles.Input(\"src\/test\/resources\")     val resources = ToolListFiles()     assertEquals(\"[directory\/,directory\/file.txt,test.txt]\", resources)     println(resources) }<\/code><\/pre>\n<p>\u0418 \u0432 <code>src\/test\/resources<\/code> \u043f\u043e\u043b\u043e\u0436\u0438\u043c \u043f\u0430\u043f\u043a\u0443 <code>directory<\/code> \u0438 \u0434\u0432\u0430 \u0444\u0430\u0439\u043b\u0430: <code>test.txt<\/code> \u0438 <code>directory\/file.txt<\/code>. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0435\u0441\u0442 \u0438 \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043f\u043e\u043a\u0430 \u0447\u0442\u043e tool \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<pre><code class=\"bash\">.\/gradlew test<\/code><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<pre><code>&gt; Task :test FAILED ToolTest &gt; test ToolListFiles() FAILED     kotlin.NotImplementedError at ToolTest.kt:11<\/code><\/pre>\n<p>\u041d\u0430\u0431\u0440\u043e\u0441\u0430\u0435\u043c \u043d\u0430\u0438\u0432\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e:<\/p>\n<pre><code class=\"kotlin\">override fun invoke(input: Input): String {     val base = File(input.path)     val files = base.list()     return files.joinToString(\",\", prefix = \"[\", postfix = \"]\") }<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0442\u0435\u0441\u0442:<\/p>\n<pre><code class=\"bash\">Expected :[directory\/,directory\/file.txt,test.txt] Actual   :[directory,test.txt]<\/code><\/pre>\n<p>\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043f\u043e\u0438\u0441\u043a \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432. Kotlin \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0442\u043b\u0438\u0447\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>File.walkTopDown<\/code> (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Depth-first_search\" rel=\"noopener noreferrer nofollow\">DFS<\/a> \u043f\u043e \u0444\u0430\u0439\u043b\u0430\u043c), \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0443\u044e <code>sequence<\/code>. \u0422\u043e \u0435\u0441\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f <a href=\"https:\/\/kotlinlang.org\/docs\/collection-transformations.html\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439<\/a> \u0431\u0435\u0437 \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0445 \u0440\u0430\u0441\u0445\u043e\u0434\u043e\u0432 \u0432 \u0432\u0438\u0434\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e \u043d\u043e\u0432\u043e\u0439 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0435:<\/p>\n<pre><code class=\"kotlin\">override fun invoke(input: Input): String {     val base = File(input.path)     val files = base.walkTopDown() \/\/ sequence         .filter { it != base }         .map { file -&gt;             val relPath = file.relativeTo(base).path             if (file.isDirectory) \"$relPath\/\" else relPath         }     return files.joinToString(\",\", prefix = \"[\", postfix = \"]\") }<\/code><\/pre>\n<p>\u0422\u0435\u0441\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0439\u0434\u0435\u043d. \u0424\u0443\u043d\u043a\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0435\u0449\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\u043c\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u044b \u043d\u0435 \u0445\u043e\u0442\u0438\u043c \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u0442\u043e\u043a\u0435\u043d\u044b \u043d\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u043f\u0430\u043f\u043e\u043a .git \u0438\u043b\u0438 .idea. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0444\u0438\u0447\u0438 \u043e\u0441\u0442\u0430\u0432\u043b\u044e \u043d\u0430 \u0441\u043e\u0432\u0435\u0441\u0442\u0438 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f.<\/p>\n<p><a class=\"anchor\" name=\"read_file\" id=\"read_file\"><\/a><\/p>\n<h3>\u041f\u0438\u0448\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0447\u0442\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430<\/h3>\n<p>\u041e\u043f\u044f\u0442\u044c \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u0442\u0435\u0441\u0442\u0430. \u0414\u043e\u043f\u0438\u0448\u0435\u043c \u0432 <code>src\/test\/resources\/test.txt<\/code> \u00abTest content\u00bb \u0441 \u043d\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u043e\u0439.<\/p>\n<pre><code class=\"kotlin\">@Test fun `test ToolReadFile`() {     println(File(\"src\/test\/resources\/test.txt\").readText())     val result = ToolReadFile(ToolReadFile.Input(\"src\/test\/resources\/test.txt\"))     assertEquals(\"Test content\\n\", result) \/\/ \\n \u0434\u043b\u044f \u043d\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0412 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0441\u0451 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u043e.<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">object ToolReadFile : ToolSetup {     override val name = \"ReadFile\"     override val description = \"Retrieve the contents of a specified file using a relative path. \" +             \"Use this to read a file's contents. Avoid using it with directory paths\"      override fun invoke(input: Input): String {         val path = input.path         val file = File(path)         return file.readText()     }      data class Input(val path: String) }<\/code><\/pre>\n<\/div>\n<\/details>\n<p><a class=\"anchor\" name=\"other_functions\" id=\"other_functions\"><\/a><\/p>\n<h3>\u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439<\/h3>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0442\u0435\u0441\u0442 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0444\u0430\u0439\u043b, \u043c\u0435\u043d\u044f\u0435\u0442 \u0435\u0433\u043e, \u0438\u0449\u0435\u0442 \u0442\u0435\u043a\u0441\u0442 \u0432 \u0444\u0430\u0439\u043b\u0430\u0445 \u0438 \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u0444\u0430\u0439\u043b:<\/p>\n<pre><code class=\"kotlin\">@Test fun `test ToolNewFile, ToolModifyFile, ToolFindTextInFiles, ToolDeleteFile lifecycle`() {     val content = \"Test\"     val resources = \"src\/test\/resources\"     val newFileName = \"${UUID.randomUUID()}.txt\"     val path = \"$resources\/$newFileName\"      \/\/ create new file     ToolNewFile(ToolNewFile.Input(path, text = content))     val fileContent = ToolReadFile(ToolReadFile.Input(path))     assertEquals(content, fileContent)      \/\/ modify new     val newContent = \"New\"     ToolModifyFile(ToolModifyFile.Input(path, oldText = content, newText = newContent))      \/\/ find     val findResult = ToolFindTextInFiles(ToolFindTextInFiles.Input(path = resources, newContent))     assertEquals(\"[$newFileName]\", findResult)      \/\/ delete     ToolDeleteFile(ToolDeleteFile.Input(path))     assertThrows { ToolReadFile(ToolReadFile.Input(path)) } } <\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u044e\u0449\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439.<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">object ToolNewFile : ToolSetup {     override val name = \"NewFile\"     override val description = \"Creates a new file at the given path with the provided content.\"      override fun invoke(input: Input): String {         val file = File(input.path)         file.parentFile?.mkdirs()         file.writeText(input.text)         return \"File created at ${input.path}\"     }      data class Input(         val path: String,         val text: String     ) }  object ToolModifyFile : ToolSetup {     override val name = \"EditFile\"     override val description = \"Replace text in a file. Replaces 'old_text' with 'new_text' in the specified file. \"      override fun invoke(input: Input): String {         val file = File(input.path)         val content = file.readText()         val newContent = content.replace(input.oldText, input.newText)         file.writeText(newContent)         return \"OK\"     }      data class Input(         val path: String,         val oldText: String,         val newText: String,     ) }  object ToolFindTextInFiles : ToolSetup {     override val name = \"FindTextInFiles\"     override val description = \"Search for a specific text across all files in a directory (recursively) \" +             \"and return matching file paths.\"      override fun invoke(input: Input): String {         val baseDir = File(input.path)         val matchedFiles = baseDir.walkTopDown()             .filter { it.isFile &amp;&amp; it.readText().contains(input.text) }             .map { it.relativeTo(baseDir).path }             .toList()          return matchedFiles.joinToString(\",\", prefix = \"[\", postfix = \"]\")     }      data class Input(         val path: String = \".\",         val text: String,     ) }  object ToolDeleteFile : ToolSetup {     override val name = \"DeleteFile\"     override val description = \"Deletes a file at the given path.\"      override fun invoke(input: Input): String {         val file = File(input.path)         file.delete()         return \"File deleted at ${input.path}\"     }      data class Input(val path: String) }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u0441\u0442 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c. \u0415\u0441\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442 <a href=\"https:\/\/github.com\/D00mch\/KOSMOS-agent\/tree\/tutorial\" rel=\"noopener noreferrer nofollow\">KOSMOS-agent<\/a> \u0438 \u0432\u0437\u044f\u0442\u044c \u043a\u043e\u0434 \u043e\u0442\u0442\u0443\u0434\u0430.<\/p>\n<p><a class=\"anchor\" name=\"security\" id=\"security\"><\/a><\/p>\n<h3>\u0417\u0430\u0431\u043e\u0442\u0438\u043c\u0441\u044f \u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438<\/h3>\n<p>\u041f\u043e\u0434\u0443\u0441\u0442\u0430\u043b\u0438? \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0441\u044b\u043f\u0430\u0442\u044c\u0441\u044f. \u041d\u0438\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u0442\u0435\u0441\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442(!) \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c, \u043f\u043e\u043a\u0430 \u0432\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u0442\u0435 \u043d\u0430 100% \u0443\u0432\u0435\u0440\u0435\u043d\u044b \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"kotlin\">class ToolSecurityTest {     @Test     fun `test delete file rejects paths outside project root`() {         assertThrows {             ToolDeleteFile.invoke(ToolDeleteFile.Input(\"\/\"))         }     } }<\/code><\/pre>\n<p>\u0420\u0438\u0441\u043a\u043e\u0432\u0430\u0442\u044c \u0438\u043b\u0438 \u043d\u0435\u0442 \u2014 \u0434\u0435\u043b\u043e \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f. \u0410\u0432\u0442\u043e\u0440 \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u0441\u0435 \u0435\u0449\u0435 \u043f\u0438\u0448\u0435\u0442, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442, \u0442\u0435\u0441\u0442 \u0431\u044b\u043b \u043f\u0440\u043e\u0439\u0434\u0435\u043d. \u0412\u043e\u0442 \u043c\u043e\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f:<\/p>\n<pre><code class=\"kotlin\">object ToolDeleteFile : ToolSetup {     \/\/ ...     override fun invoke(input: Input): String {         val file = File(input.path)         FilesToolUtil.requirePathIsSave(file)         file.delete()         return \"File deleted at ${input.path}\"     } }  object FilesToolUtil {     private val projectRoot = File(\".\").canonicalFile      fun isPathSafe(file: File): Boolean {         val canonicalPath = file.canonicalFile         return canonicalPath.startsWith(projectRoot)     }      @Throws(BadInputException::class)     fun requirePathIsSave(file: File) {         if (!isPathSafe(file)) {             throw BadInputException(\"Access denied: File path must be within project directory\")         }     } }<\/code><\/pre>\n<p><a class=\"anchor\" name=\"giga_agent_impl\" id=\"giga_agent_impl\"><\/a><\/p>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u0433\u0435\u043d\u0442\u0430 \u0441 \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u043e\u043c<\/h2>\n<p>\u0427\u0430\u0442 \u0441 \u0430\u0433\u0435\u043d\u0442\u043e\u043c \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<pre><code class=\"kotlin\">while (true) {     print(\"&gt;\")     val input = kotlin.io.readLine() ?: break     if (input.lowercase() == \"exit\") break     println(input)     \/\/ \u0442\u0443\u0442 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043a \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u0443 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 }<\/code><\/pre>\n<p><a class=\"anchor\" name=\"parrot_agent\" id=\"parrot_agent\"><\/a><\/p>\n<h3>\u0427\u0430\u0442 \u0441 \u0430\u0433\u0435\u043d\u0442\u043e\u043c-\u043f\u043e\u043f\u0443\u0433\u0430\u0435\u043c<\/h3>\n<p>\u041d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e LLM, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044e. \u0422\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c Flow \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:<\/p>\n<pre><code class=\"kotlin\">import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow  suspend fun main() {     val agent = ParrotAgent(userInputFlow())     agent.run().collect { text -&gt; print(text) } }  \/** \u0410\u0433\u0435\u043d\u0442, \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0439 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 *\/ class ParrotAgent(private val userMessages: Flow) {     fun run(): Flow = userMessages }  private fun userInputFlow(): Flow = flow {     println(\"Type `exit` to quit\")     while (true) {         print(\"&gt; \")         val input = readLine() ?: break         if (input.lowercase() == \"exit\") break         emit(input)         println(\"\\n\")     } }<\/code><\/pre>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0438 \u043f\u043e\u043e\u0431\u0449\u0430\u0442\u044c\u0441\u044f \u0441 \u043f\u0435\u0440\u0432\u044b\u043c \u0430\u0433\u0435\u043d\u0442\u043e\u043c.<\/p>\n<p><a class=\"anchor\" name=\"giga_rest_token\" id=\"giga_rest_token\"><\/a><\/p>\n<h3>\u0413\u0438\u0433\u0430\u0447\u0430\u0442 \u043f\u043e REST API. \u0417\u0430\u043f\u0440\u043e\u0441 \u0442\u043e\u043a\u0435\u043d\u0430<\/h3>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u0447\u0442\u043e \u043a\u043b\u044e\u0447 \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0438\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"kotlin\">fun main() {     val gigaKey = System.getenv(\"GIGA_KEY\")     println(gigaKey) }<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0435\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438, \u0430 \u043f\u0435\u0447\u0430\u0442\u0430\u0435\u0441\u044f null, \u043f\u0435\u0440\u0435\u043e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 Intellij IDEA.<\/p>\n<p>\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u043a\u043e\u0434 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u0442\u043e\u043a\u0435\u043d\u0430 \u0441 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 <a href=\"https:\/\/ktor.io\/docs\/client-create-new-application.html\" rel=\"noopener noreferrer nofollow\">Ktor<\/a>. \u041f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 build.gradle:<\/p>\n<pre><code class=\"kotlin\">dependencies {     \/\/ ... \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438     \/\/ ktor     implementation(\"io.ktor:ktor-client-core:${Versions.Ktor}\")     implementation(\"io.ktor:ktor-client-cio:${Versions.Ktor}\")     implementation(\"io.ktor:ktor-client-content-negotiation:${Versions.Ktor}\")     implementation(\"io.ktor:ktor-client-auth:${Versions.Ktor}\")     implementation(\"io.ktor:ktor-serialization-kotlinx-json:${Versions.Ktor}\")     implementation(\"io.ktor:ktor-serialization-jackson:${Versions.Ktor}\") }<\/code><\/pre>\n<p>\u0418 \u0441\u0430\u043c \u043a\u043e\u0434 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"kotlin\">object GigaAuth {     suspend fun requestToken(apiKey: String): String {         val client = HttpClient(CIO) {             gigaDefaults()         }         val response = client.submitForm(             url = \"https:\/\/ngw.devices.sberbank.ru:9443\/api\/v2\/oauth\",             formParameters = Parameters.build {                 append(\"scope\", \"GIGACHAT_API_PERS\")             }         ) {             header(\"Content-Type\", \"application\/x-www-form-urlencoded\")             header(\"Authorization\", \"Basic $apiKey\")         }.body&lt;GigaResponse.Token&gt;()          client.close()         return response.accessToken     } }<\/code><\/pre>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430 Ktor \u0432\u044b\u043d\u0435\u0441\u043b\u0438 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430\u043c \u0435\u0449\u0435 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0447\u0430\u0442\u0430.<\/p>\n<details class=\"spoiler\">\n<summary>gigaDefaults<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">import com.fasterxml.jackson.databind.DeserializationFeature import io.ktor.client.* import io.ktor.client.engine.cio.* import io.ktor.client.plugins.* import io.ktor.client.plugins.contentnegotiation.* import io.ktor.client.request.* import io.ktor.http.* import io.ktor.serialization.jackson.* import java.security.cert.X509Certificate import java.util.* import javax.net.ssl.X509TrustManager  fun HttpClientConfig&lt;CIOEngineConfig&gt;.gigaDefaults() {     this.defaultRequest {         header(HttpHeaders.ContentType, \"application\/json\")         header(HttpHeaders.Accept, \"application\/json\")         header(\"RqUID\", UUID.randomUUID().toString())     }     install(HttpTimeout) {         requestTimeoutMillis = 20000     }     install(ContentNegotiation) {         jackson { this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) }     }     engine {         https {             trustManager = object : X509TrustManager {                 override fun checkClientTrusted(chain: Array&lt;out X509Certificate&gt;?, authType: String?) {}                 override fun checkServerTrusted(chain: Array&lt;out X509Certificate&gt;?, authType: String?) {}                 override fun getAcceptedIssuers(): Array&lt;X509Certificate&gt; = arrayOf()             }         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0442\u043e\u043a\u0435\u043d \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442\u0441\u044f:<\/p>\n<pre><code class=\"kotlin\">suspend fun main() {     val gigaKey = System.getenv(\"GIGA_KEY\")     val gigaToken = GigaAuth.requestToken(gigaKey)     println(gigaToken) }<\/code><\/pre>\n<p><a class=\"anchor\" name=\"giga_rest_llm\" id=\"giga_rest_llm\"><\/a><\/p>\n<h3>\u0413\u0438\u0433\u0430\u0447\u0430\u0442 \u043f\u043e REST API. \u041e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 LLM<\/h3>\n<p>\u041e\u043f\u0438\u0448\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 API \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u0430.<\/p>\n<details class=\"spoiler\">\n<summary>Giga DTO<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">import com.fasterxml.jackson.annotation.JsonProperty import java.util.*  object GigaResponse {      data class Token(         @JsonProperty(\"access_token\") val accessToken: String,         @JsonProperty(\"expires_at\") val expiresAt: Date     )      sealed interface Chat {         data class Ok(val choices: List&lt;Choice&gt;, val created: Long, val model: String) : Chat         data class Error(val status: Int, val message: String) : Chat     }      data class Choice(         val message: Message,         val index: Int,         @JsonProperty(\"finish_reason\")         val finishReason: String     )      data class Message(         val content: String,         val role: GigaMessageRole,         @JsonProperty(\"function_call\")         val functionCall: FunctionCall? = null,         @JsonProperty(\"functions_state_id\")         val functionsStateId: String?     )      data class FunctionCall(         val name: String,         val arguments: Map&lt;String, Any&gt;     ) }  object GigaRequest {     data class Chat(         val model: String = \"GigaChat-Max\",         val messages: List&lt;Message&gt;,         @JsonProperty(\"function_call\")         val functionCall: String = \"auto\",         val functions: List&lt;Function&gt;? = null,     )      data class Message(         val role: GigaMessageRole,         val content: String, \/\/ Could be String or FunctionCall object         @JsonProperty(\"functions_state_id\")         val functionsStateId: String? = null     )      data class Function(         val name: String,         val description: String,         val parameters: Parameters     )      data class Parameters(         val type: String,         val properties: Map&lt;String, Property&gt;     )      data class Property(         val type: String,         val description: String? = null     ) }  @Suppress(\"EnumEntryName\") enum class GigaMessageRole { system, user, assistant, function }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0421\u0430\u043c \u043a\u043b\u0438\u0435\u043d\u0442 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<details class=\"spoiler\">\n<summary>Giga API<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">import io.ktor.client.* import io.ktor.client.call.* import io.ktor.client.engine.cio.* import io.ktor.client.plugins.auth.* import io.ktor.client.plugins.auth.providers.* import io.ktor.client.request.* import io.ktor.http.*  class GigaChatAPI(private val auth: GigaAuth) {     private val client = HttpClient(CIO) {         var token = \"\" \/\/ get form env, or cache, or db         val gigaKey = System.getenv(\"GIGA_KEY\")         gigaDefaults()         install(Auth) {             bearer {                 loadTokens {                     BearerTokens(token, \"\")                 }                 refreshTokens {                     token = auth.requestToken(gigaKey)                     BearerTokens(token, \"\")                 }             }         }     }      suspend fun message(body: GigaRequest.Chat): GigaResponse.Chat {         val response = client.post(\"https:\/\/gigachat.devices.sberbank.ru\/api\/v1\/chat\/completions\") {             setBody(body)         }         return when {             response.status.isSuccess() -&gt; response.body&lt;GigaResponse.Chat.Ok&gt;()             else -&gt; response.body&lt;GigaResponse.Chat.Error&gt;()         }     }      fun clear() = client.close() } <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 \u043e\u0442 \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u0430, \u043a\u0430\u043a \u043c\u044b \u0434\u0435\u043b\u0430\u043b\u0438 \u0440\u0443\u043a\u0430\u043c\u0438 \u0447\u0435\u0440\u0435\u0437 <code>curl<\/code>:<\/p>\n<pre><code class=\"kotlin\">suspend fun main() {     val chat = GigaChatAPI(GigaAuth)      \/\/ \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u0434\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438     val response = chat.message(         GigaRequest.Chat(             messages = listOf(                 GigaRequest.Message(                     role = GigaMessageRole.user,                     content = \"Help me find out what are the source files in the directory\",                 )             ),             functions = listOf(                 GigaRequest.Function(                     name = \"ListFiles\",                     description = \"Show the files in the current directory path\",                     parameters = GigaRequest.Parameters(                         \"object\",                         properties = mapOf(                             \"path\" to GigaRequest.Property(                                 type = \"string\",                                 description = \"Relative path to list files from\"                             )                         )                     )                 )             )         )     )      response.choices.forEach { (message, index, finishReason) -&gt;         println(message)     } }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u043d\u0430\u043f\u0435\u0447\u0430\u0442\u0430\u0442\u044c\u0441\u044f \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435:<\/p>\n<pre><code>Message(content=, role=assistant,  functionCall=FunctionCall(name=ListFiles, arguments={'path':.}),  functionsStateId=055e95ce-cbdf-46e7-ba22-6d3ad791f8c6)<\/code><\/pre>\n<p><a class=\"anchor\" name=\"giga_fn_setup\" id=\"giga_fn_setup\"><\/a><\/p>\n<h3>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/h3>\n<p>\u041f\u043e\u043c\u043d\u0438\u0442\u0435, \u043c\u044b \u043e\u0442\u043b\u043e\u0436\u0438\u043b\u0438 \u043d\u0430 \u043f\u043e\u0442\u043e\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c <abbr class=\"habraabbr\" title=\"\u041c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043f\u043e\u0440\u0438\u0442\u044c, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u044d\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0447\u0442\u043e \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0430\u0433\u0435\u043d\u0442\u0430 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u2014 \u0447\u0430\u0441\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.\" data-title=\"&lt;p&gt;\u041c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043f\u043e\u0440\u0438\u0442\u044c, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u044d\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0447\u0442\u043e \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0430\u0433\u0435\u043d\u0442\u0430 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u2014 \u0447\u0430\u0441\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.&lt;\/p&gt;&lt;p&gt;&lt;\/p&gt;\" data-abbr=\"\u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435\">\u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435<\/abbr> \u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430?<\/p>\n<pre><code class=\"kotlin\">object ToolListFiles : ToolSetup {     \/* \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u0434 *\/      data class Input(         \/\/ \u041a\u0430\u043a \u0431\u044b \u043d\u0430\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0432 \u0413\u0438\u0433\u0430\u0447\u0430\u0442 \"Relative path to list files from\"?         val path: String = \".\"     ) }<\/code><\/pre>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0439, \u043a\u0430\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c <abbr class=\"habraabbr\" data-abbr=\"\u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435\">\u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435<\/abbr>, \u043c\u043d\u043e\u0433\u043e. \u0418\u0434\u0438\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u2014 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438.<\/p>\n<blockquote>\n<p>Annotations are a means of attaching metadata to code. \u2014 <a href=\"https:\/\/kotlinlang.org\/docs\/annotations.html\" rel=\"noopener noreferrer nofollow\">kotlinlang.org<\/a><\/p>\n<\/blockquote>\n<p>\u041c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>@JsonPropertyDescription<\/code> \u0438\u0437 jackson, \u043d\u043e \u0434\u043b\u044f \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0441\u0442\u0438 \u0438 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u044e:<\/p>\n<pre><code class=\"kotlin\">@Target(AnnotationTarget.PROPERTY) \/\/ \u043d\u0430 property (val \u0432 data class) @Retention(AnnotationRetention.RUNTIME) \/\/ \u0434\u043e\u0441\u0442\u0430\u043d\u0435\u043c \u0435\u0435 \u0432 Runtime annotation class InputParamDescription(val value: String)<\/code><\/pre>\n<pre><code class=\"kotlin\">object ToolListFiles : ToolSetup {     \/* \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u0434 *\/      data class Input(         @InputParamDescription(\"Relative path to list files from\")         val path: String = \".\"     ) }<\/code><\/pre>\n<p>\u0414\u043e\u043c\u0430\u0448\u043d\u0435\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u0435 (\u0438 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044e, \u0438 \u0430\u0432\u0442\u043e\u0440\u0443):<\/p>\n<ol>\n<li>\n<p>\u041f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 name \u0438 description \u0432 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439 \u0434\u043b\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0439. \u0417\u0430\u0434\u0430\u0447\u0430 \u0441\u043e \u0437\u0432\u0435\u0437\u0434\u043e\u0447\u043a\u043e\u0439 \u2014 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0432 compile time.<\/p>\n<\/li>\n<\/ol>\n<p>\u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u043b\u0438 \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 <a href=\"https:\/\/github.com\/D00mch\/KOSMOS-agent\/tree\/tutorial\/src\/main\/kotlin\/tool\/files\" rel=\"noopener noreferrer nofollow\">KOSMOS-agent<\/a>.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u0438\u043c\u0435\u044e\u0449\u0438\u0435\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u0443\u0434\u043e\u0431\u043e\u0432\u0430\u0440\u0438\u043c\u044b\u0439 \u0434\u043b\u044f \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435:<\/p>\n<pre><code class=\"kotlin\">interface GigaToolSetup {     val fn: GigaRequest.Function     operator fun invoke(         functionCall: GigaResponse.FunctionCall     ): GigaRequest.Message }<\/code><\/pre>\n<p>\u0414\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0442\u0435\u0441\u0442 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043c\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u0431\u044b \u0432\u0438\u0434\u0435\u0442\u044c:<\/p>\n<pre><code class=\"kotlin\">class GigaToolTest {     private val gigaJsonMapper = jacksonObjectMapper()      @Test     fun `test function name and parameters setup`() {         val fn = ToolListFiles.toGiga().fn         assertEquals(fn.name, \"ListFiles\")         val jsonParams = gigaJsonMapper.writeValueAsString(fn.parameters)         assertEquals(             \"\"\"             {\"type\":\"object\",\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Relative path to list files from\"}}}         \"\"\".trimIndent(),             jsonParams         )     }      @Test     fun `test function invocation`() {         val toolsMap: Map = listOf(ToolListFiles.toGiga()).associateBy { it.fn.name }          val functionCall = GigaResponse.FunctionCall(             name = \"ListFiles\",             arguments = mapOf(\"path\" to \"src\/test\/resources\"),         )          val result = toolsMap[functionCall.name]!!.invoke(functionCall)         assertEquals(             GigaRequest.Message(                 role = GigaMessageRole.function,                 content = \"\"\"{\"result\":\"[directory\/,directory\/file.txt,test.txt]\"}\"\"\",             ),             result         )     } }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0447\u0435\u0441\u0442\u044c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u044e, \u043d\u043e \u0435\u0441\u043b\u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0442\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434 \u043d\u0438 \u043d\u0430 \u0447\u0442\u043e \u043d\u0435 \u043f\u043e\u0432\u043b\u0438\u044f\u044e\u0442.<\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c:<\/p>\n<pre><code class=\"kotlin\">dependencies {     implementation(kotlin(\"reflect\")) }<\/code><\/pre>\n<pre><code class=\"kotlin\">val gigaJsonMapper = jacksonObjectMapper()  inline fun &lt;reified Input&gt; ToolSetup&lt;Input&gt;.toGiga(): GigaToolSetup {     val toolSetup = this     return object : GigaToolSetup {         override val fn: GigaRequest.Function = GigaRequest.Function(             name = toolSetup.name,             description = toolSetup.description,             parameters = GigaRequest.Parameters(                 \"object\",                 properties = HashMap&lt;String, GigaRequest.Property&gt;().apply {                     val clazz = Input::class                     for (kProperty: KCallable&lt;*&gt; in clazz.declaredMembers) {                         val annotation = kProperty.findAnnotation&lt;InputParamDescription&gt;() ?: continue                         val description = annotation.value                         val type = kProperty.returnType.toString().substringAfterLast(\".\").lowercase()                         val gigaProperty = GigaRequest.Property(type, description)                         put(kProperty.name, gigaProperty)                     }                 }             )         )          override fun invoke(             functionCall: GigaResponse.FunctionCall,         ): GigaRequest.Message {             return try {                 val input: Input = gigaJsonMapper.convertValue(functionCall.arguments, Input::class.java)                 val toolResult = toolSetup.invoke(input)                 val gigaResult = gigaJsonMapper.writeValueAsString(                     mapOf(\"result\" to toolResult)                 )                 GigaRequest.Message(                     role = GigaMessageRole.function,                     content = gigaResult,                 )             } catch (e: Exception) {                 e.toGigaToolMessage()             }         }     } }  fun Exception.toGigaToolMessage(): GigaRequest.Message {     return GigaRequest.Message(         role = GigaMessageRole.function,         content = \"\"\"{\"result\": \"${message ?: toString()}\"}\"\"\",     ) }<\/code><\/pre>\n<p><a class=\"anchor\" name=\"giga_agent_impl_code\" id=\"giga_agent_impl_code\"><\/a><\/p>\n<h3>3. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u0433\u0435\u043d\u0442\u0430<\/h3>\n<p>\u041e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0410\u0433\u0435\u043d\u0442\u0430. \u0422\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0439 \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u044b\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c:<\/p>\n<pre><code class=\"cpp\">\u250c\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 Loop 1-5 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502 User          Agent                                   LLM  \u2502 \u2502  |              |                                      |   \u2502 \u2502  |1. msg input  |                                      |   \u2502 \u2502  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b6|2. add msg into msgs                  |   \u2502 \u2502  |              |                                      |   \u2502 \u2502  |              | \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Loop 3-5 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510   \u2502 \u2502  |              | \u2502                                    |   \u2502 \u2502  |              | \u25023. send(msgs, tools) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b6|   \u2502 \u2502  |              | \u2502                                    |   \u2502 \u2502  |              | \u25024-1. plain text  \u25c0\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500|   \u2502 \u2502  |              | \u2502      \u2514\u2500\u25ba print text                |   \u2502 \u2502  |              | \u2502                                    |   \u2502 \u2502  |              | \u25024-2. function call \u25c0\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500  |   \u2502 \u2502  |              | \u2502               \u2502                    |   \u2502 \u2502  |              | \u2502               \u2502 exec tool          |   \u2502 \u2502  |              | \u2502               \u2502 add result\u2192msgs    |   \u2502 \u2502  |              | \u2502               \u2502                    |   \u2502 \u2502  |              | \u2502\u25c0\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25005. fn call? \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b6\u2502 \u2502  |              | \u2514\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\u2518   \u2502 \u2502  |              |                                      |   \u2502 \u2502  |\u25c0\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500|                                      |   \u2502 \u2502  | 6. go to 1   |                                      |   \u2502 \u2514\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\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\u2534\u2500\u2500\u2500\u2518<\/code><\/pre>\n<ol>\n<li>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0432\u043e\u0434\u0438\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0410\u0433\u0435\u043d\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u0433\u043e \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0410\u0433\u0435\u043d\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f + \u0441\u043f\u0438\u0441\u043e\u043a \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0432 LLM.<\/p>\n<\/li>\n<li>\n<p>LLM \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442: <\/p>\n<ul>\n<li>\n<p>4.1. \u041e\u0431\u044b\u0447\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u2014 \u043f\u0435\u0447\u0430\u0442\u0430\u0435\u043c \u0442\u0435\u043a\u0441\u0442.<\/p>\n<\/li>\n<li>\n<p>4.2. \u0412\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u2014 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0431\u044b\u043b \u0432\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0438\u0434\u0435\u043c \u0432 \u0448\u0430\u0433 3.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u0441\u044f \u043a \u0448\u0430\u0433\u0443 1.<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0438\u0437\u0435\u0440 \u2014 \u0432\u043e\u0442 \u0447\u0435\u0433\u043e \u043c\u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0430\u043f\u0438\u0448\u0435\u043c:<\/p>\n<pre><code class=\"bash\">Type `exit` to quit &gt; Whats inside the settings.gradle.kts file?  \ud83e\ude90:  If there were any subprojects or additional configurations, they would also appear here. However, based on the information you've shared, these two sections (`plugins` and `rootProject`) are the only parts present.  &gt; Can you update this file and add a comment of what it does?  \ud83e\ude90:  \ud83d\ude0a\ud83d\ude80  &gt; Can you remove this project?  \ud83e\ude90:  \ud83d\ude09\ud83d\udcccei  \ud83e\ude90: Here's an overview of both options: 1. **Remove Only File:** Deletes the `settings.gradle.kts` file while keeping other project components intact. 2. **Remove Entire Project:** Removes everything related to the project, including source code, resources, etc., assuming you're okay with losing data permanently.  &gt; exit<\/code><\/pre>\n<p>\u041a\u043e\u0434 \u0430\u0433\u0435\u043d\u0442\u0430 c \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u043c\u0438.<\/p>\n<pre><code class=\"kotlin\">import kotlinx.coroutines.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.channelFlow  class GigaAgent(     private val userMessages: Flow,     private val api: GigaChatAPI,     private val tools: Map, ) {     private val functions: List = tools.map { it.value.fn }      \/\/ \u0427\u0442\u043e\u0431\u044b \u0441\u0430\u043c\u0438\u043c \u043d\u0435 \u0434\u0443\u043c\u0430\u0442\u044c \u043e\u0431 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0416\u0426, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0438\u043c\u0435\u044e\u0449\u0438\u043c\u0441\u044f channelFlow     fun run(): Flow = channelFlow {         \/\/ TODO: \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0437\u044e\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0441\u0442\u043e\u0440\u0438\u044e          val conversation = ArrayList&lt;GigaRequest.Message&gt;()          userMessages.collect { userText -&gt;             \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0447\u0430\u0442\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f             conversation.add(GigaRequest.Message(GigaMessageRole.user, userText))              while (true) { \/\/ TODO: \u0437\u0430\u0449\u0438\u0442\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430                 if (!isActive) break                  val response: GigaResponse.Chat = withContext(Dispatchers.IO) {                     chat(conversation)                 }                 when (response) {                     is GigaResponse.Chat.Ok -&gt; response                     is GigaResponse.Chat.Error -&gt; {                         \/\/ \u041f\u0440\u0435\u0440\u044b\u0432\u0430\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u043d\u0430 \u043e\u0448\u0438\u0431\u043a\u0430\u0445 \u043e\u0442 API \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u0430                         send(response.message)                         close()                         return@collect                     }                 }                          \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0447\u0430\u0442\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u0430                 conversation.addAll(response.toRequestMessages())                  val toolAwaits = ArrayList&lt;Deferred&lt;GigaRequest.Message&gt;&gt;()                 for (ch in response.choices) {                     val msg = ch.message                     when {                         \/\/ \u041e\u0431\u044b\u0447\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0447\u0430\u0442\u0430\u0435\u043c                         msg.content.isNotBlank() &amp;&amp; msg.functionsStateId == null -&gt; {                            send(msg.content)                         }                          \/\/ \u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e                         msg.functionCall != null &amp;&amp; msg.functionsStateId != null -&gt; {                             val deferred = async(Dispatchers.IO) {                                executeTool(msg.functionCall)                              }                             toolAwaits.add(deferred)                         }                     }                 }                 if (toolAwaits.isEmpty()) break                 conversation.addAll(toolAwaits.awaitAll())             }         }     }      private fun GigaResponse.Chat.Ok.toRequestMessages(): Collection {         return choices.map { ch -&gt;             val msg = ch.message             val content: String = when {                 msg.content.isNotBlank() -&gt; msg.content                  \/\/ \u0412 \u0434\u043e\u043a\u0430\u0445 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e, \u0447\u0442\u043e \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u0443 \u043d\u0443\u0436\u0435\u043d stringify json                  msg.functionCall != null -&gt; gigaJsonMapper.writeValueAsString(                     mapOf(\"name\" to msg.functionCall.name, \"arguments\" to msg.functionCall.arguments)                 )                  else -&gt; throw IllegalStateException(\"Can't get content from ${ch}\")             }             GigaRequest.Message(                 role = ch.message.role,                 content = content,                 functionsStateId = msg.functionsStateId             )         }     }      private fun executeTool(functionCall: GigaResponse.FunctionCall): GigaRequest.Message {         val fn = tools[functionCall.name] ?: return GigaRequest.Message(             GigaMessageRole.function, \"\"\"{\"result\":\"no such function ${functionCall.name}\"}\"\"\"         )         return fn.invoke(functionCall)     }      private suspend fun chat(conversation: ArrayList): GigaResponse.Chat {         val body = GigaRequest.Chat(             messages = conversation,             functions = functions,         )         return api.message(body)     } }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0441\u044f \u0441 \u0434\u0435\u0431\u0430\u0433\u0433\u0435\u0440\u043e\u043c \u0438 \u043f\u043e\u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u044c \u0437\u0430 \u0445\u043e\u0434\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u044b.<\/p>\n<p><a class=\"anchor\" name=\"anthropic_agent\" id=\"anthropic_agent\"><\/a><\/p>\n<h2>4. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u0433\u0435\u043d\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 Anthropic SDK<\/h2>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0430\u0433\u0435\u043d\u0442\u0430 \u0441 SDK, \u043f\u043e\u043b\u044c\u0437\u0443\u044f\u0441\u044c \u0438\u043c\u0435\u044e\u0449\u0438\u043c\u0438\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 (\u0442\u0443\u043b\u0430\u043c\u0438). \u0411\u0443\u0434\u0435\u0442 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 LLM \u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 (REST API \u0438\u043b\u0438 SDK) \u0432 \u043e\u0431\u0449\u0435\u043c-\u0442\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f.<\/p>\n<p>\u0412\u0435\u0441\u043e\u043c\u0430\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u0430 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0432\u0442\u043e\u0440\u043e\u0439 LLM \u2014 \u0434\u0430\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f\u043c \u043e\u0449\u0443\u0442\u0438\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u0430\u0433\u0435\u043d\u0442\u0430. \u0421 \u0413\u0438\u0433\u0430\u0447\u0430\u0442 \u043b\u0438\u0447\u043d\u043e \u0443 \u043c\u0435\u043d\u044f \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c.<\/p>\n<p><a class=\"anchor\" name=\"anthropic_agent_setup\" id=\"anthropic_agent_setup\"><\/a><\/p>\n<h3>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430<\/h3>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u043d\u0430 <a href=\"https:\/\/console.anthropic.com\/dashboard\" rel=\"noopener noreferrer nofollow\">anthropic<\/a>, \u043f\u043e\u043a\u0443\u043f\u0430\u0435\u043c API Key. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0438\u0437 \u0420\u043e\u0441\u0441\u0438\u0438 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u043e\u0432\u043e\u0437\u0438\u0442\u044c\u0441\u044f: \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043c\u043e\u0434\u0435\u043b\u044c\u044e \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f VPN. \u0423 \u0430\u0432\u0442\u043e\u0440\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u043e\u043f\u043b\u0430\u0442\u0438\u0442\u044c \u043a\u043b\u044e\u0447 \u041a\u0430\u0437\u0430\u0445\u0441\u0442\u0430\u043d\u0441\u043a\u043e\u0439 \u043a\u0430\u0440\u0442\u043e\u0439.<\/p>\n<p>\u041a\u043b\u044e\u0447 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"bash\">export ANTHROPIC_API_KEY=sk-ant-api....<\/code><\/pre>\n<p>\u041a \u043f\u0440\u043e\u0435\u043a\u0442\u0443 SDK \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u043e\u0434\u043d\u043e\u0439 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"kotlin\">dependencies {     \/\/ ...     implementation(\"com.anthropic:anthropic-java:1.0.0\") }<\/code><\/pre>\n<p><a class=\"anchor\" name=\"anthropic_agent_tools_and_agent\" id=\"anthropic_agent_tools_and_agent\"><\/a><\/p>\n<h3>\u0410\u0434\u0430\u043f\u0442\u0435\u0440 \u043d\u0430\u0434 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 \u0438 \u0430\u0433\u0435\u043d\u0442<\/h3>\n<p>\u0421 Anthropic \u0432\u0441\u0451 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0447\u0442\u043e \u0438 \u0441 \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u043e\u043c, \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438\u0445 SDK \u0432\u043c\u0435\u0441\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u043d\u0430\u043c\u0438 DTO:<\/p>\n<pre><code class=\"kotlin\">interface AnthropicToolSetup {     val tool: Tool     operator fun invoke(toolUse: ToolUseBlock): ToolResultBlockParam }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AnthropicToolSetup.kt<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">import com.anthropic.core.JsonValue import com.anthropic.core.jsonMapper import com.anthropic.models.messages.Tool import com.anthropic.models.messages.ToolResultBlockParam import com.anthropic.models.messages.ToolUseBlock import com.dumch.tool.InputParamDescription import com.dumch.tool.ToolSetup import kotlin.reflect.KCallable import kotlin.reflect.full.declaredMembers import kotlin.reflect.full.findAnnotation  interface AnthropicToolSetup {     val tool: Tool     operator fun invoke(toolUse: ToolUseBlock): ToolResultBlockParam }  val anthropicJsonMapper = jsonMapper()  inline fun &lt;reified Input&gt; ToolSetup&lt;Input&gt;.toAnthropic(): AnthropicToolSetup {     val toolSetup = this     val inputSchema: Tool.InputSchema = HashMap&lt;String, Any&gt;().let { schema -&gt;         val clazz = Input::class         for (property: KCallable&lt;*&gt; in clazz.declaredMembers) {             \/\/ We're not afraid of reflection here \u2014 it only runs once at startup and doesn't affect runtime.             val annotation = property.findAnnotation&lt;InputParamDescription&gt;() ?: continue             val description = annotation.value             val type = property.returnType.toString().substringAfterLast(\".\").lowercase()             val desc = mapOf(\"type\" to type, \"description\" to description)             schema.put(property.name, desc)         }         Tool.InputSchema.builder()             .properties(JsonValue.from(schema))             .build()     }      return object : AnthropicToolSetup {         override val tool: Tool = Tool.Companion.builder()             .name(toolSetup.name)             .description(toolSetup.description)             .inputSchema(inputSchema)             .build()          override fun invoke(toolUse: ToolUseBlock): ToolResultBlockParam {             try {                 val input: JsonValue = toolUse._input()                 val typed: Input = anthropicJsonMapper.convertValue(input, Input::class.java)                 val result = toolSetup.invoke(typed)                 return ToolResultBlockParam.builder()                     .content(result)                     .toolUseId(toolUse.id())                     .isError(false)                     .build()             } catch (e: Exception) {                 \/\/ TODO: proper logging should be implemented                 println(e)                 return ToolResultBlockParam.Companion.builder()                     .content(\"Unpredicted exception with the tool '$name': ${e.message}\")                     .isError(true)                     .build()             }         }     } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0410\u0433\u0435\u043d\u0442 1 \u0432 1, \u043a\u0430\u043a GigaAgent. \u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435, \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u043e\u0431\u0449\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0432 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044e. \u042f \u044d\u0442\u043e\u0433\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u0441\u0442\u0430\u043b, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e.<\/p>\n<details class=\"spoiler\">\n<summary>AnthropicAgent.kt<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">import com.anthropic.client.AnthropicClient import com.anthropic.client.okhttp.AnthropicOkHttpClient import com.anthropic.models.messages.* import com.dumch.tool.files.* import kotlinx.coroutines.Deferred import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.channelFlow import kotlinx.coroutines.isActive import kotlinx.coroutines.withContext  class AnthropicAgent(     private val client: AnthropicClient,     private val tools: Map,     private val model: Model,     private val userMessages: Flow, ) {     private val anthropicTools: List = tools.map { (_, tool) -&gt;         ToolUnion.ofTool(tool.tool)     }      fun run(): Flow = channelFlow {         \/\/ TODO: summarize conversation         val conversation = ArrayList&lt;MessageParam&gt;()         userMessages.collect { userText -&gt;             val userMessageParam = MessageParam.Companion.builder()                 .role(MessageParam.Role.USER)                 .content(userText)                 .build()             conversation.add(userMessageParam)              for (i in 1..MAX_TOOL_ITERATIONS) { \/\/ infinite loop protection                 if (!isActive) break                 val response = withContext(Dispatchers.IO) {                     continueChat(conversation)                 }                 conversation.add(response.toParam())                  val toolAwaits = ArrayList&lt;Deferred&lt;ToolResultBlockParam&gt;&gt;()                 for (content in response.content()) {                     when {                         content.isToolUse() -&gt;; {                             val deferred = async(Dispatchers.IO) {                                executeTool(content.asToolUse())                              }                             toolAwaits.add(deferred)                         }                          content.isText() -&gt; send(content.asText().text())                     }                 }                 if (toolAwaits.isEmpty()) break                 val toolResults = toolAwaits.awaitAll()                 val toolContentBlockParams = toolResults.map(ContentBlockParam.Companion::ofToolResult)                 val toolUseResultMessageParam = MessageParam.Companion.builder()                     .role(MessageParam.Role.USER)                     .content(MessageParam.Content.ofBlockParams(toolContentBlockParams))                     .build()                 conversation.add(toolUseResultMessageParam)             }         }     }      private fun executeTool(toolBlock: ToolUseBlock): ToolResultBlockParam {         val name = toolBlock.name()         val tool = tools[name] ?: return ToolResultBlockParam.Companion.builder()             .content(\"Tool $name not found\")             .isError(true)             .build()         return tool.invoke(toolBlock)     }      private fun continueChat(conversation: List): Message {         val paramsBuilder = MessageCreateParams.Companion.builder()             .model(model)             .maxTokens(1024)             .temperature(1.0)             .messages(conversation)          paramsBuilder.tools(anthropicTools)          return client.messages().create(paramsBuilder.build())     }      companion object {         private val MAX_TOOL_ITERATIONS = 10          fun instance(             userInputFlow: Flow,             model: Model = Model.CLAUDE_3_5_SONNET_20241022,         ): AnthropicAgent {             val client: AnthropicClient = AnthropicOkHttpClient.fromEnv()             val tools: Map = listOf(                 ToolReadFile.toAnthropic(),                 ToolListFiles.toAnthropic(),                 ToolNewFile.toAnthropic(),                 ToolDeleteFile.toAnthropic(),                 ToolModifyFile.toAnthropic(),                 ToolFindTextInFiles.toAnthropic(),             ).associateBy { it.tool.name() }             return AnthropicAgent(client, tools, model, userInputFlow)         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0418 \u0437\u0430\u043f\u0443\u0441\u043a:<\/p>\n<pre><code class=\"kotlin\">import com.dumch.anth.AnthropicAgent import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow  private const val AGENT_ALIAS = \"\ud83e\ude90\"  suspend fun main() {     val agent = AnthropicAgent.instance(userInputFlow())     agent.run().collect { text -&gt; print(\"$AGENT_ALIAS: $text\") } }  private fun userInputFlow(): Flow = flow {     println(\"Type `exit` to quit\")     while (true) {         print(\"&gt; \")         val input = readLine() ?: break         if (input.lowercase() == \"exit\") break         emit(input)         println(\"\\n\")     } }<\/code><\/pre>\n<p><a class=\"anchor\" name=\"what_next\" id=\"what_next\"><\/a><\/p>\n<h2>5. \u0427\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435?<\/h2>\n<p>\u0410 \u0434\u0430\u043b\u044c\u0448\u0435 \u2014 \u0441\u0430\u043c\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0430\u0433\u0435\u043d\u0442\u0430, \u0434\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0434\u0440\u0443\u0433\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u044f \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0434\u043b\u044f \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430 \u0432\u043e\u0442 \u0442\u0430\u043a\u0438\u043c \u043f\u0440\u043e\u043c\u043f\u0442\u043e\u043c:<\/p>\n<blockquote>\n<p>Similar with what I already have, help me implement a tool that is capable of using bash. For example, ls, echo, find, .\/gradlew commands<\/p>\n<\/blockquote>\n<p>\u0418 \u0432\u043e\u0442 \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b:<\/p>\n<pre><code class=\"kotlin\">package com.dumch.tool  import java.io.BufferedReader import java.io.InputStreamReader  object ToolRunBashCommand : ToolSetup {     override val name = \"RunBashCommand\"     override val description = \"Executes a bash command and returns its output\"      override fun invoke(input: Input): String {         val process = ProcessBuilder(\"bash\", \"-c\", input.command)             .redirectErrorStream(true)             .start()         val output = process.inputStream.bufferedReader().use(BufferedReader::readText)         val exitCode = process.waitFor()         if (exitCode != 0) throw RuntimeException(\"Command failed with exit code $exitCode\")         return output.trim()     }      data class Input(         @InputParamDescription(\"The bash command to run, e.g., 'ls', 'echo Hello', '.\/gradlew tasks'\")         val command: String     ) } <\/code><\/pre>\n<p>\u0410\u043d\u0442\u0440\u043e\u043f\u0438\u043a \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0442\u0430\u043a\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0435\u043c\u0443 \u0443\u043a\u0440\u0430\u0441\u0442\u044c \u043d\u0430\u0448\u0438 \u043a\u043b\u044e\u0447\u0438. \u041b\u0443\u0447\u0448\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043c\u0430\u043d\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c \u043e\u0434\u043d\u043e\u0439: <code>.\/gradlew<\/code>.<\/p>\n<details class=\"spoiler\">\n<summary>\u0422\u0435\u0441\u0442, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0430\u043d\u0442\u0440\u043e\u043f\u0438\u043a\u043e\u043c<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">class ToolRunBashCommandTest {     @Test     fun `test ls command execution`() {         \/\/ Execute the ls command         val result = ToolRunBashCommand.invoke(ToolRunBashCommand.Input(\"ls\"))                  \/\/ Verify the result contains some common files\/directories         assertTrue(result.contains(\"src\"), \"Output should contain 'src' directory\")         assertTrue(result.contains(\"build.gradle.kts\"), \"Output should contain 'build.gradle.kts' file\")     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u043c\u043c\u0430\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0434\u0438\u0430\u043b\u043e\u0433\u0430 \u0441 \u0447\u0430\u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0438 \u0442\u043e\u043a\u0435\u043d\u044b \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442\u044c \u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0435 \u043e\u043a\u043d\u043e.<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u0443\u043c\u043c\u0430\u0440\u0438\u0437\u0430\u0446\u0438\u044f, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u0430\u044f \u0430\u043d\u0442\u0440\u043e\u043f\u0438\u043a\u043e\u043c<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/\/ ... inside AnthropicAgent private suspend fun trySummarize(conversation: ArrayList) {     val msg = MessageCountTokensParams.builder().model(model).messages(conversation).build()     val inputTokens: Long = client.messages().countTokens(msg).inputTokens()     if (inputTokens &gt; MAX_TOKENS * THRESHOLD_PCT \/* 8096 *\/) return      val summary = withContext(Dispatchers.IO) {         client.messages().create(             MessageCreateParams.builder()                 .model(model)                 .temperature(0.7)                 .messages(conversation)                 .system(\"Summarize the conversation so far\")                 .build()         )     }      val lastMessage = conversation.last()     conversation.clear()     conversation.add(summary.toParam())     conversation.add(lastMessage) }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0425\u043e\u0440\u043e\u0448\u043e \u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u0448\u0438\u0431\u043e\u043a. \u041d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443, \u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438\u043c\u0435\u044e\u0449\u0438\u0439\u0441\u044f \u00ab\u0440\u0430\u0437\u0433\u043e\u0432\u043e\u0440\u00bb \u043d\u0430 \u0434\u0438\u0441\u043a, \u0432\u0434\u0440\u0443\u0433 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f.<\/p>\n<p>\u041d\u0435 \u043f\u043e\u043c\u0435\u0448\u0430\u0435\u0442 \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 <a href=\"https:\/\/docs.github.com\/en\/rest\/orgs?apiVersion=2022-11-28\" rel=\"noopener noreferrer nofollow\">GitHub API<\/a>, \u0447\u0442\u043e\u0431\u044b \u0410\u0433\u0435\u043d\u0442 \u043c\u043e\u0433 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u043e\u0434 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. \u0418\u043b\u0438 \u043f\u043e\u0439\u0442\u0438 \u0432 \u0441\u0442\u043e\u0440\u043e\u043d\u0443 Web Scraping, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u043b\u043e\u0436\u043d\u0435\u0435.<\/p>\n<p>\u0418\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u043e \u044f\u0432\u043d\u043e \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u043b\u043e\u0433\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u044f, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0437\u0430\u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0432\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0430\u0433\u0435\u043d\u0442\u0430 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043a\u043e\u0434\u0430, \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u2014 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/microsoft.github.io\/language-server-protocol\/\" rel=\"noopener noreferrer nofollow\">LSP-\u0441\u0435\u0440\u0432\u0435\u0440<\/a>.<\/p>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0430\u0433\u0435\u043d\u0442\u0430 \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u043e, \u0441\u043b\u043e\u0436\u043d\u043e \u043e\u043f\u043b\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0441\u0447\u0435\u0442\u0430 \u0437\u0430 Anthropic.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/930524\/\"> https:\/\/habr.com\/ru\/articles\/930524\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0437\u0430\u0432\u0430\u043b\u0435\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f\u043c\u0438 \u043d\u0430 \u041f\u0438\u0442\u043e\u043d\u0435, \u043d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f\u043c\u0438 \u043d\u0430 \u0441\u0432\u043e\u0451\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435. \u0414\u043b\u044f \u043c\u0435\u043d\u044f \u044d\u0442\u043e Kotlin.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442, \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u043a \u0432\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0435 \u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0430\u0433\u0435\u043d\u0442\u043e\u0432. \u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0432 \u043e\u043d\u043e\u0433\u043e \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e, \u0432\u044b \u043f\u043e\u0439\u043c\u0435\u0442\u0435, \u0447\u0442\u043e \u0437\u0430\u0434\u0430\u0447\u0430 \u0438\u0437 \u0441\u0435\u0431\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442.<\/p>\n<p>\u0421\u0442\u0430\u0442\u044c\u044f \u043e\u0431\u0435\u0449\u0430\u0435\u0442 \u0441\u043e\u0431\u043b\u044e\u0434\u0430\u0442\u044c \u0434\u0432\u0430 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430, \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0449\u0438\u0445 \u0432\u043e\u0441\u043f\u0440\u0438\u044f\u0442\u0438\u0435:<\/p>\n<ul>\n<li>\n<p>\u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043e\u0442 \u0447\u0430\u0441\u0442\u043d\u043e\u0433\u043e \u043a \u043e\u0431\u0449\u0435\u043c\u0443, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043b\u0435\u0433\u0447\u0435 \u0432\u043e\u0441\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u044b, \u0447\u0435\u043c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044e.<\/p>\n<\/li>\n<li>\n<p>\u0411\u044b\u0441\u0442\u0440\u0430\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0441\u0432\u044f\u0437\u044c, \u043a\u0430\u043a \u0441 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Read%E2%80%93eval%E2%80%93print_loop\" rel=\"noopener noreferrer nofollow\">REPL<\/a>.<\/p>\n<\/li>\n<\/ul>\n<p>\u0410\u0433\u0435\u043d\u0442\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043b\u0435\u0433\u043a\u043e \u0431\u044b\u043b\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u043b\u0435\u0436\u0430\u0449\u0443\u044e \u0432 \u043e\u0441\u043d\u043e\u0432\u0435 LLM. \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 REST API \u0432 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438 \u0441 SDK, \u043f\u043e\u0449\u0443\u043f\u0430\u0435\u043c \u0413\u0438\u0433\u0430\u0447\u0430\u0442 \u0438 Anthropic.<\/p>\n<p>\u0410\u0445 \u0434\u0430, \ud83e\ude90 <abbr class=\"habraabbr\" title=\"K otlin O pen S ynthetic M ind O rbiting S ystem\" data-title=\"&lt;p&gt;&lt;strong&gt;K&lt;\/strong&gt;otlin &lt;strong&gt;O&lt;\/strong&gt;pen &lt;strong&gt;S&lt;\/strong&gt;ynthetic &lt;strong&gt;M&lt;\/strong&gt;ind &lt;strong&gt;O&lt;\/strong&gt;rbiting &lt;strong&gt;S&lt;\/strong&gt;ystem&lt;\/p&gt;&lt;p&gt;&lt;\/p&gt;\" data-abbr=\"KOSMOS\">KOSMOS<\/abbr> \u2014 \u0430\u043a\u0440\u043e\u043d\u0438\u043c.<\/p>\n<h3>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435<\/h3>\n<ol>\n<li>\n<p><a href=\"#what_is_agent\" rel=\"noopener noreferrer nofollow\"><strong>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0430\u0433\u0435\u043d\u0442<\/strong><\/a><br \/>&#8212; <a href=\"#how_agent_works\" rel=\"noopener noreferrer nofollow\">\u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0430\u0433\u0435\u043d\u0442\u044b: \u043f\u0440\u0438\u043c\u0435\u0440 \u0432 \u0447\u0430\u0442\u0435<\/a><br \/>&#8212; <a href=\"#how_agent_api_works\" rel=\"noopener noreferrer nofollow\">\u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0430\u0433\u0435\u043d\u0442\u044b: \u043f\u0440\u0438\u043c\u0435\u0440 \u0441 API<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#writing_functions\" rel=\"noopener noreferrer nofollow\"><strong>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0430\u0433\u0435\u043d\u0442\u0430<\/strong><\/a><br \/>&#8212; <a href=\"#fn_contract\" rel=\"noopener noreferrer nofollow\">\u041a\u043e\u043d\u0442\u0440\u0430\u043a\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/a><br \/>&#8212; <a href=\"#list_files\" rel=\"noopener noreferrer nofollow\">\u041f\u0438\u0448\u0435\u043c \u043f\u0435\u0440\u0432\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u2014 ListFiles<\/a><br \/>&#8212; <a href=\"#read_file\" rel=\"noopener noreferrer nofollow\">\u041f\u0438\u0448\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0447\u0442\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430<\/a><br \/>&#8212; <a href=\"#other_functions\" rel=\"noopener noreferrer nofollow\">\u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439<\/a><br \/>&#8212; <a href=\"#security\" rel=\"noopener noreferrer nofollow\">\u0417\u0430\u0431\u043e\u0442\u0438\u043c\u0441\u044f \u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#giga_agent_impl\" rel=\"noopener noreferrer nofollow\"><strong>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u0433\u0435\u043d\u0442\u0430 \u0441 \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u043e\u043c<\/strong><\/a><br \/>&#8212; <a href=\"#parrot_agent\" rel=\"noopener noreferrer nofollow\">\u0427\u0430\u0442 \u0441 \u0430\u0433\u0435\u043d\u0442\u043e\u043c-\u043f\u043e\u043f\u0443\u0433\u0430\u0435\u043c<\/a><br \/>&#8212; <a href=\"#giga_rest_token\" rel=\"noopener noreferrer nofollow\">\u0413\u0438\u0433\u0430\u0447\u0430\u0442 \u043f\u043e REST API. \u0417\u0430\u043f\u0440\u043e\u0441 \u0442\u043e\u043a\u0435\u043d\u0430<\/a><br \/>&#8212; <a href=\"#giga_rest_llm\" rel=\"noopener noreferrer nofollow\">\u0413\u0438\u0433\u0430\u0447\u0430\u0442 \u043f\u043e REST API. \u041e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 LLM<\/a><br \/>&#8212; <a href=\"#giga_fn_setup\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/a><br \/>&#8212; <a href=\"#giga_agent_impl_code\" rel=\"noopener noreferrer nofollow\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u0433\u0435\u043d\u0442\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#anthropic_agent\" rel=\"noopener noreferrer nofollow\"><strong>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u0433\u0435\u043d\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 Anthropic SDK<\/strong><\/a><br \/>&#8212; <a href=\"#anthropic_agent_setup\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430<\/a><br \/>&#8212; <a href=\"#anthropic_agent_tools_and_agent\" rel=\"noopener noreferrer nofollow\">\u0410\u0434\u0430\u043f\u0442\u0435\u0440 \u043d\u0430\u0434 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 \u0438 \u0430\u0433\u0435\u043d\u0442<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#what_next\" rel=\"noopener noreferrer nofollow\"><strong>\u0427\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435?<\/strong><\/a><\/p>\n<\/li>\n<\/ol>\n<p><a class=\"anchor\" name=\"what_is_agent\" id=\"what_is_agent\"><\/a><\/p>\n<h2>1. \u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0430\u0433\u0435\u043d\u0442<\/h2>\n<p>\u0415\u0441\u043b\u0438 \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442\u044c LLM \u0443\u043c\u043d\u043e\u0436\u0438\u0442\u044c 2 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0447\u0438\u0441\u043b\u0430, \u043e\u043d\u0430 \u043e\u0448\u0438\u0431\u0435\u0442\u0441\u044f. \u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u2014 \u0434\u0430\u0442\u044c \u0435\u0439 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440. LLM \u0441 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u2014 \u044d\u0442\u043e \u0443\u0436\u0435 \u0430\u0433\u0435\u043d\u0442.<\/p>\n<p>\u0412 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0430\u0433\u0435\u043d\u0442 \u2014 \u044d\u0442\u043e \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u0430\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0430\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 LLM \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c.<\/p>\n<p>\u041f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0435 \u0430\u0433\u0435\u043d\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u0438\u043c\u0435\u0442\u044c \u0434\u043e\u043b\u0433\u043e\u0441\u0440\u043e\u0447\u043d\u0443\u044e \u043f\u0430\u043c\u044f\u0442\u044c (\u0432\u0435\u043a\u0442\u043e\u0440\u043d\u0430\u044f \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, <a href=\"https:\/\/habr.com\/ru\/companies\/raft\/articles\/791034\/\" rel=\"noopener noreferrer nofollow\">RAG<\/a>), \u0445\u0438\u0442\u0440\u044b\u0435 \u043f\u0440\u043e\u043c\u043f\u0442\u044b \u0434\u043b\u044f \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0438 \u0438 \u0441\u0430\u043c\u043e\u043a\u0440\u0438\u0442\u0438\u043a\u0438.<\/p>\n<pre><code class=\"cpp\">                              \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510                               \u2502    Short-term mem    \u2502                               \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524                               \u2502    Long-term mem     \u2502                               \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b2\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518                                           \u2502                                   \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510                                   \u2502    Memory     \u2502                                   \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b2\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518                                           \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510                     \u2502 \u2502   Calendar()      \u2502                     \u2502 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524                     \u2502 \u2502   Calculator()    \u2502                     \u2502 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524                     \u2502 \u2502 CodeInterpreter() \u2502    \u250c\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\u2510 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25c0\u2500\u2500\u2500\u2500\u2502              Agent                \u2502 \u2502     Search()      \u2502    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524                          \u2502 \u2502      ...more      \u2502                          \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518                          \u2502                                                \u2502                                          \u250c\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2510                                          \u2502 Planning  \u2502                                          \u2514\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2518                                                \u2502                                       \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510                                       \u2502 Reflection \u2502 Self-crit \u2502                                       \u2502 Chain-of-thoughts      \u2502                                       \u2502 Subgoal-decomposition  \u2502                                       \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 <\/code><\/pre>\n<p><a class=\"anchor\" name=\"how_agent_works\" id=\"how_agent_works\"><\/a><\/p>\n<h3>\u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0430\u0433\u0435\u043d\u0442\u044b: \u043f\u0440\u0438\u043c\u0435\u0440 \u0432 \u0447\u0430\u0442\u0435<\/h3>\n<p>\u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u043b\u044e\u0431\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u0432\u0430\u043c LLM-\u0447\u0430\u0442 \u0438 \u043d\u0430\u043f\u0438\u0448\u0438\u0442\u0435:<\/p>\n<pre><code class=\"markdown\">\u0415\u0441\u043b\u0438 \u044f \u043f\u043e\u043f\u0440\u043e\u0448\u0443 \u0441\u043b\u043e\u0436\u0438\u0442\u044c \u0434\u0432\u0430 \u0447\u0438\u0441\u043b\u0430, \u0442\u044b \u043c\u043e\u0436\u0435\u0448\u044c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043b\u044c\u043ay\u043b\u044f\u0442\u043e\u0440.  \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043f\u0438\u0448\u0438: ```json {     \"n1\": number1,     \"n2\": number2,     \"operation\": \"+\" } ``` \u0418 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0448\u044c \u043e\u0442\u0432\u0435\u0442. \u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u043b\u043e\u0436\u0438 22 \u0438 33<\/code><\/pre>\n<p>Json \u043e\u0431\u044a\u0435\u043a\u0442 \u0438 \u0435\u0433\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u2014 \u044d\u0442\u043e tool (\u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u0445 Anthropic, OpenAI, Deepseek) \u0438\u043b\u0438 <a href=\"https:\/\/developers.sber.ru\/docs\/ru\/gigachat\/guides\/function-calling#rabota-s-sobstvennymi-funktsiyami\" rel=\"noopener noreferrer nofollow\">\u0444\u0443\u043d\u043a\u0446\u0438\u044f<\/a> (\u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u0445 \u0413\u0438\u0433\u0430\u0447\u0430\u0442). \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u00ab\u0442\u0443\u043b\u044b\u00bb \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438. \u0422\u0435\u043a\u0441\u0442\u043e\u043c \u0432\u044b\u0448\u0435 \u043c\u044b \u0434\u0430\u043b\u0438 \u043f\u043e\u043d\u044f\u0442\u044c LLM, \u0447\u0442\u043e \u0443 \u043d\u0435\u0435 \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u00ab\u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440\u00bb.<\/p>\n<p>\u042f \u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b \u0441 Deepseek, Qwen, ChatGpt, \u0413\u0438\u0433\u0430\u0447\u0430\u0442 \u2014 \u0432\u0441\u0435 \u043e\u0442\u0432\u0435\u0442\u0438\u043b\u0438:<\/p>\n<pre><code class=\"json\">{     \"n1\": 22,     \"n2\": 33,     \"operation\": \"+\" }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043b\u0435\u0433\u043a\u043e \u043f\u0430\u0440\u0441\u0438\u0442\u0441\u044f. \u0412\u0441\u0435 \u0447\u0442\u043e \u043d\u0430\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u2014 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u043d\u0430 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440\u0435 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u00ab55\u00bb \u0432 \u0447\u0430\u0442. LLM \u043e\u0442\u0432\u0435\u0442\u0438\u0442 \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435:<\/p>\n<blockquote>\n<p>\u0421\u0443\u043c\u043c\u0430 \u0447\u0438\u0441\u0435\u043b 22 \u0438 33 \u0440\u0430\u0432\u043d\u0430 55. \ud83d\ude0a<\/p>\n<\/blockquote>\n<p><a class=\"anchor\" name=\"how_agent_api_works\" id=\"how_agent_api_works\"><\/a><\/p>\n<h3>\u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0430\u0433\u0435\u043d\u0442\u044b: \u043f\u0440\u0438\u043c\u0435\u0440 \u0441 API<\/h3>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u0440\u0438\u0442\u0432\u043e\u0440\u0438\u0442\u044c\u0441\u044f \u0430\u0433\u0435\u043d\u0442\u043e\u043c: \u0441\u0430\u043c\u0438 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c LLM.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0437\u0430\u0432\u0435\u0441\u0442\u0438 \u0430\u043a\u043a\u0430\u0443\u043d\u0442 <a href=\"https:\/\/developers.sber.ru\/portal\/products\/gigachat-api\" rel=\"noopener noreferrer nofollow\">\u0413\u0438\u0433\u0430\u0447\u0430\u0442\u0430<\/a>, \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043b\u044e\u0447 \u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\">export GIGA_KEY=\u043a\u043b\u044e\u0447<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441\u0438\u043c \u0442\u043e\u043a\u0435\u043d, \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0445\u0432\u0430\u0442\u0438\u0442 \u043d\u0430 30 \u043c\u0438\u043d\u0443\u0442:<\/p>\n<pre><code class=\"bash\">curl -L -X POST 'https:\/\/ngw.devices.sberbank.ru:9443\/api\/v2\/oauth' \\ -H 'Content-Type: application\/x-www-form-urlencoded' \\ -H 'Accept: application\/json' \\ -H 'RqUID: 9aa1df35-33f6-43fc-b92e-1e61384c8660' \\ -H \"Authorization: Basic $GIGA_KEY\" \\ --data-urlencode 'scope=GIGACHAT_API_PERS' <\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441 \u043e\u0448\u0438\u0431\u043a\u0430\u043c\u0438 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0444\u043b\u0430\u0433 <code>-k<\/code> \u0438\u043b\u0438 \u043f\u0440\u043e\u043f\u0438\u0448\u0438\u0442\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044b \u0421\u0431\u0435\u0440\u0430 \u043f\u043e <a href=\"https:\/\/www.sberbank.com\/ru\/certificates\" rel=\"noopener noreferrer nofollow\">\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438<\/a>.<\/p>\n<p>\u0412 \u043e\u0442\u0432\u0435\u0442 \u043f\u0440\u0438\u0434\u0435\u0442 \u0442\u043e\u043a\u0435\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u043e\u0436\u0435 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\">export GIGA_TOKEN=token<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f (\u0434\u0435\u0442\u0430\u043b\u0438 \u0432 <a href=\"https:\/\/developers.sber.ru\/docs\/ru\/gigachat\/api\/reference\/rest\/post-chat\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>).<\/p>\n<p>\u0417\u0430\u0434\u0430\u0434\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441 \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u0438\u0435 \u0444\u0430\u0439\u043b\u044b \u043b\u0435\u0436\u0430\u0442 \u0432 \u043a\u043e\u0434\u043e\u0432\u043e\u0439 \u0431\u0430\u0437\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (\u043d\u0430\u043c \u043a\u0430\u043a \u0430\u0433\u0435\u043d\u0442\u0443 \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438):<\/p>\n<pre><code class=\"bash\">curl -L 'https:\/\/gigachat.devices.sberbank.ru\/api\/v1\/chat\/completions' \\ -H 'Content-Type: application\/json' \\ -H 'Accept: application\/json' \\ -H \"Authorization: Bearer $GIGA_TOKEN\" \\ -d '{   \"model\": \"GigaChat-Max\",   \"messages\": [     {       \"role\": \"system\",       \"content\": \"\u0422\u044b \u2014 \u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043d\u0442, \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0449\u0438\u0439 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434\"     },     {       \"role\": \"user\",       \"content\": \"\u0427\u0442\u043e \u043b\u0435\u0436\u0438\u0442 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430?\"     }   ],   \"function_call\": \"auto\",   \"functions\": [     {         \"name\": \"ListFiles\",         \"description\": \"\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c ls \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043f\u043e \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443 \u043f\u0443\u0442\u0438. \u0422\u043e\u0447\u043a\u0430 (.) \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043f\u0430\u043f\u043a\u0443\",         \"parameters\": {             \"type\": \"object\",             \"properties\": {                 \"path\": {                 \"type\": \"string\",                 \"description\": \"\u041f\u0443\u0442\u044c \u043a \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438, \u0444\u0430\u0439\u043b\u044b \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u043a\u0430\u0436\u0435\u043c\"              }            }         }     }   ] }'<\/code><\/pre>\n<p>\u041c\u044b \u0443\u043a\u0430\u0437\u0430\u043b\u0438, \u0447\u0442\u043e \u0443 LLM \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u00abListFiles\u00bb, \u0442\u0440\u0435\u0431\u0443\u044e\u0449\u0430\u044f <code>path<\/code> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430, \u0438 \u0441\u043f\u0440\u043e\u0441\u0438\u043b\u0438, \u0447\u0442\u043e \u043b\u0435\u0436\u0438\u0442 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0412 \u043e\u0442\u0432\u0435\u0442 \u0413\u0438\u0433\u0430\u0447\u0430\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 <code>function_call<\/code>.<\/p>\n<pre><code class=\"json\">{   \"choices\": [     {       \"message\": {         \"content\": \"\",         \"role\": \"assistant\",         \"function_call\": {           \"name\": \"ListFiles\",           \"arguments\": {             \"path\": \".\"           }         },         \"functions_state_id\": \"e379e132-2cf8-4ce1-8545-c9c94cbebb1b\"       },       \"index\": 0,       \"finish_reason\": \"function_call\"     }   ],   \"created\": 1752855939,   \"model\": \"GigaChat-Max:2.0.28.2\",   \"object\": \"chat.completion\",   \"usage\": {     \"prompt_tokens\": 88,     \"completion_tokens\": 23,     \"total_tokens\": 111,     \"precached_prompt_tokens\": 3   } }<\/code><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 messages. \u041e\u0436\u0438\u0434\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0442\u0432\u0435\u0442, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 \u044d\u0442\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u0435. \u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u0435\u0440\u043d\u0443\u0432\u0448\u0438\u0439\u0441\u044f <code>functions_state_id<\/code>:<\/p>\n<pre><code class=\"bash\">curl -L 'https:\/\/gigachat.devices.sberbank.ru\/api\/v1\/chat\/completions' \\ -H 'Content-Type: application\/json' \\ -H 'Accept: application\/json' \\ -H \"Authorization: Bearer $GIGA_TOKEN\" \\ -d '{   \"model\": \"GigaChat-Max\",   \"messages\": [     {       \"role\": \"system\",       \"content\": \"\u0422\u044b \u2014 \u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043d\u0442, \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0449\u0438\u0439 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434\"     },     {       \"role\": \"user\",       \"content\": \"\u0427\u0442\u043e \u043b\u0435\u0436\u0438\u0442 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430?\"     },     {       \"role\":\"assistant\",       \"content\":          \"{\\\"name\\\": \\\"ListFiles\\\", \\\"arguments\\\": {\\\"path\\\": \\\".\\\"}} \",       \"functions_state_id\": \"e379e132-2cf8-4ce1-8545-c9c94cbebb1b\"     },     {       \"role\": \"function\",       \"content\": \"[\\\"README.md\\\", \\\"src\/\\\", \\\"src\/main.kt\/\\\"]\",       \"name\": \"ListFiles\"      }   ],   \"function_call\": \"auto\",   \"functions\": [     {         \"name\": \"ListFiles\",         \"description\": \"\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c ls \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043f\u043e \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443 \u043f\u0443\u0442\u0438. \u0422\u043e\u0447\u043a\u0430 (.) \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043f\u0430\u043f\u043a\u0443\",         \"parameters\": {             \"type\": \"object\",             \"properties\": {                 \"path\": {                 \"type\": \"string\",                 \"description\": \"\u041f\u0443\u0442\u044c \u043a \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438, \u0444\u0430\u0439\u043b\u044b \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u043a\u0430\u0436\u0435\u043c\"              }            }         }     }   ] }' <\/code><\/pre>\n<p>\u041e\u0442\u0432\u0435\u0442 \u043f\u0440\u0438\u0448\u0435\u043b, \u043a\u0430\u043a \u043c\u044b \u0438 \u043e\u0436\u0438\u0434\u0430\u043b\u0438: \u0413\u0438\u0433\u0430\u0447\u0430\u0442, \u043e\u0441\u043d\u043e\u0432\u044b\u0432\u0430\u044f\u0441\u044c \u043d\u0430 \u0432\u044b\u0437\u043e\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043e\u0442\u0432\u0435\u0442\u0438\u043b \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441 \u043f\u0440\u043e \u0444\u0430\u0439\u043b\u044b \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438.<\/p>\n<pre><code class=\"json\">{   \"choices\": [     {       \"message\": {         \"content\": \"\u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b:\\n- README.md\\n- src\/\\n- src\/main.kt\",         \"role\": \"assistant\",         \"functions_state_id\": \"de68b8a0-c2c7-448b-af8b-8a1b652fccd5\"       },       \"index\": 0,       \"finish_reason\": \"stop\"     }   ],   \"created\": 1752856961,   \"model\": \"GigaChat-Max:2.0.28.2\",   \"object\": \"chat.completion\",   \"usage\": {     \"prompt_tokens\": 150,     \"completion_tokens\": 26,     \"total_tokens\": 176,     \"precached_prompt_tokens\": 3   } } <\/code><\/pre>\n<p><a class=\"anchor\" name=\"writing_functions\" id=\"writing_functions\"><\/a><\/p>\n<h2>2. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0430\u0433\u0435\u043d\u0442\u0430<\/h2>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u2014 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 (\u0442\u0443\u043b\u044b), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u0430\u0433\u0435\u043d\u0442y \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043c\u0438\u0440\u043e\u043c.<\/p>\n<p>\u041f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435, \u0433\u0434\u0435 \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Kotlin \u043a\u043e\u0434. \u041c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 Kotlin-\u043f\u0440\u043e\u0435\u043a\u0442 \u0432 Intellij IDEA \u0438\u043b\u0438 \u0432\u0437\u044f\u0442\u044c \u0441\u043a\u0435\u043b\u0435\u0442 \u0438\u0437 \u043c\u043e\u0435\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f <a href=\"https:\/\/github.com\/D00mch\/ko-agent\/tree\/skeleton\" rel=\"noopener noreferrer nofollow\">KOSMOS-agent<\/a>.<\/p>\n<pre><code class=\"bash\">tree -I '.*|.git' --prune . \u251c\u2500\u2500 gradle... \u251c\u2500\u2500 gradle.properties \u251c\u2500\u2500 gradlew \u251c\u2500\u2500 settings.gradle.kts \u251c\u2500\u2500 build.gradle.kts \u2514\u2500\u2500 src  \u00a0\u00a0 \u251c\u2500\u2500 main  \u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 kotlin  \u00a0\u00a0 \u2502\u00a0\u00a0     \u251c\u2500\u2500 Main.kt  \u00a0\u00a0 \u2502\u00a0\u00a0     \u2514\u2500\u2500 tool  \u00a0\u00a0 \u2502\u00a0\u00a0         \u251c\u2500\u2500 files  \u00a0\u00a0 \u2502\u00a0\u00a0         \u2502\u00a0\u00a0 \u2514\u2500\u2500 ToolListFiles.kt  \u00a0\u00a0 \u2502\u00a0\u00a0         \u2514\u2500\u2500 ToolSetup.kt  \u00a0\u00a0 \u2514\u2500\u2500 test  \u00a0\u00a0     \u251c\u2500\u2500 kotlin  \u00a0\u00a0     \u2502\u00a0\u00a0 \u2514\u2500\u2500 tool  \u00a0\u00a0     \u2502\u00a0\u00a0     \u2514\u2500\u2500 ToolTest.kt  \u00a0\u00a0     \u2514\u2500\u2500 resources  \u00a0\u00a0         \u251c\u2500\u2500 directory  \u00a0\u00a0         \u2502\u00a0\u00a0 \u2514\u2500\u2500 file.txt  \u00a0\u00a0         \u2514\u2500\u2500 test.txt<\/code><\/pre>\n<p>\u0418\u0437 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u044b \u0432 build.gradle:<\/p>\n<pre><code class=\"kotlin\">dependencies {     implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.Coroutines}\")     testImplementation(kotlin(\"test\")) }<\/code><\/pre>\n<p><a class=\"anchor\" name=\"fn_contract\" id=\"fn_contract\"><\/a><\/p>\n<h3>\u041a\u043e\u043d\u0442\u0440\u0430\u043a\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0413\u0438\u0433\u0430\u0447\u0430\u0442\u0443, \u043c\u044b \u0434\u0443\u043c\u0430\u043b\u0438 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c \u0435\u0435 \u0447\u0430\u0442\u0443 \u0438 \u043a\u0430\u043a\u043e\u0439 \u0430\u043b\u0438\u0430\u0441 \u0435\u0439 \u0434\u0430\u0442\u044c. \u0422\u0430\u043a \u0447\u0442\u043e \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0438\u043c\u044f, \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438 \u0441\u0430\u043c\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f:<\/p>\n<pre><code class=\"kotlin\">interface ToolSetup&lt;input&gt; {     val name: String     val description: String     operator fun invoke(input: Input): String }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-468585","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/468585","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=468585"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/468585\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=468585"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=468585"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=468585"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}