Home/AI & Automation/LLM Agents Deep Dive, Part 3: Evaluation Frameworks and Multi-Agent Operations
AI & AutomationLLM agentsHuman-in-the-Loop

LLM Agents Deep Dive, Part 3: Evaluation Frameworks and Multi-Agent Operations

Part 2 covered tool-call orchestration and planning; in production, agents more often fail because evaluation systems are missing and debugging is hard. This installment shows how to measure execution paths, tool selection, and efficiency—n

LLM Agents Deep Dive, Part 3: Evaluation Frameworks and Multi-Agent Operations
Contents
  1. The Most Common Reasons Agents Fail
  2. Agent Evaluation Framework
  3. Structured Tracing
  4. Multi-Agent Orchestrator
  5. Human-in-the-Loop Pattern
  6. Agent Reliability Metrics (Production SLA)

The Most Common Reasons Agents Fail

In Part 2 we covered tool-call orchestration and planning. In production, the real reasons agents fail are usually the absence of an evaluation system and how hard they are to debug.

Agent Evaluation Framework

You cannot properly evaluate an agent by scoring output quality alone. You also need to measure the execution path, tool selection, and efficiency.

Python
from dataclasses import dataclass

@dataclass
class AgentTrace:
    task: str
 steps: list[dict] # : {thought, action, observation}
    final_answer: str
    total_tokens: int
    elapsed_ms: int
    tool_calls: list[str]
    success: bool

class AgentEvaluator:
    def evaluate(self, trace: AgentTrace, golden: dict) -> dict:
        return {
            "task_success": self._check_success(trace.final_answer, golden["answer"]),
            "tool_precision": self._tool_precision(trace.tool_calls, golden["expected_tools"]),
            "efficiency_score": self._efficiency(trace),
            "hallucination_rate": self._check_hallucination(trace),
            "step_count": len(trace.steps),
            "token_efficiency": golden.get("min_tokens", 500) / max(trace.total_tokens, 1),
        }

    def _tool_precision(self, used: list, expected: list) -> float:
        if not expected:
            return 1.0
        correct = sum(1 for t in used if t in expected)
        return correct / len(used) if used else 0.0

    def _efficiency(self, trace: AgentTrace) -> float:
 # path
 optimal_steps = 3 # settings
        return min(1.0, optimal_steps / max(len(trace.steps), 1))

Structured Tracing

Python
import contextvars
import uuid
from datetime import datetime

trace_id_var = contextvars.ContextVar("trace_id")

class AgentTracer:
    def __init__(self, backend="langfuse"):
        self.backend = backend

    def start_trace(self, task: str) -> str:
        tid = str(uuid.uuid4())
        trace_id_var.set(tid)
        self._emit({
            "event": "trace_start",
            "trace_id": tid,
            "task": task,
            "timestamp": datetime.utcnow().isoformat(),
        })
        return tid

    def log_step(self, step_type: str, content: dict):
        self._emit({
            "event": "step",
            "trace_id": trace_id_var.get(),
            "step_type": step_type,  # thought | action | observation | answer
            "content": content,
            "timestamp": datetime.utcnow().isoformat(),
        })

    def end_trace(self, success: bool, final_answer: str):
        self._emit({
            "event": "trace_end",
            "trace_id": trace_id_var.get(),
            "success": success,
            "final_answer": final_answer,
            "timestamp": datetime.utcnow().isoformat(),
        })

Multi-Agent Orchestrator

A pattern where specialized agents collaborate, going beyond the limits of a single agent:

Python
class OrchestratorAgent:
 """ """

    AGENTS = {
 "research": ResearchAgent, # ·
 "code": CodeAgent, # ·run
 "data": DataAnalysisAgent, #
 "writer": WriterAgent, #
    }

    async def execute(self, task: str) -> str:
 # 1.
        subtasks = await self.decompose(task)

 # 2. run
        results = {}
        independent = [s for s in subtasks if not s.dependencies]
        parallel_results = await asyncio.gather(*[
            self.AGENTS[s.agent_type].run(s.prompt)
            for s in independent
        ])
        for s, r in zip(independent, parallel_results):
            results[s.id] = r

 # 3. run
        dependent = [s for s in subtasks if s.dependencies]
        for s in dependent:
            context = {dep: results[dep] for dep in s.dependencies}
            results[s.id] = await self.AGENTS[s.agent_type].run(
                s.prompt, context=context
            )

 # 4. Result
        return await self.synthesize(task, results)

Human-in-the-Loop Pattern

A design that brings a human in only at the points an autonomous agent actually needs:

Python
class HumanInLoopAgent:
    HIGH_RISK_ACTIONS = {
        "delete_records", "send_email", "execute_payment", "deploy_code"
    }

    async def execute_action(self, action: str, params: dict) -> dict:
        if action in self.HIGH_RISK_ACTIONS:
            approved = await self.request_approval(
                action=action,
                params=params,
                context=self.current_trace(),
                timeout_seconds=300,
            )
            if not approved:
                return {"status": "rejected", "action": action}

        return await self.tool_registry.call(action, **params)

    async def request_approval(self, **kwargs) -> bool:
 # Slack / / Request
        approval_id = await self.notify_reviewer(**kwargs)
        return await self.wait_for_approval(approval_id, kwargs["timeout_seconds"])

Agent Reliability Metrics (Production SLA)

MetricTargetAlert threshold
Task success rate≥ 90%< 85%
Average step count≤ 8> 12
Tool precision≥ 85%< 75%
P95 latency≤ 30s> 45s
Hallucination rate≤ 5%> 8%

This three-part series completes the LLM Agent Deep-Dive Master Guide (fundamentals → tool orchestration → evaluation and operations).

✦ ✦ ✦
Sources and verification

Sources and checks vary by article. Only articles with a recorded check date, scope and sources below were checked, and only within that scope. For other articles, verify against the current docs for your version before applying anything, and email us about errors. Editorial policy · email us

This article has no recorded human check (date and scope) yet.

Published ·

Comments

Be the first to comment.