agentex-sdk 0.1.0a6__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 (289) hide show
  1. agentex/__init__.py +103 -0
  2. agentex/_base_client.py +1992 -0
  3. agentex/_client.py +506 -0
  4. agentex/_compat.py +219 -0
  5. agentex/_constants.py +14 -0
  6. agentex/_exceptions.py +108 -0
  7. agentex/_files.py +123 -0
  8. agentex/_models.py +829 -0
  9. agentex/_qs.py +150 -0
  10. agentex/_resource.py +43 -0
  11. agentex/_response.py +830 -0
  12. agentex/_streaming.py +333 -0
  13. agentex/_types.py +219 -0
  14. agentex/_utils/__init__.py +57 -0
  15. agentex/_utils/_logs.py +25 -0
  16. agentex/_utils/_proxy.py +65 -0
  17. agentex/_utils/_reflection.py +42 -0
  18. agentex/_utils/_resources_proxy.py +24 -0
  19. agentex/_utils/_streams.py +12 -0
  20. agentex/_utils/_sync.py +86 -0
  21. agentex/_utils/_transform.py +447 -0
  22. agentex/_utils/_typing.py +151 -0
  23. agentex/_utils/_utils.py +422 -0
  24. agentex/_version.py +4 -0
  25. agentex/lib/.keep +4 -0
  26. agentex/lib/__init__.py +0 -0
  27. agentex/lib/adk/__init__.py +41 -0
  28. agentex/lib/adk/_modules/__init__.py +0 -0
  29. agentex/lib/adk/_modules/acp.py +247 -0
  30. agentex/lib/adk/_modules/agent_task_tracker.py +176 -0
  31. agentex/lib/adk/_modules/agents.py +77 -0
  32. agentex/lib/adk/_modules/events.py +141 -0
  33. agentex/lib/adk/_modules/messages.py +285 -0
  34. agentex/lib/adk/_modules/state.py +291 -0
  35. agentex/lib/adk/_modules/streaming.py +75 -0
  36. agentex/lib/adk/_modules/tasks.py +124 -0
  37. agentex/lib/adk/_modules/tracing.py +194 -0
  38. agentex/lib/adk/providers/__init__.py +9 -0
  39. agentex/lib/adk/providers/_modules/__init__.py +0 -0
  40. agentex/lib/adk/providers/_modules/litellm.py +232 -0
  41. agentex/lib/adk/providers/_modules/openai.py +416 -0
  42. agentex/lib/adk/providers/_modules/sgp.py +85 -0
  43. agentex/lib/adk/utils/__init__.py +5 -0
  44. agentex/lib/adk/utils/_modules/__init__.py +0 -0
  45. agentex/lib/adk/utils/_modules/templating.py +94 -0
  46. agentex/lib/cli/__init__.py +0 -0
  47. agentex/lib/cli/commands/__init__.py +0 -0
  48. agentex/lib/cli/commands/agents.py +328 -0
  49. agentex/lib/cli/commands/init.py +227 -0
  50. agentex/lib/cli/commands/main.py +33 -0
  51. agentex/lib/cli/commands/secrets.py +169 -0
  52. agentex/lib/cli/commands/tasks.py +118 -0
  53. agentex/lib/cli/commands/uv.py +133 -0
  54. agentex/lib/cli/handlers/__init__.py +0 -0
  55. agentex/lib/cli/handlers/agent_handlers.py +160 -0
  56. agentex/lib/cli/handlers/cleanup_handlers.py +186 -0
  57. agentex/lib/cli/handlers/deploy_handlers.py +351 -0
  58. agentex/lib/cli/handlers/run_handlers.py +452 -0
  59. agentex/lib/cli/handlers/secret_handlers.py +670 -0
  60. agentex/lib/cli/templates/default/.dockerignore.j2 +43 -0
  61. agentex/lib/cli/templates/default/Dockerfile-uv.j2 +42 -0
  62. agentex/lib/cli/templates/default/Dockerfile.j2 +42 -0
  63. agentex/lib/cli/templates/default/README.md.j2 +193 -0
  64. agentex/lib/cli/templates/default/deploy/example.yaml.j2 +55 -0
  65. agentex/lib/cli/templates/default/manifest.yaml.j2 +116 -0
  66. agentex/lib/cli/templates/default/project/acp.py.j2 +29 -0
  67. agentex/lib/cli/templates/default/pyproject.toml.j2 +33 -0
  68. agentex/lib/cli/templates/default/requirements.txt.j2 +5 -0
  69. agentex/lib/cli/templates/deploy/Screenshot 2025-03-19 at 10.36.57/342/200/257AM.png +0 -0
  70. agentex/lib/cli/templates/deploy/example.yaml.j2 +55 -0
  71. agentex/lib/cli/templates/sync/.dockerignore.j2 +43 -0
  72. agentex/lib/cli/templates/sync/Dockerfile-uv.j2 +42 -0
  73. agentex/lib/cli/templates/sync/Dockerfile.j2 +42 -0
  74. agentex/lib/cli/templates/sync/README.md.j2 +293 -0
  75. agentex/lib/cli/templates/sync/deploy/example.yaml.j2 +55 -0
  76. agentex/lib/cli/templates/sync/manifest.yaml.j2 +116 -0
  77. agentex/lib/cli/templates/sync/project/acp.py.j2 +26 -0
  78. agentex/lib/cli/templates/sync/pyproject.toml.j2 +33 -0
  79. agentex/lib/cli/templates/sync/requirements.txt.j2 +5 -0
  80. agentex/lib/cli/templates/temporal/.dockerignore.j2 +43 -0
  81. agentex/lib/cli/templates/temporal/Dockerfile-uv.j2 +48 -0
  82. agentex/lib/cli/templates/temporal/Dockerfile.j2 +48 -0
  83. agentex/lib/cli/templates/temporal/README.md.j2 +316 -0
  84. agentex/lib/cli/templates/temporal/deploy/example.yaml.j2 +55 -0
  85. agentex/lib/cli/templates/temporal/manifest.yaml.j2 +137 -0
  86. agentex/lib/cli/templates/temporal/project/acp.py.j2 +30 -0
  87. agentex/lib/cli/templates/temporal/project/run_worker.py.j2 +33 -0
  88. agentex/lib/cli/templates/temporal/project/workflow.py.j2 +66 -0
  89. agentex/lib/cli/templates/temporal/pyproject.toml.j2 +34 -0
  90. agentex/lib/cli/templates/temporal/requirements.txt.j2 +5 -0
  91. agentex/lib/cli/utils/cli_utils.py +14 -0
  92. agentex/lib/cli/utils/credential_utils.py +103 -0
  93. agentex/lib/cli/utils/exceptions.py +6 -0
  94. agentex/lib/cli/utils/kubectl_utils.py +135 -0
  95. agentex/lib/cli/utils/kubernetes_secrets_utils.py +185 -0
  96. agentex/lib/core/__init__.py +0 -0
  97. agentex/lib/core/adapters/__init__.py +0 -0
  98. agentex/lib/core/adapters/llm/__init__.py +1 -0
  99. agentex/lib/core/adapters/llm/adapter_litellm.py +46 -0
  100. agentex/lib/core/adapters/llm/adapter_sgp.py +55 -0
  101. agentex/lib/core/adapters/llm/port.py +24 -0
  102. agentex/lib/core/adapters/streams/adapter_redis.py +128 -0
  103. agentex/lib/core/adapters/streams/port.py +50 -0
  104. agentex/lib/core/clients/__init__.py +1 -0
  105. agentex/lib/core/clients/temporal/__init__.py +0 -0
  106. agentex/lib/core/clients/temporal/temporal_client.py +181 -0
  107. agentex/lib/core/clients/temporal/types.py +47 -0
  108. agentex/lib/core/clients/temporal/utils.py +56 -0
  109. agentex/lib/core/services/__init__.py +0 -0
  110. agentex/lib/core/services/adk/__init__.py +0 -0
  111. agentex/lib/core/services/adk/acp/__init__.py +0 -0
  112. agentex/lib/core/services/adk/acp/acp.py +210 -0
  113. agentex/lib/core/services/adk/agent_task_tracker.py +85 -0
  114. agentex/lib/core/services/adk/agents.py +43 -0
  115. agentex/lib/core/services/adk/events.py +61 -0
  116. agentex/lib/core/services/adk/messages.py +164 -0
  117. agentex/lib/core/services/adk/providers/__init__.py +0 -0
  118. agentex/lib/core/services/adk/providers/litellm.py +256 -0
  119. agentex/lib/core/services/adk/providers/openai.py +723 -0
  120. agentex/lib/core/services/adk/providers/sgp.py +99 -0
  121. agentex/lib/core/services/adk/state.py +120 -0
  122. agentex/lib/core/services/adk/streaming.py +262 -0
  123. agentex/lib/core/services/adk/tasks.py +69 -0
  124. agentex/lib/core/services/adk/tracing.py +36 -0
  125. agentex/lib/core/services/adk/utils/__init__.py +0 -0
  126. agentex/lib/core/services/adk/utils/templating.py +58 -0
  127. agentex/lib/core/temporal/__init__.py +0 -0
  128. agentex/lib/core/temporal/activities/__init__.py +207 -0
  129. agentex/lib/core/temporal/activities/activity_helpers.py +37 -0
  130. agentex/lib/core/temporal/activities/adk/__init__.py +0 -0
  131. agentex/lib/core/temporal/activities/adk/acp/__init__.py +0 -0
  132. agentex/lib/core/temporal/activities/adk/acp/acp_activities.py +86 -0
  133. agentex/lib/core/temporal/activities/adk/agent_task_tracker_activities.py +76 -0
  134. agentex/lib/core/temporal/activities/adk/agents_activities.py +35 -0
  135. agentex/lib/core/temporal/activities/adk/events_activities.py +50 -0
  136. agentex/lib/core/temporal/activities/adk/messages_activities.py +94 -0
  137. agentex/lib/core/temporal/activities/adk/providers/__init__.py +0 -0
  138. agentex/lib/core/temporal/activities/adk/providers/litellm_activities.py +71 -0
  139. agentex/lib/core/temporal/activities/adk/providers/openai_activities.py +210 -0
  140. agentex/lib/core/temporal/activities/adk/providers/sgp_activities.py +42 -0
  141. agentex/lib/core/temporal/activities/adk/state_activities.py +85 -0
  142. agentex/lib/core/temporal/activities/adk/streaming_activities.py +33 -0
  143. agentex/lib/core/temporal/activities/adk/tasks_activities.py +48 -0
  144. agentex/lib/core/temporal/activities/adk/tracing_activities.py +55 -0
  145. agentex/lib/core/temporal/activities/adk/utils/__init__.py +0 -0
  146. agentex/lib/core/temporal/activities/adk/utils/templating_activities.py +41 -0
  147. agentex/lib/core/temporal/services/__init__.py +0 -0
  148. agentex/lib/core/temporal/services/temporal_task_service.py +69 -0
  149. agentex/lib/core/temporal/types/__init__.py +0 -0
  150. agentex/lib/core/temporal/types/workflow.py +5 -0
  151. agentex/lib/core/temporal/workers/__init__.py +0 -0
  152. agentex/lib/core/temporal/workers/worker.py +162 -0
  153. agentex/lib/core/temporal/workflows/workflow.py +26 -0
  154. agentex/lib/core/tracing/__init__.py +5 -0
  155. agentex/lib/core/tracing/processors/agentex_tracing_processor.py +117 -0
  156. agentex/lib/core/tracing/processors/sgp_tracing_processor.py +119 -0
  157. agentex/lib/core/tracing/processors/tracing_processor_interface.py +40 -0
  158. agentex/lib/core/tracing/trace.py +311 -0
  159. agentex/lib/core/tracing/tracer.py +70 -0
  160. agentex/lib/core/tracing/tracing_processor_manager.py +62 -0
  161. agentex/lib/environment_variables.py +87 -0
  162. agentex/lib/py.typed +0 -0
  163. agentex/lib/sdk/__init__.py +0 -0
  164. agentex/lib/sdk/config/__init__.py +0 -0
  165. agentex/lib/sdk/config/agent_config.py +61 -0
  166. agentex/lib/sdk/config/agent_manifest.py +219 -0
  167. agentex/lib/sdk/config/build_config.py +35 -0
  168. agentex/lib/sdk/config/deployment_config.py +117 -0
  169. agentex/lib/sdk/config/local_development_config.py +56 -0
  170. agentex/lib/sdk/config/project_config.py +103 -0
  171. agentex/lib/sdk/fastacp/__init__.py +3 -0
  172. agentex/lib/sdk/fastacp/base/base_acp_server.py +406 -0
  173. agentex/lib/sdk/fastacp/fastacp.py +74 -0
  174. agentex/lib/sdk/fastacp/impl/agentic_base_acp.py +72 -0
  175. agentex/lib/sdk/fastacp/impl/sync_acp.py +109 -0
  176. agentex/lib/sdk/fastacp/impl/temporal_acp.py +97 -0
  177. agentex/lib/sdk/fastacp/tests/README.md +297 -0
  178. agentex/lib/sdk/fastacp/tests/conftest.py +307 -0
  179. agentex/lib/sdk/fastacp/tests/pytest.ini +10 -0
  180. agentex/lib/sdk/fastacp/tests/run_tests.py +227 -0
  181. agentex/lib/sdk/fastacp/tests/test_base_acp_server.py +450 -0
  182. agentex/lib/sdk/fastacp/tests/test_fastacp_factory.py +344 -0
  183. agentex/lib/sdk/fastacp/tests/test_integration.py +477 -0
  184. agentex/lib/sdk/state_machine/__init__.py +6 -0
  185. agentex/lib/sdk/state_machine/noop_workflow.py +21 -0
  186. agentex/lib/sdk/state_machine/state.py +10 -0
  187. agentex/lib/sdk/state_machine/state_machine.py +189 -0
  188. agentex/lib/sdk/state_machine/state_workflow.py +16 -0
  189. agentex/lib/sdk/utils/__init__.py +0 -0
  190. agentex/lib/sdk/utils/messages.py +223 -0
  191. agentex/lib/types/__init__.py +0 -0
  192. agentex/lib/types/acp.py +94 -0
  193. agentex/lib/types/agent_configs.py +79 -0
  194. agentex/lib/types/agent_results.py +29 -0
  195. agentex/lib/types/credentials.py +34 -0
  196. agentex/lib/types/fastacp.py +61 -0
  197. agentex/lib/types/files.py +13 -0
  198. agentex/lib/types/json_rpc.py +49 -0
  199. agentex/lib/types/llm_messages.py +354 -0
  200. agentex/lib/types/task_message_updates.py +171 -0
  201. agentex/lib/types/tracing.py +34 -0
  202. agentex/lib/utils/__init__.py +0 -0
  203. agentex/lib/utils/completions.py +131 -0
  204. agentex/lib/utils/console.py +14 -0
  205. agentex/lib/utils/io.py +29 -0
  206. agentex/lib/utils/iterables.py +14 -0
  207. agentex/lib/utils/json_schema.py +23 -0
  208. agentex/lib/utils/logging.py +31 -0
  209. agentex/lib/utils/mcp.py +17 -0
  210. agentex/lib/utils/model_utils.py +46 -0
  211. agentex/lib/utils/parsing.py +15 -0
  212. agentex/lib/utils/regex.py +6 -0
  213. agentex/lib/utils/temporal.py +13 -0
  214. agentex/py.typed +0 -0
  215. agentex/resources/__init__.py +103 -0
  216. agentex/resources/agents.py +707 -0
  217. agentex/resources/events.py +294 -0
  218. agentex/resources/messages/__init__.py +33 -0
  219. agentex/resources/messages/batch.py +271 -0
  220. agentex/resources/messages/messages.py +492 -0
  221. agentex/resources/spans.py +557 -0
  222. agentex/resources/states.py +544 -0
  223. agentex/resources/tasks.py +615 -0
  224. agentex/resources/tracker.py +384 -0
  225. agentex/types/__init__.py +56 -0
  226. agentex/types/acp_type.py +7 -0
  227. agentex/types/agent.py +29 -0
  228. agentex/types/agent_list_params.py +13 -0
  229. agentex/types/agent_list_response.py +10 -0
  230. agentex/types/agent_rpc_by_name_params.py +21 -0
  231. agentex/types/agent_rpc_params.py +51 -0
  232. agentex/types/agent_rpc_params1.py +21 -0
  233. agentex/types/agent_rpc_response.py +20 -0
  234. agentex/types/agent_rpc_result.py +90 -0
  235. agentex/types/agent_task_tracker.py +34 -0
  236. agentex/types/data_content.py +30 -0
  237. agentex/types/data_content_param.py +31 -0
  238. agentex/types/data_delta.py +14 -0
  239. agentex/types/event.py +29 -0
  240. agentex/types/event_list_params.py +22 -0
  241. agentex/types/event_list_response.py +10 -0
  242. agentex/types/message_author.py +7 -0
  243. agentex/types/message_create_params.py +18 -0
  244. agentex/types/message_list_params.py +14 -0
  245. agentex/types/message_list_response.py +10 -0
  246. agentex/types/message_style.py +7 -0
  247. agentex/types/message_update_params.py +18 -0
  248. agentex/types/messages/__init__.py +8 -0
  249. agentex/types/messages/batch_create_params.py +16 -0
  250. agentex/types/messages/batch_create_response.py +10 -0
  251. agentex/types/messages/batch_update_params.py +16 -0
  252. agentex/types/messages/batch_update_response.py +10 -0
  253. agentex/types/shared/__init__.py +3 -0
  254. agentex/types/shared/task_message_update.py +83 -0
  255. agentex/types/span.py +36 -0
  256. agentex/types/span_create_params.py +40 -0
  257. agentex/types/span_list_params.py +12 -0
  258. agentex/types/span_list_response.py +10 -0
  259. agentex/types/span_update_params.py +37 -0
  260. agentex/types/state.py +25 -0
  261. agentex/types/state_create_params.py +16 -0
  262. agentex/types/state_list_params.py +16 -0
  263. agentex/types/state_list_response.py +10 -0
  264. agentex/types/state_update_params.py +16 -0
  265. agentex/types/task.py +23 -0
  266. agentex/types/task_delete_by_name_response.py +8 -0
  267. agentex/types/task_delete_response.py +8 -0
  268. agentex/types/task_list_response.py +10 -0
  269. agentex/types/task_message.py +33 -0
  270. agentex/types/task_message_content.py +16 -0
  271. agentex/types/task_message_content_param.py +17 -0
  272. agentex/types/task_message_delta.py +16 -0
  273. agentex/types/text_content.py +53 -0
  274. agentex/types/text_content_param.py +54 -0
  275. agentex/types/text_delta.py +14 -0
  276. agentex/types/tool_request_content.py +36 -0
  277. agentex/types/tool_request_content_param.py +37 -0
  278. agentex/types/tool_request_delta.py +18 -0
  279. agentex/types/tool_response_content.py +36 -0
  280. agentex/types/tool_response_content_param.py +36 -0
  281. agentex/types/tool_response_delta.py +18 -0
  282. agentex/types/tracker_list_params.py +16 -0
  283. agentex/types/tracker_list_response.py +10 -0
  284. agentex/types/tracker_update_params.py +19 -0
  285. agentex_sdk-0.1.0a6.dist-info/METADATA +426 -0
  286. agentex_sdk-0.1.0a6.dist-info/RECORD +289 -0
  287. agentex_sdk-0.1.0a6.dist-info/WHEEL +4 -0
  288. agentex_sdk-0.1.0a6.dist-info/entry_points.txt +2 -0
  289. agentex_sdk-0.1.0a6.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,311 @@
