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,37 @@
1
+ """LangGraph-related schema definitions for agent tool interactions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Any
7
+
8
+ from gllm_core.schema import Chunk
9
+ from langchain_core.messages import ToolMessage
10
+ from langchain_core.messages.ai import UsageMetadata
11
+ from langchain_core.tools import BaseTool
12
+
13
+ __all__ = ["ToolCallResult", "ToolStorageParams"]
14
+
15
+
16
+ @dataclass
17
+ class ToolCallResult:
18
+ """Container for the results of a single tool call execution."""
19
+
20
+ messages: list[ToolMessage]
21
+ artifacts: list[dict[str, Any]]
22
+ metadata_delta: dict[str, Any]
23
+ references: list[Chunk]
24
+ step_usage: UsageMetadata | None
25
+ pii_mapping: dict[str, str] | None = None
26
+
27
+
28
+ @dataclass
29
+ class ToolStorageParams:
30
+ """Parameters required for automatically storing tool outputs."""
31
+
32
+ tool: BaseTool
33
+ tool_output: Any
34
+ tool_call: dict[str, Any]
35
+ tool_call_id: str
36
+ resolved_args: dict[str, Any]
37
+ state: dict[str, Any]
@@ -0,0 +1,97 @@
1
+ """Model identifiers and provider definitions for the AI agent platform."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from enum import StrEnum
6
+
7
+
8
+ class ModelProvider(StrEnum):
9
+ """Enumeration of supported model providers for the AI agent platform."""
10
+
11
+ OPENAI = "openai"
12
+ ANTHROPIC = "anthropic"
13
+ AZURE_OPENAI = "azure-openai"
14
+ GOOGLE_GENAI = "google"
15
+ GROQ = "groq"
16
+ TOGETHER_AI = "together"
17
+ DEEPINFRA = "deepinfra"
18
+ DEEPSEEK = "deepseek"
19
+ OPENAI_COMPATIBLE = "openai-compatible"
20
+
21
+
22
+ class ModelId:
23
+ """Model identifier class for representing language models."""
24
+
25
+ def __init__(self, provider: str, name: str, path: str | None = None):
26
+ """Initialize a ModelId.
27
+
28
+ Args:
29
+ provider: The model provider (e.g., 'openai', 'anthropic')
30
+ name: The specific model name
31
+ path: Optional path component for some providers
32
+ """
33
+ self.provider = provider
34
+ self.name = name
35
+ self.path = path
36
+
37
+ @classmethod
38
+ def from_string(cls, model_string: str) -> ModelId:
39
+ """Create a ModelId from a string representation.
40
+
41
+ Args:
42
+ model_string: String in format 'provider:name' or 'provider/path:name'
43
+
44
+ Returns:
45
+ ModelId instance
46
+
47
+ Raises:
48
+ ValueError: If the string format is invalid
49
+ """
50
+ if ":" not in model_string:
51
+ raise ValueError(
52
+ f"Invalid model string format: {model_string}. Expected 'provider:name' or 'provider/path:name'"
53
+ )
54
+
55
+ # Find the last colon to separate provider+path from name
56
+ last_colon_idx = model_string.rindex(":")
57
+ provider_part = model_string[:last_colon_idx]
58
+ name = model_string[last_colon_idx + 1 :]
59
+
60
+ # Split provider_part on "/" to separate provider from path
61
+ if "/" in provider_part:
62
+ provider, path = provider_part.split("/", 1)
63
+ else:
64
+ provider = provider_part
65
+ path = None
66
+
67
+ return cls(provider, name, path)
68
+
69
+ def __str__(self) -> str:
70
+ """String representation of the ModelId."""
71
+ if self.path:
72
+ return f"{self.provider}/{self.path}:{self.name}"
73
+ return f"{self.provider}:{self.name}"
74
+
75
+ def __repr__(self) -> str:
76
+ """String representation of the ModelId for debugging."""
77
+ return f"ModelId(provider='{self.provider}', name='{self.name}', path='{self.path}')"
78
+
79
+ def __eq__(self, other: object) -> bool:
80
+ """Check equality with another ModelId object.
81
+
82
+ Args:
83
+ other (object): The object to compare with.
84
+
85
+ Returns:
86
+ bool: True if the objects are equal, False otherwise.
87
+ """
88
+ if not isinstance(other, ModelId):
89
+ return NotImplemented
90
+ return self.provider == other.provider and self.name == other.name and self.path == other.path
91
+
92
+ def __hash__(self) -> int:
93
+ """Return hash of the ModelId."""
94
+ return hash((self.provider, self.name, self.path))
95
+
96
+
97
+ __all__ = ["ModelId", "ModelProvider"]
@@ -0,0 +1,108 @@
1
+ """Step limit configuration and error classes for agent execution limits."""
2
+
3
+ import os
4
+ from dataclasses import dataclass, field
5
+ from enum import StrEnum
6
+
7
+
8
+ class StepLimitErrorType(StrEnum):
9
+ """Types of step-related limit violations."""
10
+
11
+ STEP_LIMIT_EXCEEDED = "STEP_LIMIT_EXCEEDED"
12
+ DELEGATION_DEPTH_EXCEEDED = "DELEGATION_DEPTH_EXCEEDED"
13
+
14
+
15
+ @dataclass
16
+ class StepLimitConfig:
17
+ """Configuration for agent step and delegation limits.
18
+
19
+ Attributes:
20
+ max_steps: Maximum number of execution steps allowed per invocation.
21
+ Includes agent node (LLM call) and every tool call (parallel batches count per call).
22
+ max_delegation_depth: Maximum depth of delegation chain allowed.
23
+ Depth 0 means no delegation allowed.
24
+ """
25
+
26
+ max_steps: int = field(
27
+ default_factory=lambda: int(os.getenv("STEP_LIMIT_MAX_STEPS_DEFAULT", "100")),
28
+ )
29
+ max_delegation_depth: int = field(
30
+ default_factory=lambda: int(os.getenv("STEP_LIMIT_MAX_DELEGATION_DEPTH_DEFAULT", "5")),
31
+ )
32
+
33
+ def __post_init__(self):
34
+ """Validate configuration values and normalize range."""
35
+ from aip_agents.utils.logger import get_logger
36
+
37
+ logger = get_logger(__name__)
38
+
39
+ # Validate and clamp max_steps
40
+ if self.max_steps < 1:
41
+ logger.warning(f"Invalid max_steps={self.max_steps}, resetting to default (25). max_steps must be >= 1.")
42
+ self.max_steps = 25
43
+ elif self.max_steps > 1000:
44
+ logger.warning(f"Invalid max_steps={self.max_steps}, capping at 1000.")
45
+ self.max_steps = 1000
46
+
47
+ # Validate and clamp max_delegation_depth
48
+ if self.max_delegation_depth < 0:
49
+ logger.warning(
50
+ f"Invalid max_delegation_depth={self.max_delegation_depth}, resetting to default (5). "
51
+ "max_delegation_depth must be >= 0."
52
+ )
53
+ self.max_delegation_depth = 5
54
+ elif self.max_delegation_depth > 10:
55
+ logger.warning(f"Invalid max_delegation_depth={self.max_delegation_depth}, capping at 10.")
56
+ self.max_delegation_depth = 10
57
+
58
+
59
+ @dataclass
60
+ class StepLimitErrorResponse:
61
+ """Structured error response for step limit violations.
62
+
63
+ Attributes:
64
+ error_type: The type of limit that was exceeded.
65
+ agent_name: Name of the agent that hit the limit.
66
+ current_value: Current step count or delegation depth.
67
+ configured_limit: The configured limit that was exceeded.
68
+ message: Human-readable error message.
69
+ delegation_chain: Full chain for delegation errors.
70
+ partial_result: Any output generated before hitting the limit.
71
+ """
72
+
73
+ error_type: StepLimitErrorType
74
+ agent_name: str
75
+ current_value: int
76
+ configured_limit: int
77
+ message: str
78
+ delegation_chain: list[str] | None = None
79
+ partial_result: str | None = None
80
+
81
+
82
+ class StepLimitError(Exception):
83
+ """Base exception for step and delegation limit violations.
84
+
85
+ Attributes:
86
+ error_response: Structured error response with details.
87
+ """
88
+
89
+ def __init__(self, error_response: StepLimitErrorResponse):
90
+ """Initialize with error response.
91
+
92
+ Args:
93
+ error_response: Structured error details.
94
+ """
95
+ self.error_response = error_response
96
+ super().__init__(error_response.message)
97
+
98
+
99
+ class MaxStepsExceededError(StepLimitError):
100
+ """Raised when agent exceeds configured max_steps limit."""
101
+
102
+ pass
103
+
104
+
105
+ class MaxDelegationDepthExceededError(StepLimitError):
106
+ """Raised when delegation would exceed max_delegation_depth limit."""
107
+
108
+ pass
@@ -0,0 +1,40 @@
1
+ """Schema definitions for storage configuration."""
2
+
3
+ import os
4
+ from dataclasses import dataclass
5
+ from enum import StrEnum
6
+
7
+ __all__ = ["OBJECT_STORAGE_PREFIX", "StorageType", "StorageConfig"]
8
+
9
+ OBJECT_STORAGE_PREFIX = "tool_outputs/"
10
+
11
+
12
+ class StorageType(StrEnum):
13
+ """Supported storage types."""
14
+
15
+ MEMORY = "memory"
16
+ OBJECT_STORAGE = "object_storage"
17
+
18
+
19
+ @dataclass
20
+ class StorageConfig:
21
+ """Configuration for storage providers."""
22
+
23
+ storage_type: StorageType = StorageType.MEMORY
24
+ object_prefix: str = OBJECT_STORAGE_PREFIX
25
+ object_use_json: bool = False
26
+
27
+ @classmethod
28
+ def from_env(cls) -> "StorageConfig":
29
+ """Create StorageConfig from environment variables."""
30
+ storage_type_str = os.getenv("TOOL_OUTPUT_STORAGE_TYPE", StorageType.MEMORY.value).lower()
31
+ if storage_type_str == StorageType.MEMORY.value:
32
+ storage_type = StorageType.MEMORY
33
+ else:
34
+ storage_type = StorageType.OBJECT_STORAGE
35
+
36
+ object_prefix = os.getenv("TOOL_OUTPUT_OBJECT_PREFIX", OBJECT_STORAGE_PREFIX)
37
+ use_json_str = os.getenv("TOOL_OUTPUT_USE_JSON", "false").lower()
38
+ use_json = use_json_str in ("true", "1", "yes", "on")
39
+
40
+ return cls(storage_type=storage_type, object_prefix=object_prefix, object_use_json=use_json)
@@ -0,0 +1,11 @@
1
+ """This module provides a centralized way to handle Sentry and OpenTelemetry configuration for BOSA SDK.
2
+
3
+ Authors:
4
+ Saul Sayers (saul.sayers@gdplabs.id)
5
+ """
6
+
7
+ from aip_agents.sentry.sentry import setup_telemetry
8
+
9
+ __all__ = [
10
+ "setup_telemetry",
11
+ ]
@@ -0,0 +1,151 @@
1
+ """This file contains the Sentry and OpenTelemetry configuration for BOSA SDK.
2
+
3
+ Authors:
4
+ Saul Sayers (saul.sayers@gdplabs.id)
5
+ """
6
+
7
+ import inspect
8
+ import os
9
+
10
+ from bosa_core.telemetry import (
11
+ FastAPIConfig,
12
+ OpenTelemetryConfig,
13
+ SentryConfig,
14
+ TelemetryConfig,
15
+ init_telemetry,
16
+ )
17
+ from bosa_core.telemetry.opentelemetry.instrument.functions import (
18
+ BOSAFunctionsInstrumentor,
19
+ )
20
+ from dotenv import load_dotenv
21
+ from fastapi import FastAPI
22
+
23
+ from aip_agents.agent import BaseAgent, GoogleADKAgent, LangChainAgent, LangGraphAgent
24
+ from aip_agents.utils.logger import get_logger
25
+
26
+ load_dotenv()
27
+
28
+
29
+ logger = get_logger(__name__)
30
+
31
+ SENTRY_DSN = os.getenv("SENTRY_DSN")
32
+ SENTRY_ENVIRONMENT = os.getenv("SENTRY_ENVIRONMENT", "development")
33
+ SENTRY_PROJECT = os.getenv("SENTRY_PROJECT")
34
+ VERSION_NUMBER = os.getenv("VERSION_NUMBER", "0.0.0")
35
+ BUILD_NUMBER = os.getenv("BUILD_NUMBER", "0")
36
+ USE_OPENTELEMETRY = os.getenv("USE_OPENTELEMETRY", "true").lower() == "true"
37
+
38
+ CLASSES_TO_INSTRUMENT = [
39
+ BaseAgent,
40
+ LangGraphAgent,
41
+ LangChainAgent,
42
+ GoogleADKAgent,
43
+ ]
44
+
45
+
46
+ def get_all_methods(cls: type) -> list:
47
+ """Get all methods from a class.
48
+
49
+ Args:
50
+ cls: The class to get methods from.
51
+
52
+ Returns:
53
+ list: A list of methods.
54
+ """
55
+ methods = []
56
+ for name, member in inspect.getmembers(cls):
57
+ if name.startswith("_"):
58
+ continue # skip dunder and private
59
+ if inspect.isfunction(member) or inspect.ismethod(member) or inspect.iscoroutinefunction(member):
60
+ methods.append(member)
61
+ return methods
62
+
63
+
64
+ def instrument_bosa_functions() -> None:
65
+ """Instrument BOSA functions."""
66
+ if BOSAFunctionsInstrumentor is None:
67
+ return
68
+ agent_methods = []
69
+ for cls in CLASSES_TO_INSTRUMENT:
70
+ agent_methods.extend(get_all_methods(cls))
71
+ BOSAFunctionsInstrumentor().instrument(methods=agent_methods)
72
+
73
+
74
+ def traces_sampler(*args) -> float:
75
+ """Determine appropriate sampling rate for Sentry transactions.
76
+
77
+ Args:
78
+ *args: Additional positional arguments
79
+
80
+ Returns:
81
+ float: Sampling rate between 0 and 1
82
+ """
83
+ # TODO: Dont sample healthcheck endpoints (return 0.0)
84
+ return 1.0
85
+
86
+
87
+ def setup_sentry_with_open_telemetry(app: FastAPI) -> None:
88
+ """Configure telemetry with both Sentry and OpenTelemetry.
89
+
90
+ Args:
91
+ app: FastAPI application instance
92
+ """
93
+ try:
94
+ fastapi_config = FastAPIConfig(app)
95
+
96
+ # Create OpenTelemetry configuration
97
+ opentelemetry_init = OpenTelemetryConfig(
98
+ use_langchain=True,
99
+ fastapi_config=fastapi_config,
100
+ )
101
+
102
+ # Sentry configuration with OpenTelemetry
103
+ sentry_config = SentryConfig(
104
+ dsn=SENTRY_DSN,
105
+ traces_sampler=traces_sampler,
106
+ environment=SENTRY_ENVIRONMENT,
107
+ release=f"{SENTRY_PROJECT}@{VERSION_NUMBER}+{BUILD_NUMBER}",
108
+ send_default_pii=True,
109
+ open_telemetry_config=opentelemetry_init,
110
+ )
111
+
112
+ telemetry_config = TelemetryConfig(sentry_config=sentry_config)
113
+ init_telemetry(telemetry_config)
114
+ logger.info(f"Telemetry initialized with OpenTelemetry for environment: {SENTRY_ENVIRONMENT}")
115
+ except Exception as e:
116
+ logger.error(f"Failed to initialize telemetry with OpenTelemetry: {e}")
117
+
118
+
119
+ def setup_sentry_only() -> None:
120
+ """Configure telemetry with Sentry only (no OpenTelemetry)."""
121
+ try:
122
+ # Sentry configuration without OpenTelemetry
123
+ sentry_config = SentryConfig(
124
+ dsn=SENTRY_DSN,
125
+ traces_sampler=traces_sampler,
126
+ environment=SENTRY_ENVIRONMENT,
127
+ release=f"{SENTRY_PROJECT}@{VERSION_NUMBER}+{BUILD_NUMBER}",
128
+ send_default_pii=True,
129
+ )
130
+
131
+ telemetry_config = TelemetryConfig(sentry_config=sentry_config)
132
+ init_telemetry(telemetry_config)
133
+ logger.info(f"Telemetry initialized with Sentry only for environment: {SENTRY_ENVIRONMENT}")
134
+ except Exception as e:
135
+ logger.error(f"Failed to initialize telemetry with Sentry only: {e}")
136
+
137
+
138
+ def setup_telemetry(app: FastAPI) -> None:
139
+ """Configure and initialize telemetry based on configuration.
140
+
141
+ Args:
142
+ app: FastAPI application instance
143
+ """
144
+ if not SENTRY_DSN:
145
+ logger.warning("Warning: SENTRY_DSN not set. Sentry will not be enabled.")
146
+ return
147
+ if USE_OPENTELEMETRY:
148
+ setup_sentry_with_open_telemetry(app)
149
+ else:
150
+ setup_sentry_only()
151
+ instrument_bosa_functions()
@@ -0,0 +1,41 @@
1
+ """Storage module for aip_agents.
2
+
3
+ This module provides comprehensive storage functionality including object storage
4
+ clients, storage providers for tool outputs, and configuration management.
5
+
6
+ Authors:
7
+ Fachriza Adhiatma (fachriza.d.adhiatma@gdplabs.id)
8
+ Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
9
+ """
10
+
11
+ # Object storage clients
12
+ from aip_agents.storage.base import BaseObjectStorageClient
13
+ from aip_agents.storage.clients.minio_client import MinioConfig, MinioObjectStorage
14
+
15
+ # Configuration and factory
16
+ from aip_agents.storage.config import (
17
+ StorageConfig,
18
+ StorageProviderFactory,
19
+ StorageType,
20
+ )
21
+
22
+ # Storage providers
23
+ from aip_agents.storage.providers.base import BaseStorageProvider, StorageError
24
+ from aip_agents.storage.providers.memory import InMemoryStorageProvider
25
+ from aip_agents.storage.providers.object_storage import ObjectStorageProvider
26
+
27
+ __all__ = [
28
+ # Object storage
29
+ "BaseObjectStorageClient",
30
+ "MinioConfig",
31
+ "MinioObjectStorage",
32
+ # Storage providers
33
+ "BaseStorageProvider",
34
+ "StorageError",
35
+ "InMemoryStorageProvider",
36
+ "ObjectStorageProvider",
37
+ # Configuration
38
+ "StorageConfig",
39
+ "StorageType",
40
+ "StorageProviderFactory",
41
+ ]
@@ -0,0 +1,85 @@
1
+ """Base class for object storage clients.
2
+
3
+ Authors:
4
+ Fachriza Adhiatma (fachriza.d.adhiatma@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 typing import BinaryIO
10
+
11
+
12
+ class BaseObjectStorageClient(ABC):
13
+ """Abstract base class for object storage clients."""
14
+
15
+ @abstractmethod
16
+ def object_exists(self, object_key: str) -> bool:
17
+ """Check if an object exists in the storage.
18
+
19
+ Args:
20
+ object_key: The key of the object to check.
21
+
22
+ Returns:
23
+ True if the object exists, False otherwise.
24
+ """
25
+ raise NotImplementedError
26
+
27
+ @abstractmethod
28
+ def upload(
29
+ self,
30
+ object_key: str,
31
+ file_stream: bytes | BinaryIO,
32
+ filename: str | None = None,
33
+ content_type: str | None = None,
34
+ metadata: dict[str, str] | None = None,
35
+ ) -> str:
36
+ """Upload data to object storage.
37
+
38
+ Args:
39
+ object_key: The key of the object in the storage
40
+ file_stream: The binary data to upload
41
+ filename: The name of the file
42
+ content_type: The content type of the file
43
+ metadata: Additional metadata to store with the object
44
+
45
+ Returns:
46
+ The key of the uploaded object
47
+ """
48
+ raise NotImplementedError
49
+
50
+ @abstractmethod
51
+ def get(self, object_key: str) -> bytes:
52
+ """Get data from object storage.
53
+
54
+ Args:
55
+ object_key: The key of the object in the storage
56
+
57
+ Returns:
58
+ The binary data of the object
59
+ """
60
+ raise NotImplementedError
61
+
62
+ @abstractmethod
63
+ def delete(self, object_key: str) -> None:
64
+ """Delete data from object storage.
65
+
66
+ Args:
67
+ object_key: The key of the object in the storage
68
+ """
69
+ raise NotImplementedError
70
+
71
+ @abstractmethod
72
+ def generate_presigned_url(
73
+ self, object_key: str, expires: int = 24, response_headers: dict[str, str] | None = None
74
+ ) -> str:
75
+ """Generate a presigned URL for accessing the object.
76
+
77
+ Args:
78
+ object_key: The key of the object in the storage
79
+ expires: The number of hours the URL is valid for
80
+ response_headers: Additional headers to include in the response
81
+
82
+ Returns:
83
+ The presigned URL
84
+ """
85
+ raise NotImplementedError
@@ -0,0 +1,12 @@
1
+ """Storage client implementations.
2
+
3
+ This module contains concrete implementations of object storage clients
4
+ for various backends like MinIO, AWS S3, etc.
5
+
6
+ Authors:
7
+ Fachriza Adhiatma (fachriza.d.adhiatma@gdplabs.id)
8
+ """
9
+
10
+ from aip_agents.storage.clients.minio_client import MinioConfig, MinioObjectStorage
11
+
12
+ __all__ = ["MinioConfig", "MinioObjectStorage"]