Skip to content

Commit 543cf15

Browse files
committed
Updates to the agentic project
1 parent 7b0a446 commit 543cf15

File tree

11 files changed

+223
-112
lines changed

11 files changed

+223
-112
lines changed

agentic/README.md

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ Then open your browser and navigate to:
7777
http://localhost:8080
7878
```
7979

80+
**✅ System Status: Fully Functional** - All WebSocket connection issues have been resolved and the system works seamlessly.
81+
8082
![](https://raw.githubusercontent.com/open-experiments/Telco-AIX/refs/heads/main/agentic/images/agentic.png)<br>
8183

8284
You'll see the dashboard with real-time visualization of agent activities, network telemetry, and workflow status.
@@ -147,24 +149,34 @@ The entire workflow is managed by the orchestration service, which ensures prope
147149

148150
## Troubleshooting
149151

150-
### WebSocket Connection Issues
151-
152-
If you see errors like:
153-
```
154-
WARNING: No supported WebSocket library detected
155-
```
156-
157-
Install the required WebSocket support:
152+
### Prerequisites
153+
Make sure you have installed the WebSocket support:
158154
```bash
159155
pip install websockets
160156
```
161157

162-
### Agent Communication Errors
158+
### Service URLs
159+
- **MCP Server**: http://localhost:8000
160+
- **ACP Broker**: http://localhost:8002
161+
- **Dashboard**: http://localhost:8080
163162

164-
If agents cannot communicate with each other:
165-
1. Ensure the ACP broker is running
166-
2. Confirm there are no firewall rules blocking the ports
167-
3. Verify all services are using the correct host/port configurations
163+
### Health Checks
164+
You can verify services are running:
165+
```bash
166+
# Check ACP broker health
167+
curl http://localhost:8002/health
168+
169+
# Check if agents are connected
170+
curl http://localhost:8002/agents
171+
```
172+
173+
### Recent Fixes Applied
174+
-**WebSocket Connection Issues**: All services now use `127.0.0.1` instead of `localhost` to avoid DNS resolution conflicts
175+
-**Service Startup**: Added health check verification before agent initialization
176+
-**Timeout Issues**: Enhanced retry logic and connection timeouts
177+
-**Python Compatibility**: Updated deprecated `datetime.utcnow()` calls for future Python versions
178+
-**Dashboard Issues**: Fixed agent details and workflow details pages with proper API endpoints
179+
-**Data Serialization**: Resolved JSON serialization issues with datetime and numpy data types
168180

169181
## Extending the Framework
170182

@@ -222,9 +234,18 @@ agentic/
222234
├── dashboard/ # Dashboard web interface
223235
├── main.py # Main application
224236
├── dashboard_mode.py # Dashboard-only mode
237+
├── CLAUDE.md # AI assistant guidance for development
225238
└── requirements.txt # Python dependencies
226239
```
227240

241+
## For AI Assistants
242+
243+
This project includes a `CLAUDE.md` file that provides specific guidance for AI assistants working with this codebase, including:
244+
- Architecture overview and key components
245+
- Essential commands and troubleshooting steps
246+
- Development workflow information
247+
- Implementation notes and best practices
248+
228249

229250
## Disclaimer
230251

agentic/agents/diagnostic/network_diagnostic_agent.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import time
77
from typing import Dict, Any, List, Optional, Tuple
88
import numpy as np
9-
from datetime import datetime, timedelta
9+
from datetime import datetime, timedelta, timezone
1010

