aip-agents-binary 0.5.25b1__py3-none-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (566) hide show
  1. aip_agents/__init__.py +65 -0
  2. aip_agents/__init__.pyi +19 -0
  3. aip_agents/a2a/__init__.py +19 -0
  4. aip_agents/a2a/__init__.pyi +3 -0
  5. aip_agents/a2a/server/__init__.py +10 -0
  6. aip_agents/a2a/server/__init__.pyi +4 -0
  7. aip_agents/a2a/server/base_executor.py +1086 -0
  8. aip_agents/a2a/server/base_executor.pyi +73 -0
  9. aip_agents/a2a/server/google_adk_executor.py +198 -0
  10. aip_agents/a2a/server/google_adk_executor.pyi +51 -0
  11. aip_agents/a2a/server/langflow_executor.py +180 -0
  12. aip_agents/a2a/server/langflow_executor.pyi +43 -0
  13. aip_agents/a2a/server/langgraph_executor.py +270 -0
  14. aip_agents/a2a/server/langgraph_executor.pyi +47 -0
  15. aip_agents/a2a/types.py +232 -0
  16. aip_agents/a2a/types.pyi +132 -0
  17. aip_agents/agent/__init__.py +27 -0
  18. aip_agents/agent/__init__.pyi +9 -0
  19. aip_agents/agent/base_agent.py +970 -0
  20. aip_agents/agent/base_agent.pyi +221 -0
  21. aip_agents/agent/base_langgraph_agent.py +2948 -0
  22. aip_agents/agent/base_langgraph_agent.pyi +232 -0
  23. aip_agents/agent/google_adk_agent.py +926 -0
  24. aip_agents/agent/google_adk_agent.pyi +141 -0
  25. aip_agents/agent/google_adk_constants.py +6 -0
  26. aip_agents/agent/google_adk_constants.pyi +3 -0
  27. aip_agents/agent/hitl/__init__.py +24 -0
  28. aip_agents/agent/hitl/__init__.pyi +6 -0
  29. aip_agents/agent/hitl/config.py +28 -0
  30. aip_agents/agent/hitl/config.pyi +15 -0
  31. aip_agents/agent/hitl/langgraph_hitl_mixin.py +515 -0
  32. aip_agents/agent/hitl/langgraph_hitl_mixin.pyi +42 -0
  33. aip_agents/agent/hitl/manager.py +532 -0
  34. aip_agents/agent/hitl/manager.pyi +200 -0
  35. aip_agents/agent/hitl/models.py +18 -0
  36. aip_agents/agent/hitl/models.pyi +3 -0
  37. aip_agents/agent/hitl/prompt/__init__.py +9 -0
  38. aip_agents/agent/hitl/prompt/__init__.pyi +4 -0
  39. aip_agents/agent/hitl/prompt/base.py +42 -0
  40. aip_agents/agent/hitl/prompt/base.pyi +24 -0
  41. aip_agents/agent/hitl/prompt/deferred.py +73 -0
  42. aip_agents/agent/hitl/prompt/deferred.pyi +30 -0
  43. aip_agents/agent/hitl/registry.py +149 -0
  44. aip_agents/agent/hitl/registry.pyi +101 -0
  45. aip_agents/agent/interface.py +138 -0
  46. aip_agents/agent/interface.pyi +81 -0
  47. aip_agents/agent/interfaces.py +65 -0
  48. aip_agents/agent/interfaces.pyi +44 -0
  49. aip_agents/agent/langflow_agent.py +464 -0
  50. aip_agents/agent/langflow_agent.pyi +133 -0
  51. aip_agents/agent/langgraph_memory_enhancer_agent.py +433 -0
  52. aip_agents/agent/langgraph_memory_enhancer_agent.pyi +49 -0
  53. aip_agents/agent/langgraph_react_agent.py +2596 -0
  54. aip_agents/agent/langgraph_react_agent.pyi +131 -0
  55. aip_agents/agent/system_instruction_context.py +34 -0
  56. aip_agents/agent/system_instruction_context.pyi +13 -0
  57. aip_agents/clients/__init__.py +10 -0
  58. aip_agents/clients/__init__.pyi +4 -0
  59. aip_agents/clients/langflow/__init__.py +10 -0
  60. aip_agents/clients/langflow/__init__.pyi +4 -0
  61. aip_agents/clients/langflow/client.py +477 -0
  62. aip_agents/clients/langflow/client.pyi +140 -0
  63. aip_agents/clients/langflow/types.py +18 -0
  64. aip_agents/clients/langflow/types.pyi +7 -0
  65. aip_agents/constants.py +23 -0
  66. aip_agents/constants.pyi +7 -0
  67. aip_agents/credentials/manager.py +132 -0
  68. aip_agents/examples/__init__.py +5 -0
  69. aip_agents/examples/__init__.pyi +0 -0
  70. aip_agents/examples/compare_streaming_client.py +783 -0
  71. aip_agents/examples/compare_streaming_client.pyi +48 -0
  72. aip_agents/examples/compare_streaming_server.py +142 -0
  73. aip_agents/examples/compare_streaming_server.pyi +18 -0
  74. aip_agents/examples/demo_memory_recall.py +401 -0
  75. aip_agents/examples/demo_memory_recall.pyi +58 -0
  76. aip_agents/examples/hello_world_a2a_google_adk_client.py +49 -0
  77. aip_agents/examples/hello_world_a2a_google_adk_client.pyi +9 -0
  78. aip_agents/examples/hello_world_a2a_google_adk_client_agent.py +48 -0
  79. aip_agents/examples/hello_world_a2a_google_adk_client_agent.pyi +9 -0
  80. aip_agents/examples/hello_world_a2a_google_adk_client_streaming.py +60 -0
  81. aip_agents/examples/hello_world_a2a_google_adk_client_streaming.pyi +9 -0
  82. aip_agents/examples/hello_world_a2a_google_adk_server.py +79 -0
  83. aip_agents/examples/hello_world_a2a_google_adk_server.pyi +15 -0
  84. aip_agents/examples/hello_world_a2a_langchain_client.py +39 -0
  85. aip_agents/examples/hello_world_a2a_langchain_client.pyi +5 -0
  86. aip_agents/examples/hello_world_a2a_langchain_client_agent.py +39 -0
  87. aip_agents/examples/hello_world_a2a_langchain_client_agent.pyi +5 -0
  88. aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.py +37 -0
  89. aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.pyi +5 -0
  90. aip_agents/examples/hello_world_a2a_langchain_client_streaming.py +41 -0
  91. aip_agents/examples/hello_world_a2a_langchain_client_streaming.pyi +5 -0
  92. aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.py +60 -0
  93. aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.pyi +5 -0
  94. aip_agents/examples/hello_world_a2a_langchain_reference_server.py +105 -0
  95. aip_agents/examples/hello_world_a2a_langchain_reference_server.pyi +15 -0
  96. aip_agents/examples/hello_world_a2a_langchain_server.py +79 -0
  97. aip_agents/examples/hello_world_a2a_langchain_server.pyi +15 -0
  98. aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.py +78 -0
  99. aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.pyi +15 -0
  100. aip_agents/examples/hello_world_a2a_langflow_client.py +83 -0
  101. aip_agents/examples/hello_world_a2a_langflow_client.pyi +9 -0
  102. aip_agents/examples/hello_world_a2a_langflow_server.py +82 -0
  103. aip_agents/examples/hello_world_a2a_langflow_server.pyi +14 -0
  104. aip_agents/examples/hello_world_a2a_langgraph_artifact_client.py +73 -0
  105. aip_agents/examples/hello_world_a2a_langgraph_artifact_client.pyi +5 -0
  106. aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.py +76 -0
  107. aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.pyi +5 -0
  108. aip_agents/examples/hello_world_a2a_langgraph_artifact_server.py +92 -0
  109. aip_agents/examples/hello_world_a2a_langgraph_artifact_server.pyi +16 -0
  110. aip_agents/examples/hello_world_a2a_langgraph_client.py +54 -0
  111. aip_agents/examples/hello_world_a2a_langgraph_client.pyi +9 -0
  112. aip_agents/examples/hello_world_a2a_langgraph_client_agent.py +54 -0
  113. aip_agents/examples/hello_world_a2a_langgraph_client_agent.pyi +9 -0
  114. aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.py +32 -0
  115. aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.pyi +2 -0
  116. aip_agents/examples/hello_world_a2a_langgraph_client_streaming.py +50 -0
  117. aip_agents/examples/hello_world_a2a_langgraph_client_streaming.pyi +9 -0
  118. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.py +44 -0
  119. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.pyi +5 -0
  120. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.py +92 -0
  121. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.pyi +5 -0
  122. aip_agents/examples/hello_world_a2a_langgraph_server.py +84 -0
  123. aip_agents/examples/hello_world_a2a_langgraph_server.pyi +14 -0
  124. aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.py +79 -0
  125. aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.pyi +15 -0
  126. aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.py +132 -0
  127. aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.pyi +15 -0
  128. aip_agents/examples/hello_world_a2a_mcp_langgraph.py +196 -0
  129. aip_agents/examples/hello_world_a2a_mcp_langgraph.pyi +48 -0
  130. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.py +244 -0
  131. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.pyi +48 -0
  132. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.py +251 -0
  133. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.pyi +45 -0
  134. aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.py +57 -0
  135. aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.pyi +5 -0
  136. aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.py +80 -0
  137. aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.pyi +15 -0
  138. aip_agents/examples/hello_world_google_adk.py +41 -0
  139. aip_agents/examples/hello_world_google_adk.pyi +5 -0
  140. aip_agents/examples/hello_world_google_adk_mcp_http.py +34 -0
  141. aip_agents/examples/hello_world_google_adk_mcp_http.pyi +5 -0
  142. aip_agents/examples/hello_world_google_adk_mcp_http_stream.py +40 -0
  143. aip_agents/examples/hello_world_google_adk_mcp_http_stream.pyi +5 -0
  144. aip_agents/examples/hello_world_google_adk_mcp_sse.py +44 -0
  145. aip_agents/examples/hello_world_google_adk_mcp_sse.pyi +5 -0
  146. aip_agents/examples/hello_world_google_adk_mcp_sse_stream.py +48 -0
  147. aip_agents/examples/hello_world_google_adk_mcp_sse_stream.pyi +5 -0
  148. aip_agents/examples/hello_world_google_adk_mcp_stdio.py +44 -0
  149. aip_agents/examples/hello_world_google_adk_mcp_stdio.pyi +5 -0
  150. aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.py +48 -0
  151. aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.pyi +5 -0
  152. aip_agents/examples/hello_world_google_adk_stream.py +44 -0
  153. aip_agents/examples/hello_world_google_adk_stream.pyi +5 -0
  154. aip_agents/examples/hello_world_langchain.py +28 -0
  155. aip_agents/examples/hello_world_langchain.pyi +5 -0
  156. aip_agents/examples/hello_world_langchain_lm_invoker.py +15 -0
  157. aip_agents/examples/hello_world_langchain_lm_invoker.pyi +2 -0
  158. aip_agents/examples/hello_world_langchain_mcp_http.py +34 -0
  159. aip_agents/examples/hello_world_langchain_mcp_http.pyi +5 -0
  160. aip_agents/examples/hello_world_langchain_mcp_http_interactive.py +130 -0
  161. aip_agents/examples/hello_world_langchain_mcp_http_interactive.pyi +16 -0
  162. aip_agents/examples/hello_world_langchain_mcp_http_stream.py +42 -0
  163. aip_agents/examples/hello_world_langchain_mcp_http_stream.pyi +5 -0
  164. aip_agents/examples/hello_world_langchain_mcp_multi_server.py +155 -0
  165. aip_agents/examples/hello_world_langchain_mcp_multi_server.pyi +18 -0
  166. aip_agents/examples/hello_world_langchain_mcp_sse.py +34 -0
  167. aip_agents/examples/hello_world_langchain_mcp_sse.pyi +5 -0
  168. aip_agents/examples/hello_world_langchain_mcp_sse_stream.py +40 -0
  169. aip_agents/examples/hello_world_langchain_mcp_sse_stream.pyi +5 -0
  170. aip_agents/examples/hello_world_langchain_mcp_stdio.py +30 -0
  171. aip_agents/examples/hello_world_langchain_mcp_stdio.pyi +5 -0
  172. aip_agents/examples/hello_world_langchain_mcp_stdio_stream.py +41 -0
  173. aip_agents/examples/hello_world_langchain_mcp_stdio_stream.pyi +5 -0
  174. aip_agents/examples/hello_world_langchain_stream.py +36 -0
  175. aip_agents/examples/hello_world_langchain_stream.pyi +5 -0
  176. aip_agents/examples/hello_world_langchain_stream_lm_invoker.py +39 -0
  177. aip_agents/examples/hello_world_langchain_stream_lm_invoker.pyi +5 -0
  178. aip_agents/examples/hello_world_langflow_agent.py +163 -0
  179. aip_agents/examples/hello_world_langflow_agent.pyi +35 -0
  180. aip_agents/examples/hello_world_langgraph.py +39 -0
  181. aip_agents/examples/hello_world_langgraph.pyi +5 -0
  182. aip_agents/examples/hello_world_langgraph_gl_connector_twitter.py +44 -0
  183. aip_agents/examples/hello_world_langgraph_gl_connector_twitter.pyi +5 -0
  184. aip_agents/examples/hello_world_langgraph_mcp_http.py +31 -0
  185. aip_agents/examples/hello_world_langgraph_mcp_http.pyi +5 -0
  186. aip_agents/examples/hello_world_langgraph_mcp_http_stream.py +34 -0
  187. aip_agents/examples/hello_world_langgraph_mcp_http_stream.pyi +5 -0
  188. aip_agents/examples/hello_world_langgraph_mcp_sse.py +35 -0
  189. aip_agents/examples/hello_world_langgraph_mcp_sse.pyi +5 -0
  190. aip_agents/examples/hello_world_langgraph_mcp_sse_stream.py +50 -0
  191. aip_agents/examples/hello_world_langgraph_mcp_sse_stream.pyi +5 -0
  192. aip_agents/examples/hello_world_langgraph_mcp_stdio.py +35 -0
  193. aip_agents/examples/hello_world_langgraph_mcp_stdio.pyi +5 -0
  194. aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.py +50 -0
  195. aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.pyi +5 -0
  196. aip_agents/examples/hello_world_langgraph_stream.py +43 -0
  197. aip_agents/examples/hello_world_langgraph_stream.pyi +5 -0
  198. aip_agents/examples/hello_world_langgraph_stream_lm_invoker.py +37 -0
  199. aip_agents/examples/hello_world_langgraph_stream_lm_invoker.pyi +5 -0
  200. aip_agents/examples/hello_world_model_switch_cli.py +210 -0
  201. aip_agents/examples/hello_world_model_switch_cli.pyi +30 -0
  202. aip_agents/examples/hello_world_multi_agent_adk.py +75 -0
  203. aip_agents/examples/hello_world_multi_agent_adk.pyi +6 -0
  204. aip_agents/examples/hello_world_multi_agent_langchain.py +54 -0
  205. aip_agents/examples/hello_world_multi_agent_langchain.pyi +5 -0
  206. aip_agents/examples/hello_world_multi_agent_langgraph.py +66 -0
  207. aip_agents/examples/hello_world_multi_agent_langgraph.pyi +5 -0
  208. aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.py +69 -0
  209. aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.pyi +5 -0
  210. aip_agents/examples/hello_world_pii_logger.py +21 -0
  211. aip_agents/examples/hello_world_pii_logger.pyi +5 -0
  212. aip_agents/examples/hello_world_sentry.py +133 -0
  213. aip_agents/examples/hello_world_sentry.pyi +21 -0
  214. aip_agents/examples/hello_world_step_limits.py +273 -0
  215. aip_agents/examples/hello_world_step_limits.pyi +17 -0
  216. aip_agents/examples/hello_world_stock_a2a_server.py +103 -0
  217. aip_agents/examples/hello_world_stock_a2a_server.pyi +17 -0
  218. aip_agents/examples/hello_world_tool_output_client.py +46 -0
  219. aip_agents/examples/hello_world_tool_output_client.pyi +5 -0
  220. aip_agents/examples/hello_world_tool_output_server.py +114 -0
  221. aip_agents/examples/hello_world_tool_output_server.pyi +19 -0
  222. aip_agents/examples/hitl_demo.py +724 -0
  223. aip_agents/examples/hitl_demo.pyi +67 -0
  224. aip_agents/examples/mcp_configs/configs.py +63 -0
  225. aip_agents/examples/mcp_servers/common.py +76 -0
  226. aip_agents/examples/mcp_servers/mcp_name.py +29 -0
  227. aip_agents/examples/mcp_servers/mcp_server_http.py +19 -0
  228. aip_agents/examples/mcp_servers/mcp_server_sse.py +19 -0
  229. aip_agents/examples/mcp_servers/mcp_server_stdio.py +19 -0
  230. aip_agents/examples/mcp_servers/mcp_time.py +10 -0
  231. aip_agents/examples/pii_demo_langgraph_client.py +69 -0
  232. aip_agents/examples/pii_demo_langgraph_client.pyi +5 -0
  233. aip_agents/examples/pii_demo_langgraph_server.py +126 -0
  234. aip_agents/examples/pii_demo_langgraph_server.pyi +20 -0
  235. aip_agents/examples/pii_demo_multi_agent_client.py +80 -0
  236. aip_agents/examples/pii_demo_multi_agent_client.pyi +5 -0
  237. aip_agents/examples/pii_demo_multi_agent_server.py +247 -0
  238. aip_agents/examples/pii_demo_multi_agent_server.pyi +40 -0
  239. aip_agents/examples/todolist_planning_a2a_langchain_client.py +70 -0
  240. aip_agents/examples/todolist_planning_a2a_langchain_client.pyi +5 -0
  241. aip_agents/examples/todolist_planning_a2a_langgraph_server.py +88 -0
  242. aip_agents/examples/todolist_planning_a2a_langgraph_server.pyi +19 -0
  243. aip_agents/examples/tools/__init__.py +27 -0
  244. aip_agents/examples/tools/__init__.pyi +9 -0
  245. aip_agents/examples/tools/adk_arithmetic_tools.py +36 -0
  246. aip_agents/examples/tools/adk_arithmetic_tools.pyi +24 -0
  247. aip_agents/examples/tools/adk_weather_tool.py +60 -0
  248. aip_agents/examples/tools/adk_weather_tool.pyi +18 -0
  249. aip_agents/examples/tools/data_generator_tool.py +103 -0
  250. aip_agents/examples/tools/data_generator_tool.pyi +15 -0
  251. aip_agents/examples/tools/data_visualization_tool.py +312 -0
  252. aip_agents/examples/tools/data_visualization_tool.pyi +19 -0
  253. aip_agents/examples/tools/image_artifact_tool.py +136 -0
  254. aip_agents/examples/tools/image_artifact_tool.pyi +26 -0
  255. aip_agents/examples/tools/langchain_arithmetic_tools.py +26 -0
  256. aip_agents/examples/tools/langchain_arithmetic_tools.pyi +17 -0
  257. aip_agents/examples/tools/langchain_currency_exchange_tool.py +88 -0
  258. aip_agents/examples/tools/langchain_currency_exchange_tool.pyi +20 -0
  259. aip_agents/examples/tools/langchain_graph_artifact_tool.py +172 -0
  260. aip_agents/examples/tools/langchain_graph_artifact_tool.pyi +25 -0
  261. aip_agents/examples/tools/langchain_weather_tool.py +48 -0
  262. aip_agents/examples/tools/langchain_weather_tool.pyi +19 -0
  263. aip_agents/examples/tools/langgraph_streaming_tool.py +130 -0
  264. aip_agents/examples/tools/langgraph_streaming_tool.pyi +43 -0
  265. aip_agents/examples/tools/mock_retrieval_tool.py +56 -0
  266. aip_agents/examples/tools/mock_retrieval_tool.pyi +13 -0
  267. aip_agents/examples/tools/pii_demo_tools.py +189 -0
  268. aip_agents/examples/tools/pii_demo_tools.pyi +54 -0
  269. aip_agents/examples/tools/random_chart_tool.py +142 -0
  270. aip_agents/examples/tools/random_chart_tool.pyi +20 -0
  271. aip_agents/examples/tools/serper_tool.py +202 -0
  272. aip_agents/examples/tools/serper_tool.pyi +16 -0
  273. aip_agents/examples/tools/stock_tools.py +82 -0
  274. aip_agents/examples/tools/stock_tools.pyi +36 -0
  275. aip_agents/examples/tools/table_generator_tool.py +167 -0
  276. aip_agents/examples/tools/table_generator_tool.pyi +22 -0
  277. aip_agents/examples/tools/time_tool.py +82 -0
  278. aip_agents/examples/tools/time_tool.pyi +15 -0
  279. aip_agents/examples/tools/weather_forecast_tool.py +38 -0
  280. aip_agents/examples/tools/weather_forecast_tool.pyi +14 -0
  281. aip_agents/executor/agent_executor.py +473 -0
  282. aip_agents/executor/base.py +48 -0
  283. aip_agents/guardrails/__init__.py +83 -0
  284. aip_agents/guardrails/__init__.pyi +6 -0
  285. aip_agents/guardrails/engines/__init__.py +69 -0
  286. aip_agents/guardrails/engines/__init__.pyi +4 -0
  287. aip_agents/guardrails/engines/base.py +90 -0
  288. aip_agents/guardrails/engines/base.pyi +61 -0
  289. aip_agents/guardrails/engines/nemo.py +101 -0
  290. aip_agents/guardrails/engines/nemo.pyi +46 -0
  291. aip_agents/guardrails/engines/phrase_matcher.py +113 -0
  292. aip_agents/guardrails/engines/phrase_matcher.pyi +48 -0
  293. aip_agents/guardrails/exceptions.py +39 -0
  294. aip_agents/guardrails/exceptions.pyi +23 -0
  295. aip_agents/guardrails/manager.py +163 -0
  296. aip_agents/guardrails/manager.pyi +42 -0
  297. aip_agents/guardrails/middleware.py +199 -0
  298. aip_agents/guardrails/middleware.pyi +87 -0
  299. aip_agents/guardrails/schemas.py +63 -0
  300. aip_agents/guardrails/schemas.pyi +43 -0
  301. aip_agents/guardrails/utils.py +45 -0
  302. aip_agents/guardrails/utils.pyi +19 -0
  303. aip_agents/mcp/__init__.py +1 -0
  304. aip_agents/mcp/__init__.pyi +0 -0
  305. aip_agents/mcp/client/__init__.py +14 -0
  306. aip_agents/mcp/client/__init__.pyi +5 -0
  307. aip_agents/mcp/client/base_mcp_client.py +369 -0
  308. aip_agents/mcp/client/base_mcp_client.pyi +148 -0
  309. aip_agents/mcp/client/connection_manager.py +193 -0
  310. aip_agents/mcp/client/connection_manager.pyi +48 -0
  311. aip_agents/mcp/client/google_adk/__init__.py +11 -0
  312. aip_agents/mcp/client/google_adk/__init__.pyi +3 -0
  313. aip_agents/mcp/client/google_adk/client.py +381 -0
  314. aip_agents/mcp/client/google_adk/client.pyi +75 -0
  315. aip_agents/mcp/client/langchain/__init__.py +11 -0
  316. aip_agents/mcp/client/langchain/__init__.pyi +3 -0
  317. aip_agents/mcp/client/langchain/client.py +265 -0
  318. aip_agents/mcp/client/langchain/client.pyi +48 -0
  319. aip_agents/mcp/client/persistent_session.py +362 -0
  320. aip_agents/mcp/client/persistent_session.pyi +113 -0
  321. aip_agents/mcp/client/session_pool.py +351 -0
  322. aip_agents/mcp/client/session_pool.pyi +101 -0
  323. aip_agents/mcp/client/transports.py +228 -0
  324. aip_agents/mcp/client/transports.pyi +123 -0
  325. aip_agents/mcp/utils/__init__.py +7 -0
  326. aip_agents/mcp/utils/__init__.pyi +0 -0
  327. aip_agents/mcp/utils/config_validator.py +139 -0
  328. aip_agents/mcp/utils/config_validator.pyi +82 -0
  329. aip_agents/memory/__init__.py +14 -0
  330. aip_agents/memory/__init__.pyi +5 -0
  331. aip_agents/memory/adapters/__init__.py +10 -0
  332. aip_agents/memory/adapters/__init__.pyi +4 -0
  333. aip_agents/memory/adapters/base_adapter.py +717 -0
  334. aip_agents/memory/adapters/base_adapter.pyi +150 -0
  335. aip_agents/memory/adapters/mem0.py +84 -0
  336. aip_agents/memory/adapters/mem0.pyi +22 -0
  337. aip_agents/memory/base.py +84 -0
  338. aip_agents/memory/base.pyi +60 -0
  339. aip_agents/memory/constants.py +49 -0
  340. aip_agents/memory/constants.pyi +25 -0
  341. aip_agents/memory/factory.py +86 -0
  342. aip_agents/memory/factory.pyi +24 -0
  343. aip_agents/memory/guidance.py +20 -0
  344. aip_agents/memory/guidance.pyi +3 -0
  345. aip_agents/memory/simple_memory.py +47 -0
  346. aip_agents/memory/simple_memory.pyi +23 -0
  347. aip_agents/middleware/__init__.py +17 -0
  348. aip_agents/middleware/__init__.pyi +5 -0
  349. aip_agents/middleware/base.py +96 -0
  350. aip_agents/middleware/base.pyi +75 -0
  351. aip_agents/middleware/manager.py +150 -0
  352. aip_agents/middleware/manager.pyi +84 -0
  353. aip_agents/middleware/todolist.py +274 -0
  354. aip_agents/middleware/todolist.pyi +125 -0
  355. aip_agents/schema/__init__.py +69 -0
  356. aip_agents/schema/__init__.pyi +9 -0
  357. aip_agents/schema/a2a.py +56 -0
  358. aip_agents/schema/a2a.pyi +40 -0
  359. aip_agents/schema/agent.py +111 -0
  360. aip_agents/schema/agent.pyi +65 -0
  361. aip_agents/schema/hitl.py +157 -0
  362. aip_agents/schema/hitl.pyi +89 -0
  363. aip_agents/schema/langgraph.py +37 -0
  364. aip_agents/schema/langgraph.pyi +28 -0
  365. aip_agents/schema/model_id.py +97 -0
  366. aip_agents/schema/model_id.pyi +54 -0
  367. aip_agents/schema/step_limit.py +108 -0
  368. aip_agents/schema/step_limit.pyi +63 -0
  369. aip_agents/schema/storage.py +40 -0
  370. aip_agents/schema/storage.pyi +21 -0
  371. aip_agents/sentry/__init__.py +11 -0
  372. aip_agents/sentry/__init__.pyi +3 -0
  373. aip_agents/sentry/sentry.py +151 -0
  374. aip_agents/sentry/sentry.pyi +48 -0
  375. aip_agents/storage/__init__.py +41 -0
  376. aip_agents/storage/__init__.pyi +8 -0
  377. aip_agents/storage/base.py +85 -0
  378. aip_agents/storage/base.pyi +58 -0
  379. aip_agents/storage/clients/__init__.py +12 -0
  380. aip_agents/storage/clients/__init__.pyi +3 -0
  381. aip_agents/storage/clients/minio_client.py +318 -0
  382. aip_agents/storage/clients/minio_client.pyi +137 -0
  383. aip_agents/storage/config.py +62 -0
  384. aip_agents/storage/config.pyi +29 -0
  385. aip_agents/storage/providers/__init__.py +15 -0
  386. aip_agents/storage/providers/__init__.pyi +5 -0
  387. aip_agents/storage/providers/base.py +106 -0
  388. aip_agents/storage/providers/base.pyi +88 -0
  389. aip_agents/storage/providers/memory.py +114 -0
  390. aip_agents/storage/providers/memory.pyi +79 -0
  391. aip_agents/storage/providers/object_storage.py +214 -0
  392. aip_agents/storage/providers/object_storage.pyi +98 -0
  393. aip_agents/tools/__init__.py +53 -0
  394. aip_agents/tools/__init__.pyi +9 -0
  395. aip_agents/tools/browser_use/__init__.py +82 -0
  396. aip_agents/tools/browser_use/__init__.pyi +14 -0
  397. aip_agents/tools/browser_use/action_parser.py +103 -0
  398. aip_agents/tools/browser_use/action_parser.pyi +18 -0
  399. aip_agents/tools/browser_use/browser_use_tool.py +1112 -0
  400. aip_agents/tools/browser_use/browser_use_tool.pyi +50 -0
  401. aip_agents/tools/browser_use/llm_config.py +120 -0
  402. aip_agents/tools/browser_use/llm_config.pyi +52 -0
  403. aip_agents/tools/browser_use/minio_storage.py +198 -0
  404. aip_agents/tools/browser_use/minio_storage.pyi +109 -0
  405. aip_agents/tools/browser_use/schemas.py +119 -0
  406. aip_agents/tools/browser_use/schemas.pyi +32 -0
  407. aip_agents/tools/browser_use/session.py +76 -0
  408. aip_agents/tools/browser_use/session.pyi +4 -0
  409. aip_agents/tools/browser_use/session_errors.py +132 -0
  410. aip_agents/tools/browser_use/session_errors.pyi +53 -0
  411. aip_agents/tools/browser_use/steel_session_recording.py +317 -0
  412. aip_agents/tools/browser_use/steel_session_recording.pyi +63 -0
  413. aip_agents/tools/browser_use/streaming.py +813 -0
  414. aip_agents/tools/browser_use/streaming.pyi +81 -0
  415. aip_agents/tools/browser_use/structured_data_parser.py +257 -0
  416. aip_agents/tools/browser_use/structured_data_parser.pyi +86 -0
  417. aip_agents/tools/browser_use/structured_data_recovery.py +204 -0
  418. aip_agents/tools/browser_use/structured_data_recovery.pyi +43 -0
  419. aip_agents/tools/browser_use/types.py +78 -0
  420. aip_agents/tools/browser_use/types.pyi +45 -0
  421. aip_agents/tools/code_sandbox/__init__.py +26 -0
  422. aip_agents/tools/code_sandbox/__init__.pyi +3 -0
  423. aip_agents/tools/code_sandbox/constant.py +13 -0
  424. aip_agents/tools/code_sandbox/constant.pyi +4 -0
  425. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +306 -0
  426. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.pyi +102 -0
  427. aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +411 -0
  428. aip_agents/tools/code_sandbox/e2b_sandbox_tool.pyi +29 -0
  429. aip_agents/tools/constants.py +177 -0
  430. aip_agents/tools/constants.pyi +138 -0
  431. aip_agents/tools/document_loader/__init__.py +44 -0
  432. aip_agents/tools/document_loader/__init__.pyi +7 -0
  433. aip_agents/tools/document_loader/base_reader.py +302 -0
  434. aip_agents/tools/document_loader/base_reader.pyi +75 -0
  435. aip_agents/tools/document_loader/docx_reader_tool.py +68 -0
  436. aip_agents/tools/document_loader/docx_reader_tool.pyi +10 -0
  437. aip_agents/tools/document_loader/excel_reader_tool.py +171 -0
  438. aip_agents/tools/document_loader/excel_reader_tool.pyi +26 -0
  439. aip_agents/tools/document_loader/pdf_reader_tool.py +79 -0
  440. aip_agents/tools/document_loader/pdf_reader_tool.pyi +11 -0
  441. aip_agents/tools/document_loader/pdf_splitter.py +169 -0
  442. aip_agents/tools/document_loader/pdf_splitter.pyi +18 -0
  443. aip_agents/tools/gl_connector/__init__.py +5 -0
  444. aip_agents/tools/gl_connector/__init__.pyi +3 -0
  445. aip_agents/tools/gl_connector/tool.py +383 -0
  446. aip_agents/tools/gl_connector/tool.pyi +74 -0
  447. aip_agents/tools/gl_connector_tools.py +119 -0
  448. aip_agents/tools/gl_connector_tools.pyi +39 -0
  449. aip_agents/tools/memory_search/__init__.py +22 -0
  450. aip_agents/tools/memory_search/__init__.pyi +5 -0
  451. aip_agents/tools/memory_search/base.py +200 -0
  452. aip_agents/tools/memory_search/base.pyi +69 -0
  453. aip_agents/tools/memory_search/mem0.py +258 -0
  454. aip_agents/tools/memory_search/mem0.pyi +19 -0
  455. aip_agents/tools/memory_search/schema.py +48 -0
  456. aip_agents/tools/memory_search/schema.pyi +15 -0
  457. aip_agents/tools/memory_search_tool.py +26 -0
  458. aip_agents/tools/memory_search_tool.pyi +3 -0
  459. aip_agents/tools/time_tool.py +117 -0
  460. aip_agents/tools/time_tool.pyi +16 -0
  461. aip_agents/tools/tool_config_injector.py +300 -0
  462. aip_agents/tools/tool_config_injector.pyi +26 -0
  463. aip_agents/tools/web_search/__init__.py +15 -0
  464. aip_agents/tools/web_search/__init__.pyi +3 -0
  465. aip_agents/tools/web_search/serper_tool.py +187 -0
  466. aip_agents/tools/web_search/serper_tool.pyi +19 -0
  467. aip_agents/types/__init__.py +70 -0
  468. aip_agents/types/__init__.pyi +36 -0
  469. aip_agents/types/a2a_events.py +13 -0
  470. aip_agents/types/a2a_events.pyi +3 -0
  471. aip_agents/utils/__init__.py +79 -0
  472. aip_agents/utils/__init__.pyi +11 -0
  473. aip_agents/utils/a2a_connector.py +1757 -0
  474. aip_agents/utils/a2a_connector.pyi +146 -0
  475. aip_agents/utils/artifact_helpers.py +502 -0
  476. aip_agents/utils/artifact_helpers.pyi +203 -0
  477. aip_agents/utils/constants.py +22 -0
  478. aip_agents/utils/constants.pyi +10 -0
  479. aip_agents/utils/datetime/__init__.py +34 -0
  480. aip_agents/utils/datetime/__init__.pyi +4 -0
  481. aip_agents/utils/datetime/normalization.py +231 -0
  482. aip_agents/utils/datetime/normalization.pyi +95 -0
  483. aip_agents/utils/datetime/timezone.py +206 -0
  484. aip_agents/utils/datetime/timezone.pyi +48 -0
  485. aip_agents/utils/env_loader.py +27 -0
  486. aip_agents/utils/env_loader.pyi +10 -0
  487. aip_agents/utils/event_handler_registry.py +58 -0
  488. aip_agents/utils/event_handler_registry.pyi +23 -0
  489. aip_agents/utils/file_prompt_utils.py +176 -0
  490. aip_agents/utils/file_prompt_utils.pyi +21 -0
  491. aip_agents/utils/final_response_builder.py +211 -0
  492. aip_agents/utils/final_response_builder.pyi +34 -0
  493. aip_agents/utils/formatter_llm_client.py +231 -0
  494. aip_agents/utils/formatter_llm_client.pyi +71 -0
  495. aip_agents/utils/langgraph/__init__.py +19 -0
  496. aip_agents/utils/langgraph/__init__.pyi +3 -0
  497. aip_agents/utils/langgraph/converter.py +128 -0
  498. aip_agents/utils/langgraph/converter.pyi +49 -0
  499. aip_agents/utils/langgraph/tool_managers/__init__.py +15 -0
  500. aip_agents/utils/langgraph/tool_managers/__init__.pyi +5 -0
  501. aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.py +99 -0
  502. aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.pyi +35 -0
  503. aip_agents/utils/langgraph/tool_managers/base_tool_manager.py +66 -0
  504. aip_agents/utils/langgraph/tool_managers/base_tool_manager.pyi +48 -0
  505. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +1071 -0
  506. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.pyi +56 -0
  507. aip_agents/utils/langgraph/tool_output_management.py +967 -0
  508. aip_agents/utils/langgraph/tool_output_management.pyi +292 -0
  509. aip_agents/utils/logger.py +195 -0
  510. aip_agents/utils/logger.pyi +60 -0
  511. aip_agents/utils/metadata/__init__.py +27 -0
  512. aip_agents/utils/metadata/__init__.pyi +5 -0
  513. aip_agents/utils/metadata/activity_metadata_helper.py +407 -0
  514. aip_agents/utils/metadata/activity_metadata_helper.pyi +25 -0
  515. aip_agents/utils/metadata/activity_narrative/__init__.py +35 -0
  516. aip_agents/utils/metadata/activity_narrative/__init__.pyi +7 -0
  517. aip_agents/utils/metadata/activity_narrative/builder.py +817 -0
  518. aip_agents/utils/metadata/activity_narrative/builder.pyi +35 -0
  519. aip_agents/utils/metadata/activity_narrative/constants.py +51 -0
  520. aip_agents/utils/metadata/activity_narrative/constants.pyi +10 -0
  521. aip_agents/utils/metadata/activity_narrative/context.py +49 -0
  522. aip_agents/utils/metadata/activity_narrative/context.pyi +32 -0
  523. aip_agents/utils/metadata/activity_narrative/formatters.py +230 -0
  524. aip_agents/utils/metadata/activity_narrative/formatters.pyi +48 -0
  525. aip_agents/utils/metadata/activity_narrative/utils.py +35 -0
  526. aip_agents/utils/metadata/activity_narrative/utils.pyi +12 -0
  527. aip_agents/utils/metadata/schemas/__init__.py +16 -0
  528. aip_agents/utils/metadata/schemas/__init__.pyi +4 -0
  529. aip_agents/utils/metadata/schemas/activity_schema.py +29 -0
  530. aip_agents/utils/metadata/schemas/activity_schema.pyi +18 -0
  531. aip_agents/utils/metadata/schemas/thinking_schema.py +31 -0
  532. aip_agents/utils/metadata/schemas/thinking_schema.pyi +20 -0
  533. aip_agents/utils/metadata/thinking_metadata_helper.py +38 -0
  534. aip_agents/utils/metadata/thinking_metadata_helper.pyi +4 -0
  535. aip_agents/utils/metadata_helper.py +358 -0
  536. aip_agents/utils/metadata_helper.pyi +117 -0
  537. aip_agents/utils/name_preprocessor/__init__.py +17 -0
  538. aip_agents/utils/name_preprocessor/__init__.pyi +6 -0
  539. aip_agents/utils/name_preprocessor/base_name_preprocessor.py +73 -0
  540. aip_agents/utils/name_preprocessor/base_name_preprocessor.pyi +52 -0
  541. aip_agents/utils/name_preprocessor/google_name_preprocessor.py +100 -0
  542. aip_agents/utils/name_preprocessor/google_name_preprocessor.pyi +38 -0
  543. aip_agents/utils/name_preprocessor/name_preprocessor.py +87 -0
  544. aip_agents/utils/name_preprocessor/name_preprocessor.pyi +41 -0
  545. aip_agents/utils/name_preprocessor/openai_name_preprocessor.py +48 -0
  546. aip_agents/utils/name_preprocessor/openai_name_preprocessor.pyi +34 -0
  547. aip_agents/utils/pii/__init__.py +25 -0
  548. aip_agents/utils/pii/__init__.pyi +5 -0
  549. aip_agents/utils/pii/pii_handler.py +397 -0
  550. aip_agents/utils/pii/pii_handler.pyi +96 -0
  551. aip_agents/utils/pii/pii_helper.py +207 -0
  552. aip_agents/utils/pii/pii_helper.pyi +78 -0
  553. aip_agents/utils/pii/uuid_deanonymizer_mapping.py +195 -0
  554. aip_agents/utils/pii/uuid_deanonymizer_mapping.pyi +73 -0
  555. aip_agents/utils/reference_helper.py +273 -0
  556. aip_agents/utils/reference_helper.pyi +81 -0
  557. aip_agents/utils/sse_chunk_transformer.py +831 -0
  558. aip_agents/utils/sse_chunk_transformer.pyi +166 -0
  559. aip_agents/utils/step_limit_manager.py +265 -0
  560. aip_agents/utils/step_limit_manager.pyi +112 -0
  561. aip_agents/utils/token_usage_helper.py +156 -0
  562. aip_agents/utils/token_usage_helper.pyi +60 -0
  563. aip_agents_binary-0.5.25b1.dist-info/METADATA +681 -0
  564. aip_agents_binary-0.5.25b1.dist-info/RECORD +566 -0
  565. aip_agents_binary-0.5.25b1.dist-info/WHEEL +5 -0
  566. aip_agents_binary-0.5.25b1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,515 @@
