aip-agents-binary 0.5.20__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.
Files changed (280) hide show
  1. aip_agents/__init__.py +65 -0
  2. aip_agents/a2a/__init__.py +19 -0
  3. aip_agents/a2a/server/__init__.py +10 -0
  4. aip_agents/a2a/server/base_executor.py +1086 -0
  5. aip_agents/a2a/server/google_adk_executor.py +198 -0
  6. aip_agents/a2a/server/langflow_executor.py +180 -0
  7. aip_agents/a2a/server/langgraph_executor.py +270 -0
  8. aip_agents/a2a/types.py +232 -0
  9. aip_agents/agent/__init__.py +27 -0
  10. aip_agents/agent/base_agent.py +970 -0
  11. aip_agents/agent/base_langgraph_agent.py +2942 -0
  12. aip_agents/agent/google_adk_agent.py +926 -0
  13. aip_agents/agent/google_adk_constants.py +6 -0
  14. aip_agents/agent/hitl/__init__.py +24 -0
  15. aip_agents/agent/hitl/config.py +28 -0
  16. aip_agents/agent/hitl/langgraph_hitl_mixin.py +515 -0
  17. aip_agents/agent/hitl/manager.py +532 -0
  18. aip_agents/agent/hitl/models.py +18 -0
  19. aip_agents/agent/hitl/prompt/__init__.py +9 -0
  20. aip_agents/agent/hitl/prompt/base.py +42 -0
  21. aip_agents/agent/hitl/prompt/deferred.py +73 -0
  22. aip_agents/agent/hitl/registry.py +149 -0
  23. aip_agents/agent/interface.py +138 -0
  24. aip_agents/agent/interfaces.py +65 -0
  25. aip_agents/agent/langflow_agent.py +464 -0
  26. aip_agents/agent/langgraph_memory_enhancer_agent.py +433 -0
  27. aip_agents/agent/langgraph_react_agent.py +2514 -0
  28. aip_agents/agent/system_instruction_context.py +34 -0
  29. aip_agents/clients/__init__.py +10 -0
  30. aip_agents/clients/langflow/__init__.py +10 -0
  31. aip_agents/clients/langflow/client.py +477 -0
  32. aip_agents/clients/langflow/types.py +18 -0
  33. aip_agents/constants.py +23 -0
  34. aip_agents/credentials/manager.py +132 -0
  35. aip_agents/examples/__init__.py +5 -0
  36. aip_agents/examples/compare_streaming_client.py +783 -0
  37. aip_agents/examples/compare_streaming_server.py +142 -0
  38. aip_agents/examples/demo_memory_recall.py +401 -0
  39. aip_agents/examples/hello_world_a2a_google_adk_client.py +49 -0
  40. aip_agents/examples/hello_world_a2a_google_adk_client_agent.py +48 -0
  41. aip_agents/examples/hello_world_a2a_google_adk_client_streaming.py +60 -0
  42. aip_agents/examples/hello_world_a2a_google_adk_server.py +79 -0
  43. aip_agents/examples/hello_world_a2a_langchain_client.py +39 -0
  44. aip_agents/examples/hello_world_a2a_langchain_client_agent.py +39 -0
  45. aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.py +37 -0
  46. aip_agents/examples/hello_world_a2a_langchain_client_streaming.py +41 -0
  47. aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.py +60 -0
  48. aip_agents/examples/hello_world_a2a_langchain_reference_server.py +105 -0
  49. aip_agents/examples/hello_world_a2a_langchain_server.py +79 -0
  50. aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.py +78 -0
  51. aip_agents/examples/hello_world_a2a_langflow_client.py +83 -0
  52. aip_agents/examples/hello_world_a2a_langflow_server.py +82 -0
  53. aip_agents/examples/hello_world_a2a_langgraph_artifact_client.py +73 -0
  54. aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.py +76 -0
  55. aip_agents/examples/hello_world_a2a_langgraph_artifact_server.py +92 -0
  56. aip_agents/examples/hello_world_a2a_langgraph_client.py +54 -0
  57. aip_agents/examples/hello_world_a2a_langgraph_client_agent.py +54 -0
  58. aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.py +32 -0
  59. aip_agents/examples/hello_world_a2a_langgraph_client_streaming.py +50 -0
  60. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.py +44 -0
  61. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.py +92 -0
  62. aip_agents/examples/hello_world_a2a_langgraph_server.py +84 -0
  63. aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.py +79 -0
  64. aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.py +132 -0
  65. aip_agents/examples/hello_world_a2a_mcp_langgraph.py +196 -0
  66. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.py +244 -0
  67. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.py +251 -0
  68. aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.py +57 -0
  69. aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.py +80 -0
  70. aip_agents/examples/hello_world_google_adk.py +41 -0
  71. aip_agents/examples/hello_world_google_adk_mcp_http.py +34 -0
  72. aip_agents/examples/hello_world_google_adk_mcp_http_stream.py +40 -0
  73. aip_agents/examples/hello_world_google_adk_mcp_sse.py +44 -0
  74. aip_agents/examples/hello_world_google_adk_mcp_sse_stream.py +48 -0
  75. aip_agents/examples/hello_world_google_adk_mcp_stdio.py +44 -0
  76. aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.py +48 -0
  77. aip_agents/examples/hello_world_google_adk_stream.py +44 -0
  78. aip_agents/examples/hello_world_langchain.py +28 -0
  79. aip_agents/examples/hello_world_langchain_lm_invoker.py +15 -0
  80. aip_agents/examples/hello_world_langchain_mcp_http.py +34 -0
  81. aip_agents/examples/hello_world_langchain_mcp_http_interactive.py +130 -0
  82. aip_agents/examples/hello_world_langchain_mcp_http_stream.py +42 -0
  83. aip_agents/examples/hello_world_langchain_mcp_multi_server.py +155 -0
  84. aip_agents/examples/hello_world_langchain_mcp_sse.py +34 -0
  85. aip_agents/examples/hello_world_langchain_mcp_sse_stream.py +40 -0
  86. aip_agents/examples/hello_world_langchain_mcp_stdio.py +30 -0
  87. aip_agents/examples/hello_world_langchain_mcp_stdio_stream.py +41 -0
  88. aip_agents/examples/hello_world_langchain_stream.py +36 -0
  89. aip_agents/examples/hello_world_langchain_stream_lm_invoker.py +39 -0
  90. aip_agents/examples/hello_world_langflow_agent.py +163 -0
  91. aip_agents/examples/hello_world_langgraph.py +39 -0
  92. aip_agents/examples/hello_world_langgraph_bosa_twitter.py +41 -0
  93. aip_agents/examples/hello_world_langgraph_mcp_http.py +31 -0
  94. aip_agents/examples/hello_world_langgraph_mcp_http_stream.py +34 -0
  95. aip_agents/examples/hello_world_langgraph_mcp_sse.py +35 -0
  96. aip_agents/examples/hello_world_langgraph_mcp_sse_stream.py +50 -0
  97. aip_agents/examples/hello_world_langgraph_mcp_stdio.py +35 -0
  98. aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.py +50 -0
  99. aip_agents/examples/hello_world_langgraph_stream.py +43 -0
  100. aip_agents/examples/hello_world_langgraph_stream_lm_invoker.py +37 -0
  101. aip_agents/examples/hello_world_model_switch_cli.py +210 -0
  102. aip_agents/examples/hello_world_multi_agent_adk.py +75 -0
  103. aip_agents/examples/hello_world_multi_agent_langchain.py +54 -0
  104. aip_agents/examples/hello_world_multi_agent_langgraph.py +66 -0
  105. aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.py +69 -0
  106. aip_agents/examples/hello_world_pii_logger.py +21 -0
  107. aip_agents/examples/hello_world_sentry.py +133 -0
  108. aip_agents/examples/hello_world_step_limits.py +273 -0
  109. aip_agents/examples/hello_world_stock_a2a_server.py +103 -0
  110. aip_agents/examples/hello_world_tool_output_client.py +46 -0
  111. aip_agents/examples/hello_world_tool_output_server.py +114 -0
  112. aip_agents/examples/hitl_demo.py +724 -0
  113. aip_agents/examples/mcp_configs/configs.py +63 -0
  114. aip_agents/examples/mcp_servers/common.py +76 -0
  115. aip_agents/examples/mcp_servers/mcp_name.py +29 -0
  116. aip_agents/examples/mcp_servers/mcp_server_http.py +19 -0
  117. aip_agents/examples/mcp_servers/mcp_server_sse.py +19 -0
  118. aip_agents/examples/mcp_servers/mcp_server_stdio.py +19 -0
  119. aip_agents/examples/mcp_servers/mcp_time.py +10 -0
  120. aip_agents/examples/pii_demo_langgraph_client.py +69 -0
  121. aip_agents/examples/pii_demo_langgraph_server.py +126 -0
  122. aip_agents/examples/pii_demo_multi_agent_client.py +80 -0
  123. aip_agents/examples/pii_demo_multi_agent_server.py +247 -0
  124. aip_agents/examples/todolist_planning_a2a_langchain_client.py +70 -0
  125. aip_agents/examples/todolist_planning_a2a_langgraph_server.py +88 -0
  126. aip_agents/examples/tools/__init__.py +27 -0
  127. aip_agents/examples/tools/adk_arithmetic_tools.py +36 -0
  128. aip_agents/examples/tools/adk_weather_tool.py +60 -0
  129. aip_agents/examples/tools/data_generator_tool.py +103 -0
  130. aip_agents/examples/tools/data_visualization_tool.py +312 -0
  131. aip_agents/examples/tools/image_artifact_tool.py +136 -0
  132. aip_agents/examples/tools/langchain_arithmetic_tools.py +26 -0
  133. aip_agents/examples/tools/langchain_currency_exchange_tool.py +88 -0
  134. aip_agents/examples/tools/langchain_graph_artifact_tool.py +172 -0
  135. aip_agents/examples/tools/langchain_weather_tool.py +48 -0
  136. aip_agents/examples/tools/langgraph_streaming_tool.py +130 -0
  137. aip_agents/examples/tools/mock_retrieval_tool.py +56 -0
  138. aip_agents/examples/tools/pii_demo_tools.py +189 -0
  139. aip_agents/examples/tools/random_chart_tool.py +142 -0
  140. aip_agents/examples/tools/serper_tool.py +202 -0
  141. aip_agents/examples/tools/stock_tools.py +82 -0
  142. aip_agents/examples/tools/table_generator_tool.py +167 -0
  143. aip_agents/examples/tools/time_tool.py +82 -0
  144. aip_agents/examples/tools/weather_forecast_tool.py +38 -0
  145. aip_agents/executor/agent_executor.py +473 -0
  146. aip_agents/executor/base.py +48 -0
  147. aip_agents/mcp/__init__.py +1 -0
  148. aip_agents/mcp/client/__init__.py +14 -0
  149. aip_agents/mcp/client/base_mcp_client.py +369 -0
  150. aip_agents/mcp/client/connection_manager.py +193 -0
  151. aip_agents/mcp/client/google_adk/__init__.py +11 -0
  152. aip_agents/mcp/client/google_adk/client.py +381 -0
  153. aip_agents/mcp/client/langchain/__init__.py +11 -0
  154. aip_agents/mcp/client/langchain/client.py +265 -0
  155. aip_agents/mcp/client/persistent_session.py +359 -0
  156. aip_agents/mcp/client/session_pool.py +351 -0
  157. aip_agents/mcp/client/transports.py +215 -0
  158. aip_agents/mcp/utils/__init__.py +7 -0
  159. aip_agents/mcp/utils/config_validator.py +139 -0
  160. aip_agents/memory/__init__.py +14 -0
  161. aip_agents/memory/adapters/__init__.py +10 -0
  162. aip_agents/memory/adapters/base_adapter.py +717 -0
  163. aip_agents/memory/adapters/mem0.py +84 -0
  164. aip_agents/memory/base.py +84 -0
  165. aip_agents/memory/constants.py +49 -0
  166. aip_agents/memory/factory.py +86 -0
  167. aip_agents/memory/guidance.py +20 -0
  168. aip_agents/memory/simple_memory.py +47 -0
  169. aip_agents/middleware/__init__.py +17 -0
  170. aip_agents/middleware/base.py +88 -0
  171. aip_agents/middleware/manager.py +128 -0
  172. aip_agents/middleware/todolist.py +274 -0
  173. aip_agents/schema/__init__.py +69 -0
  174. aip_agents/schema/a2a.py +56 -0
  175. aip_agents/schema/agent.py +111 -0
  176. aip_agents/schema/hitl.py +157 -0
  177. aip_agents/schema/langgraph.py +37 -0
  178. aip_agents/schema/model_id.py +97 -0
  179. aip_agents/schema/step_limit.py +108 -0
  180. aip_agents/schema/storage.py +40 -0
  181. aip_agents/sentry/__init__.py +11 -0
  182. aip_agents/sentry/sentry.py +151 -0
  183. aip_agents/storage/__init__.py +41 -0
  184. aip_agents/storage/base.py +85 -0
  185. aip_agents/storage/clients/__init__.py +12 -0
  186. aip_agents/storage/clients/minio_client.py +318 -0
  187. aip_agents/storage/config.py +62 -0
  188. aip_agents/storage/providers/__init__.py +15 -0
  189. aip_agents/storage/providers/base.py +106 -0
  190. aip_agents/storage/providers/memory.py +114 -0
  191. aip_agents/storage/providers/object_storage.py +214 -0
  192. aip_agents/tools/__init__.py +33 -0
  193. aip_agents/tools/bosa_tools.py +105 -0
  194. aip_agents/tools/browser_use/__init__.py +82 -0
  195. aip_agents/tools/browser_use/action_parser.py +103 -0
  196. aip_agents/tools/browser_use/browser_use_tool.py +1112 -0
  197. aip_agents/tools/browser_use/llm_config.py +120 -0
  198. aip_agents/tools/browser_use/minio_storage.py +198 -0
  199. aip_agents/tools/browser_use/schemas.py +119 -0
  200. aip_agents/tools/browser_use/session.py +76 -0
  201. aip_agents/tools/browser_use/session_errors.py +132 -0
  202. aip_agents/tools/browser_use/steel_session_recording.py +317 -0
  203. aip_agents/tools/browser_use/streaming.py +813 -0
  204. aip_agents/tools/browser_use/structured_data_parser.py +257 -0
  205. aip_agents/tools/browser_use/structured_data_recovery.py +204 -0
  206. aip_agents/tools/browser_use/types.py +78 -0
  207. aip_agents/tools/code_sandbox/__init__.py +26 -0
  208. aip_agents/tools/code_sandbox/constant.py +13 -0
  209. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +257 -0
  210. aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +411 -0
  211. aip_agents/tools/constants.py +165 -0
  212. aip_agents/tools/document_loader/__init__.py +44 -0
  213. aip_agents/tools/document_loader/base_reader.py +302 -0
  214. aip_agents/tools/document_loader/docx_reader_tool.py +68 -0
  215. aip_agents/tools/document_loader/excel_reader_tool.py +171 -0
  216. aip_agents/tools/document_loader/pdf_reader_tool.py +79 -0
  217. aip_agents/tools/document_loader/pdf_splitter.py +169 -0
  218. aip_agents/tools/gl_connector/__init__.py +5 -0
  219. aip_agents/tools/gl_connector/tool.py +351 -0
  220. aip_agents/tools/memory_search/__init__.py +22 -0
  221. aip_agents/tools/memory_search/base.py +200 -0
  222. aip_agents/tools/memory_search/mem0.py +258 -0
  223. aip_agents/tools/memory_search/schema.py +48 -0
  224. aip_agents/tools/memory_search_tool.py +26 -0
  225. aip_agents/tools/time_tool.py +117 -0
  226. aip_agents/tools/tool_config_injector.py +300 -0
  227. aip_agents/tools/web_search/__init__.py +15 -0
  228. aip_agents/tools/web_search/serper_tool.py +187 -0
  229. aip_agents/types/__init__.py +70 -0
  230. aip_agents/types/a2a_events.py +13 -0
  231. aip_agents/utils/__init__.py +79 -0
  232. aip_agents/utils/a2a_connector.py +1757 -0
  233. aip_agents/utils/artifact_helpers.py +502 -0
  234. aip_agents/utils/constants.py +22 -0
  235. aip_agents/utils/datetime/__init__.py +34 -0
  236. aip_agents/utils/datetime/normalization.py +231 -0
  237. aip_agents/utils/datetime/timezone.py +206 -0
  238. aip_agents/utils/env_loader.py +27 -0
  239. aip_agents/utils/event_handler_registry.py +58 -0
  240. aip_agents/utils/file_prompt_utils.py +176 -0
  241. aip_agents/utils/final_response_builder.py +211 -0
  242. aip_agents/utils/formatter_llm_client.py +231 -0
  243. aip_agents/utils/langgraph/__init__.py +19 -0
  244. aip_agents/utils/langgraph/converter.py +128 -0
  245. aip_agents/utils/langgraph/tool_managers/__init__.py +15 -0
  246. aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.py +99 -0
  247. aip_agents/utils/langgraph/tool_managers/base_tool_manager.py +66 -0
  248. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +1071 -0
  249. aip_agents/utils/langgraph/tool_output_management.py +967 -0
  250. aip_agents/utils/logger.py +195 -0
  251. aip_agents/utils/metadata/__init__.py +27 -0
  252. aip_agents/utils/metadata/activity_metadata_helper.py +407 -0
  253. aip_agents/utils/metadata/activity_narrative/__init__.py +35 -0
  254. aip_agents/utils/metadata/activity_narrative/builder.py +817 -0
  255. aip_agents/utils/metadata/activity_narrative/constants.py +51 -0
  256. aip_agents/utils/metadata/activity_narrative/context.py +49 -0
  257. aip_agents/utils/metadata/activity_narrative/formatters.py +230 -0
  258. aip_agents/utils/metadata/activity_narrative/utils.py +35 -0
  259. aip_agents/utils/metadata/schemas/__init__.py +16 -0
  260. aip_agents/utils/metadata/schemas/activity_schema.py +29 -0
  261. aip_agents/utils/metadata/schemas/thinking_schema.py +31 -0
  262. aip_agents/utils/metadata/thinking_metadata_helper.py +38 -0
  263. aip_agents/utils/metadata_helper.py +358 -0
  264. aip_agents/utils/name_preprocessor/__init__.py +17 -0
  265. aip_agents/utils/name_preprocessor/base_name_preprocessor.py +73 -0
  266. aip_agents/utils/name_preprocessor/google_name_preprocessor.py +100 -0
  267. aip_agents/utils/name_preprocessor/name_preprocessor.py +87 -0
  268. aip_agents/utils/name_preprocessor/openai_name_preprocessor.py +48 -0
  269. aip_agents/utils/pii/__init__.py +25 -0
  270. aip_agents/utils/pii/pii_handler.py +397 -0
  271. aip_agents/utils/pii/pii_helper.py +207 -0
  272. aip_agents/utils/pii/uuid_deanonymizer_mapping.py +195 -0
  273. aip_agents/utils/reference_helper.py +273 -0
  274. aip_agents/utils/sse_chunk_transformer.py +831 -0
  275. aip_agents/utils/step_limit_manager.py +265 -0
  276. aip_agents/utils/token_usage_helper.py +156 -0
  277. aip_agents_binary-0.5.20.dist-info/METADATA +681 -0
  278. aip_agents_binary-0.5.20.dist-info/RECORD +280 -0
  279. aip_agents_binary-0.5.20.dist-info/WHEEL +5 -0
  280. aip_agents_binary-0.5.20.dist-info/top_level.txt +1 -0