1111
from agent.base import DiagnosticAgent
1212
from protocols.mcp.client import MCPClient
@@ -39,7 +39,7 @@ def add_value(self, value: float, timestamp: Optional[datetime] = None):
3939
timestamp: Timestamp for the value (default: current time)
4040
"""
4141
if timestamp is None:
42-
timestamp = datetime.utcnow()
42+
timestamp = datetime.now(timezone.utc)
4343

4444
self.values.append(value)
4545
self.timestamps.append(timestamp)
@@ -91,21 +91,21 @@ def get_statistics(self) -> Dict[str, Any]:
9191
return {
9292
"name": self.name,
9393
"count": len(self.values),
94-
"current": self.values[-1],
95-
"mean": np.mean(self.values),
96-
"std": np.std(self.values),
97-
"min": np.min(self.values),
98-
"max": np.max(self.values),
94+
"current": float(self.values[-1]),
95+
"mean": float(np.mean(self.values)),
96+
"std": float(np.std(self.values)),
97+
"min": float(np.min(self.values)),
98+
"max": float(np.max(self.values)),
9999
"timestamp": self.timestamps[-1].isoformat()
100100
}
101101

102102
class NetworkDiagnosticAgent(DiagnosticAgent):
103103
"""Agent for diagnosing network issues based on telemetry data."""
104104

105105
def __init__(self, agent_id: Optional[str] = None, name: str = None,
106-
telemetry_url: str = "http://localhost:8001/telemetry",
107-
mcp_url: str = "http://localhost:8000",
108-
acp_broker_url: str = "http://localhost:8002",
106+
telemetry_url: str = "http://127.0.0.1:8001/telemetry",
107+
mcp_url: str = "http://127.0.0.1:8000",
108+
acp_broker_url: str = "ws://127.0.0.1:8002",
109109
metrics_config: Optional[Dict[str, Dict[str, Any]]] = None,
110110
poll_interval: float = 60.0,
111111
config: Dict[str, Any] = None):
@@ -133,6 +133,7 @@ def __init__(self, agent_id: Optional[str] = None, name: str = None,
133133
self.acp_broker_url = acp_broker_url
134134
self.poll_interval = poll_interval
135135

136+
136137
# Set up metrics to monitor
137138
self.metrics: Dict[str, NetworkMetric] = {}
138139
metrics_config = metrics_config or {
@@ -241,7 +242,7 @@ async def _fetch_telemetry(self) -> Dict[str, Any]:
241242
"""
242243
# In a real implementation, this would make an API call to get telemetry data
243244
# For this example, we'll generate some simulated telemetry data
244-
timestamp = datetime.utcnow()
245+
timestamp = datetime.now(timezone.utc)
245246

