aip-agents-binary 0.6.4__py3-none-any.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.

Potentially problematic release.


This version of aip-agents-binary might be problematic. Click here for more details.

Files changed (612) 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 +3037 -0
  22. aip_agents/agent/base_langgraph_agent.pyi +233 -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 +767 -0
  52. aip_agents/agent/langgraph_memory_enhancer_agent.pyi +50 -0
  53. aip_agents/agent/langgraph_react_agent.py +2856 -0
  54. aip_agents/agent/langgraph_react_agent.pyi +170 -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/hello_world_a2a_google_adk_client.py +49 -0
  75. aip_agents/examples/hello_world_a2a_google_adk_client.pyi +9 -0
  76. aip_agents/examples/hello_world_a2a_google_adk_client_agent.py +48 -0
  77. aip_agents/examples/hello_world_a2a_google_adk_client_agent.pyi +9 -0
  78. aip_agents/examples/hello_world_a2a_google_adk_client_streaming.py +60 -0
  79. aip_agents/examples/hello_world_a2a_google_adk_client_streaming.pyi +9 -0
  80. aip_agents/examples/hello_world_a2a_google_adk_server.py +79 -0
  81. aip_agents/examples/hello_world_a2a_google_adk_server.pyi +15 -0
  82. aip_agents/examples/hello_world_a2a_langchain_client.py +39 -0
  83. aip_agents/examples/hello_world_a2a_langchain_client.pyi +5 -0
  84. aip_agents/examples/hello_world_a2a_langchain_client_agent.py +39 -0
  85. aip_agents/examples/hello_world_a2a_langchain_client_agent.pyi +5 -0
  86. aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.py +37 -0
  87. aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.pyi +5 -0
  88. aip_agents/examples/hello_world_a2a_langchain_client_streaming.py +41 -0
  89. aip_agents/examples/hello_world_a2a_langchain_client_streaming.pyi +5 -0
  90. aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.py +60 -0
  91. aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.pyi +5 -0
  92. aip_agents/examples/hello_world_a2a_langchain_reference_server.py +105 -0
  93. aip_agents/examples/hello_world_a2a_langchain_reference_server.pyi +15 -0
  94. aip_agents/examples/hello_world_a2a_langchain_server.py +79 -0
  95. aip_agents/examples/hello_world_a2a_langchain_server.pyi +15 -0
  96. aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.py +78 -0
  97. aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.pyi +15 -0
  98. aip_agents/examples/hello_world_a2a_langflow_client.py +83 -0
  99. aip_agents/examples/hello_world_a2a_langflow_client.pyi +9 -0
  100. aip_agents/examples/hello_world_a2a_langflow_server.py +82 -0
  101. aip_agents/examples/hello_world_a2a_langflow_server.pyi +14 -0
  102. aip_agents/examples/hello_world_a2a_langgraph_artifact_client.py +73 -0
  103. aip_agents/examples/hello_world_a2a_langgraph_artifact_client.pyi +5 -0
  104. aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.py +76 -0
  105. aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.pyi +5 -0
  106. aip_agents/examples/hello_world_a2a_langgraph_artifact_server.py +92 -0
  107. aip_agents/examples/hello_world_a2a_langgraph_artifact_server.pyi +16 -0
  108. aip_agents/examples/hello_world_a2a_langgraph_client.py +54 -0
  109. aip_agents/examples/hello_world_a2a_langgraph_client.pyi +9 -0
  110. aip_agents/examples/hello_world_a2a_langgraph_client_agent.py +54 -0
  111. aip_agents/examples/hello_world_a2a_langgraph_client_agent.pyi +9 -0
  112. aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.py +32 -0
  113. aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.pyi +2 -0
  114. aip_agents/examples/hello_world_a2a_langgraph_client_streaming.py +50 -0
  115. aip_agents/examples/hello_world_a2a_langgraph_client_streaming.pyi +9 -0
  116. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.py +44 -0
  117. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.pyi +5 -0
  118. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.py +92 -0
  119. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.pyi +5 -0
  120. aip_agents/examples/hello_world_a2a_langgraph_server.py +84 -0
  121. aip_agents/examples/hello_world_a2a_langgraph_server.pyi +14 -0
  122. aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.py +79 -0
  123. aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.pyi +15 -0
  124. aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.py +132 -0
  125. aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.pyi +15 -0
  126. aip_agents/examples/hello_world_a2a_mcp_langgraph.py +196 -0
  127. aip_agents/examples/hello_world_a2a_mcp_langgraph.pyi +48 -0
  128. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.py +244 -0
  129. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.pyi +48 -0
  130. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.py +251 -0
  131. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.pyi +45 -0
  132. aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.py +57 -0
  133. aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.pyi +5 -0
  134. aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.py +80 -0
  135. aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.pyi +15 -0
  136. aip_agents/examples/hello_world_google_adk.py +41 -0
  137. aip_agents/examples/hello_world_google_adk.pyi +5 -0
  138. aip_agents/examples/hello_world_google_adk_mcp_http.py +34 -0
  139. aip_agents/examples/hello_world_google_adk_mcp_http.pyi +5 -0
  140. aip_agents/examples/hello_world_google_adk_mcp_http_stream.py +40 -0
  141. aip_agents/examples/hello_world_google_adk_mcp_http_stream.pyi +5 -0
  142. aip_agents/examples/hello_world_google_adk_mcp_sse.py +44 -0
  143. aip_agents/examples/hello_world_google_adk_mcp_sse.pyi +5 -0
  144. aip_agents/examples/hello_world_google_adk_mcp_sse_stream.py +48 -0
  145. aip_agents/examples/hello_world_google_adk_mcp_sse_stream.pyi +5 -0
  146. aip_agents/examples/hello_world_google_adk_mcp_stdio.py +44 -0
  147. aip_agents/examples/hello_world_google_adk_mcp_stdio.pyi +5 -0
  148. aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.py +48 -0
  149. aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.pyi +5 -0
  150. aip_agents/examples/hello_world_google_adk_stream.py +44 -0
  151. aip_agents/examples/hello_world_google_adk_stream.pyi +5 -0
  152. aip_agents/examples/hello_world_langchain.py +28 -0
  153. aip_agents/examples/hello_world_langchain.pyi +5 -0
  154. aip_agents/examples/hello_world_langchain_lm_invoker.py +15 -0
  155. aip_agents/examples/hello_world_langchain_lm_invoker.pyi +2 -0
  156. aip_agents/examples/hello_world_langchain_mcp_http.py +34 -0
  157. aip_agents/examples/hello_world_langchain_mcp_http.pyi +5 -0
  158. aip_agents/examples/hello_world_langchain_mcp_http_interactive.py +130 -0
  159. aip_agents/examples/hello_world_langchain_mcp_http_interactive.pyi +16 -0
  160. aip_agents/examples/hello_world_langchain_mcp_http_stream.py +42 -0
  161. aip_agents/examples/hello_world_langchain_mcp_http_stream.pyi +5 -0
  162. aip_agents/examples/hello_world_langchain_mcp_multi_server.py +155 -0
  163. aip_agents/examples/hello_world_langchain_mcp_multi_server.pyi +18 -0
  164. aip_agents/examples/hello_world_langchain_mcp_sse.py +34 -0
  165. aip_agents/examples/hello_world_langchain_mcp_sse.pyi +5 -0
  166. aip_agents/examples/hello_world_langchain_mcp_sse_stream.py +40 -0
  167. aip_agents/examples/hello_world_langchain_mcp_sse_stream.pyi +5 -0
  168. aip_agents/examples/hello_world_langchain_mcp_stdio.py +30 -0
  169. aip_agents/examples/hello_world_langchain_mcp_stdio.pyi +5 -0
  170. aip_agents/examples/hello_world_langchain_mcp_stdio_stream.py +41 -0
  171. aip_agents/examples/hello_world_langchain_mcp_stdio_stream.pyi +5 -0
  172. aip_agents/examples/hello_world_langchain_stream.py +36 -0
  173. aip_agents/examples/hello_world_langchain_stream.pyi +5 -0
  174. aip_agents/examples/hello_world_langchain_stream_lm_invoker.py +39 -0
  175. aip_agents/examples/hello_world_langchain_stream_lm_invoker.pyi +5 -0
  176. aip_agents/examples/hello_world_langflow_agent.py +163 -0
  177. aip_agents/examples/hello_world_langflow_agent.pyi +35 -0
  178. aip_agents/examples/hello_world_langgraph.py +39 -0
  179. aip_agents/examples/hello_world_langgraph.pyi +5 -0
  180. aip_agents/examples/hello_world_langgraph_gl_connector_twitter.py +44 -0
  181. aip_agents/examples/hello_world_langgraph_gl_connector_twitter.pyi +5 -0
  182. aip_agents/examples/hello_world_langgraph_mcp_http.py +31 -0
  183. aip_agents/examples/hello_world_langgraph_mcp_http.pyi +5 -0
  184. aip_agents/examples/hello_world_langgraph_mcp_http_stream.py +34 -0
  185. aip_agents/examples/hello_world_langgraph_mcp_http_stream.pyi +5 -0
  186. aip_agents/examples/hello_world_langgraph_mcp_sse.py +35 -0
  187. aip_agents/examples/hello_world_langgraph_mcp_sse.pyi +5 -0
  188. aip_agents/examples/hello_world_langgraph_mcp_sse_stream.py +50 -0
  189. aip_agents/examples/hello_world_langgraph_mcp_sse_stream.pyi +5 -0
  190. aip_agents/examples/hello_world_langgraph_mcp_stdio.py +35 -0
  191. aip_agents/examples/hello_world_langgraph_mcp_stdio.pyi +5 -0
  192. aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.py +50 -0
  193. aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.pyi +5 -0
  194. aip_agents/examples/hello_world_langgraph_stream.py +43 -0
  195. aip_agents/examples/hello_world_langgraph_stream.pyi +5 -0
  196. aip_agents/examples/hello_world_langgraph_stream_lm_invoker.py +37 -0
  197. aip_agents/examples/hello_world_langgraph_stream_lm_invoker.pyi +5 -0
  198. aip_agents/examples/hello_world_model_switch_cli.py +210 -0
  199. aip_agents/examples/hello_world_model_switch_cli.pyi +30 -0
  200. aip_agents/examples/hello_world_multi_agent_adk.py +75 -0
  201. aip_agents/examples/hello_world_multi_agent_adk.pyi +6 -0
  202. aip_agents/examples/hello_world_multi_agent_langchain.py +54 -0
  203. aip_agents/examples/hello_world_multi_agent_langchain.pyi +5 -0
  204. aip_agents/examples/hello_world_multi_agent_langgraph.py +66 -0
  205. aip_agents/examples/hello_world_multi_agent_langgraph.pyi +5 -0
  206. aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.py +69 -0
  207. aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.pyi +5 -0
  208. aip_agents/examples/hello_world_pii_logger.py +21 -0
  209. aip_agents/examples/hello_world_pii_logger.pyi +5 -0
  210. aip_agents/examples/hello_world_ptc.py +49 -0
  211. aip_agents/examples/hello_world_ptc.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 +55 -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 +228 -0
  310. aip_agents/mcp/client/connection_manager.pyi +51 -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 +612 -0
  320. aip_agents/mcp/client/persistent_session.pyi +122 -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 +263 -0
  324. aip_agents/mcp/client/transports.pyi +132 -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 +811 -0
  334. aip_agents/memory/adapters/base_adapter.pyi +176 -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/ptc/__init__.py +48 -0
  356. aip_agents/ptc/__init__.pyi +10 -0
  357. aip_agents/ptc/doc_gen.py +122 -0
  358. aip_agents/ptc/doc_gen.pyi +40 -0
  359. aip_agents/ptc/exceptions.py +39 -0
  360. aip_agents/ptc/exceptions.pyi +22 -0
  361. aip_agents/ptc/executor.py +143 -0
  362. aip_agents/ptc/executor.pyi +73 -0
  363. aip_agents/ptc/mcp/__init__.py +45 -0
  364. aip_agents/ptc/mcp/__init__.pyi +7 -0
  365. aip_agents/ptc/mcp/sandbox_bridge.py +668 -0
  366. aip_agents/ptc/mcp/sandbox_bridge.pyi +47 -0
  367. aip_agents/ptc/mcp/templates/__init__.py +1 -0
  368. aip_agents/ptc/mcp/templates/__init__.pyi +0 -0
  369. aip_agents/ptc/mcp/templates/mcp_client.py.template +239 -0
  370. aip_agents/ptc/naming.py +184 -0
  371. aip_agents/ptc/naming.pyi +76 -0
  372. aip_agents/ptc/payload.py +26 -0
  373. aip_agents/ptc/payload.pyi +15 -0
  374. aip_agents/ptc/prompt_builder.py +571 -0
  375. aip_agents/ptc/prompt_builder.pyi +55 -0
  376. aip_agents/ptc/ptc_helper.py +16 -0
  377. aip_agents/ptc/ptc_helper.pyi +1 -0
  378. aip_agents/ptc/sandbox_bridge.py +58 -0
  379. aip_agents/ptc/sandbox_bridge.pyi +25 -0
  380. aip_agents/ptc/template_utils.py +33 -0
  381. aip_agents/ptc/template_utils.pyi +13 -0
  382. aip_agents/ptc/templates/__init__.py +1 -0
  383. aip_agents/ptc/templates/__init__.pyi +0 -0
  384. aip_agents/ptc/templates/ptc_helper.py.template +134 -0
  385. aip_agents/sandbox/__init__.py +43 -0
  386. aip_agents/sandbox/__init__.pyi +5 -0
  387. aip_agents/sandbox/defaults.py +9 -0
  388. aip_agents/sandbox/defaults.pyi +2 -0
  389. aip_agents/sandbox/e2b_runtime.py +267 -0
  390. aip_agents/sandbox/e2b_runtime.pyi +51 -0
  391. aip_agents/sandbox/template_builder.py +131 -0
  392. aip_agents/sandbox/template_builder.pyi +36 -0
  393. aip_agents/sandbox/types.py +24 -0
  394. aip_agents/sandbox/types.pyi +14 -0
  395. aip_agents/sandbox/validation.py +50 -0
  396. aip_agents/sandbox/validation.pyi +20 -0
  397. aip_agents/schema/__init__.py +69 -0
  398. aip_agents/schema/__init__.pyi +9 -0
  399. aip_agents/schema/a2a.py +56 -0
  400. aip_agents/schema/a2a.pyi +40 -0
  401. aip_agents/schema/agent.py +111 -0
  402. aip_agents/schema/agent.pyi +65 -0
  403. aip_agents/schema/hitl.py +157 -0
  404. aip_agents/schema/hitl.pyi +89 -0
  405. aip_agents/schema/langgraph.py +37 -0
  406. aip_agents/schema/langgraph.pyi +28 -0
  407. aip_agents/schema/model_id.py +97 -0
  408. aip_agents/schema/model_id.pyi +54 -0
  409. aip_agents/schema/step_limit.py +108 -0
  410. aip_agents/schema/step_limit.pyi +63 -0
  411. aip_agents/schema/storage.py +40 -0
  412. aip_agents/schema/storage.pyi +21 -0
  413. aip_agents/sentry/__init__.py +11 -0
  414. aip_agents/sentry/__init__.pyi +3 -0
  415. aip_agents/sentry/sentry.py +151 -0
  416. aip_agents/sentry/sentry.pyi +48 -0
  417. aip_agents/storage/__init__.py +41 -0
  418. aip_agents/storage/__init__.pyi +8 -0
  419. aip_agents/storage/base.py +85 -0
  420. aip_agents/storage/base.pyi +58 -0
  421. aip_agents/storage/clients/__init__.py +12 -0
  422. aip_agents/storage/clients/__init__.pyi +3 -0
  423. aip_agents/storage/clients/minio_client.py +318 -0
  424. aip_agents/storage/clients/minio_client.pyi +137 -0
  425. aip_agents/storage/config.py +62 -0
  426. aip_agents/storage/config.pyi +29 -0
  427. aip_agents/storage/providers/__init__.py +15 -0
  428. aip_agents/storage/providers/__init__.pyi +5 -0
  429. aip_agents/storage/providers/base.py +106 -0
  430. aip_agents/storage/providers/base.pyi +88 -0
  431. aip_agents/storage/providers/memory.py +114 -0
  432. aip_agents/storage/providers/memory.pyi +79 -0
  433. aip_agents/storage/providers/object_storage.py +214 -0
  434. aip_agents/storage/providers/object_storage.pyi +98 -0
  435. aip_agents/tools/__init__.py +64 -0
  436. aip_agents/tools/__init__.pyi +11 -0
  437. aip_agents/tools/browser_use/__init__.py +82 -0
  438. aip_agents/tools/browser_use/__init__.pyi +14 -0
  439. aip_agents/tools/browser_use/action_parser.py +103 -0
  440. aip_agents/tools/browser_use/action_parser.pyi +18 -0
  441. aip_agents/tools/browser_use/browser_use_tool.py +1120 -0
  442. aip_agents/tools/browser_use/browser_use_tool.pyi +50 -0
  443. aip_agents/tools/browser_use/llm_config.py +120 -0
  444. aip_agents/tools/browser_use/llm_config.pyi +52 -0
  445. aip_agents/tools/browser_use/minio_storage.py +198 -0
  446. aip_agents/tools/browser_use/minio_storage.pyi +109 -0
  447. aip_agents/tools/browser_use/schemas.py +119 -0
  448. aip_agents/tools/browser_use/schemas.pyi +32 -0
  449. aip_agents/tools/browser_use/session.py +76 -0
  450. aip_agents/tools/browser_use/session.pyi +4 -0
  451. aip_agents/tools/browser_use/session_errors.py +132 -0
  452. aip_agents/tools/browser_use/session_errors.pyi +53 -0
  453. aip_agents/tools/browser_use/steel_session_recording.py +317 -0
  454. aip_agents/tools/browser_use/steel_session_recording.pyi +63 -0
  455. aip_agents/tools/browser_use/streaming.py +815 -0
  456. aip_agents/tools/browser_use/streaming.pyi +81 -0
  457. aip_agents/tools/browser_use/structured_data_parser.py +257 -0
  458. aip_agents/tools/browser_use/structured_data_parser.pyi +86 -0
  459. aip_agents/tools/browser_use/structured_data_recovery.py +204 -0
  460. aip_agents/tools/browser_use/structured_data_recovery.pyi +43 -0
  461. aip_agents/tools/browser_use/types.py +78 -0
  462. aip_agents/tools/browser_use/types.pyi +45 -0
  463. aip_agents/tools/code_sandbox/__init__.py +26 -0
  464. aip_agents/tools/code_sandbox/__init__.pyi +3 -0
  465. aip_agents/tools/code_sandbox/constant.py +13 -0
  466. aip_agents/tools/code_sandbox/constant.pyi +4 -0
  467. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +306 -0
  468. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.pyi +102 -0
  469. aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +411 -0
  470. aip_agents/tools/code_sandbox/e2b_sandbox_tool.pyi +29 -0
  471. aip_agents/tools/constants.py +177 -0
  472. aip_agents/tools/constants.pyi +138 -0
  473. aip_agents/tools/date_range_tool.py +554 -0
  474. aip_agents/tools/date_range_tool.pyi +21 -0
  475. aip_agents/tools/document_loader/__init__.py +44 -0
  476. aip_agents/tools/document_loader/__init__.pyi +7 -0
  477. aip_agents/tools/document_loader/base_reader.py +302 -0
  478. aip_agents/tools/document_loader/base_reader.pyi +75 -0
  479. aip_agents/tools/document_loader/docx_reader_tool.py +68 -0
  480. aip_agents/tools/document_loader/docx_reader_tool.pyi +10 -0
  481. aip_agents/tools/document_loader/excel_reader_tool.py +171 -0
  482. aip_agents/tools/document_loader/excel_reader_tool.pyi +26 -0
  483. aip_agents/tools/document_loader/pdf_reader_tool.py +79 -0
  484. aip_agents/tools/document_loader/pdf_reader_tool.pyi +11 -0
  485. aip_agents/tools/document_loader/pdf_splitter.py +169 -0
  486. aip_agents/tools/document_loader/pdf_splitter.pyi +18 -0
  487. aip_agents/tools/execute_ptc_code.py +308 -0
  488. aip_agents/tools/execute_ptc_code.pyi +90 -0
  489. aip_agents/tools/gl_connector/__init__.py +5 -0
  490. aip_agents/tools/gl_connector/__init__.pyi +3 -0
  491. aip_agents/tools/gl_connector/tool.py +383 -0
  492. aip_agents/tools/gl_connector/tool.pyi +74 -0
  493. aip_agents/tools/gl_connector_tools.py +119 -0
  494. aip_agents/tools/gl_connector_tools.pyi +39 -0
  495. aip_agents/tools/memory_search/__init__.py +29 -0
  496. aip_agents/tools/memory_search/__init__.pyi +5 -0
  497. aip_agents/tools/memory_search/base.py +200 -0
  498. aip_agents/tools/memory_search/base.pyi +69 -0
  499. aip_agents/tools/memory_search/mem0.py +365 -0
  500. aip_agents/tools/memory_search/mem0.pyi +29 -0
  501. aip_agents/tools/memory_search/schema.py +81 -0
  502. aip_agents/tools/memory_search/schema.pyi +25 -0
  503. aip_agents/tools/memory_search_tool.py +34 -0
  504. aip_agents/tools/memory_search_tool.pyi +3 -0
  505. aip_agents/tools/time_tool.py +117 -0
  506. aip_agents/tools/time_tool.pyi +16 -0
  507. aip_agents/tools/tool_config_injector.py +300 -0
  508. aip_agents/tools/tool_config_injector.pyi +26 -0
  509. aip_agents/tools/web_search/__init__.py +15 -0
  510. aip_agents/tools/web_search/__init__.pyi +3 -0
  511. aip_agents/tools/web_search/serper_tool.py +187 -0
  512. aip_agents/tools/web_search/serper_tool.pyi +19 -0
  513. aip_agents/types/__init__.py +70 -0
  514. aip_agents/types/__init__.pyi +36 -0
  515. aip_agents/types/a2a_events.py +13 -0
  516. aip_agents/types/a2a_events.pyi +3 -0
  517. aip_agents/utils/__init__.py +79 -0
  518. aip_agents/utils/__init__.pyi +11 -0
  519. aip_agents/utils/a2a_connector.py +1757 -0
  520. aip_agents/utils/a2a_connector.pyi +146 -0
  521. aip_agents/utils/artifact_helpers.py +502 -0
  522. aip_agents/utils/artifact_helpers.pyi +203 -0
  523. aip_agents/utils/constants.py +22 -0
  524. aip_agents/utils/constants.pyi +10 -0
  525. aip_agents/utils/datetime/__init__.py +34 -0
  526. aip_agents/utils/datetime/__init__.pyi +4 -0
  527. aip_agents/utils/datetime/normalization.py +231 -0
  528. aip_agents/utils/datetime/normalization.pyi +95 -0
  529. aip_agents/utils/datetime/timezone.py +206 -0
  530. aip_agents/utils/datetime/timezone.pyi +48 -0
  531. aip_agents/utils/env_loader.py +27 -0
  532. aip_agents/utils/env_loader.pyi +10 -0
  533. aip_agents/utils/event_handler_registry.py +58 -0
  534. aip_agents/utils/event_handler_registry.pyi +23 -0
  535. aip_agents/utils/file_prompt_utils.py +176 -0
  536. aip_agents/utils/file_prompt_utils.pyi +21 -0
  537. aip_agents/utils/final_response_builder.py +211 -0
  538. aip_agents/utils/final_response_builder.pyi +34 -0
  539. aip_agents/utils/formatter_llm_client.py +231 -0
  540. aip_agents/utils/formatter_llm_client.pyi +71 -0
  541. aip_agents/utils/langgraph/__init__.py +19 -0
  542. aip_agents/utils/langgraph/__init__.pyi +3 -0
  543. aip_agents/utils/langgraph/converter.py +128 -0
  544. aip_agents/utils/langgraph/converter.pyi +49 -0
  545. aip_agents/utils/langgraph/tool_managers/__init__.py +15 -0
  546. aip_agents/utils/langgraph/tool_managers/__init__.pyi +5 -0
  547. aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.py +99 -0
  548. aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.pyi +35 -0
  549. aip_agents/utils/langgraph/tool_managers/base_tool_manager.py +66 -0
  550. aip_agents/utils/langgraph/tool_managers/base_tool_manager.pyi +48 -0
  551. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +1096 -0
  552. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.pyi +56 -0
  553. aip_agents/utils/langgraph/tool_output_management.py +1047 -0
  554. aip_agents/utils/langgraph/tool_output_management.pyi +329 -0
  555. aip_agents/utils/logger.py +195 -0
  556. aip_agents/utils/logger.pyi +60 -0
  557. aip_agents/utils/metadata/__init__.py +27 -0
  558. aip_agents/utils/metadata/__init__.pyi +5 -0
  559. aip_agents/utils/metadata/activity_metadata_helper.py +407 -0
  560. aip_agents/utils/metadata/activity_metadata_helper.pyi +25 -0
  561. aip_agents/utils/metadata/activity_narrative/__init__.py +35 -0
  562. aip_agents/utils/metadata/activity_narrative/__init__.pyi +7 -0
  563. aip_agents/utils/metadata/activity_narrative/builder.py +817 -0
  564. aip_agents/utils/metadata/activity_narrative/builder.pyi +35 -0
  565. aip_agents/utils/metadata/activity_narrative/constants.py +51 -0
  566. aip_agents/utils/metadata/activity_narrative/constants.pyi +10 -0
  567. aip_agents/utils/metadata/activity_narrative/context.py +49 -0
  568. aip_agents/utils/metadata/activity_narrative/context.pyi +32 -0
  569. aip_agents/utils/metadata/activity_narrative/formatters.py +230 -0
  570. aip_agents/utils/metadata/activity_narrative/formatters.pyi +48 -0
  571. aip_agents/utils/metadata/activity_narrative/utils.py +35 -0
  572. aip_agents/utils/metadata/activity_narrative/utils.pyi +12 -0
  573. aip_agents/utils/metadata/schemas/__init__.py +16 -0
  574. aip_agents/utils/metadata/schemas/__init__.pyi +4 -0
  575. aip_agents/utils/metadata/schemas/activity_schema.py +29 -0
  576. aip_agents/utils/metadata/schemas/activity_schema.pyi +18 -0
  577. aip_agents/utils/metadata/schemas/thinking_schema.py +31 -0
  578. aip_agents/utils/metadata/schemas/thinking_schema.pyi +20 -0
  579. aip_agents/utils/metadata/thinking_metadata_helper.py +38 -0
  580. aip_agents/utils/metadata/thinking_metadata_helper.pyi +4 -0
  581. aip_agents/utils/metadata_helper.py +358 -0
  582. aip_agents/utils/metadata_helper.pyi +117 -0
  583. aip_agents/utils/name_preprocessor/__init__.py +17 -0
  584. aip_agents/utils/name_preprocessor/__init__.pyi +6 -0
  585. aip_agents/utils/name_preprocessor/base_name_preprocessor.py +73 -0
  586. aip_agents/utils/name_preprocessor/base_name_preprocessor.pyi +52 -0
  587. aip_agents/utils/name_preprocessor/google_name_preprocessor.py +100 -0
  588. aip_agents/utils/name_preprocessor/google_name_preprocessor.pyi +38 -0
  589. aip_agents/utils/name_preprocessor/name_preprocessor.py +87 -0
  590. aip_agents/utils/name_preprocessor/name_preprocessor.pyi +41 -0
  591. aip_agents/utils/name_preprocessor/openai_name_preprocessor.py +48 -0
  592. aip_agents/utils/name_preprocessor/openai_name_preprocessor.pyi +34 -0
  593. aip_agents/utils/pii/__init__.py +25 -0
  594. aip_agents/utils/pii/__init__.pyi +5 -0
  595. aip_agents/utils/pii/pii_handler.py +397 -0
  596. aip_agents/utils/pii/pii_handler.pyi +96 -0
  597. aip_agents/utils/pii/pii_helper.py +207 -0
  598. aip_agents/utils/pii/pii_helper.pyi +78 -0
  599. aip_agents/utils/pii/uuid_deanonymizer_mapping.py +195 -0
  600. aip_agents/utils/pii/uuid_deanonymizer_mapping.pyi +73 -0
  601. aip_agents/utils/reference_helper.py +273 -0
  602. aip_agents/utils/reference_helper.pyi +81 -0
  603. aip_agents/utils/sse_chunk_transformer.py +831 -0
  604. aip_agents/utils/sse_chunk_transformer.pyi +166 -0
  605. aip_agents/utils/step_limit_manager.py +265 -0
  606. aip_agents/utils/step_limit_manager.pyi +112 -0
  607. aip_agents/utils/token_usage_helper.py +156 -0
  608. aip_agents/utils/token_usage_helper.pyi +60 -0
  609. aip_agents_binary-0.6.4.dist-info/METADATA +673 -0
  610. aip_agents_binary-0.6.4.dist-info/RECORD +612 -0
  611. aip_agents_binary-0.6.4.dist-info/WHEEL +5 -0
  612. aip_agents_binary-0.6.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,274 @@
