A provider-agnostic GenAI observability & evaluation framework benchmarked on Mind2Web
Plug in any OpenAI-compatible LLM and run a rigorous, observable evaluation of single- and multi-agent web-navigation systems β
OpenTelemetry-compliant tracing Β· hybrid rule + LLM-judge scoring Β· tool-correctness metrics Β· cost & health monitoring Β· safety validation
Status: Independent personal research project
As autonomous agents move into production, two questions become mission-critical: can you see what the agent did (observability), and can you prove it did the right thing (evaluation)? This demo is an end-to-end showcase of both, applied to a multi-agent web-navigation system on a real benchmark.
- Observability β Every agent decision, LLM call, and tool invocation is captured as an OpenTelemetry-compliant span. The result is a portable, audit-ready trace tree you can ship to Datadog, Splunk, Phoenix, or Langfuse β the same instrumentation pattern you'd use to monitor agents in production.
- Evaluation β A hybrid scoring engine (deterministic rules + LLM-as-judge), tool-selection correctness metrics, and safety validation quantify how well each agent performed β not just whether it finished.
- Multi-agent architecture β A supervisor pattern (Planner β Navigator β Validator) is benchmarked head-to-head against a single-agent baseline, so you can see what orchestration buys you in quality, cost, and traceability.
- Audit-grade reporting β A one-call generator turns the run into a structured Markdown report (executive summary, scope & compliance, section-by-section results, conclusion, audit trail) β deterministic by default, with optional LLM narratives clearly labeled π€ AI Assessment. See a sample β
The notebook is deliberately coding-light: every component lives in src/, so the
notebook reads as a clean narrative of the observability-and-evaluation workflow.
A 10-task run (single agent vs. multi-agent system) with real API token/cost accounting β your numbers will vary by model and sample, but the pattern is representative.
Single-Agent vs. Multi-Agent System β the multi-agent system lifted the pass rate substantially, at a measurable cost/latency premium:
| Metric | Single Agent | Multi-Agent | Rating |
|---|---|---|---|
| Pass rate | 60% | 100% | π’ High |
| Avg task score | 0.697 | 0.809 | π’ High |
| Tool F1 | 0.399 | 0.462 | π‘ Medium |
| Avg cost / task | $0.0346 | $0.0414 (1.2Γ) | π’ High |
| Median latency | 8.3 s | 19.5 s | π‘ Medium |
| Safety | 100% | 100% | π’ High |
| Overall | π’ High |
(Cost reflects real API usage β counting every ReAct round-trip, not just the final output. Latency is the median, robust to occasional API stalls.)
OpenTelemetry trace tree β every task is a hierarchical span tree
(task.execute β planner β navigator β tool.execute β validator) with per-agent cost,
exported to OTLP JSON:
Evaluation dashboard β score distribution, pass/fail, tool-F1, and cost-vs-latency:
π These visuals come straight from the framework. See the full sample evaluation report β (Markdown) or the HTML executive summary β for the complete write-up.
Most agent evaluation toolkits answer one question: "Did the agent complete the task?"
This framework answers five β and captures an OpenTelemetry-compliant trace that tells you how:
| Question | How |
|---|---|
| Did the agent complete the task? | Hybrid rule-based + LLM-as-judge score |
| Did it pick the right tools? | Precision / recall / F1 with flexible tool-equivalence mapping |
| Is it safe? | PII, injection, harmful-content, and budget-violation checks |
| What does it cost to run? | Per-call token + cost tracking, agent vs. judge separation |
| Is it healthy over time? | Rolling-window success rate, latency percentiles, drift detection |
Novel contributions: The full OpenTelemetry GenAI Semantic Convention span tree (portable to Datadog, Splunk, Phoenix, Langfuse) and the flexible tool-equivalence mapping are purpose-built for production agent observability β not found in standard evaluation toolkits.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Agent Evaluation Pipeline β
ββββββββββββ¬ββββββββββββββββββ¬βββββββββββββββββββββββββββ¬βββββββββββββββββββββββ€
β DATA β AGENTS β EXECUTION β EVALUATION β
β β β β β
β Mind2Web β Single ReAct β Hybrid real/mock tools β Hybrid score β
β web-nav β + multi-agent β OTel span tracing β (rule + LLM judge) β
β benchmarkβ supervisor β token + cost tracking β Tool correctness F1 β
β (NeurIPS β (planner / β health monitoring β Safety validation β
β 2023) β navigator / β β Cost & latency β
β β validator) β β Audit-ready traces β
ββββββββββββ΄ββββββββββββββββββ΄βββββββββββββββββββββββββββ΄βββββββββββββββββββββββ
Every agent, LLM call, and tool invocation creates a span that follows the OpenTelemetry GenAI Semantic Conventions. Spans form a parent-child tree and export to OTLP JSON β portable to any observability backend (Datadog, Splunk, Phoenix, Langfuse, Jaeger).
task.execute β root span
βββ agent.planner.plan (gen_ai.agent.role = task_decomposer)
βββ agent.navigator.execute (gen_ai.agent.role = executor)
β βββ tool.execute (gen_ai.tool.name = site_search)
β βββ tool.execute (gen_ai.tool.name = filter_content)
β βββ tool.execute (gen_ai.tool.name = site_navigation)
βββ agent.validator.validate (gen_ai.evaluation.score = 0.82)
Standard attributes captured per span: gen_ai.system, gen_ai.request.model,
gen_ai.usage.input_tokens, gen_ai.usage.output_tokens, gen_ai.agent.name,
gen_ai.tool.name, gen_ai.usage.cost_usd, plus custom evaluation extensions.
| Mode | What it does | When |
|---|---|---|
| Local (default) | HierarchicalTracer records the span tree to JSONL + the offline trace-tree chart β zero extra dependencies |
Always on |
| Real OTel β Phoenix | setup_phoenix() registers the OpenTelemetry SDK and auto-instruments LangChain/LangGraph (OpenInference), streaming live spans to Arize Phoenix or any OTLP backend (Datadog, Jaeger, Grafana Tempo, Langfuse) |
One optional call |
from src import setup_phoenix
setup_phoenix() # local Phoenix UI at :6006
setup_phoenix(endpoint="http://collector:4317") # or any OTLP collectorReal token & cost. Token counts come from actual API usage metadata
(LangChain usage callbacks) whenever the provider returns it, falling back to a
tiktoken estimate otherwise β the tokens_source field records which was used, so
cost figures are honest rather than guessed.
π New to OTel or want to wire up a specific backend? See the Observability Guide β β a systematic walkthrough of OpenTelemetry concepts, how this framework emits spans, how to read a trace, and step-by-step setup for Phoenix, Jaeger, Grafana Tempo, Datadog, Splunk, Langfuse, and the generic OpenTelemetry Collector.
| Component | Method | Weight |
|---|---|---|
| Length adequacy | β₯ 40 words in the plan | 0.2 (rule) |
| Specificity | Contains numeric detail | 0.1 (rule) |
| Goal alignment | Task β plan keyword overlap | 0.3 (rule) |
| Structured format | Uses action verbs (CLICK, TYPE, β¦) | 0.2 (rule) |
| Action overlap | Plan verbs β reference verbs | 0.2 (rule) |
| LLM judge | Holistic 0.0β1.0 quality rating | 0.6 (total) |
total_score = 0.4 Γ rule_score + 0.6 Γ llm_score (weights configurable)
| Metric | Method |
|---|---|
| Precision / Recall / F1 | Predicted vs. reference tools, flexible equivalence |
| Exact Match | No missing or extra tools |
| Order Accuracy | Longest common subsequence vs. reference order |
Flexible tool equivalence recognizes that Mind2Web's basic action set (CLICK, TYPE) maps to the agent's richer toolset β
site_navigation β site_search β filter_contentfor navigation,site_search β web_searchfor search.
| Check | Detects |
|---|---|
| PII | SSN, credit card, email, phone |
| Injection | XSS, SQL injection, code injection |
| Harmful content | Jailbreak / bypass / exploit keywords |
| Financial | Prices exceeding a stated budget |
The demo runs the same tasks through two architectures and puts the trade-off side by side β when is orchestration worth it?
| Architecture | Pattern | Specialists | Models |
|---|---|---|---|
| Single Agent | One ReAct loop with all tools | 1 | AGENT_MODEL |
| Multi-Agent System | Supervisor β Planner β Navigator β Validator | 4 | per-role (configurable) |
In the MAS, work is divided: the Planner decomposes the task, the Navigator executes it with tools, and the Validator independently checks the result. This decomposition tends to lift task quality on complex, multi-step tasks β at the cost of more tokens and latency (4 LLM roles vs. 1).
Each specialist gets its own model (set PLANNER_MODEL, NAVIGATOR_MODEL,
SUPERVISOR_MODEL, VALIDATOR_MODEL in .env) and its own OTel span with
per-agent cost attribution. The notebook produces a comparison table, a 3-panel
chart, and an auto-generated interpretation of which system won and why.
Takeaway: simple lookups favor the single agent; complex, multi-step tasks favor the MAS. The framework lets you measure exactly where that line is for your tasks and models.
The final step generates a structured Markdown evaluation report (src/report.py)
suitable for model-risk review:
evaluation_report_<timestamp>.md
βββ 1. Executive Summary β key findings & observations
βββ 2. Testing Scope β what we test Β· Mind2Web data Β· regulations & compliance
βββ 3. Testing Approach β hybrid sandbox method Β· scoring stack Β· judge model
βββ 4. Testing Results β section-by-section assessment + embedded visualization
β 4.1 Task completion 4.2 Tool correctness 4.3 Safety
β 4.4 Cost & performance 4.5 Single-vs-multi 4.6 Observability
βββ 5. Conclusion β recommendation from the cost/quality trade-off
βββ 6. Appendices β artifacts Β· per-task audit trail Β· AI disclosure
Hybrid, audit-safe assessment. All tables, metrics, pass/fail decisions, and the audit trail are computed deterministically (rule-based) and are audit-safe.
Selective LLM judge (default-on, used only when needed). The LLM judge is enabled by default but invoked only where deterministic interpretation is genuinely ambiguous β borderline scores, mixed cost/quality trade-offs, or safety violations. Clear-cut sections stay rule-based, which is cheaper, faster, and fully reproducible. Every LLM narrative is labeled π€ AI Assessment with a disclosure notice, so LLM inference is never confused with the deterministic record (mapping to NIST AI RMF transparency).
generate_report(..., use_llm=True, llm_selective=True) # default β AI only when ambiguous
generate_report(..., use_llm=True, llm_selective=False) # AI narrative on every section
generate_report(..., use_llm=False) # fully deterministic, no LLM callsFindings are numbered (F1βF7) in the Executive Summary and cross-referenced
from each results section, so a reviewer can trace every headline claim back to its
underlying metric and assessment. Each finding carries a π’ High / π‘ Medium /
π΄ Low rating, and the report rolls these up into a single overall testing rating
(from task completion, quality, and safety). Model names render as friendly labels
(e.g. GPT 5-4 (Azure)), not raw deployment IDs.
π₯ Download a sample report β (with embedded charts) to see the full output before running anything.
The industry-standard approach for safe pre-deployment agent evaluation:
READ tools (real when API keys present, mock fallback)
web_search Β· site_search Β· get_price_info Β· check_availability
site_navigation Β· filter_content Β· get_page_info
WRITE tools (ALWAYS mocked β no real-world side effects)
book_reservation Β· make_phone_call Β· submit_form Β· make_purchase
COMPUTE (always real)
budget_calculator
This balances rigor (real agent behavior, real web data via Tavily) with
safety (no real bookings, purchases, or form submissions). Set TAVILY_API_KEY
to enable live web search; without it, READ tools return realistic mock data.
Recommended: run locally with Jupyter. This demo is designed to run on your own machine. The reference Azure OpenAI setup uses IP-allowlist access (no interactive login), which is the smoothest path for uninterrupted evaluation runs β but it means Google Colab will not work with Azure (Colab's Google Cloud IPs are not on corporate allowlists). Colab remains available for users who bring a non-Azure provider (OpenAI, Groq, Together, etc.).
git clone https://github.com/minw0607/multi_agent_otel_eval.git
cd multi_agent_otel_eval
pip install -r requirements.txtcp .env.example .env
# Edit .env β uncomment the section for your provider and fill in credentialsThe provider is auto-detected from OPENAI_API_VERSION:
- Set (e.g.
2025-04-01-preview) β Azure OpenAI (AzureChatOpenAI) - Blank β OpenAI direct, Ollama, Groq, or any compatible endpoint (
ChatOpenAI)
See docs/provider-setup.md for step-by-step instructions per provider.
jupyter notebook agentic_otel_demo_notebook.ipynbRun cells in order. The Mind2Web dataset streams from HuggingFace on first run and caches locally β subsequent runs skip the download.
β οΈ Not compatible with the reference Azure OpenAI setup (IP allowlisting blocks Colab). Use this only with OpenAI, Groq, Together, or another IP-independent provider.
Click the Open in Colab badge at the top of this README, then add your credentials as Colab Secrets (π in the left sidebar) and run all cells:
| Secret name | Example value |
|---|---|
OPENAI_API_KEY |
sk-... |
OPENAI_BASE_URL |
https://api.openai.com/v1 |
AGENT_MODEL |
gpt-4o |
JUDGE_MODEL |
gpt-4o |
TAVILY_API_KEY |
tvly-... (optional β enables real web search) |
Leave
OPENAI_API_VERSIONunset on Colab β it activates Azure mode, which won't connect.
multi_agent_otel_eval/
βββ README.md
βββ requirements.txt
βββ .env.example β Copy to .env and fill in credentials (never committed)
βββ .gitignore
βββ LICENSE
β
βββ agentic_otel_demo_notebook.ipynb β β
Start here β coding-light, all heavy lifting in src/
βββ Enhanced_Agentic_Framework_Multi_Agent.ipynb β Original monolithic research notebook
β
βββ src/ β Importable Python modules
β βββ config.py β Provider-agnostic LLM factory, reads from .env
β βββ tracer.py β Local OTel-shaped spans (HierarchicalTracer) + ExecutionTrace
β βββ otel.py β Real OpenTelemetry β Phoenix + real token/cost callbacks
β βββ monitors.py β CostTracker + HealthMonitor (rolling window)
β βββ safety.py β PII, injection, harmful-content, budget checks
β βββ tools.py β Hybrid real/mock web-navigation tools
β βββ dataset.py β Mind2Web streaming loader with local cache
β βββ agents.py β Baseline ReAct + multi-agent supervisor pipeline
β βββ runner.py β evaluate_batch() β runs N tasks through either system
β βββ evaluator.py β HybridEvaluator + ToolCorrectnessEval
β βββ visualizer.py β Eval dashboard, trace tree, telemetry, comparison charts
β βββ report.py β Audit-grade Markdown report generator
β
βββ docs/
β βββ provider-setup.md β Step-by-step setup for Azure, OpenAI, Ollama, Groq
β βββ observability.md β OTel concepts + backend setup (Phoenix/Datadog/Jaeger/β¦)
β
βββ outputs/ β Results, traces, charts, reports (gitignored)
βββ traces/ β OTLP JSON span exports
βββ data/ β Cached Mind2Web dataset
βββ baseline_vs_multi.png
βββ single_agent_*.csv / multi_agent_*.csv
βββ evaluation_report_*.md β Audit-grade report
The framework auto-detects your provider from .env β no code changes required.
OPENAI_API_VERSION |
Provider | LangChain class |
|---|---|---|
Set (e.g. 2025-04-01-preview) |
Azure OpenAI | AzureChatOpenAI |
| Blank | OpenAI / Ollama / Groq / etc. | ChatOpenAI |
Supported providers:
| Provider | OPENAI_BASE_URL |
Notes |
|---|---|---|
| Azure OpenAI | https://<resource>.openai.azure.com |
Set OPENAI_API_VERSION |
| OpenAI (direct) | https://api.openai.com/v1 |
Default |
| Ollama (local) | http://localhost:11434/v1 |
Free, no API key |
| Groq | https://api.groq.com/openai/v1 |
β |
| Together AI | https://api.together.xyz/v1 |
β |
| LM Studio | http://localhost:1234/v1 |
β |
See docs/provider-setup.md for step-by-step setup and troubleshooting.
Mind2Web is the first large-scale benchmark for evaluating AI agents that perform web-navigation tasks from natural language instructions. Published at NeurIPS 2023 (Spotlight) by The Ohio State University, it spans 2,000+ tasks across 137 real websites and 31 domains.
This framework streams the lightweight text metadata (task descriptions, websites,
reference action sequences) from the osunlp/Multimodal-Mind2Web HuggingFace
dataset, skipping the heavy HTML and screenshot fields.
- LLM-as-judge bias: When the agent and judge use the same model, self-evaluation biases toward higher scores. A separate judge model is preferable when budget allows β set
JUDGE_MODELto a different model. - Hypothetical-plan scoring: The evaluator scores the agent's plan (intended actions), not live browser execution. Mind2Web tasks run against mock/scraped data, not the live target site.
- Tool-equivalence mapping: The flexible mapping is tuned for Mind2Web's basic action set. Custom toolsets may need their own equivalence rules in
evaluator.py. - Synchronous execution: The evaluation loop is single-threaded. For large runs (>100 tasks), parallelise at the process level.
If you use this framework, please cite the Mind2Web benchmark:
@inproceedings{deng2023mind2web,
title={Mind2Web: Towards a Generalist Agent for the Web},
author={Deng, Xiang and Gu, Yu and Zheng, Boyuan and Chen, Shijie and
Stevens, Samuel and Wang, Boshi and Sun, Huan and Su, Yu},
booktitle={NeurIPS},
year={2023}
}And the OpenTelemetry GenAI Semantic Conventions:
https://opentelemetry.io/docs/specs/semconv/gen-ai/
This repository is an independent personal project created outside of my employment using my own time and equipment.
Unless explicitly stated otherwise, the code, notebooks, demonstrations, analyses, and documentation in this repository are developed independently, using only publicly available research papers, technical documentation, regulations, and other public sources. They do not rely on, incorporate, or disclose any confidential, proprietary, non-public, or client information obtained through my employment or professional engagements.
The views, designs, implementations, and conclusions expressed in this repository are solely my own and do not represent the views of any employer, client, or affiliated organization.
This repository is provided for research and educational purposes only.
Made with β€οΈ for rigorous, observable agent evaluation
Open an issue Β· Provider setup Β· Observability guide