246247
# Generate baseline values
247248
base_values = {
@@ -356,7 +357,7 @@ async def _notify_planning_agents(self, anomalies: List[Dict[str, Any]], context
356357
payload={
357358
"anomalies": anomalies,
358359
"severity": "medium",
359-
"detection_time": datetime.utcnow().isoformat()
360+
"detection_time": datetime.now(timezone.utc).isoformat()
360361
},
361362
priority=MessagePriority.HIGH,
362363
context_refs=[context_id]
@@ -407,7 +408,7 @@ async def perform_diagnostic(self, request: Dict[str, Any]) -> Dict[str, Any]:
407408
"metrics_statistics": {
408409
name: metric.get_statistics() for name, metric in self.metrics.items()
409410
},
410-
"diagnostic_time": datetime.utcnow().isoformat(),
411+
"diagnostic_time": datetime.now(timezone.utc).isoformat(),
411412
"diagnostic_agent": self.agent_id
412413
}
413414

@@ -435,7 +436,7 @@ async def process_message(self, message: Dict[str, Any]) -> Dict[str, Any]:
435436
# For now, we'll just return a simple acknowledgement
436437
return {
437438
"status": "acknowledged",
438-
"timestamp": datetime.utcnow().isoformat()
439+
"timestamp": datetime.now(timezone.utc).isoformat()
439440
}
440441

441442
def get_capabilities(self) -> List[str]:

agentic/agents/execution/network_execution_agent.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import logging
66
import uuid
77
from typing import Dict, Any, List, Optional
8-
from datetime import datetime
8+
from datetime import datetime, timezone
99

1010
from agent.base import ExecutionAgent
1111
from protocols.mcp.client import MCPClient
@@ -17,9 +17,9 @@ class NetworkExecutionAgent(ExecutionAgent):
1717
"""Agent for executing network configuration and optimization plans."""
1818

1919
def __init__(self, agent_id: Optional[str] = None, name: str = None,
20-
mcp_url: str = "http://localhost:8000",
21-
acp_broker_url: str = "http://localhost:8002",
22-
network_api_url: str = "http://localhost:8003/api/network",
20+
mcp_url: str = "http://127.0.0.1:8000",
21+
acp_broker_url: str = "ws://127.0.0.1:8002",
22+
network_api_url: str = "http://127.0.0.1:8003/api/network",
2323
config: Dict[str, Any] = None):
2424
"""Initialize a new network execution agent.
2525
@@ -111,7 +111,7 @@ async def _check_executing_plans(self) -> None:
111111

112112
for plan_id, plan_data in self.executing_plans.items():
113113
# Check if the plan has timed out
114-
current_time = datetime.utcnow()
114+
current_time = datetime.now(timezone.utc)
115115
start_time = datetime.fromisoformat(plan_data["start_time"])
116116
timeout = plan_data.get("timeout", 3600) # Default 1 hour timeout
117117

@@ -234,7 +234,7 @@ async def _store_execution_result(self, plan_id: str, result: Dict[str, Any]) ->
234234
"execution_result": result,
235235
"plan_id": plan_id,
236236
"agent_id": self.agent_id,
237-
"timestamp": datetime.utcnow().isoformat()
237+
"timestamp": datetime.now(timezone.utc).isoformat()
238238
},
239239
priority=3,
240240
confidence=ConfidenceLevel.HIGH,
@@ -298,7 +298,7 @@ async def execute_network_command(self, command: str, target: str) -> Dict[str,
298298
"status": "success",
299299
"command": command,
300300
"target": target,
301-
"timestamp": datetime.utcnow().isoformat(),
301+
"timestamp": datetime.now(timezone.utc).isoformat(),
302302
"output": f"Simulated output for {command} on {target}"
303303
}
304304

@@ -319,16 +319,16 @@ async def execute_plan(self, plan: Dict[str, Any]) -> Dict[str, Any]:
319319
"plan_id": plan_id,
320320
"status": "failed",
321321
"error": "Plan contains no steps to execute",
322-
"start_time": datetime.utcnow().isoformat(),
323-
"end_time": datetime.utcnow().isoformat(),
322+
"start_time": datetime.now(timezone.utc).isoformat(),
323+
"end_time": datetime.now(timezone.utc).isoformat(),
324324
"executed_by": self.agent_id
325325
}
326326

327327
# Initialize execution result
328328
result = {
329329
"plan_id": plan_id,
330330
"status": "in_progress",
331-
"start_time": datetime.utcnow().isoformat(),
331+
"start_time": datetime.now(timezone.utc).isoformat(),
332332
"executed_by": self.agent_id,
333333
"steps_total": len(steps),
334334
"steps_completed": 0,
@@ -354,7 +354,7 @@ async def execute_plan(self, plan: Dict[str, Any]) -> Dict[str, Any]:
354354
"step_id": step_id,
355355
"name": step_name,
356356
"status": "in_progress",
357-
"start_time": datetime.utcnow().isoformat()
357+
"start_time": datetime.now(timezone.utc).isoformat()
358358
}
359359

360360
try:
@@ -396,7 +396,7 @@ async def execute_plan(self, plan: Dict[str, Any]) -> Dict[str, Any]:
396396
result["steps_failed"] += 1
397397
finally:
398398
# Finalize step result
399-
step_result["end_time"] = datetime.utcnow().isoformat()
399+
step_result["end_time"] = datetime.now(timezone.utc).isoformat()
400400
step_result["duration"] = (datetime.fromisoformat(step_result["end_time"]) -
401401
datetime.fromisoformat(step_result["start_time"])).total_seconds()
402402
result["step_results"].append(step_result)
@@ -409,7 +409,7 @@ async def execute_plan(self, plan: Dict[str, Any]) -> Dict[str, Any]:
409409
self.executing_plans[plan_id] = result
410410

411411
# Finalize execution result
412-
end_time = datetime.utcnow().isoformat()
412+
end_time = datetime.now(timezone.utc).isoformat()
413413
result.update({
414414
"status": "completed" if result["steps_failed"] == 0 else "partial",
415415
"end_time": end_time,
@@ -445,7 +445,7 @@ async def process_message(self, message: Dict[str, Any]) -> Dict[str, Any]:
445445
# Default response for other message types
446446
return {
447447
"status": "acknowledged",
448-
"timestamp": datetime.utcnow().isoformat(),
448+
"timestamp": datetime.now(timezone.utc).isoformat(),
449449
"execution_agent": self.agent_id
450450
}
451451

agentic/agents/planning/network_planning_agent.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import logging
66
import uuid
77
from typing import Dict, Any, List, Optional
8-
from datetime import datetime
8+
from datetime import datetime, timezone
99

1010
from agent.base import PlanningAgent
1111
from protocols.mcp.client import MCPClient
@@ -17,8 +17,8 @@ class NetworkPlanningAgent(PlanningAgent):
1717
"""Agent for generating plans to resolve network issues."""
1818

1919
def __init__(self, agent_id: Optional[str] = None, name: str = None,
20-
mcp_url: str = "http://localhost:8000",
21-
acp_broker_url: str = "http://localhost:8002",
20+
mcp_url: str = "http://127.0.0.1:8000",
21+
acp_broker_url: str = "ws://127.0.0.1:8002",
2222
config: Dict[str, Any] = None):
2323
"""Initialize a new network planning agent.
2424
@@ -210,7 +210,7 @@ async def _notify_execution_agents(self, plan: Dict[str, Any], plan_context_id:
210210
payload={
211211
"plan_summary": plan.get("summary", "Network issue resolution plan"),
212212
"priority": plan.get("priority", "medium"),
213-
"generation_time": datetime.utcnow().isoformat()
213+
"generation_time": datetime.now(timezone.utc).isoformat()
214214
},
215215
priority=MessagePriority.HIGH,
216216
context_refs=[plan_context_id]
@@ -235,7 +235,7 @@ async def generate_plan(self, problem_context: Dict[str, Any]) -> Dict[str, Any]
235235
if not anomalies:
236236
return {
237237
"error": "No anomalies provided to generate a plan",
238-
"timestamp": datetime.utcnow().isoformat(),
238+
"timestamp": datetime.now(timezone.utc).isoformat(),
239239
"planning_agent": self.agent_id
240240
}
241241

@@ -245,7 +245,7 @@ async def generate_plan(self, problem_context: Dict[str, Any]) -> Dict[str, Any]
245245
"summary": f"Plan to resolve {len(anomalies)} network anomalies",
246246
"severity": severity,
247247
"priority": self._calculate_priority(anomalies, severity),
248-
"created_at": datetime.utcnow().isoformat(),
248+
"created_at": datetime.now(timezone.utc).isoformat(),
249249
"created_by": self.agent_id,
250250
"steps": [],
251251
"estimated_duration": 0, # Will be calculated based on steps
@@ -494,7 +494,7 @@ async def process_message(self, message: Dict[str, Any]) -> Dict[str, Any]:
494494
# Default response for other message types
495495
return {
496496
"status": "acknowledged",
497-
"timestamp": datetime.utcnow().isoformat(),
497+
"timestamp": datetime.now(timezone.utc).isoformat(),
498498
"planning_agent": self.agent_id
499499
}
500500

agentic/agents/validation/network_validation_agent.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import logging
66
import uuid
77
from typing import Dict, Any, List, Optional
8-
from datetime import datetime
8+
from datetime import datetime, timezone
99

1010
from agent.base import ValidationAgent
1111
from protocols.mcp.client import MCPClient
@@ -17,9 +17,9 @@ class NetworkValidationAgent(ValidationAgent):
1717
"""Agent for validating network changes and resolution of issues."""
1818

1919
def __init__(self, agent_id: Optional[str] = None, name: str = None,
20-
mcp_url: str = "http://localhost:8000",
21-
acp_broker_url: str = "http://localhost:8002",
22-
telemetry_url: str = "http://localhost:8001/telemetry",
20+
mcp_url: str = "http://127.0.0.1:8000",
21+
acp_broker_url: str = "ws://127.0.0.1:8002",
22+
telemetry_url: str = "http://127.0.0.1:8001/telemetry",
2323
config: Dict[str, Any] = None):
2424
"""Initialize a new network validation agent.
2525
@@ -237,7 +237,7 @@ async def _store_validation_result(self, result: Dict[str, Any], correlation_id:
237237
payload={
238238
"validation_result": result,
239239
"agent_id": self.agent_id,
240-
"timestamp": datetime.utcnow().isoformat()
240+
"timestamp": datetime.now(timezone.utc).isoformat()
241241
},
242242
priority=3,
243243
confidence=ConfidenceLevel.HIGH,
@@ -301,7 +301,7 @@ async def _fetch_current_telemetry(self, scope: str) -> Dict[str, Any]:
301301
}
302302

303303
# Add timestamp and metadata
304-
telemetry["timestamp"] = datetime.utcnow().isoformat()
304+
telemetry["timestamp"] = datetime.now(timezone.utc).isoformat()
305305
telemetry["cell_id"] = scope
306306
telemetry["region"] = scope.split("_")[0] if "_" in scope else "UNKNOWN"
307307

@@ -331,7 +331,7 @@ async def validate_execution(self,
331331
result = {
332332
"plan_id": plan_id,
333333
"validation_status": "in_progress",
334-
"validation_time": datetime.utcnow().isoformat(),
334+
"validation_time": datetime.now(timezone.utc).isoformat(),
335335
"executed_by": execution_result.get("executed_by", "unknown"),
336336
"validated_by": self.agent_id,
337337
"scope": scope,
@@ -523,7 +523,7 @@ async def process_message(self, message: Dict[str, Any]) -> Dict[str, Any]:
523523
# Default response for other message types
524524
return {
525525
"status": "acknowledged",
526-
"timestamp": datetime.utcnow().isoformat(),
526+
"timestamp": datetime.now(timezone.utc).isoformat(),
527527
"validation_agent": self.agent_id
528528
}
529529

0 commit comments

Comments
 (0)