1
+ """TodoList middleware for agent planning and task decomposition.
2
+
3
+ Provides a write_todos tool that allows agents to break down complex tasks
4
+ into discrete, trackable steps with status management.
5
+ """
6
+
7
+ import threading
8
+ from enum import StrEnum
9
+ from typing import Any
10
+
11
+ from langchain_core.runnables import RunnableConfig
12
+ from langchain_core.tools import BaseTool
13
+ from pydantic import BaseModel, Field, SkipValidation
14
+
15
+ from aip_agents.middleware.base import ModelRequest
16
+ from aip_agents.utils.logger import get_logger
17
+
18
+ logger = get_logger(__name__)
19
+
20
+
21
+ class TodoStatus(StrEnum):
22
+ """Enumeration of possible todo item statuses."""
23
+
24
+ PENDING = "pending"
25
+ IN_PROGRESS = "in_progress"
26
+ COMPLETED = "completed"
27
+
28
+
29
+ WRITE_TODOS_SYSTEM_PROMPT = """## Task Planning with `write_todos`
30
+
31
+ Use `write_todos` to plan and track complex multi-step objectives (3+ steps, multiple deliverables, or tasks described as "comprehensive"). Skip for trivial single-action requests.
32
+
33
+ **Execution rules:**
34
+ 1. Create the plan with `write_todos` BEFORE executing work
35
+ 2. Execute ALL tasks autonomously—do NOT pause to ask "should I continue?" or "would you like a preview?"
36
+ 3. Revise the plan as needed when new information emerges
37
+ 4. Mark tasks completed as you finish them
38
+ 5. **CRITICAL: Before your final response, call `write_todos` one last time to mark ALL tasks as `completed`. Never respond to the user while any task is `pending` or `in_progress`.**
39
+ """
40
+
41
+ EMPTY_TODO_REMINDER = (
42
+ "\n\n**Todo List Reminder:** Your todo list is currently empty. "
43
+ "If you are working on tasks that would benefit from a todo list, "
44
+ "use the write_todos tool to create one. This helps track progress "
45
+ "and ensures you don't forget important steps.\n"
46
+ )
47
+
48
+
49
+ class TodoItem(BaseModel):
50
+ """Represents a single todo item in the agent's plan.
51
+
52
+ Attributes:
53
+ content: Human-readable description of the task.
54
+ active_form: Short imperative phrase for UI display.
55
+ status: Current status of the todo item.
56
+ """
57
+
58
+ content: str = Field(description="Description of what needs to be done")
59
+ active_form: str = Field(description="Short active form for display (e.g., 'researching topic')")
60
+ status: TodoStatus = Field(default=TodoStatus.PENDING, description="Current status of this todo")
61
+
62
+
63
+ class TodoList(BaseModel):
64
+ """Represents a complete todo list for a thread.
65
+
66
+ Attributes:
67
+ items: List of todo items in order.
68
+ """
69
+
70
+ items: list[TodoItem] = Field(default_factory=list)
71
+
72
+
73
+ WRITE_TODOS_TOOL_DESCRIPTION = """Create and manage a structured task list for complex work sessions (3+ steps).
74
+
75
+ ## When to Use
76
+ - Multi-step tasks with 3+ distinct steps
77
+ - Requests with multiple deliverables
78
+ - User provides a list of tasks
79
+ - User explicitly requests a todo list
80
+
81
+ ## When to Skip
82
+ - Single straightforward action
83
+ - Trivial tasks with no tracking benefit
84
+
85
+ ## Task States
86
+ - `pending`: Not started
87
+ - `in_progress`: Currently working
88
+ - `completed`: Fully finished
89
+
90
+ ## Workflow
91
+ 1. **Plan first**: Call `write_todos` before executing work. Mark first task(s) as `in_progress`.
92
+ 2. **Stay autonomous**: Execute all tasks without pausing for user confirmation.
93
+ 3. **Adapt the plan**: Add new tasks as discovered, remove irrelevant ones.
94
+ 4. **Mark progress**: Update task status as you complete work.
95
+ 5. **Final update**: Before responding to user, call `write_todos` to mark ALL remaining tasks `completed`.
96
+
97
+ ## CRITICAL: Final Response Rule
98
+ You must NOT respond to the user until EVERY task is marked `completed`. Your final action before responding should be a `write_todos` call that marks the last task(s) complete. If any task remains `pending` or `in_progress`, you are not done—keep working or update the plan."""
99
+
100
+
101
+ class WriteTodosInput(BaseModel):
102
+ """Input schema for the write_todos tool."""
103
+
104
+ todos: TodoList = Field(
105
+ ...,
106
+ description="List of todo items, each with 'content' and 'activeForm' keys.",
107
+ )
108
+
109
+
110
+ class WriteTodosTool(BaseTool):
111
+ """LangChain-compatible tool for managing todo lists via TodoListMiddleware."""
112
+
113
+ name: str = "write_todos_tool"
114
+ description: str = WRITE_TODOS_TOOL_DESCRIPTION
115
+ args_schema: type[BaseModel] = WriteTodosInput
116
+
117
+ # Instance reference to middleware storage (excluded from serialization, skip validation)
118
+ storage: SkipValidation[dict[str, TodoList]] = Field(default_factory=dict, exclude=True)
119
+ storage_lock: SkipValidation[threading.RLock] = Field(default_factory=threading.RLock, exclude=True)
120
+
121
+ def _run(self, todos: TodoList, config: RunnableConfig | None = None) -> str: # type: ignore[override]
122
+ """Synchronous entrypoint used by generic tool runners.
123
+
124
+ Args:
125
+ todos: The todo list to write.
126
+ config: Optional configuration for the tool run.
127
+
128
+ Returns:
129
+ str: A success message indicating the number of todo items written.
130
+ """
131
+ tid = "default"
132
+ if config and "configurable" in config:
133
+ tid = config["configurable"].get("thread_id", "default")
134
+
135
+ try:
136
+ # Store in thread-safe manner
137
+ with self.storage_lock:
138
+ self.storage[tid] = todos
139
+
140
+ return f"Successfully wrote {len(todos.items)} todo items to your plan."
141
+ except Exception as e: # pragma: no cover - defensive
142
+ return f"Error writing todos: {str(e)}"
143
+
144
+
145
+ class TodoListMiddleware:
146
+ """Middleware that provides planning capabilities via todo list management.
147
+
148
+ Adds the write_todos tool and enhances the system prompt with planning
149
+ instructions, encouraging agents to break down complex tasks.
150
+
151
+ This middleware maintains thread-isolated todo lists, ensuring that
152
+ different conversation threads don't interfere with each other.
153
+
154
+ Each middleware instance has its own storage, preventing race conditions
155
+ when multiple agent instances are used concurrently.
156
+ """
157
+
158
+ def __init__(self) -> None:
159
+ """Initialize the TodoList middleware with planning tools and instructions."""
160
+ # Instance-level storage to prevent race conditions across agent instances
161
+ self._storage: dict[str, TodoList] = {}
162
+ self._storage_lock = threading.RLock()
163
+
164
+ # Create tool with reference to this instance's storage
165
+ self.tools = [WriteTodosTool(storage=self._storage, storage_lock=self._storage_lock)]
166
+ self.system_prompt_additions = WRITE_TODOS_SYSTEM_PROMPT
167
+
168
+ def before_model(self, state: dict[str, Any]) -> dict[str, Any]:
169
+ """Hook executed before model invocation.
170
+
171
+ Syncs todos FROM state TO internal storage for LangGraph agents.
172
+ This allows todos to be persisted via LangGraph checkpointer.
173
+
174
+ Args:
175
+ state: Current agent state (may contain 'todos' key).
176
+
177
+ Returns:
178
+ Empty dict (no state updates needed).
179
+ """
180
+ # Sync from LangGraph state to internal storage (if state has todos)
181
+ if "todos" in state and state["todos"] is not None:
182
+ thread_id = state.get("thread_id", "default")
183
+
184
+ # Deep copy to prevent mutation issues between state and storage
185
+ with self._storage_lock:
186
+ self._storage[thread_id] = state["todos"].model_copy(deep=True)
187
+
188
+ return {}
189
+
190
+ def modify_model_request(self, request: ModelRequest, state: dict[str, Any]) -> ModelRequest:
191
+ """Hook to modify model request before invocation.
192
+
193
+ Injects current todo list status into the system prompt, ensuring
194
+ the agent has visibility into its current plan on every turn.
195
+ This follows Claude Code's pattern of injecting system reminders.
196
+
197
+ Args:
198
+ request: The model request.
199
+ state: Current agent state.
200
+
201
+ Returns:
202
+ Modified request with todo status injected into system prompt.
203
+ """
204
+ thread_id = state.get("thread_id", "default")
205
+
206
+ # Get current todos from storage
207
+ with self._storage_lock:
208
+ current_todos = self._storage.get(thread_id)
209
+
210
+ # Inject todo status into system prompt
211
+ if current_todos and current_todos.items:
212
+ # Build todo status reminder
213
+ todo_reminder = "\n\n## Current Todo List Status\n\n"
214
+ todo_reminder += "Your current todo list:\n"
215
+
216
+ for item in current_todos.items:
217
+ todo_reminder += f"[{item.status.value.upper()}] {item.content}\n"
218
+
219
+ todo_reminder += "\n**Remember to update the todo list as you complete tasks using write_todos.**\n"
220
+
221
+ # Append to system prompt
222
+ current_system_prompt = request.get("system_prompt", "")
223
+ request["system_prompt"] = current_system_prompt + todo_reminder
224
+ else:
225
+ # Static reminder when no todos exist
226
+ current_system_prompt = request.get("system_prompt", "")
227
+ request["system_prompt"] = current_system_prompt + EMPTY_TODO_REMINDER
228
+
229
+ return request
230
+
231
+ def after_model(self, state: dict[str, Any]) -> dict[str, Any]:
232
+ """Hook executed after model invocation.
233
+
234
+ Syncs todos FROM internal storage TO state for LangGraph agents.
235
+ This ensures any tool updates are reflected in the checkpointed state.
236
+
237
+ Args:
238
+ state: Current agent state.
239
+
240
+ Returns:
241
+ Dict with 'todos' key containing updated TodoList, or empty dict.
242
+ """
243
+ thread_id = state.get("thread_id", "default")
244
+
245
+ with self._storage_lock:
246
+ if thread_id in self._storage:
247
+ # Deep copy to prevent mutation issues between storage and state
248
+ return {"todos": self._storage[thread_id].model_copy(deep=True)}
249
+
250
+ return {}
251
+
252
+ def get_todos(self, thread_id: str = "default") -> TodoList:
253
+ """Retrieve the todo list for a specific thread.
254
+
255
+ Args:
256
+ thread_id: Thread identifier. Defaults to "default".
257
+
258
+ Returns:
259
+ TodoList for the thread, or empty list if none exists.
260
+ """
261
+ with self._storage_lock:
262
+ return self._storage.get(thread_id, TodoList())
263
+
264
+ def clear_todos(self, thread_id: str = "default") -> None:
265
+ """Clear the todo list for a specific thread.
266
+
267
+ Useful for cleanup between test runs or conversation resets.
268
+
269
+ Args:
270
+ thread_id: Thread identifier. Defaults to "default".
271
+ """
272
+ with self._storage_lock:
273
+ if thread_id in self._storage:
274
+ del self._storage[thread_id]
@@ -0,0 +1,125 @@
1
+ import threading
2
+ from _typeshed import Incomplete
3
+ from aip_agents.middleware.base import ModelRequest as ModelRequest
4
+ from aip_agents.utils.logger import get_logger as get_logger
5
+ from enum import StrEnum
6
+ from langchain_core.tools import BaseTool
7
+ from pydantic import BaseModel, SkipValidation
8
+ from typing import Any
9
+
10
+ logger: Incomplete
11
+
12
+ class TodoStatus(StrEnum):
13
+ """Enumeration of possible todo item statuses."""
14
+ PENDING: str
15
+ IN_PROGRESS: str
16
+ COMPLETED: str
17
+
18
+ WRITE_TODOS_SYSTEM_PROMPT: str
19
+ EMPTY_TODO_REMINDER: str
20
+
21
+ class TodoItem(BaseModel):
22
+ """Represents a single todo item in the agent's plan.
23
+
24
+ Attributes:
25
+ content: Human-readable description of the task.
26
+ active_form: Short imperative phrase for UI display.
27
+ status: Current status of the todo item.
28
+ """
29
+ content: str
30
+ active_form: str
31
+ status: TodoStatus
32
+
33
+ class TodoList(BaseModel):
34
+ """Represents a complete todo list for a thread.
35
+
36
+ Attributes:
37
+ items: List of todo items in order.
38
+ """
39
+ items: list[TodoItem]
40
+
41
+ WRITE_TODOS_TOOL_DESCRIPTION: str
42
+
43
+ class WriteTodosInput(BaseModel):
44
+ """Input schema for the write_todos tool."""
45
+ todos: TodoList
46
+
47
+ class WriteTodosTool(BaseTool):
48
+ """LangChain-compatible tool for managing todo lists via TodoListMiddleware."""
49
+ name: str
50
+ description: str
51
+ args_schema: type[BaseModel]
52
+ storage: SkipValidation[dict[str, TodoList]]
53
+ storage_lock: SkipValidation[threading.RLock]
54
+
55
+ class TodoListMiddleware:
56
+ """Middleware that provides planning capabilities via todo list management.
57
+
58
+ Adds the write_todos tool and enhances the system prompt with planning
59
+ instructions, encouraging agents to break down complex tasks.
60
+
61
+ This middleware maintains thread-isolated todo lists, ensuring that
62
+ different conversation threads don't interfere with each other.
63
+
64
+ Each middleware instance has its own storage, preventing race conditions
65
+ when multiple agent instances are used concurrently.
66
+ """
67
+ tools: Incomplete
68
+ system_prompt_additions: Incomplete
69
+ def __init__(self) -> None:
70
+ """Initialize the TodoList middleware with planning tools and instructions."""
71
+ def before_model(self, state: dict[str, Any]) -> dict[str, Any]:
72
+ """Hook executed before model invocation.
73
+
74
+ Syncs todos FROM state TO internal storage for LangGraph agents.
75
+ This allows todos to be persisted via LangGraph checkpointer.
76
+
77
+ Args:
78
+ state: Current agent state (may contain 'todos' key).
79
+
80
+ Returns:
81
+ Empty dict (no state updates needed).
82
+ """
83
+ def modify_model_request(self, request: ModelRequest, state: dict[str, Any]) -> ModelRequest:
84
+ """Hook to modify model request before invocation.
85
+
86
+ Injects current todo list status into the system prompt, ensuring
87
+ the agent has visibility into its current plan on every turn.
88
+ This follows Claude Code's pattern of injecting system reminders.
89
+
90
+ Args:
91
+ request: The model request.
92
+ state: Current agent state.
93
+
94
+ Returns:
95
+ Modified request with todo status injected into system prompt.
96
+ """
97
+ def after_model(self, state: dict[str, Any]) -> dict[str, Any]:
98
+ """Hook executed after model invocation.
99
+
100
+ Syncs todos FROM internal storage TO state for LangGraph agents.
101
+ This ensures any tool updates are reflected in the checkpointed state.
102
+
103
+ Args:
104
+ state: Current agent state.
105
+
106
+ Returns:
107
+ Dict with 'todos' key containing updated TodoList, or empty dict.
108
+ """
109
+ def get_todos(self, thread_id: str = 'default') -> TodoList:
110
+ '''Retrieve the todo list for a specific thread.
111
+
112
+ Args:
113
+ thread_id: Thread identifier. Defaults to "default".
114
+
115
+ Returns:
116
+ TodoList for the thread, or empty list if none exists.
117
+ '''
118
+ def clear_todos(self, thread_id: str = 'default') -> None:
119
+ '''Clear the todo list for a specific thread.
120
+
121
+ Useful for cleanup between test runs or conversation resets.
122
+
123
+ Args:
124
+ thread_id: Thread identifier. Defaults to "default".
125
+ '''
@@ -0,0 +1,48 @@
1
+ """PTC (Programmatic Tool Calling) core module (MCP-only).
2
+
3
+ This module provides the core PTC functionality for MCP tools, including
4
+ executor, prompt builder, and sandbox bridge.
5
+
6
+ Authors:
7
+ Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
8
+ """
9
+
10
+ from aip_agents.ptc.exceptions import PTCError, PTCToolError
11
+ from aip_agents.ptc.prompt_builder import PromptConfig, build_ptc_prompt, compute_ptc_prompt_hash
12
+
13
+ __all__ = [
14
+ # Exceptions
15
+ "PTCError",
16
+ "PTCToolError",
17
+ # Executor
18
+ "PTCSandboxConfig",
19
+ "PTCSandboxExecutor",
20
+ # Prompt builder
21
+ "PromptConfig",
22
+ "build_ptc_prompt",
23
+ "compute_ptc_prompt_hash",
24
+ # Sandbox bridge
25
+ "build_sandbox_payload",
26
+ "wrap_ptc_code",
27
+ ]
28
+
29
+
30
+ def __getattr__(name: str):
31
+ """Lazy import to avoid circular dependencies."""
32
+ if name == "PTCSandboxConfig":
33
+ from aip_agents.ptc.executor import PTCSandboxConfig
34
+
35
+ return PTCSandboxConfig
36
+ elif name == "PTCSandboxExecutor":
37
+ from aip_agents.ptc.executor import PTCSandboxExecutor
38
+
39
+ return PTCSandboxExecutor
40
+ elif name == "build_sandbox_payload":
41
+ from aip_agents.ptc.sandbox_bridge import build_sandbox_payload
42
+
43
+ return build_sandbox_payload
44
+ elif name == "wrap_ptc_code":
45
+ from aip_agents.ptc.sandbox_bridge import wrap_ptc_code
46
+
47
+ return wrap_ptc_code
48
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
@@ -0,0 +1,10 @@
1
+ from aip_agents.ptc.exceptions import PTCError as PTCError, PTCToolError as PTCToolError
2
+ from aip_agents.ptc.prompt_builder import PromptConfig as PromptConfig, build_ptc_prompt as build_ptc_prompt, compute_ptc_prompt_hash as compute_ptc_prompt_hash
3
+
4
+ __all__ = ['PTCError', 'PTCToolError', 'PTCSandboxConfig', 'PTCSandboxExecutor', 'PromptConfig', 'build_ptc_prompt', 'compute_ptc_prompt_hash', 'build_sandbox_payload', 'wrap_ptc_code']
5
+
6
+ # Names in __all__ with no definition:
7
+ # PTCSandboxConfig
8
+ # PTCSandboxExecutor
9
+ # build_sandbox_payload
10
+ # wrap_ptc_code
@@ -0,0 +1,122 @@
1
+ """Documentation generation utilities for PTC.
2
+
3
+ Shared constants and helpers for generating tool documentation in sandbox payloads.
4
+
5
+ Authors:
6
+ Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
7
+ """
8
+
9
+ from typing import Any
10
+
11
+ from aip_agents.ptc.naming import sanitize_function_name
12
+
13
+ # Documentation limits (fixed constants per plan)
14
+ DOC_DESC_LIMIT = 120 # Tool description trim limit
15
+ DOC_PARAM_DESC_LIMIT = 80 # Parameter description trim limit
16
+
17
+
18
+ def json_type_to_display(json_type: Any) -> str:
19
+ """Convert JSON type to display string.
20
+
21
+ Args:
22
+ json_type: JSON schema type.
23
+
24
+ Returns:
25
+ Human-readable type string.
26
+ """
27
+ if isinstance(json_type, list):
28
+ return "any"
29
+ type_map = {
30
+ "string": "str",
31
+ "integer": "int",
32
+ "number": "float",
33
+ "boolean": "bool",
34
+ "array": "list",
35
+ "object": "dict",
36
+ "null": "None",
37
+ }
38
+ return type_map.get(str(json_type), "any")
39
+
40
+
41
+ def trim_text(text: str | None, limit: int) -> str:
42
+ """Trim text to limit with ellipsis if needed.
43
+
44
+ Args:
45
+ text: Text to trim.
46
+ limit: Maximum length before trimming.
47
+
48
+ Returns:
49
+ Trimmed text.
50
+ """
51
+ if not text:
52
+ return ""
53
+ if len(text) > limit:
54
+ return text[:limit] + "..."
55
+ return text
56
+
57
+
58
+ def render_tool_doc(
59
+ func_name: str,
60
+ signature: str,
61
+ description: str,
62
+ schema: dict[str, Any],
63
+ is_stub: bool = False,
64
+ example_code: str | None = None,
65
+ example_heading: str = "## Example",
66
+ ) -> str:
67
+ """Render markdown documentation for a tool.
68
+
69
+ Args:
70
+ func_name: Sanitized function name.
71
+ signature: Full function signature.
72
+ description: Tool description.
73
+ schema: Input schema for parameters.
74
+ is_stub: Whether this is a stub documentation.
75
+ example_code: Optional example code block content (without ```python).
76
+ example_heading: Heading for the example section.
77
+
78
+ Returns:
79
+ Markdown documentation string.
80
+ """
81
+ if is_stub:
82
+ desc = "Details unavailable because tool definitions are not loaded yet."
83
+ else:
84
+ desc = trim_text(description, DOC_DESC_LIMIT) or "No description available."
85
+
86
+ lines = [
87
+ f"# {func_name}",
88
+ "",
89
+ f"**Description:** {desc}",
90
+ "",
91
+ f"**Signature:** `{signature}`",
92
+ "",
93
+ ]
94
+
95
+ # Add parameters section
96
+ properties = schema.get("properties", {})
97
+ required = set(schema.get("required", []))
98
+
99
+ if properties:
100
+ lines.append("## Parameters")
101
+ lines.append("")
102
+ for prop_name, prop_schema in sorted(properties.items()):
103
+ safe_param = sanitize_function_name(prop_name)
104
+ prop_type = json_type_to_display(prop_schema.get("type", "any"))
105
+ is_required = "required" if prop_name in required else "optional"
106
+
107
+ # Trim param description
108
+ raw_param_desc = prop_schema.get("description", "")
109
+ param_desc = trim_text(raw_param_desc, DOC_PARAM_DESC_LIMIT)
110
+
111
+ lines.append(f"- **{safe_param}** ({prop_type}, {is_required}): {param_desc}")
112
+ lines.append("")
113
+
114
+ # Add example section
115
+ if example_code:
116
+ lines.append(example_heading)
117
+ lines.append("")
118
+ lines.append("```python")
119
+ lines.append(example_code)
120
+ lines.append("```")
121
+
122
+ return "\n".join(lines)
@@ -0,0 +1,40 @@
1
+ from aip_agents.ptc.naming import sanitize_function_name as sanitize_function_name
2
+ from typing import Any
3
+
4
+ DOC_DESC_LIMIT: int
5
+ DOC_PARAM_DESC_LIMIT: int
6
+
7
+ def json_type_to_display(json_type: Any) -> str:
8
+ """Convert JSON type to display string.
9
+
10
+ Args:
11
+ json_type: JSON schema type.
12
+
13
+ Returns:
14
+ Human-readable type string.
15
+ """
16
+ def trim_text(text: str | None, limit: int) -> str:
17
+ """Trim text to limit with ellipsis if needed.
18
+
19
+ Args:
20
+ text: Text to trim.
21
+ limit: Maximum length before trimming.
22
+
23
+ Returns:
24
+ Trimmed text.
25
+ """
26
+ def render_tool_doc(func_name: str, signature: str, description: str, schema: dict[str, Any], is_stub: bool = False, example_code: str | None = None, example_heading: str = '## Example') -> str:
27
+ """Render markdown documentation for a tool.
28
+
29
+ Args:
30
+ func_name: Sanitized function name.
31
+ signature: Full function signature.
32
+ description: Tool description.
33
+ schema: Input schema for parameters.
34
+ is_stub: Whether this is a stub documentation.
35
+ example_code: Optional example code block content (without ```python).
36
+ example_heading: Heading for the example section.
37
+
38
+ Returns:
39
+ Markdown documentation string.
40
+ """
@@ -0,0 +1,39 @@
1
+ """PTC-specific exceptions.
2
+
3
+ This module defines exceptions for Programmatic Tool Calling operations.
4
+
5
+ Authors:
6
+ Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
7
+ """
8
+
9
+
10
+ class PTCError(Exception):
11
+ """Base exception for PTC errors."""
12
+
13
+ pass
14
+
15
+
16
+ class PTCToolError(PTCError):
17
+ """Error during tool execution.
18
+
19
+ Attributes:
20
+ server_name: The MCP server where the error occurred.
21
+ tool_name: The tool that failed.
22
+ """
23
+
24
+ def __init__(
25
+ self,
26
+ message: str,
27
+ server_name: str | None = None,
28
+ tool_name: str | None = None,
29
+ ) -> None:
30
+ """Initialize PTCToolError.
31
+
32
+ Args:
33
+ message: Error message.
34
+ server_name: The MCP server name (optional).
35
+ tool_name: The tool name (optional).
36
+ """
37
+ super().__init__(message)
38
+ self.server_name = server_name
39
+ self.tool_name = tool_name
@@ -0,0 +1,22 @@
1
+ from _typeshed import Incomplete
2
+
3
+ class PTCError(Exception):
4
+ """Base exception for PTC errors."""
5
+
6
+ class PTCToolError(PTCError):
7
+ """Error during tool execution.
8
+
9
+ Attributes:
10
+ server_name: The MCP server where the error occurred.
11
+ tool_name: The tool that failed.
12
+ """
13
+ server_name: Incomplete
14
+ tool_name: Incomplete
15
+ def __init__(self, message: str, server_name: str | None = None, tool_name: str | None = None) -> None:
16
+ """Initialize PTCToolError.
17
+
18
+ Args:
19
+ message: Error message.
20
+ server_name: The MCP server name (optional).
21
+ tool_name: The tool name (optional).
22
+ """