diff --git a/services/agent/observability/__init__.py b/services/agent/observability/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/services/agent/observability/events.py b/services/agent/observability/events.py new file mode 100644 index 00000000..761d1298 --- /dev/null +++ b/services/agent/observability/events.py @@ -0,0 +1,23 @@ +from dataclasses import dataclass, field +from datetime import datetime, UTC + + +@dataclass +class LearningEvent: + agent_id: str + event_type: str + payload: dict + created_at: datetime = field( + default_factory=lambda: datetime.now(UTC) + ) + + +class LearningEventBus: + def __init__(self): + self.events = [] + + def publish(self, event: LearningEvent): + self.events.append(event) + + def latest(self): + return self.events[-1] if self.events else None diff --git a/services/agent/observability/metrics.py b/services/agent/observability/metrics.py new file mode 100644 index 00000000..37e319e8 --- /dev/null +++ b/services/agent/observability/metrics.py @@ -0,0 +1,23 @@ +from dataclasses import dataclass, field +from datetime import datetime, UTC + + +@dataclass +class LearningMetric: + agent_id: str + metric: str + value: float + created_at: datetime = field( + default_factory=lambda: datetime.now(UTC) + ) + + +class LearningMetricsStore: + def __init__(self): + self.metrics = [] + + def record(self, metric: LearningMetric): + self.metrics.append(metric) + + def latest(self): + return self.metrics[-1] if self.metrics else None diff --git a/services/agent/observability/tracing.py b/services/agent/observability/tracing.py new file mode 100644 index 00000000..2761caa2 --- /dev/null +++ b/services/agent/observability/tracing.py @@ -0,0 +1,23 @@ +from dataclasses import dataclass, field +from datetime import datetime, UTC + + +@dataclass +class LearningTrace: + agent_id: str + action: str + outcome: str + created_at: datetime = field( + default_factory=lambda: datetime.now(UTC) + ) + + +class LearningTracer: + def __init__(self): + self.traces = [] + + def trace(self, item: LearningTrace): + self.traces.append(item) + + def last(self): + return self.traces[-1] if self.traces else None diff --git a/tests/agent/test_learning_observability.py b/tests/agent/test_learning_observability.py new file mode 100644 index 00000000..43a86c1f --- /dev/null +++ b/tests/agent/test_learning_observability.py @@ -0,0 +1,54 @@ +from services.agent.observability.metrics import ( + LearningMetric, + LearningMetricsStore, +) +from services.agent.observability.events import ( + LearningEvent, + LearningEventBus, +) +from services.agent.observability.tracing import ( + LearningTrace, + LearningTracer, +) + + +def test_learning_metrics(): + store = LearningMetricsStore() + + store.record( + LearningMetric( + agent_id="AEON-001", + metric="accuracy", + value=0.98, + ) + ) + + assert store.latest().value == 0.98 + + +def test_learning_events(): + bus = LearningEventBus() + + bus.publish( + LearningEvent( + agent_id="AEON-001", + event_type="learning_update", + payload={"score": 0.95}, + ) + ) + + assert bus.latest().event_type == "learning_update" + + +def test_learning_trace(): + tracer = LearningTracer() + + tracer.trace( + LearningTrace( + agent_id="AEON-001", + action="policy_update", + outcome="approved", + ) + ) + + assert tracer.last().outcome == "approved"