agentex-sdk 0.2.5__py3-none-any.whl → 0.2.7__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.
- agentex/_base_client.py +4 -1
- agentex/_files.py +4 -4
- agentex/_version.py +1 -1
- agentex/lib/adk/_modules/acp.py +2 -2
- agentex/lib/adk/_modules/agent_task_tracker.py +2 -2
- agentex/lib/adk/_modules/agents.py +2 -2
- agentex/lib/adk/_modules/events.py +2 -2
- agentex/lib/adk/_modules/messages.py +2 -2
- agentex/lib/adk/_modules/state.py +2 -2
- agentex/lib/adk/_modules/streaming.py +2 -2
- agentex/lib/adk/_modules/tasks.py +2 -2
- agentex/lib/adk/_modules/tracing.py +2 -2
- agentex/lib/adk/providers/_modules/litellm.py +2 -1
- agentex/lib/adk/providers/_modules/openai.py +2 -1
- agentex/lib/adk/providers/_modules/sgp.py +2 -1
- agentex/lib/adk/utils/_modules/client.py +21 -35
- agentex/lib/adk/utils/_modules/templating.py +2 -1
- agentex/lib/cli/commands/agents.py +36 -2
- agentex/lib/cli/debug/__init__.py +15 -0
- agentex/lib/cli/debug/debug_config.py +116 -0
- agentex/lib/cli/debug/debug_handlers.py +174 -0
- agentex/lib/cli/handlers/agent_handlers.py +3 -2
- agentex/lib/cli/handlers/deploy_handlers.py +1 -2
- agentex/lib/cli/handlers/run_handlers.py +24 -7
- agentex/lib/cli/templates/default/pyproject.toml.j2 +0 -1
- agentex/lib/cli/templates/sync/pyproject.toml.j2 +0 -1
- agentex/lib/cli/templates/temporal/project/acp.py.j2 +31 -0
- agentex/lib/cli/templates/temporal/project/run_worker.py.j2 +4 -1
- agentex/lib/cli/templates/temporal/pyproject.toml.j2 +1 -1
- agentex/lib/core/services/adk/acp/acp.py +5 -5
- agentex/lib/core/temporal/activities/__init__.py +2 -1
- agentex/lib/core/temporal/workers/worker.py +24 -0
- agentex/lib/core/tracing/processors/agentex_tracing_processor.py +2 -1
- agentex/lib/environment_variables.py +7 -1
- agentex/lib/sdk/fastacp/base/base_acp_server.py +13 -89
- agentex/lib/sdk/fastacp/impl/agentic_base_acp.py +3 -1
- agentex/lib/utils/debug.py +63 -0
- agentex/lib/utils/registration.py +101 -0
- agentex/resources/tasks.py +54 -4
- agentex/types/__init__.py +1 -0
- agentex/types/agent.py +7 -0
- agentex/types/task_list_params.py +14 -0
- {agentex_sdk-0.2.5.dist-info → agentex_sdk-0.2.7.dist-info}/METADATA +32 -1
- {agentex_sdk-0.2.5.dist-info → agentex_sdk-0.2.7.dist-info}/RECORD +47 -41
- {agentex_sdk-0.2.5.dist-info → agentex_sdk-0.2.7.dist-info}/WHEEL +0 -0
- {agentex_sdk-0.2.5.dist-info → agentex_sdk-0.2.7.dist-info}/entry_points.txt +0 -0
- {agentex_sdk-0.2.5.dist-info → agentex_sdk-0.2.7.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,174 @@
|
|
1
|
+
"""
|
2
|
+
Debug process handlers for AgentEx CLI.
|
3
|
+
|
4
|
+
Provides debug-enabled versions of ACP server and temporal worker startup.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import asyncio
|
8
|
+
import sys
|
9
|
+
from pathlib import Path
|
10
|
+
from typing import Dict, TYPE_CHECKING
|
11
|
+
|
12
|
+
from rich.console import Console
|
13
|
+
|
14
|
+
if TYPE_CHECKING:
|
15
|
+
import asyncio.subprocess
|
16
|
+
|
17
|
+
from .debug_config import DebugConfig, resolve_debug_port
|
18
|
+
from agentex.lib.utils.logging import make_logger
|
19
|
+
|
20
|
+
logger = make_logger(__name__)
|
21
|
+
console = Console()
|
22
|
+
|
23
|
+
|
24
|
+
async def start_temporal_worker_debug(
|
25
|
+
worker_path: Path,
|
26
|
+
env: Dict[str, str],
|
27
|
+
debug_config: DebugConfig
|
28
|
+
):
|
29
|
+
"""Start temporal worker with debug support"""
|
30
|
+
|
31
|
+
if not debug_config.should_debug_worker():
|
32
|
+
raise ValueError("Debug config is not configured for worker debugging")
|
33
|
+
|
34
|
+
# Resolve the actual debug port
|
35
|
+
debug_port = resolve_debug_port(debug_config, debug_config.get_worker_port())
|
36
|
+
|
37
|
+
# Add debug environment variables
|
38
|
+
debug_env = env.copy()
|
39
|
+
debug_env.update({
|
40
|
+
"AGENTEX_DEBUG_ENABLED": "true",
|
41
|
+
"AGENTEX_DEBUG_PORT": str(debug_port),
|
42
|
+
"AGENTEX_DEBUG_WAIT_FOR_ATTACH": str(debug_config.wait_for_attach).lower(),
|
43
|
+
"AGENTEX_DEBUG_TYPE": "worker"
|
44
|
+
})
|
45
|
+
|
46
|
+
# Start the worker process
|
47
|
+
# For debugging, use absolute path to run_worker.py to run from workspace root
|
48
|
+
worker_script = worker_path.parent / "run_worker.py"
|
49
|
+
cmd = [sys.executable, str(worker_script)]
|
50
|
+
|
51
|
+
console.print(f"[blue]🐛 Starting Temporal worker in debug mode[/blue]")
|
52
|
+
console.print(f"[yellow]📡 Debug server will listen on port {debug_port}[/yellow]")
|
53
|
+
console.print(f"[green]✓ VS Code should connect to: localhost:{debug_port}[/green]")
|
54
|
+
|
55
|
+
if debug_config.wait_for_attach:
|
56
|
+
console.print(f"[yellow]⏳ Worker will wait for debugger to attach[/yellow]")
|
57
|
+
|
58
|
+
console.print(f"[dim]💡 In your IDE: Attach to localhost:{debug_port}[/dim]")
|
59
|
+
console.print(f"[dim]🔧 If connection fails, check that VS Code launch.json uses port {debug_port}[/dim]")
|
60
|
+
|
61
|
+
return await asyncio.create_subprocess_exec(
|
62
|
+
*cmd,
|
63
|
+
cwd=Path.cwd(), # Run from current working directory (workspace root)
|
64
|
+
env=debug_env,
|
65
|
+
stdout=asyncio.subprocess.PIPE,
|
66
|
+
stderr=asyncio.subprocess.STDOUT,
|
67
|
+
)
|
68
|
+
|
69
|
+
|
70
|
+
async def start_acp_server_debug(
|
71
|
+
acp_path: Path,
|
72
|
+
port: int,
|
73
|
+
env: Dict[str, str],
|
74
|
+
debug_config: DebugConfig
|
75
|
+
):
|
76
|
+
"""Start ACP server with debug support"""
|
77
|
+
|
78
|
+
if not debug_config.should_debug_acp():
|
79
|
+
raise ValueError("Debug config is not configured for ACP debugging")
|
80
|
+
|
81
|
+
# Resolve the actual debug port
|
82
|
+
debug_port = resolve_debug_port(debug_config, debug_config.get_acp_port())
|
83
|
+
|
84
|
+
# Add debug environment variables
|
85
|
+
debug_env = env.copy()
|
86
|
+
debug_env.update({
|
87
|
+
"AGENTEX_DEBUG_ENABLED": "true",
|
88
|
+
"AGENTEX_DEBUG_PORT": str(debug_port),
|
89
|
+
"AGENTEX_DEBUG_WAIT_FOR_ATTACH": str(debug_config.wait_for_attach).lower(),
|
90
|
+
"AGENTEX_DEBUG_TYPE": "acp"
|
91
|
+
})
|
92
|
+
|
93
|
+
# Disable uvicorn auto-reload in debug mode to prevent conflicts
|
94
|
+
cmd = [
|
95
|
+
sys.executable,
|
96
|
+
"-m",
|
97
|
+
"uvicorn",
|
98
|
+
f"{acp_path.parent.name}.acp:acp",
|
99
|
+
"--port",
|
100
|
+
str(port),
|
101
|
+
"--host",
|
102
|
+
"0.0.0.0",
|
103
|
+
# Note: No --reload flag when debugging
|
104
|
+
]
|
105
|
+
|
106
|
+
console.print(f"[blue]🐛 Starting ACP server in debug mode[/blue]")
|
107
|
+
console.print(f"[yellow]📡 Debug server will listen on port {debug_port}[/yellow]")
|
108
|
+
|
109
|
+
if debug_config.wait_for_attach:
|
110
|
+
console.print(f"[yellow]⏳ ACP server will wait for debugger to attach[/yellow]")
|
111
|
+
|
112
|
+
console.print(f"[dim]💡 In your IDE: Attach to localhost:{debug_port}[/dim]")
|
113
|
+
|
114
|
+
return await asyncio.create_subprocess_exec(
|
115
|
+
*cmd,
|
116
|
+
cwd=acp_path.parent.parent,
|
117
|
+
env=debug_env,
|
118
|
+
stdout=asyncio.subprocess.PIPE,
|
119
|
+
stderr=asyncio.subprocess.STDOUT,
|
120
|
+
)
|
121
|
+
|
122
|
+
|
123
|
+
def create_debug_startup_script() -> str:
|
124
|
+
"""Create a Python script snippet for debug initialization"""
|
125
|
+
return '''
|
126
|
+
import os
|
127
|
+
import sys
|
128
|
+
|
129
|
+
# Debug initialization for AgentEx
|
130
|
+
if os.getenv("AGENTEX_DEBUG_ENABLED") == "true":
|
131
|
+
try:
|
132
|
+
import debugpy
|
133
|
+
debug_port = int(os.getenv("AGENTEX_DEBUG_PORT", "5678"))
|
134
|
+
debug_type = os.getenv("AGENTEX_DEBUG_TYPE", "unknown")
|
135
|
+
wait_for_attach = os.getenv("AGENTEX_DEBUG_WAIT_FOR_ATTACH", "false").lower() == "true"
|
136
|
+
|
137
|
+
# Configure debugpy
|
138
|
+
debugpy.configure(subProcess=False)
|
139
|
+
debugpy.listen(debug_port)
|
140
|
+
|
141
|
+
print(f"🐛 [{debug_type.upper()}] Debug server listening on port {debug_port}")
|
142
|
+
|
143
|
+
if wait_for_attach:
|
144
|
+
print(f"⏳ [{debug_type.upper()}] Waiting for debugger to attach...")
|
145
|
+
debugpy.wait_for_client()
|
146
|
+
print(f"✅ [{debug_type.upper()}] Debugger attached!")
|
147
|
+
else:
|
148
|
+
print(f"📡 [{debug_type.upper()}] Ready for debugger attachment")
|
149
|
+
|
150
|
+
except ImportError:
|
151
|
+
print("❌ debugpy not available. Install with: pip install debugpy")
|
152
|
+
sys.exit(1)
|
153
|
+
except Exception as e:
|
154
|
+
print(f"❌ Debug setup failed: {e}")
|
155
|
+
sys.exit(1)
|
156
|
+
'''
|
157
|
+
|
158
|
+
|
159
|
+
def inject_debug_code_to_worker_template() -> str:
|
160
|
+
"""Generate debug code to inject into worker template"""
|
161
|
+
return """
|
162
|
+
# === DEBUG SETUP (Auto-generated by AgentEx CLI) ===
|
163
|
+
""" + create_debug_startup_script() + """
|
164
|
+
# === END DEBUG SETUP ===
|
165
|
+
"""
|
166
|
+
|
167
|
+
|
168
|
+
def inject_debug_code_to_acp_template() -> str:
|
169
|
+
"""Generate debug code to inject into ACP template"""
|
170
|
+
return """
|
171
|
+
# === DEBUG SETUP (Auto-generated by AgentEx CLI) ===
|
172
|
+
""" + create_debug_startup_script() + """
|
173
|
+
# === END DEBUG SETUP ===
|
174
|
+
"""
|
@@ -7,6 +7,7 @@ from rich.console import Console
|
|
7
7
|
|
8
8
|
from agentex.lib.cli.handlers.run_handlers import RunError
|
9
9
|
from agentex.lib.cli.handlers.run_handlers import run_agent as _run_agent
|
10
|
+
from agentex.lib.cli.debug import DebugConfig
|
10
11
|
from agentex.lib.sdk.config.agent_manifest import AgentManifest
|
11
12
|
from agentex.lib.utils.logging import make_logger
|
12
13
|
|
@@ -126,7 +127,7 @@ def build_agent(
|
|
126
127
|
return image_name
|
127
128
|
|
128
129
|
|
129
|
-
def run_agent(manifest_path: str):
|
130
|
+
def run_agent(manifest_path: str, debug_config: "DebugConfig | None" = None):
|
130
131
|
"""Run an agent locally from the given manifest"""
|
131
132
|
import asyncio
|
132
133
|
import signal
|
@@ -152,7 +153,7 @@ def run_agent(manifest_path: str):
|
|
152
153
|
signal.signal(signal.SIGTERM, signal_handler)
|
153
154
|
|
154
155
|
try:
|
155
|
-
asyncio.run(_run_agent(manifest_path))
|
156
|
+
asyncio.run(_run_agent(manifest_path, debug_config))
|
156
157
|
except KeyboardInterrupt:
|
157
158
|
print("Shutdown completed.")
|
158
159
|
sys.exit(0)
|
@@ -22,7 +22,7 @@ logger = make_logger(__name__)
|
|
22
22
|
console = Console()
|
23
23
|
|
24
24
|
TEMPORAL_WORKER_KEY = "temporal-worker"
|
25
|
-
AGENTEX_AGENTS_HELM_CHART_VERSION = "0.1.
|
25
|
+
AGENTEX_AGENTS_HELM_CHART_VERSION = "0.1.6-v1-beta"
|
26
26
|
|
27
27
|
|
28
28
|
class InputDeployOverrides(BaseModel):
|
@@ -204,7 +204,6 @@ def merge_deployment_configs(
|
|
204
204
|
for pull_secret in manifest.deployment.imagePullSecrets
|
205
205
|
]
|
206
206
|
helm_values["global"]["imagePullSecrets"] = pull_secrets
|
207
|
-
# TODO: Remove this once i bump the chart version again
|
208
207
|
helm_values["imagePullSecrets"] = pull_secrets
|
209
208
|
|
210
209
|
# Apply cluster-specific overrides
|
@@ -18,6 +18,9 @@ from agentex.lib.cli.utils.path_utils import (
|
|
18
18
|
|
19
19
|
from agentex.lib.environment_variables import EnvVarKeys
|
20
20
|
from agentex.lib.sdk.config.agent_manifest import AgentManifest
|
21
|
+
|
22
|
+
# Import debug functionality
|
23
|
+
from agentex.lib.cli.debug import DebugConfig, start_acp_server_debug, start_temporal_worker_debug
|
21
24
|
from agentex.lib.utils.logging import make_logger
|
22
25
|
|
23
26
|
logger = make_logger(__name__)
|
@@ -249,7 +252,7 @@ async def stream_process_output(process: asyncio.subprocess.Process, prefix: str
|
|
249
252
|
logger.debug(f"Output streaming ended for {prefix}: {e}")
|
250
253
|
|
251
254
|
|
252
|
-
async def run_agent(manifest_path: str):
|
255
|
+
async def run_agent(manifest_path: str, debug_config: "DebugConfig | None" = None):
|
253
256
|
"""Run an agent locally from the given manifest"""
|
254
257
|
|
255
258
|
# Validate manifest exists
|
@@ -289,11 +292,16 @@ async def run_agent(manifest_path: str):
|
|
289
292
|
)
|
290
293
|
)
|
291
294
|
|
292
|
-
# Start ACP server
|
295
|
+
# Start ACP server (with debug support if enabled)
|
293
296
|
manifest_dir = Path(manifest_path).parent
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
+
if debug_config and debug_config.should_debug_acp():
|
298
|
+
acp_process = await start_acp_server_debug(
|
299
|
+
file_paths["acp"], manifest.local_development.agent.port, agent_env, debug_config
|
300
|
+
)
|
301
|
+
else:
|
302
|
+
acp_process = await start_acp_server(
|
303
|
+
file_paths["acp"], manifest.local_development.agent.port, agent_env, manifest_dir
|
304
|
+
)
|
297
305
|
process_manager.add_process(acp_process)
|
298
306
|
|
299
307
|
# Start output streaming for ACP
|
@@ -301,9 +309,18 @@ async def run_agent(manifest_path: str):
|
|
301
309
|
|
302
310
|
tasks = [acp_output_task]
|
303
311
|
|
304
|
-
# Start temporal worker if needed
|
312
|
+
# Start temporal worker if needed (with debug support if enabled)
|
305
313
|
if is_temporal_agent(manifest) and file_paths["worker"]:
|
306
|
-
|
314
|
+
if debug_config and debug_config.should_debug_worker():
|
315
|
+
# In debug mode, start worker without auto-reload to prevent conflicts
|
316
|
+
worker_process = await start_temporal_worker_debug(
|
317
|
+
file_paths["worker"], agent_env, debug_config
|
318
|
+
)
|
319
|
+
process_manager.add_process(worker_process)
|
320
|
+
worker_task = asyncio.create_task(stream_process_output(worker_process, "WORKER"))
|
321
|
+
else:
|
322
|
+
# Normal mode with auto-reload
|
323
|
+
worker_task = await start_temporal_worker_with_reload(file_paths["worker"], agent_env, process_manager)
|
307
324
|
tasks.append(worker_task)
|
308
325
|
|
309
326
|
console.print(
|
@@ -1,4 +1,35 @@
|
|
1
1
|
import os
|
2
|
+
import sys
|
3
|
+
|
4
|
+
# === DEBUG SETUP (AgentEx CLI Debug Support) ===
|
5
|
+
if os.getenv("AGENTEX_DEBUG_ENABLED") == "true":
|
6
|
+
try:
|
7
|
+
import debugpy
|
8
|
+
debug_port = int(os.getenv("AGENTEX_DEBUG_PORT", "5679"))
|
9
|
+
debug_type = os.getenv("AGENTEX_DEBUG_TYPE", "acp")
|
10
|
+
wait_for_attach = os.getenv("AGENTEX_DEBUG_WAIT_FOR_ATTACH", "false").lower() == "true"
|
11
|
+
|
12
|
+
# Configure debugpy
|
13
|
+
debugpy.configure(subProcess=False)
|
14
|
+
debugpy.listen(debug_port)
|
15
|
+
|
16
|
+
print(f"🐛 [{debug_type.upper()}] Debug server listening on port {debug_port}")
|
17
|
+
|
18
|
+
if wait_for_attach:
|
19
|
+
print(f"⏳ [{debug_type.upper()}] Waiting for debugger to attach...")
|
20
|
+
debugpy.wait_for_client()
|
21
|
+
print(f"✅ [{debug_type.upper()}] Debugger attached!")
|
22
|
+
else:
|
23
|
+
print(f"📡 [{debug_type.upper()}] Ready for debugger attachment")
|
24
|
+
|
25
|
+
except ImportError:
|
26
|
+
print("❌ debugpy not available. Install with: pip install debugpy")
|
27
|
+
sys.exit(1)
|
28
|
+
except Exception as e:
|
29
|
+
print(f"❌ Debug setup failed: {e}")
|
30
|
+
sys.exit(1)
|
31
|
+
# === END DEBUG SETUP ===
|
32
|
+
|
2
33
|
from agentex.lib.sdk.fastacp.fastacp import FastACP
|
3
34
|
from agentex.lib.types.fastacp import TemporalACPConfig
|
4
35
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import asyncio
|
2
|
-
import os
|
3
2
|
|
4
3
|
from agentex.lib.core.temporal.activities import get_all_activities
|
5
4
|
from agentex.lib.core.temporal.workers.worker import AgentexWorker
|
6
5
|
from agentex.lib.utils.logging import make_logger
|
6
|
+
from agentex.lib.utils.debug import setup_debug_if_enabled
|
7
7
|
from agentex.lib.environment_variables import EnvironmentVariables
|
8
8
|
|
9
9
|
from workflow import {{ workflow_class }}
|
@@ -15,6 +15,9 @@ logger = make_logger(__name__)
|
|
15
15
|
|
16
16
|
|
17
17
|
async def main():
|
18
|
+
# Setup debug mode if enabled
|
19
|
+
setup_debug_if_enabled()
|
20
|
+
|
18
21
|
task_queue_name = environment_variables.WORKFLOW_TASK_QUEUE
|
19
22
|
if task_queue_name is None:
|
20
23
|
raise ValueError("WORKFLOW_TASK_QUEUE is not set")
|
@@ -6,7 +6,6 @@ build-backend = "hatchling.build"
|
|
6
6
|
name = "{{ project_name }}"
|
7
7
|
version = "0.1.0"
|
8
8
|
description = "{{ description }}"
|
9
|
-
readme = "README.md"
|
10
9
|
requires-python = ">=3.12"
|
11
10
|
dependencies = [
|
12
11
|
"agentex-sdk",
|
@@ -20,6 +19,7 @@ dev = [
|
|
20
19
|
"black",
|
21
20
|
"isort",
|
22
21
|
"flake8",
|
22
|
+
"debugpy>=1.8.15",
|
23
23
|
]
|
24
24
|
|
25
25
|
[tool.hatch.build.targets.wheel]
|
@@ -64,7 +64,7 @@ class ACPService:
|
|
64
64
|
else:
|
65
65
|
raise ValueError("Either agent_name or agent_id must be provided")
|
66
66
|
|
67
|
-
task_entry = Task.model_validate(json_rpc_response
|
67
|
+
task_entry = Task.model_validate(json_rpc_response.result)
|
68
68
|
if span:
|
69
69
|
span.output = task_entry.model_dump()
|
70
70
|
return task_entry
|
@@ -115,7 +115,7 @@ class ACPService:
|
|
115
115
|
else:
|
116
116
|
raise ValueError("Either agent_name or agent_id must be provided")
|
117
117
|
|
118
|
-
task_message = TaskMessage.model_validate(json_rpc_response
|
118
|
+
task_message = TaskMessage.model_validate(json_rpc_response.result)
|
119
119
|
if span:
|
120
120
|
span.output = task_message.model_dump()
|
121
121
|
return task_message
|
@@ -147,7 +147,7 @@ class ACPService:
|
|
147
147
|
agent_name=agent_name,
|
148
148
|
method="event/send",
|
149
149
|
params={
|
150
|
-
"
|
150
|
+
"task_id": task_id,
|
151
151
|
"content": cast(TaskMessageContentParam, content.model_dump()),
|
152
152
|
},
|
153
153
|
)
|
@@ -163,7 +163,7 @@ class ACPService:
|
|
163
163
|
else:
|
164
164
|
raise ValueError("Either agent_name or agent_id must be provided")
|
165
165
|
|
166
|
-
event_entry = Event.model_validate(json_rpc_response
|
166
|
+
event_entry = Event.model_validate(json_rpc_response.result)
|
167
167
|
if span:
|
168
168
|
span.output = event_entry.model_dump()
|
169
169
|
return event_entry
|
@@ -204,7 +204,7 @@ class ACPService:
|
|
204
204
|
else:
|
205
205
|
raise ValueError("Either task_name or task_id must be provided")
|
206
206
|
|
207
|
-
task_entry = Task.model_validate(json_rpc_response
|
207
|
+
task_entry = Task.model_validate(json_rpc_response.result)
|
208
208
|
if span:
|
209
209
|
span.output = task_entry.model_dump()
|
210
210
|
return task_entry
|
@@ -1,3 +1,4 @@
|
|
1
|
+
from agentex.lib.adk.utils._modules.client import create_async_agentex_client
|
1
2
|
from scale_gp import SGPClient, SGPClientError
|
2
3
|
|
3
4
|
from agentex import AsyncAgentex
|
@@ -58,7 +59,7 @@ def get_all_activities(sgp_client=None):
|
|
58
59
|
|
59
60
|
llm_gateway = LiteLLMGateway()
|
60
61
|
stream_repository = RedisStreamRepository()
|
61
|
-
agentex_client =
|
62
|
+
agentex_client = create_async_agentex_client()
|
62
63
|
tracer = AsyncTracer(agentex_client)
|
63
64
|
|
64
65
|
# Services
|
@@ -24,6 +24,8 @@ from temporalio.worker import (
|
|
24
24
|
)
|
25
25
|
|
26
26
|
from agentex.lib.utils.logging import make_logger
|
27
|
+
from agentex.lib.utils.registration import register_agent
|
28
|
+
from agentex.lib.environment_variables import EnvironmentVariables
|
27
29
|
|
28
30
|
logger = make_logger(__name__)
|
29
31
|
|
@@ -103,9 +105,16 @@ class AgentexWorker:
|
|
103
105
|
workflow: type,
|
104
106
|
):
|
105
107
|
await self.start_health_check_server()
|
108
|
+
await self._register_agent()
|
106
109
|
temporal_client = await get_temporal_client(
|
107
110
|
temporal_address=os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"),
|
108
111
|
)
|
112
|
+
|
113
|
+
# Enable debug mode if AgentEx debug is enabled (disables deadlock detection)
|
114
|
+
debug_enabled = os.environ.get("AGENTEX_DEBUG_ENABLED", "false").lower() == "true"
|
115
|
+
if debug_enabled:
|
116
|
+
logger.info("🐛 [WORKER] Temporal debug mode enabled - deadlock detection disabled")
|
117
|
+
|
109
118
|
worker = Worker(
|
110
119
|
client=temporal_client,
|
111
120
|
task_queue=self.task_queue,
|
@@ -115,6 +124,7 @@ class AgentexWorker:
|
|
115
124
|
workflow_runner=UnsandboxedWorkflowRunner(),
|
116
125
|
max_concurrent_activities=self.max_concurrent_activities,
|
117
126
|
build_id=str(uuid.uuid4()),
|
127
|
+
debug_mode=debug_enabled, # Disable deadlock detection in debug mode
|
118
128
|
)
|
119
129
|
|
120
130
|
logger.info(f"Starting workers for task queue: {self.task_queue}")
|
@@ -160,3 +170,17 @@ class AgentexWorker:
|
|
160
170
|
f"Failed to start health check server on alternative port {alt_port}: {e}"
|
161
171
|
)
|
162
172
|
raise
|
173
|
+
|
174
|
+
"""
|
175
|
+
Register the worker with the Agentex server.
|
176
|
+
|
177
|
+
Even though the Temporal server will also register the agent with the server,
|
178
|
+
doing this on the worker side is required to make sure that both share the API key
|
179
|
+
which is returned on registration and used to authenticate the worker with the Agentex server.
|
180
|
+
"""
|
181
|
+
async def _register_agent(self):
|
182
|
+
env_vars = EnvironmentVariables.refresh()
|
183
|
+
if env_vars and env_vars.AGENTEX_BASE_URL:
|
184
|
+
await register_agent(env_vars)
|
185
|
+
else:
|
186
|
+
logger.warning("AGENTEX_BASE_URL not set, skipping worker registration")
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Any, Dict, override
|
2
2
|
|
3
3
|
from agentex import Agentex, AsyncAgentex
|
4
|
+
from agentex.lib.adk.utils._modules.client import create_async_agentex_client
|
4
5
|
from agentex.lib.core.tracing.processors.tracing_processor_interface import (
|
5
6
|
AsyncTracingProcessor,
|
6
7
|
SyncTracingProcessor,
|
@@ -65,7 +66,7 @@ class AgentexSyncTracingProcessor(SyncTracingProcessor):
|
|
65
66
|
|
66
67
|
class AgentexAsyncTracingProcessor(AsyncTracingProcessor):
|
67
68
|
def __init__(self, config: AgentexTracingProcessorConfig):
|
68
|
-
self.client =
|
69
|
+
self.client = create_async_agentex_client()
|
69
70
|
|
70
71
|
@override
|
71
72
|
async def on_span_start(self, span: Span) -> None:
|
@@ -4,12 +4,15 @@ import os
|
|
4
4
|
from enum import Enum
|
5
5
|
from pathlib import Path
|
6
6
|
|
7
|
+
from agentex.lib.utils.logging import make_logger
|
7
8
|
from dotenv import load_dotenv
|
8
9
|
|
9
10
|
from agentex.lib.utils.model_utils import BaseModel
|
10
11
|
|
11
12
|
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
12
13
|
|
14
|
+
logger = make_logger(__name__)
|
15
|
+
|
13
16
|
|
14
17
|
class EnvVarKeys(str, Enum):
|
15
18
|
ENVIRONMENT = "ENVIRONMENT"
|
@@ -20,6 +23,7 @@ class EnvVarKeys(str, Enum):
|
|
20
23
|
AGENT_NAME = "AGENT_NAME"
|
21
24
|
AGENT_DESCRIPTION = "AGENT_DESCRIPTION"
|
22
25
|
AGENT_ID = "AGENT_ID"
|
26
|
+
AGENT_API_KEY = "AGENT_API_KEY"
|
23
27
|
# ACP Configuration
|
24
28
|
ACP_URL = "ACP_URL"
|
25
29
|
ACP_PORT = "ACP_PORT"
|
@@ -37,7 +41,7 @@ class Environment(str, Enum):
|
|
37
41
|
PROD = "production"
|
38
42
|
|
39
43
|
|
40
|
-
refreshed_environment_variables = None
|
44
|
+
refreshed_environment_variables: "EnvironmentVariables" | None = None
|
41
45
|
|
42
46
|
|
43
47
|
class EnvironmentVariables(BaseModel):
|
@@ -49,6 +53,7 @@ class EnvironmentVariables(BaseModel):
|
|
49
53
|
AGENT_NAME: str
|
50
54
|
AGENT_DESCRIPTION: str | None = None
|
51
55
|
AGENT_ID: str | None = None
|
56
|
+
AGENT_API_KEY: str | None = None
|
52
57
|
ACP_TYPE: str | None = "agentic"
|
53
58
|
# ACP Configuration
|
54
59
|
ACP_URL: str
|
@@ -64,6 +69,7 @@ class EnvironmentVariables(BaseModel):
|
|
64
69
|
if refreshed_environment_variables is not None:
|
65
70
|
return refreshed_environment_variables
|
66
71
|
|
72
|
+
logger.info("Refreshing environment variables")
|
67
73
|
if os.environ.get(EnvVarKeys.ENVIRONMENT) == Environment.DEV:
|
68
74
|
# Load global .env file first
|
69
75
|
global_env_path = PROJECT_ROOT / ".env"
|