@@ -0,0 +1,149 @@
1
+ """Registry for tracking HITL approval manager ownership across agent hierarchies.
2
+
3
+ This module provides a thread-safe singleton registry that maps request IDs to their
4
+ owning ApprovalManager instances. This enables proper decision routing in hierarchical
5
+ agent architectures where sub-agents have HITL enabled but parents do not.
6
+
7
+ Authors:
8
+ Raymond Christopher (raymond.christopher@gdplabs.id)
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import threading
14
+ from typing import TYPE_CHECKING
15
+ from weakref import WeakValueDictionary
16
+
17
+ if TYPE_CHECKING:
18
+ from aip_agents.agent.hitl.manager import ApprovalManager
19
+
20
+
21
+ class HITLManagerRegistry:
22
+ """Global registry mapping request_id → owning ApprovalManager.
23
+
24
+ Uses weak references to avoid preventing manager garbage collection.
25
+ Thread-safe for concurrent agent execution.
26
+
27
+ This singleton registry allows the HITL decision endpoint to route decisions
28
+ to the correct manager in hierarchical agent setups, where a sub-agent may
29
+ create a pending request but the parent agent receives the decision.
30
+
31
+ Example:
32
+ >>> from aip_agents.agent.hitl.registry import hitl_registry
33
+ >>> # Manager auto-registers when creating requests
34
+ >>> manager.create_approval_request(...)
35
+ >>> # Later, decision handler looks up the owning manager
36
+ >>> owning_manager = hitl_registry.get_manager(request_id)
37
+ >>> owning_manager.resolve_pending_request(request_id, "approved")
38
+ """
39
+
40
+ _instance: HITLManagerRegistry | None = None
41
+ _lock = threading.RLock()
42
+ _registry: WeakValueDictionary[str, ApprovalManager]
43
+ _registry_lock: threading.RLock
44
+
45
+ def __new__(cls) -> HITLManagerRegistry:
46
+ """Ensure only one instance exists (singleton pattern).
47
+
48
+ Returns:
49
+ The singleton HITLManagerRegistry instance.
50
+ """
51
+ if cls._instance is None:
52
+ with cls._lock:
53
+ if cls._instance is None:
54
+ instance = super().__new__(cls)
55
+ instance._registry = WeakValueDictionary()
56
+ instance._registry_lock = threading.RLock()
57
+ cls._instance = instance
58
+ return cls._instance
59
+
60
+ def register(self, request_id: str, manager: ApprovalManager) -> None:
61
+ """Register a pending request with its owning manager.
62
+
63
+ This method is typically called automatically by ApprovalManager when
64
+ creating a new pending request. It establishes the ownership mapping
65
+ needed for proper decision routing.
66
+
67
+ Args:
68
+ request_id: Unique identifier for the pending request
69
+ manager: ApprovalManager instance that owns this request
70
+
71
+ Example:
72
+ >>> hitl_registry.register("req_abc123", my_manager)
73
+ """
74
+ with self._registry_lock:
75
+ self._registry[request_id] = manager
76
+
77
+ def unregister(self, request_id: str) -> None:
78
+ """Remove a request from the registry.
79
+
80
+ This method is called when a request is resolved, times out, or expires.
81
+ It's important for cleanup to prevent the registry from growing unbounded.
82
+
83
+ Args:
84
+ request_id: Unique identifier to remove
85
+
86
+ Example:
87
+ >>> hitl_registry.unregister("req_abc123")
88
+ """
89
+ with self._registry_lock:
90
+ self._registry.pop(request_id, None)
91
+
92
+ def get_manager(self, request_id: str) -> ApprovalManager | None:
93
+ """Retrieve the manager owning a specific request.
94
+
95
+ This is the primary lookup method used by decision handlers to route
96
+ decisions to the correct manager in hierarchical agent setups.
97
+
98
+ Args:
99
+ request_id: Unique identifier to lookup
100
+
101
+ Returns:
102
+ ApprovalManager instance if found, None otherwise. None can indicate
103
+ the request was resolved, timed out, or the manager was garbage collected.
104
+
105
+ Example:
106
+ >>> manager = hitl_registry.get_manager("req_abc123")
107
+ >>> if manager:
108
+ ... manager.resolve_pending_request("req_abc123", "approved")
109
+ """
110
+ with self._registry_lock:
111
+ return self._registry.get(request_id)
112
+
113
+ def clear(self) -> None:
114
+ """Clear all registrations.
115
+
116
+ This method is primarily intended for testing to ensure a clean state
117
+ between test cases. It removes all registered mappings.
118
+
119
+ Warning:
120
+ This should not be called in production code as it will prevent
121
+ pending requests from being resolved.
122
+
123
+ Example:
124
+ >>> hitl_registry.clear() # For testing only
125
+ """
126
+ with self._registry_lock:
127
+ self._registry.clear()
128
+
129
+ def list_all(self) -> list[str]:
130
+ """List all currently registered request IDs.
131
+
132
+ Returns:
133
+ List of request IDs currently in the registry.
134
+
135
+ Note:
136
+ Due to weak references, managers may be garbage collected between
137
+ calling this method and accessing them, so the actual available
138
+ managers might be fewer than the returned list length.
139
+
140
+ Example:
141
+ >>> request_ids = hitl_registry.list_all()
142
+ >>> print(f"Pending requests: {request_ids}")
143
+ """
144
+ with self._registry_lock:
145
+ return list(self._registry.keys())
146
+
147
+
148
+ # Global singleton instance
149
+ hitl_registry = HITLManagerRegistry()
@@ -0,0 +1,138 @@
1
+ """Defines the abstract base class AgentInterface for all agent implementations, now with MCP and A2A support.
2
+
3
+ Authors:
4
+ Raymond Christopher (raymond.christopher@gdplabs.id)
5
+ Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
6
+ """
7
+
8
+ from abc import ABC, abstractmethod
9
+ from collections.abc import AsyncGenerator
10
+ from typing import Any
11
+
12
+ from a2a.types import AgentCard
13
+ from gllm_inference.lm_invoker.lm_invoker import BaseLMInvoker
14
+
15
+ from aip_agents.schema.agent import BaseAgentConfig
16
+
17
+
18
+ class AgentInterface(ABC):
19
+ """A general and minimal interface for agent implementations.
20
+
21
+ Defines core execution methods (`__init__`, `run`, `arun`, `arun_stream`).
22
+ Concrete subclasses must implement all abstract methods.
23
+ """
24
+
25
+ name: str
26
+ instruction: str
27
+ description: str | None
28
+ mcp_config: dict[str, Any] = {}
29
+ lm_invoker: BaseLMInvoker | None = None
30
+ config: BaseAgentConfig | None = None
31
+
32
+ def __init__(
33
+ self,
34
+ name: str,
35
+ instruction: str,
36
+ description: str | None = None,
37
+ lm_invoker: BaseLMInvoker | None = None,
38
+ config: BaseAgentConfig | None = None,
39
+ **kwargs: Any,
40
+ ):
41
+ """Initializes the agent.
42
+
43
+ Args:
44
+ name: The name of the agent.
45
+ instruction: The core directive or system prompt for the agent.
46
+ description: Human-readable description. Defaults to instruction if not provided.
47
+ lm_invoker: The language model invoker to use for LLM interactions. Defaults to None.
48
+ config: Additional configuration for the agent.
49
+ **kwargs: Additional keyword arguments for concrete implementations.
50
+ """
51
+ self.name = name
52
+ self.instruction = instruction
53
+ self.description = description or self.instruction
54
+ self.lm_invoker = lm_invoker
55
+ self.config = config
56
+
57
+ @abstractmethod
58
+ def run(
59
+ self,
60
+ query: str,
61
+ **kwargs: Any,
62
+ ) -> dict[str, Any]:
63
+ """Synchronously runs the agent.
64
+
65
+ Args:
66
+ query: The input query for the agent.
67
+ **kwargs: Additional keyword arguments for execution.
68
+
69
+ Returns:
70
+ Dict containing at least {'output': ...}.
71
+ """
72
+ raise NotImplementedError(
73
+ f"'{self.__class__.__name__}' has not implemented the 'run' method."
74
+ ) # pragma: no cover
75
+
76
+ @abstractmethod
77
+ async def arun(
78
+ self,
79
+ query: str,
80
+ **kwargs: Any,
81
+ ) -> dict[str, Any]:
82
+ """Asynchronously runs the agent.
83
+
84
+ Args:
85
+ query: The input query for the agent.
86
+ **kwargs: Additional keyword arguments for execution.
87
+
88
+ Returns:
89
+ Dict containing at least {'output': ...}.
90
+ """
91
+ raise NotImplementedError(
92
+ f"'{self.__class__.__name__}' has not implemented the 'arun' method."
93
+ ) # pragma: no cover
94
+
95
+ @abstractmethod
96
+ async def arun_stream(
97
+ self,
98
+ query: str,
99
+ **kwargs: Any,
100
+ ) -> AsyncGenerator[str | dict[str, Any], None]:
101
+ """Asynchronously streams the agent's response.
102
+
103
+ Args:
104
+ query: The input query.
105
+ **kwargs: Extra parameters for execution.
106
+
107
+ Yields:
108
+ Chunks of output (strings or dicts).
109
+ """
110
+ raise NotImplementedError(
111
+ f"'{self.__class__.__name__}' has not implemented the 'arun_stream' method."
112
+ ) # pragma: no cover
113
+
114
+ @abstractmethod
115
+ def add_mcp_server(self, mcp_config: dict[str, dict[str, Any]]) -> None:
116
+ """Adds a new MCP server configuration.
117
+
118
+ Args:
119
+ mcp_config: Dictionary containing server name as key and its configuration as value.
120
+
121
+ Raises:
122
+ ValueError: If mcp_config is empty or None, or if any server configuration is invalid.
123
+ KeyError: If any server name already exists in the configuration.
124
+ """
125
+ raise NotImplementedError(
126
+ f"'{self.__class__.__name__}' has not implemented the 'add_mcp_server' method."
127
+ ) # pragma: no cover
128
+
129
+ @abstractmethod
130
+ def register_a2a_agents(self, agents: list[AgentCard]):
131
+ """Registers A2A agents from a list of AgentCards.
132
+
133
+ Args:
134
+ agents: A list of AgentCard instances.
135
+ """
136
+ raise NotImplementedError(
137
+ f"'{self.__class__.__name__}' has not implemented the 'register_a2a_agents' method."
138
+ ) # pragma: no cover
@@ -0,0 +1,65 @@
1
+ """Common agent-facing protocols used by A2A executors.
2
+
3
+ These runtime-checkable protocols let executors validate agent instances
4
+ without importing the concrete implementation classes, which avoids
5
+ introducing circular import chains at runtime.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from collections.abc import AsyncIterator
11
+ from typing import Any, Protocol, runtime_checkable
12
+
13
+
14
+ @runtime_checkable
15
+ class LangGraphAgentProtocol(Protocol):
16
+ """Minimal interface required by LangGraphA2AExecutor."""
17
+
18
+ name: str
19
+
20
+ async def arun_a2a_stream(self, query: str, **kwargs: Any) -> AsyncIterator[dict[str, Any]]:
21
+ """Stream A2A-compatible chunks for the given query.
22
+
23
+ Args:
24
+ query (str): The query to execute and stream.
25
+ **kwargs (Any): Additional keyword arguments for execution.
26
+
27
+ Yields:
28
+ dict[str, Any]: A2A-compatible streaming chunks.
29
+ """
30
+
31
+
32
+ @runtime_checkable
33
+ class LangflowAgentProtocol(Protocol):
34
+ """Minimal interface required by LangflowA2AExecutor."""
35
+
36
+ name: str
37
+
38
+ async def arun_a2a_stream(self, query: str, **kwargs: Any) -> AsyncIterator[dict[str, Any]]:
39
+ """Stream A2A-compatible chunks for the given query.
40
+
41
+ Args:
42
+ query (str): The query to execute and stream.
43
+ **kwargs (Any): Additional keyword arguments for execution.
44
+
45
+ Yields:
46
+ dict[str, Any]: A2A-compatible streaming chunks.
47
+ """
48
+
49
+
50
+ @runtime_checkable
51
+ class GoogleADKAgentProtocol(Protocol):
52
+ """Minimal interface required by GoogleADKExecutor."""
53
+
54
+ name: str
55
+
56
+ async def arun_a2a_stream(self, query: str, **kwargs: Any) -> AsyncIterator[dict[str, Any]]:
57
+ """Stream A2A-compatible chunks for the given query.
58
+
59
+ Args:
60
+ query (str): The query to execute and stream.
61
+ **kwargs (Any): Additional keyword arguments for execution.
62
+
63
+ Yields:
64
+ dict[str, Any]: A2A-compatible streaming chunks.
65
+ """