Adding Logging
Logging is built into the agent architecture from the start — not added as an afterthought. Every node writes structured logs.
6 min•By Priygop Team•Updated 2026
Logging Architecture
Logging Architecture
# Production logging setup for a real-world agent
import json
import time
from datetime import datetime, timezone
class ProductionAgentLogger:
"""
Structured, leveled logging for production agent systems.
In production, integrate with Datadog, CloudWatch, or similar.
"""
LOG_LEVELS = {"DEBUG": 0, "INFO": 1, "WARN": 2, "ERROR": 3, "CRITICAL": 4}
MIN_LEVEL = "INFO" # Change to DEBUG during development
def __init__(self, agent_id: str, task_id: str, service: str = "agent-service"):
self.agent_id = agent_id
self.task_id = task_id
self.service = service
self._step_start_times = {}
def _emit(self, level: str, event: str, **fields):
if self.LOG_LEVELS.get(level, 0) < self.LOG_LEVELS.get(self.MIN_LEVEL, 0):
return
entry = {
"ts": datetime.now(timezone.utc).isoformat(),
"level": level,
"service": self.service,
"agent_id": self.agent_id,
"task_id": self.task_id,
"event": event,
**{k: v for k, v in fields.items() if v is not None},
}
# In production: send to log aggregation service
print(json.dumps(entry))
def info(self, event: str, **fields): self._emit("INFO", event, **fields)
def warn(self, event: str, **fields): self._emit("WARN", event, **fields)
def error(self, event: str, **fields): self._emit("ERROR", event, **fields)
def node_enter(self, node: str):
self._step_start_times[node] = time.perf_counter()
self.info("node_enter", node=node)
def node_exit(self, node: str, condition: str, result_summary: str = None):
elapsed = (time.perf_counter() - self._step_start_times.get(node, time.perf_counter())) * 1000
self.info("node_exit", node=node, condition=condition,
duration_ms=round(elapsed, 1), result=result_summary)
def node_error(self, node: str, error_type: str, message: str, retry: int = 0):
self.error("node_error", node=node, error_type=error_type,
message=message[:200], retry=retry)
# Usage in a workflow node
logger = ProductionAgentLogger("refund-agent-1", "TASK-001")
logger.node_enter("lookup_order")
time.sleep(0.01)
logger.node_exit("lookup_order", "found", "ORD-123 retrieved")