1
+ """Mixin that encapsulates HITL helper logic for LangGraph agents."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Callable
6
+ from datetime import datetime
7
+ from typing import Any
8
+
9
+ from langchain_core.messages import ToolMessage
10
+ from langgraph.config import get_stream_writer
11
+ from langgraph.types import StreamWriter
12
+
13
+ from aip_agents.agent.hitl.config import ToolApprovalConfig
14
+ from aip_agents.agent.hitl.manager import ApprovalManager
15
+ from aip_agents.schema.hitl import ApprovalDecision, ApprovalDecisionType, ApprovalRequest, HitlMetadata
16
+ from aip_agents.schema.langgraph import ToolCallResult
17
+ from aip_agents.tools.tool_config_injector import TOOL_CONFIGS_KEY
18
+ from aip_agents.utils.datetime import ensure_utc_datetime
19
+ from aip_agents.utils.logger import get_logger
20
+
21
+ logger = get_logger(__name__)
22
+
23
+ MAX_CONTEXT_MESSAGE_LENGTH = 200
24
+
25
+
26
+ class LangGraphHitLMixin:
27
+ """Provide Human-in-the-Loop helpers for LangGraph agents."""
28
+
29
+ _hitl_manager: ApprovalManager | None
30
+ tool_configs: dict[str, Any] | None
31
+ name: str
32
+
33
+ @property
34
+ def hitl_manager(self) -> ApprovalManager | None:
35
+ """Return the active ``ApprovalManager``, creating one if needed."""
36
+ manager = getattr(self, "_hitl_manager", None)
37
+ if manager is not None:
38
+ return manager
39
+ return self._initialize_hitl_manager_if_needed()
40
+
41
+ @hitl_manager.setter
42
+ def hitl_manager(self, manager: ApprovalManager | None) -> None:
43
+ """Set the HITL approval manager instance.
44
+
45
+ Args:
46
+ manager: ApprovalManager instance or None.
47
+ """
48
+ self._hitl_manager = manager
49
+
50
+ async def _check_hitl_approval(
51
+ self,
52
+ tool_call: dict[str, Any],
53
+ tool_name: str,
54
+ state: dict[str, Any],
55
+ ) -> ApprovalDecision | None:
56
+ """Resolve approval gating for a tool call if HITL is configured.
57
+
58
+ Args:
59
+ tool_call: The tool call information containing id, name, and args.
60
+ tool_name: Name of the tool being executed.
61
+ state: Current agent state containing conversation context.
62
+
63
+ Returns:
64
+ ApprovalDecision if HITL is configured and decision is made, None otherwise.
65
+ """
66
+ hitl_config = self._get_hitl_config(tool_name)
67
+ manager = self.hitl_manager
68
+ if manager is None and hitl_config is not None:
69
+ manager = self._initialize_hitl_manager_for_tool(tool_name)
70
+
71
+ if manager is None or hitl_config is None:
72
+ return None
73
+
74
+ request = manager.create_approval_request(
75
+ tool_name=tool_name,
76
+ arguments=tool_call.get("args", {}),
77
+ config=hitl_config,
78
+ context=self._extract_hitl_context(state),
79
+ )
80
+
81
+ try:
82
+ decision = await manager.prompt_for_decision(
83
+ request=request,
84
+ timeout_seconds=hitl_config.timeout_seconds,
85
+ )
86
+ except Exception as exc: # noqa: BLE001
87
+ logger.warning(
88
+ "HITL approval check failed, proceeding with tool execution",
89
+ extra={"tool_name": tool_name, "error": str(exc), "error_type": type(exc).__name__},
90
+ )
91
+ return None
92
+
93
+ if decision.decision == ApprovalDecisionType.PENDING:
94
+ return await self._handle_pending_hitl_decision(
95
+ tool_call=tool_call,
96
+ pending_decision=decision,
97
+ request=request,
98
+ hitl_config=hitl_config,
99
+ state=state,
100
+ )
101
+
102
+ finalized_decision = self._finalize_hitl_decision(request, decision)
103
+ self._log_hitl_decision(tool_name, finalized_decision, state)
104
+ return finalized_decision
105
+
106
+ def _finalize_hitl_decision(
107
+ self,
108
+ request: ApprovalRequest,
109
+ decision: ApprovalDecision,
110
+ ) -> ApprovalDecision:
111
+ """Convert prompt handler output into a manager-recorded decision.
112
+
113
+ Args:
114
+ request: The approval request that was made.
115
+ decision: The decision returned by the prompt handler.
116
+
117
+ Returns:
118
+ Finalized ApprovalDecision recorded with the manager.
119
+ """
120
+ manager = self.hitl_manager
121
+ if manager is None:
122
+ return decision
123
+
124
+ operator_input = decision.operator_input or ""
125
+
126
+ if decision.decision == ApprovalDecisionType.PENDING:
127
+ return decision
128
+
129
+ if decision.decision == ApprovalDecisionType.TIMEOUT_SKIP:
130
+ return manager.timeout_request(
131
+ request,
132
+ operator_input=operator_input or "TIMEOUT",
133
+ )
134
+
135
+ decision_handlers = {
136
+ ApprovalDecisionType.APPROVED: manager.approve_request,
137
+ ApprovalDecisionType.REJECTED: manager.reject_request,
138
+ ApprovalDecisionType.SKIPPED: manager.skip_request,
139
+ }
140
+
141
+ handler = decision_handlers.get(decision.decision)
142
+ if handler:
143
+ return handler(request, operator_input)
144
+
145
+ return manager.skip_request(request, operator_input)
146
+
147
+ async def _handle_pending_hitl_decision(
148
+ self,
149
+ tool_call: dict[str, Any],
150
+ pending_decision: ApprovalDecision,
151
+ request: ApprovalRequest | None,
152
+ hitl_config: ToolApprovalConfig | None,
153
+ state: dict[str, Any],
154
+ ) -> ApprovalDecision:
155
+ """Emit a pending sentinel and wait for resolution from the manager.
156
+
157
+ Args:
158
+ tool_call: The tool call information that requires approval.
159
+ pending_decision: The initial pending decision from the prompt handler.
160
+ request: The approval request that was created.
161
+ hitl_config: Configuration for the HITL approval process.
162
+ state: Current agent state containing conversation context.
163
+
164
+ Returns:
165
+ Final approval decision after waiting for external resolution.
166
+ """
167
+ manager = self.hitl_manager
168
+ if manager is None or request is None or hitl_config is None:
169
+ return pending_decision
170
+
171
+ self._emit_hitl_pending_event(
172
+ tool_call=tool_call,
173
+ decision=pending_decision,
174
+ request=request,
175
+ hitl_config=hitl_config,
176
+ )
177
+
178
+ final_decision = await manager.wait_for_pending_decision(
179
+ request=request,
180
+ timeout_seconds=hitl_config.timeout_seconds,
181
+ )
182
+
183
+ self._log_hitl_decision(tool_call["name"], final_decision, state)
184
+ return final_decision
185
+
186
+ def _log_hitl_decision(self, tool_name: str, decision: ApprovalDecision, state: dict[str, Any]) -> None:
187
+ """Emit a structured log entry for a resolved HITL decision.
188
+
189
+ Args:
190
+ tool_name: Name of the tool that required approval.
191
+ decision: The final approval decision that was made.
192
+ state: Current agent state containing thread_id and other context.
193
+ """
194
+ manager = self.hitl_manager
195
+ if manager is None:
196
+ return
197
+
198
+ log_entry = manager.create_log_entry(
199
+ decision=decision,
200
+ tool_name=tool_name,
201
+ agent_id=getattr(self, "name", None),
202
+ thread_id=state.get("thread_id"),
203
+ )
204
+ logger.info("HITL decision recorded", extra=log_entry.__dict__)
205
+
206
+ def _emit_hitl_pending_event(
207
+ self,
208
+ tool_call: dict[str, Any],
209
+ decision: ApprovalDecision,
210
+ request: ApprovalRequest | None = None,
211
+ hitl_config: ToolApprovalConfig | None = None,
212
+ ) -> None:
213
+ """Send a streaming sentinel describing a pending HITL request.
214
+
215
+ Args:
216
+ tool_call: The tool call information that requires approval.
217
+ decision: The pending approval decision.
218
+ request: The approval request that was created.
219
+ hitl_config: Configuration for the HITL approval process.
220
+ """
221
+ # Pending uses the same sentinel builder as other blocking decisions so streaming stays consistent.
222
+ sentinel_result = self._create_hitl_blocking_result(
223
+ tool_call=tool_call,
224
+ decision=decision,
225
+ pending_request=request,
226
+ hitl_config=hitl_config,
227
+ )
228
+ if not sentinel_result.messages:
229
+ return
230
+
231
+ try:
232
+ writer: StreamWriter | None = get_stream_writer()
233
+ except Exception: # noqa: BLE001
234
+ writer = None
235
+
236
+ if writer is None:
237
+ return
238
+
239
+ event = self._create_tool_result_event(sentinel_result.messages[0])
240
+ try:
241
+ writer(event)
242
+ except Exception: # noqa: BLE001
243
+ logger.warning(f"Failed to emit HITL pending event: {tool_call['name']}")
244
+
245
+ def _get_hitl_config(self, tool_name: str) -> ToolApprovalConfig | None:
246
+ """Extract the HITL configuration for a tool from agent-level settings.
247
+
248
+ Args:
249
+ tool_name: Name of the tool to get HITL configuration for.
250
+
251
+ Returns:
252
+ ToolApprovalConfig if HITL is configured for the tool, None otherwise.
253
+ """
254
+ tool_configs = self.tool_configs
255
+ if not isinstance(tool_configs, dict):
256
+ return None
257
+
258
+ direct_config = self._get_direct_tool_hitl_config(tool_name)
259
+ if direct_config:
260
+ return direct_config
261
+
262
+ nested_config = self._get_nested_tool_hitl_config(tool_name)
263
+ if nested_config:
264
+ return nested_config
265
+
266
+ return None
267
+
268
+ def _get_direct_tool_hitl_config(self, tool_name: str) -> ToolApprovalConfig | None:
269
+ """Resolve HITL configuration using a direct tool name lookup.
270
+
271
+ Args:
272
+ tool_name: Name of the tool to get HITL configuration for.
273
+
274
+ Returns:
275
+ ToolApprovalConfig if found using direct lookup, None otherwise.
276
+ """
277
+ tool_configs = self.tool_configs or {}
278
+ tool_config = tool_configs.get(tool_name)
279
+ return self._parse_hitl_config_value(tool_config, tool_name)
280
+
281
+ def _get_nested_tool_hitl_config(self, tool_name: str) -> ToolApprovalConfig | None:
282
+ """Resolve HITL configuration from a nested ``tool_configs`` map.
283
+
284
+ Args:
285
+ tool_name: Name of the tool to get HITL configuration for.
286
+
287
+ Returns:
288
+ ToolApprovalConfig if found in nested configuration, None otherwise.
289
+ """
290
+ tool_configs = self.tool_configs or {}
291
+ nested_configs = tool_configs.get(TOOL_CONFIGS_KEY)
292
+ if not isinstance(nested_configs, dict):
293
+ return None
294
+
295
+ tool_config = nested_configs.get(tool_name)
296
+ return self._parse_hitl_config_value(tool_config, tool_name)
297
+
298
+ def _parse_hitl_config_value(self, value: Any, tool_name: str) -> ToolApprovalConfig | None:
299
+ """Convert a configuration value into ``ToolApprovalConfig`` if possible.
300
+
301
+ Args:
302
+ value: The configuration value to parse (can be ToolApprovalConfig, dict, or other).
303
+ tool_name: Name of the tool this configuration is for.
304
+
305
+ Returns:
306
+ ToolApprovalConfig if parsing succeeds, None otherwise.
307
+ """
308
+ if isinstance(value, ToolApprovalConfig):
309
+ return value
310
+
311
+ if isinstance(value, dict):
312
+ return self._parse_hitl_config_dict(value, tool_name)
313
+
314
+ return None
315
+
316
+ def _parse_hitl_config_dict(self, value: dict[str, Any], tool_name: str) -> ToolApprovalConfig | None:
317
+ """Construct ``ToolApprovalConfig`` from a dictionary of values.
318
+
319
+ Args:
320
+ value: Dictionary containing HITL configuration parameters.
321
+ tool_name: Name of the tool this configuration is for.
322
+
323
+ Returns:
324
+ ToolApprovalConfig if construction succeeds, None otherwise.
325
+ """
326
+ if "hitl" in value:
327
+ return self._parse_hitl_config_value(value["hitl"], tool_name)
328
+
329
+ allowed_keys = {"timeout_seconds", "requires_approval"}
330
+ if not set(value.keys()).issubset(allowed_keys):
331
+ return None
332
+
333
+ config_kwargs = dict(value)
334
+ config_kwargs.pop("requires_approval", None)
335
+ try:
336
+ return ToolApprovalConfig(**config_kwargs)
337
+ except (TypeError, ValueError):
338
+ return None
339
+
340
+ def ensure_hitl_manager(self) -> ApprovalManager | None:
341
+ """Ensure an ``ApprovalManager`` exists when HITL configs are present."""
342
+ return self._initialize_hitl_manager_if_needed()
343
+
344
+ def use_hitl_manager(self, manager: ApprovalManager) -> None:
345
+ """Replace the current ``ApprovalManager`` with the supplied instance.
346
+
347
+ Args:
348
+ manager: The ApprovalManager instance to use for HITL approvals.
349
+ """
350
+ self.hitl_manager = manager
351
+
352
+ def register_hitl_notifier(self, notifier: Callable[[ApprovalRequest], None]) -> None:
353
+ """Register a notifier callback to receive HITL approval requests.
354
+
355
+ Args:
356
+ notifier: Callback function that will be called with approval requests.
357
+ """
358
+ manager = self.ensure_hitl_manager()
359
+ if manager is None:
360
+ manager = self._create_default_hitl_manager()
361
+ self.hitl_manager = manager
362
+
363
+ handler = getattr(manager, "_prompt_handler", None)
364
+ if handler is None:
365
+ return
366
+
367
+ if hasattr(handler, "attach_manager"):
368
+ try:
369
+ handler.attach_manager(manager) # type: ignore[call-arg]
370
+ except Exception:
371
+ pass
372
+
373
+ try:
374
+ handler._notify = notifier
375
+ except Exception:
376
+ logger.warning("Failed to attach HITL notifier callback", extra={"agent": getattr(self, "name", None)})
377
+
378
+ def _initialize_hitl_manager_for_tool(self, tool_name: str) -> ApprovalManager | None:
379
+ """Create a default ``ApprovalManager`` for a specific tool if required.
380
+
381
+ Args:
382
+ tool_name: Name of the tool that requires HITL approval.
383
+
384
+ Returns:
385
+ ApprovalManager instance if HITL is needed, None otherwise.
386
+ """
387
+ return self._initialize_hitl_manager_if_needed(tool_name)
388
+
389
+ def _initialize_hitl_manager_if_needed(self, tool_name: str | None = None) -> ApprovalManager | None:
390
+ """Create a default ``ApprovalManager`` when HITL configs require it.
391
+
392
+ Args:
393
+ tool_name: Optional name of the tool that triggered the initialization.
394
+
395
+ Returns:
396
+ ApprovalManager instance if HITL is needed, None otherwise.
397
+ """
398
+ manager = getattr(self, "_hitl_manager", None)
399
+ if manager is not None:
400
+ return manager
401
+
402
+ candidate_names = {tool_name} if tool_name else self._collect_hitl_tool_names()
403
+ if candidate_names and any(self._get_hitl_config(name) for name in candidate_names):
404
+ self._hitl_manager = self._create_default_hitl_manager()
405
+ logger.debug("Agent '%s': HITL manager auto-initialized", self.name)
406
+
407
+ return getattr(self, "_hitl_manager", None)
408
+
409
+ def _collect_hitl_tool_names(self) -> set[str]:
410
+ """Gather candidate tool names that may have HITL configuration."""
411
+ names: set[str] = set()
412
+
413
+ try:
414
+ names.update(tool.name for tool in getattr(self, "resolved_tools", []) if getattr(tool, "name", None))
415
+ except Exception:
416
+ pass
417
+
418
+ tool_configs = getattr(self, "tool_configs", {})
419
+ if isinstance(tool_configs, dict):
420
+ for key, value in tool_configs.items():
421
+ if key != TOOL_CONFIGS_KEY and isinstance(value, dict):
422
+ names.add(str(key))
423
+
424
+ nested = tool_configs.get(TOOL_CONFIGS_KEY)
425
+ if isinstance(nested, dict):
426
+ names.update(str(k) for k in nested.keys())
427
+
428
+ return names
429
+
430
+ def _create_default_hitl_manager(self) -> ApprovalManager:
431
+ """Create the default ``ApprovalManager`` used for auto HITL handling."""
432
+ return ApprovalManager()
433
+
434
+ def _extract_hitl_context(self, state: dict[str, Any]) -> dict[str, str] | None:
435
+ """Collect human-readable context for approval prompts.
436
+
437
+ Args:
438
+ state: Current agent state containing messages and thread information.
439
+
440
+ Returns:
441
+ Dictionary containing context information like last user message and thread_id,
442
+ or None if no context is available.
443
+ """
444
+ context: dict[str, str] = {}
445
+
446
+ messages = state.get("messages", [])
447
+ for msg in reversed(messages):
448
+ if hasattr(msg, "type") and msg.type == "human":
449
+ content = getattr(msg, "content", "")
450
+ if content:
451
+ truncated_content = content[:MAX_CONTEXT_MESSAGE_LENGTH]
452
+ context["last_user_message"] = truncated_content
453
+ break
454
+
455
+ thread_id = state.get("thread_id")
456
+ if thread_id:
457
+ context["thread_id"] = str(thread_id)
458
+
459
+ return context or None
460
+
461
+ def _create_hitl_blocking_result(
462
+ self,
463
+ tool_call: dict[str, Any],
464
+ decision: ApprovalDecision,
465
+ pending_request: ApprovalRequest | None = None,
466
+ hitl_config: ToolApprovalConfig | None = None,
467
+ ) -> ToolCallResult:
468
+ """Build a sentinel ``ToolCallResult`` for any tool-execution-blocking HITL decision.
469
+
470
+ Covers ``REJECTED``, ``SKIPPED``, ``TIMEOUT_SKIP`` and ``PENDING`` decisions, providing a
471
+ consistent message payload for streaming and logging when execution does not proceed.
472
+
473
+ Args:
474
+ tool_call: The tool call information that was blocked.
475
+ decision: The approval decision that blocked execution.
476
+ pending_request: The approval request if decision is pending.
477
+ hitl_config: Configuration for the HITL approval process.
478
+
479
+ Returns:
480
+ ToolCallResult with sentinel messages and metadata for the blocking decision.
481
+ """
482
+ manager = self.hitl_manager
483
+ if manager is None:
484
+ return ToolCallResult(messages=[], artifacts=[], metadata_delta={}, references=[], step_usage=None)
485
+
486
+ tool_call_id = tool_call["id"]
487
+ message_content = manager.get_decision_message(decision)
488
+
489
+ timeout_seconds = None
490
+ if hitl_config and getattr(hitl_config, "timeout_seconds", None) is not None:
491
+ timeout_seconds = hitl_config.timeout_seconds
492
+
493
+ timeout_at = getattr(pending_request, "timeout_at", None)
494
+ timeout_at_utc = ensure_utc_datetime(timeout_at) if isinstance(timeout_at, datetime) else None
495
+
496
+ hitl_meta = HitlMetadata.from_decision(
497
+ decision,
498
+ timeout_seconds=timeout_seconds,
499
+ timeout_at=timeout_at_utc,
500
+ ).as_payload()
501
+
502
+ sentinel_message = ToolMessage(
503
+ content=message_content,
504
+ tool_call_id=tool_call_id,
505
+ name=tool_call["name"],
506
+ response_metadata={"hitl": hitl_meta},
507
+ )
508
+
509
+ return ToolCallResult(
510
+ messages=[sentinel_message],
511
+ artifacts=[],
512
+ metadata_delta={},
513
+ references=[],
514
+ step_usage=None,
515
+ )
@@ -0,0 +1,42 @@
1
+ from _typeshed import Incomplete
2
+ from aip_agents.agent.hitl.config import ToolApprovalConfig as ToolApprovalConfig
3
+ from aip_agents.agent.hitl.manager import ApprovalManager as ApprovalManager
4
+ from aip_agents.schema.hitl import ApprovalDecision as ApprovalDecision, ApprovalDecisionType as ApprovalDecisionType, ApprovalRequest as ApprovalRequest, HitlMetadata as HitlMetadata
5
+ from aip_agents.schema.langgraph import ToolCallResult as ToolCallResult
6
+ from aip_agents.tools.tool_config_injector import TOOL_CONFIGS_KEY as TOOL_CONFIGS_KEY
7
+ from aip_agents.utils.datetime import ensure_utc_datetime as ensure_utc_datetime
8
+ from aip_agents.utils.logger import get_logger as get_logger
9
+ from collections.abc import Callable
10
+ from typing import Any
11
+
12
+ logger: Incomplete
13
+ MAX_CONTEXT_MESSAGE_LENGTH: int
14
+
15
+ class LangGraphHitLMixin:
16
+ """Provide Human-in-the-Loop helpers for LangGraph agents."""
17
+ tool_configs: dict[str, Any] | None
18
+ name: str
19
+ @property
20
+ def hitl_manager(self) -> ApprovalManager | None:
21
+ """Return the active ``ApprovalManager``, creating one if needed."""
22
+ @hitl_manager.setter
23
+ def hitl_manager(self, manager: ApprovalManager | None) -> None:
24
+ """Set the HITL approval manager instance.
25
+
26
+ Args:
27
+ manager: ApprovalManager instance or None.
28
+ """
29
+ def ensure_hitl_manager(self) -> ApprovalManager | None:
30
+ """Ensure an ``ApprovalManager`` exists when HITL configs are present."""
31
+ def use_hitl_manager(self, manager: ApprovalManager) -> None:
32
+ """Replace the current ``ApprovalManager`` with the supplied instance.
33
+
34
+ Args:
35
+ manager: The ApprovalManager instance to use for HITL approvals.
36
+ """
37
+ def register_hitl_notifier(self, notifier: Callable[[ApprovalRequest], None]) -> None:
38
+ """Register a notifier callback to receive HITL approval requests.
39
+
40
+ Args:
41
+ notifier: Callback function that will be called with approval requests.
42
+ """