1
+ import asyncio
2
+ from contextlib import asynccontextmanager, contextmanager
3
+ from datetime import UTC, datetime
4
+ from typing import Any, AsyncGenerator
5
+ import uuid
6
+
7
+ from pydantic import BaseModel
8
+
9
+ from agentex import Agentex, AsyncAgentex
10
+ from agentex.lib.core.tracing.processors.tracing_processor_interface import (
11
+ AsyncTracingProcessor,
12
+ SyncTracingProcessor,
13
+ )
14
+ from agentex.lib.utils.logging import make_logger
15
+ from agentex.lib.utils.model_utils import recursive_model_dump
16
+ from agentex.types.span import Span
17
+
18
+ logger = make_logger(__name__)
19
+
20
+
21
+ class Trace:
22
+ """
23
+ Trace is a wrapper around the Agentex API for tracing.
24
+ It provides a context manager for spans and a way to start and end spans.
25
+ It also provides a way to get spans by ID and list all spans in a trace.
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ processors: list[SyncTracingProcessor],
31
+ client: Agentex,
32
+ trace_id: str | None = None,
33
+ ):
34
+ """
35
+ Initialize a new trace with the specified trace ID.
36
+
37
+ Args:
38
+ trace_id: Required trace ID to use for this trace.
39
+ processors: Optional list of tracing processors to use for this trace.
40
+ """
41
+ self.processors = processors
42
+ self.client = client
43
+ self.trace_id = trace_id
44
+
45
+ def start_span(
46
+ self,
47
+ name: str,
48
+ parent_id: str | None = None,
49
+ input: dict[str, Any] | list[dict[str, Any]] | BaseModel | None = None,
50
+ data: dict[str, Any] | list[dict[str, Any]] | BaseModel | None = None,
51
+ ) -> Span:
52
+ """
53
+ Start a new span and register it with the API.
54
+
55
+ Args:
56
+ name: Name of the span.
57
+ parent_id: Optional parent span ID.
58
+ input: Optional input data for the span.
59
+ data: Optional additional data for the span.
60
+
61
+ Returns:
62
+ The newly created span.
63
+ """
64
+
65
+ if not self.trace_id:
66
+ raise ValueError("Trace ID is required to start a span")
67
+
68
+ # Create a span using the client's spans resource
69
+ start_time = datetime.now(UTC)
70
+
71
+ serialized_input = recursive_model_dump(input) if input else None
72
+ serialized_data = recursive_model_dump(data) if data else None
73
+ id = str(uuid.uuid4())
74
+
75
+ span = Span(
76
+ id=id,
77
+ trace_id=self.trace_id,
78
+ name=name,
79
+ parent_id=parent_id,
80
+ start_time=start_time,
81
+ input=serialized_input,
82
+ data=serialized_data,
83
+ )
84
+
85
+ for processor in self.processors:
86
+ processor.on_span_start(span)
87
+
88
+ return span
89
+
90
+ def end_span(
91
+ self,
92
+ span: Span,
93
+ ) -> Span:
94
+ """
95
+ End a span by updating it with any changes made to the span object.
96
+
97
+ Args:
98
+ span: The span object to update.
99
+
100
+ Returns:
101
+ The updated span.
102
+ """
103
+ if span.end_time is None:
104
+ span.end_time = datetime.now(UTC)
105
+
106
+ span.input = recursive_model_dump(span.input) if span.input else None
107
+ span.output = recursive_model_dump(span.output) if span.output else None
108
+ span.data = recursive_model_dump(span.data) if span.data else None
109
+
110
+ for processor in self.processors:
111
+ processor.on_span_end(span)
112
+
113
+ return span
114
+
115
+ def get_span(self, span_id: str) -> Span:
116
+ """
117
+ Get a span by ID.
118
+
119
+ Args:
120
+ span_id: The ID of the span to get.
121
+
122
+ Returns:
123
+ The requested span.
124
+ """
125
+ # Query from Agentex API
126
+ span = self.client.spans.retrieve(span_id)
127
+ return span
128
+
129
+ def list_spans(self) -> list[Span]:
130
+ """
131
+ List all spans in this trace.
132
+
133
+ Returns:
134
+ List of spans in this trace.
135
+ """
136
+ # Query from Agentex API
137
+ spans = self.client.spans.list(trace_id=self.trace_id)
138
+ return spans
139
+
140
+ @contextmanager
141
+ def span(
142
+ self,
143
+ name: str,
144
+ parent_id: str | None = None,
145
+ input: dict[str, Any] | list[dict[str, Any]] | BaseModel | None = None,
146
+ data: dict[str, Any] | list[dict[str, Any]] | BaseModel | None = None,
147
+ ):
148
+ """
149
+ Context manager for spans.
150
+ If trace_id is falsy, acts as a no-op context manager.
151
+ """
152
+ if not self.trace_id:
153
+ yield None
154
+ return
155
+ span = self.start_span(name, parent_id, input, data)
156
+ try:
157
+ yield span
158
+ finally:
159
+ self.end_span(span)
160
+
161
+
162
+ class AsyncTrace:
163
+ """
164
+ AsyncTrace is a wrapper around the Agentex API for tracing.
165
+ It provides a context manager for spans and a way to start and end spans.
166
+ It also provides a way to get spans by ID and list all spans in a trace.
167
+ """
168
+
169
+ def __init__(
170
+ self,
171
+ processors: list[AsyncTracingProcessor],
172
+ client: AsyncAgentex,
173
+ trace_id: str | None = None,
174
+ ):
175
+ """
176
+ Initialize a new trace with the specified trace ID.
177
+
178
+ Args:
179
+ trace_id: Required trace ID to use for this trace.
180
+ processors: Optional list of tracing processors to use for this trace.
181
+ """
182
+ self.processors = processors
183
+ self.client = client
184
+ self.trace_id = trace_id
185
+
186
+ async def start_span(
187
+ self,
188
+ name: str,
189
+ parent_id: str | None = None,
190
+ input: dict[str, Any] | list[dict[str, Any]] | BaseModel | None = None,
191
+ data: dict[str, Any] | list[dict[str, Any]] | BaseModel | None = None,
192
+ ) -> Span:
193
+ """
194
+ Start a new span and register it with the API.
195
+
196
+ Args:
197
+ name: Name of the span.
198
+ parent_id: Optional parent span ID.
199
+ input: Optional input data for the span.
200
+ data: Optional additional data for the span.
201
+
202
+ Returns:
203
+ The newly created span.
204
+ """
205
+ if not self.trace_id:
206
+ raise ValueError("Trace ID is required to start a span")
207
+
208
+ # Create a span using the client's spans resource
209
+ start_time = datetime.now(UTC)
210
+
211
+ serialized_input = recursive_model_dump(input) if input else None
212
+ serialized_data = recursive_model_dump(data) if data else None
213
+ id = str(uuid.uuid4())
214
+
215
+ span = Span(
216
+ id=id,
217
+ trace_id=self.trace_id,
218
+ name=name,
219
+ parent_id=parent_id,
220
+ start_time=start_time,
221
+ input=serialized_input,
222
+ data=serialized_data,
223
+ )
224
+
225
+ if self.processors:
226
+ await asyncio.gather(
227
+ *[processor.on_span_start(span) for processor in self.processors]
228
+ )
229
+
230
+ return span
231
+
232
+ async def end_span(
233
+ self,
234
+ span: Span,
235
+ ) -> Span:
236
+ """
237
+ End a span by updating it with any changes made to the span object.
238
+
239
+ Args:
240
+ span: The span object to update.
241
+
242
+ Returns:
243
+ The updated span.
244
+ """
245
+ if span.end_time is None:
246
+ span.end_time = datetime.now(UTC)
247
+
248
+ span.input = recursive_model_dump(span.input) if span.input else None
249
+ span.output = recursive_model_dump(span.output) if span.output else None
250
+ span.data = recursive_model_dump(span.data) if span.data else None
251
+
252
+ if self.processors:
253
+ await asyncio.gather(
254
+ *[processor.on_span_end(span) for processor in self.processors]
255
+ )
256
+
257
+ return span
258
+
259
+ async def get_span(self, span_id: str) -> Span:
260
+ """
261
+ Get a span by ID.
262
+
263
+ Args:
264
+ span_id: The ID of the span to get.
265
+
266
+ Returns:
267
+ The requested span.
268
+ """
269
+ # Query from Agentex API
270
+ span = await self.client.spans.retrieve(span_id)
271
+ return span
272
+
273
+ async def list_spans(self) -> list[Span]:
274
+ """
275
+ List all spans in this trace.
276
+
277
+ Returns:
278
+ List of spans in this trace.
279
+ """
280
+ # Query from Agentex API
281
+ spans = await self.client.spans.list(trace_id=self.trace_id)
282
+ return spans
283
+
284
+ @asynccontextmanager
285
+ async def span(
286
+ self,
287
+ name: str,
288
+ parent_id: str | None = None,
289
+ input: dict[str, Any] | list[dict[str, Any]] | BaseModel | None = None,
290
+ data: dict[str, Any] | list[dict[str, Any]] | BaseModel | None = None,
291
+ ) -> AsyncGenerator[Span | None, None]:
292
+ """
293
+ Context manager for spans.
294
+
295
+ Args:
296
+ name: Name of the span.
297
+ parent_id: Optional parent span ID.
298
+ input: Optional input data for the span.
299
+ data: Optional additional data for the span.
300
+
301
+ Yields:
302
+ The span object.
303
+ """
304
+ if not self.trace_id:
305
+ yield None
306
+ return
307
+ span = await self.start_span(name, parent_id, input, data)
308
+ try:
309
+ yield span
310
+ finally:
311
+ await self.end_span(span)
@@ -0,0 +1,70 @@
1
+ from agentex import Agentex, AsyncAgentex
2
+ from agentex.lib.core.tracing.trace import AsyncTrace, Trace
3
+ from agentex.lib.core.tracing.tracing_processor_manager import (
4
+ get_async_tracing_processors,
5
+ get_sync_tracing_processors,
6
+ )
7
+
8
+
9
+ class Tracer:
10
+ """
11
+ Tracer is the main entry point for tracing in Agentex.
12
+ It manages the client connection and creates traces.
13
+ """
14
+
15
+ def __init__(self, client: Agentex):
16
+ """
17
+ Initialize a new sync tracer with the provided client.
18
+
19
+ Args:
20
+ client: Agentex client instance used for API communication.
21
+ """
22
+ self.client = client
23
+
24
+ def trace(self, trace_id: str | None = None) -> Trace:
25
+ """
26
+ Create a new trace with the given trace ID.
27
+
28
+ Args:
29
+ trace_id: The trace ID to use.
30
+
31
+ Returns:
32
+ A new Trace instance.
33
+ """
34
+ return Trace(
35
+ processors=get_sync_tracing_processors(),
36
+ client=self.client,
37
+ trace_id=trace_id,
38
+ )
39
+
40
+
41
+ class AsyncTracer:
42
+ """
43
+ AsyncTracer is the async version of Tracer.
44
+ It manages the async client connection and creates async traces.
45
+ """
46
+
47
+ def __init__(self, client: AsyncAgentex):
48
+ """
49
+ Initialize a new async tracer with the provided client.
50
+
51
+ Args:
52
+ client: AsyncAgentex client instance used for API communication.
53
+ """
54
+ self.client = client
55
+
56
+ def trace(self, trace_id: str | None = None) -> AsyncTrace:
57
+ """
58
+ Create a new trace with the given trace ID.
59
+
60
+ Args:
61
+ trace_id: The trace ID to use.
62
+
63
+ Returns:
64
+ A new AsyncTrace instance.
65
+ """
66
+ return AsyncTrace(
67
+ processors=get_async_tracing_processors(),
68
+ client=self.client,
69
+ trace_id=trace_id,
70
+ )
@@ -0,0 +1,62 @@
1
+ from threading import Lock
2
+
3
+ from agentex.lib.core.tracing.processors.agentex_tracing_processor import (
4
+ AgentexAsyncTracingProcessor,
5
+ AgentexSyncTracingProcessor,
6
+ )
7
+ from agentex.lib.core.tracing.processors.sgp_tracing_processor import (
8
+ SGPAsyncTracingProcessor,
9
+ SGPSyncTracingProcessor,
10
+ )
11
+ from agentex.lib.core.tracing.processors.tracing_processor_interface import (
12
+ AsyncTracingProcessor,
13
+ SyncTracingProcessor,
14
+ )
15
+ from agentex.lib.types.tracing import AgentexTracingProcessorConfig, TracingProcessorConfig
16
+
17
+
18
+ class TracingProcessorManager:
19
+ def __init__(self):
20
+ # Mapping of processor config type to processor class
21
+ self.sync_config_registry: dict[str, type[SyncTracingProcessor]] = {
22
+ "agentex": AgentexSyncTracingProcessor,
23
+ "sgp": SGPSyncTracingProcessor,
24
+ }
25
+ self.async_config_registry: dict[str, type[AsyncTracingProcessor]] = {
26
+ "agentex": AgentexAsyncTracingProcessor,
27
+ "sgp": SGPAsyncTracingProcessor,
28
+ }
29
+ # Cache for processors
30
+ self.sync_processors: list[SyncTracingProcessor] = []
31
+ self.async_processors: list[AsyncTracingProcessor] = []
32
+ self.lock = Lock()
33
+
34
+ def add_processor_config(self, processor_config: TracingProcessorConfig) -> None:
35
+ with self.lock:
36
+ sync_processor = self.sync_config_registry[processor_config.type]
37
+ async_processor = self.async_config_registry[processor_config.type]
38
+ self.sync_processors.append(sync_processor(processor_config))
39
+ self.async_processors.append(async_processor(processor_config))
40
+
41
+ def set_processor_configs(self, processor_configs: list[TracingProcessorConfig]):
42
+ with self.lock:
43
+ for processor_config in processor_configs:
44
+ self.add_processor_config(processor_config)
45
+
46
+ def get_sync_processors(self) -> list[SyncTracingProcessor]:
47
+ return self.sync_processors
48
+
49
+ def get_async_processors(self) -> list[AsyncTracingProcessor]:
50
+ return self.async_processors
51
+
52
+
53
+ # Global instance
54
+ GLOBAL_TRACING_PROCESSOR_MANAGER = TracingProcessorManager()
55
+
56
+ add_tracing_processor_config = GLOBAL_TRACING_PROCESSOR_MANAGER.add_processor_config
57
+ set_tracing_processor_configs = GLOBAL_TRACING_PROCESSOR_MANAGER.set_processor_configs
58
+ get_sync_tracing_processors = GLOBAL_TRACING_PROCESSOR_MANAGER.get_sync_processors
59
+ get_async_tracing_processors = GLOBAL_TRACING_PROCESSOR_MANAGER.get_async_processors
60
+
61
+ # Add the Agentex tracing processor by default
62
+ add_tracing_processor_config(AgentexTracingProcessorConfig())
@@ -0,0 +1,87 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from enum import Enum
5
+ from pathlib import Path
6
+
7
+ from dotenv import load_dotenv
8
+
9
+ from agentex.lib.utils.model_utils import BaseModel
10
+
11
+ PROJECT_ROOT = Path(__file__).resolve().parents[2]
12
+
13
+
14
+ class EnvVarKeys(str, Enum):
15
+ ENVIRONMENT = "ENVIRONMENT"
16
+ TEMPORAL_ADDRESS = "TEMPORAL_ADDRESS"
17
+ REDIS_URL = "REDIS_URL"
18
+ AGENTEX_BASE_URL = "AGENTEX_BASE_URL"
19
+ # Agent Identifiers
20
+ AGENT_NAME = "AGENT_NAME"
21
+ AGENT_DESCRIPTION = "AGENT_DESCRIPTION"
22
+ AGENT_ID = "AGENT_ID"
23
+ # ACP Configuration
24
+ ACP_URL = "ACP_URL"
25
+ ACP_PORT = "ACP_PORT"
26
+ ACP_TYPE = "ACP_TYPE"
27
+ # Workflow Configuraiton
28
+ WORKFLOW_NAME = "WORKFLOW_NAME"
29
+ WORKFLOW_TASK_QUEUE = "WORKFLOW_TASK_QUEUE"
30
+
31
+
32
+ class Environment(str, Enum):
33
+ DEV = "development"
34
+ STAGING = "staging"
35
+ PROD = "production"
36
+
37
+
38
+ refreshed_environment_variables = None
39
+
40
+
41
+ class EnvironmentVariables(BaseModel):
42
+ ENVIRONMENT: str = Environment.DEV
43
+ TEMPORAL_ADDRESS: str | None = "localhost:7233"
44
+ REDIS_URL: str | None = None
45
+ AGENTEX_BASE_URL: str | None = "http://localhost:5003"
46
+ # Agent Identifiers
47
+ AGENT_NAME: str
48
+ AGENT_DESCRIPTION: str | None = None
49
+ AGENT_ID: str | None = None
50
+ ACP_TYPE: str | None = "agentic"
51
+ # ACP Configuration
52
+ ACP_URL: str
53
+ ACP_PORT: int = 8000
54
+ # Workflow Configuration
55
+ WORKFLOW_TASK_QUEUE: str | None = None
56
+ WORKFLOW_NAME: str | None = None
57
+
58
+ @classmethod
59
+ def refresh(cls) -> EnvironmentVariables | None:
60
+ global refreshed_environment_variables
61
+ if refreshed_environment_variables is not None:
62
+ return refreshed_environment_variables
63
+
64
+ if os.environ.get(EnvVarKeys.ENVIRONMENT) == Environment.DEV:
65
+ # Load global .env file first
66
+ global_env_path = PROJECT_ROOT / ".env"
67
+ if global_env_path.exists():
68
+ print(f"Loading global environment variables FROM: {global_env_path}")
69
+ load_dotenv(dotenv_path=global_env_path, override=False)
70
+
71
+ # Load local project .env.local file (takes precedence)
72
+ local_env_path = Path.cwd().parent / ".env.local"
73
+ if local_env_path.exists():
74
+ print(f"Loading local environment variables FROM: {local_env_path}")
75
+ load_dotenv(dotenv_path=local_env_path, override=True)
76
+
77
+ # Create kwargs dict with environment variables, using None for missing values
78
+ # Pydantic will use the default values when None is passed for optional fields
79
+ kwargs = {}
80
+ for key in EnvVarKeys:
81
+ env_value = os.environ.get(key.value)
82
+ if env_value is not None:
83
+ kwargs[key.value] = env_value
84
+
85
+ environment_variables = EnvironmentVariables(**kwargs)
86
+ refreshed_environment_variables = environment_variables
87
+ return refreshed_environment_variables
agentex/lib/py.typed ADDED
File without changes
File without changes
File without changes
@@ -0,0 +1,61 @@
1
+ from typing import Any, Literal
2
+
3
+ from pydantic import Field
4
+
5
+ from agentex.lib.types.agent_configs import TemporalConfig, TemporalWorkflowConfig
6
+ from agentex.lib.types.credentials import CredentialMapping
7
+ from agentex.lib.utils.logging import make_logger
8
+ from agentex.lib.utils.model_utils import BaseModel
9
+
10
+ logger = make_logger(__name__)
11
+
12
+
13
+ class AgentConfig(BaseModel):
14
+ name: str = Field(
15
+ ...,
16
+ description="The name of the agent.",
17
+ pattern=r"^[a-z0-9-]+$",
18
+ )
19
+ acp_type: Literal["sync", "agentic"] = Field(..., description="The type of agent.")
20
+ description: str = Field(..., description="The description of the agent.")
21
+ env: dict[str, str] | None = Field(
22
+ default=None, description="Environment variables to set directly in the agent deployment"
23
+ )
24
+ credentials: list[CredentialMapping | dict[str, Any]] | None = Field(
25
+ default=None,
26
+ description="List of credential mappings to mount to the agent deployment. Supports both legacy format and new typed credentials.",
27
+ )
28
+ temporal: TemporalConfig | None = Field(
29
+ default=None, description="Temporal workflow configuration for this agent"
30
+ )
31
+
32
+ def is_temporal_agent(self) -> bool:
33
+ """Check if this agent uses Temporal workflows"""
34
+ # Check temporal config with enabled flag
35
+ if self.temporal and self.temporal.enabled:
36
+ return True
37
+ return False
38
+
39
+ def get_temporal_workflow_config(self) -> TemporalWorkflowConfig | None:
40
+ """Get temporal workflow configuration, checking both new and legacy formats"""
41
+ # Check new workflows list first
42
+ if self.temporal and self.temporal.enabled and self.temporal.workflows:
43
+ return self.temporal.workflows[0] # Return first workflow for backward compatibility
44
+
45
+ # Check legacy single workflow
46
+ if self.temporal and self.temporal.enabled and self.temporal.workflow:
47
+ return self.temporal.workflow
48
+
49
+ return None
50
+
51
+ def get_temporal_workflows(self) -> list[TemporalWorkflowConfig]:
52
+ """Get all temporal workflow configurations"""
53
+ # Check new workflows list first
54
+ if self.temporal and self.temporal.enabled and self.temporal.workflows:
55
+ return self.temporal.workflows
56
+
57
+ # Check legacy single workflow
58
+ if self.temporal and self.temporal.enabled and self.temporal.workflow:
59
+ return [self.temporal.workflow]
60
+
61
+ return []