- SDK: client with BatchTransport, trace decorator/context manager, log_decision, thread-local context stack, nested trace→span support - API: POST /api/traces (batch ingest), GET /api/traces (paginated list), GET /api/traces/[id] (full trace with relations), GET /api/health - Tests: 8 unit tests for SDK (all passing) - Transport: thread-safe buffer with background flush thread
48 lines
1.3 KiB
Python
48 lines
1.3 KiB
Python
"""Decision logging for tracking agent decision points."""
|
|
|
|
import logging
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
from agentlens.models import DecisionPoint
|
|
from agentlens.trace import get_current_trace, get_current_span_id
|
|
|
|
logger = logging.getLogger("agentlens")
|
|
|
|
|
|
def log_decision(
|
|
type: str,
|
|
chosen: Dict[str, Any],
|
|
alternatives: Optional[List[Dict[str, Any]]] = None,
|
|
reasoning: Optional[str] = None,
|
|
context_snapshot: Optional[Dict[str, Any]] = None,
|
|
cost_usd: Optional[float] = None,
|
|
duration_ms: Optional[int] = None,
|
|
) -> Optional[DecisionPoint]:
|
|
current_trace = get_current_trace()
|
|
if current_trace is None:
|
|
logger.warning(
|
|
"AgentLens: log_decision called outside of a trace context. Decision not recorded."
|
|
)
|
|
return None
|
|
|
|
parent_span_id = get_current_span_id()
|
|
|
|
decision = DecisionPoint(
|
|
type=type,
|
|
chosen=chosen,
|
|
alternatives=alternatives or [],
|
|
reasoning=reasoning,
|
|
context_snapshot=context_snapshot,
|
|
cost_usd=cost_usd,
|
|
duration_ms=duration_ms,
|
|
parent_span_id=parent_span_id,
|
|
)
|
|
|
|
current_trace.decision_points.append(decision)
|
|
logger.debug(
|
|
"AgentLens: Decision logged: type=%s, chosen=%s",
|
|
type,
|
|
chosen.get("name", str(chosen)),
|
|
)
|
|
return decision
|