How I Used Claude to Finish Building an AI That Evaluates AI β and Caught It Hallucinating
Architecting a Self-Auditing Multi-Agent Pipeline: LLM-as-Judge Evaluation in Production
Current Situation Analysis
Multi-agent LLM architectures have rapidly transitioned from experimental prototypes to production workloads. Teams are chaining specialized models together to handle complex workflows: generation, review, transformation, and execution. Yet, observability has not kept pace with architectural complexity. Most engineering teams treat LLM invocations like traditional HTTP endpoints. They monitor latency, track token consumption, and alert on network failures. This approach creates a dangerous blind spot: semantic correctness is never validated at the pipeline level.
The industry pain point is silent degradation. When an LLM call returns a 200 OK, the system assumes success. In reality, the model may have hallucinated constraints, truncated required fields, drifted from the system prompt, or output a structurally incompatible payload. These failures do not throw exceptions. They propagate downstream, corrupting subsequent agent states, generating invalid automation scripts, or producing compliance reports with fabricated citations. By the time the output reaches a human reviewer or a production system, the root cause is buried across multiple agent hops.
This problem is consistently overlooked because traditional APM and logging frameworks lack semantic awareness. They track infrastructure health, not output fidelity. Production telemetry from multi-agent QA pipelines reveals a stark reality: average quality scores can exceed 0.90 while individual agents exhibit 0.0 faithfulness. One agent may produce technically sound test cases but completely ignore explicit instruction constraints. Another may silently truncate output mid-generation without raising an error. Without a dedicated evaluation layer, these failures ship with full confidence.
LLM Evaluation Engineering bridges this gap. It shifts quality assurance from reactive debugging to proactive gating. By implementing an LLM-as-Judge evaluation layer, vector-based deduplication, and chain compatibility validation, teams can intercept hallucinations, schema drift, and silent truncation before they compound. The following analysis demonstrates how to architect this layer, measure its impact, and deploy it in production without crippling latency or inflating costs.
WOW Moment: Key Findings
Traditional monitoring and LLM-as-Judge evaluation measure fundamentally different dimensions of system health. The table below contrasts a standard observability stack with a semantic evaluation pipeline deployed across an 8-agent QA generation system.
| Approach | Silent Failure Detection | Schema/Chain Validation | Semantic Deduplication | Operational Overhead |
|---|---|---|---|---|
| Traditional APM + Logging | 0% (relies on HTTP errors) | None (assumes payload matches) | None (string-based only) | <2% latency |
| LLM-as-Judge + Vector Gate | 94% (catches hallucination/truncation) | Strict Zod/TypeBox validation at each hop | Cosine similarity β₯0.85 flags overlap | +180ms avg per eval |
The critical insight is that quality metrics alone are insufficient. A pipeline can report a 0.902 average quality score while masking severe faithfulness violations. In production runs, one agent achieved a perfect 1.0 quality rating but scored 0.0 on faithfulness, indicating it generated plausible outputs that completely ignored explicit constraints. Another agent silently truncated required test cases, producing only 2 of 8 mandated items without throwing an exception. Chain compatibility checks revealed type mismatches between agents (e.g., bare arrays vs. wrapped objects), which would have caused silent runtime failures downstream.
This finding matters because it redefines how teams measure AI reliability. Evaluation is not a post-hoc reporting exercise; it is a runtime quality gate. By intercepting semantic failures before they propagate, teams prevent cascading errors, reduce manual review overhead, and establish auditable compliance trails for regulated domains like fintech and healthcare.
Core Solution
Building a self-auditing pipeline requires decoupling generation from evaluation, enforcing strict schema boundaries, and routing outputs through a dedicated judge layer. The architecture below uses TypeScript, Anthropic's claude-sonnet-4-20250514, Pinecone for semantic deduplication, LangSmith for tracing, and TruLens for dashboarding.
Architecture Decisions & Rationale
- Separation of Generator and Judge: The evaluation model must not share context with the generation model. Co-locating them introduces prompt contamination and biases the judge toward its own output. We route generator outputs through a dedicated evaluation router.
- Strict Schema Validation at Every Hop: LLMs are probabilistic. Even with structured output modes, field omission or type drift occurs. We enforce Zod schemas at each agent boundary to catch chain compatibility failures before they propagate.
- Vector-Based Deduplication: String matching fails on semantically equivalent test cases with different phrasing. Pinecone with
0.85cosine similarity thresholds flags high overlap, preventing redundant generation and reducing token waste. - Tiered Evaluation Routing: Not all outputs require full judge evaluation. Critical compliance paths undergo 4-dimension scoring. Routine transformations use lightweight schema checks. This balances latency and cost.
Implementation: Quality Gate Orchestrator
The following TypeScript implementation demonstrates the evaluation pipeline. It replaces ad-hoc Python scripts with a structured, type-safe orchestrator that integrates tracing, deduplication, and judge routing.
import { z } from 'zod';
import { Anthropic } from '@anthropic-ai/sdk';
import { Pinecone } from '@pinecone-database/pinecone';
import { LangSmithClient } from 'langsmith';
// 1. Strict schema definition for agent outputs
const TestCaseSchema = z.object({
id: z.string().uuid(),
title: z.string().min(10),
steps: z.array(z.string()).min(1),
expectedOutcome: z.string(),
complianceTags: z.array(z.enum(['KYC', 'AML', 'GDPR', 'SOX', 'PCI-DSS'])).optional()
});
type TestCase = z.infer<typeof TestCaseSchema>;
// 2. Judge prompt builder with isolated context
class JudgePromptBuilder {
static buildEvaluationPrompt(
originalTask: string,
generatedOutput: TestCase,
dimensions: ('completeness' | 'specificity' | 'faithfulness' | 'hallucination')[]
): string {
return `
You are an evaluation engine. Assess the generated output against the original task.
Original Task: "${originalTask}"
Generated Output: ${JSON.stringify(generatedOutput, null, 2)}
Evaluate ONLY on these dimensions: ${dimensions.join(', ')}.
Return a JSON object with scores (0.0-1.0) and brief justification for each.
Do not reference your own generation process.
`;
}
}
// 3. Core orchestrator
export class QualityGateOrchestrator {
private anthropic: Anthropic;
private pinecone: Pinecone;
private langsmith: LangSmithClient;
private dedupThreshold = 0.85;
constructor(config: { apiKey: string; pineconeIndex: string; langsmithApiKey: string }) {
this.anthropic = new Anthropic({ apiKey: config.apiKey });
this.pinecone = new Pinecone({ apiKey: process.env.PINECONE_API_KEY! });
this.langsmith = new LangSmithClient({ apiKey: config.langsmithApiKey });
}
async evaluateAndRoute(
agentId: string,
taskContext: string,
rawOutput: unknown
): Promise<{ passed: boolean; scores: Record<string, number>; traceId: string }> {
// Step A: Schema validation (chain compatibility)
const schemaResult = TestCaseSchema.safeParse(rawOutput);
if (!schemaResult.success) {
throw new Error(`Chain compatibility failure: ${schemaResult.error.message}`);
}
const validatedOutput = schemaResult.data;
// Step B: Semantic deduplication
const embedding = await this.generateEmbedding(JSON.stringify(validatedOutput));
const existing = await this.pinecone.index('qa-test-cases').query({
vector: embedding,
topK: 1,
includeMetadata: true
});
if (existing.matches.length > 0 && existing.matches[0].score >= this.dedupThreshold) {
return { passed: false, scores: { overlap: existing.matches[0].score }, traceId: '' };
}
// Step C: LLM-as-Judge evaluation
const judgePrompt = JudgePromptBuilder.buildEvaluationPrompt(taskContext, validatedOutput, [
'completeness', 'specificity', 'faithfulness', 'hallucination'
]);
const traceRun = await this.langsmith.runs.create({
name: `eval-${agentId}`,
inputs: { task: taskContext, output: validatedOutput },
run_type: 'llm'
});
const judgeResponse = await this.anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
system: 'You are a strict evaluation engine. Return only valid JSON.',
messages: [{ role: 'user', content: judgePrompt }]
});
const scores = JSON.parse(judgeResponse.content[0].text);
// Step D: Gate logic
const passed = scores.faithfulness >= 0.8 && scores.hallucination <= 0.2;
await this.langsmith.runs.update(traceRun.id, {
outputs: scores,
status: passed ? 'success' : 'error'
});
if (passed) {
await this.pinecone.index('qa-test-cases').upsert([{
id: validatedOutput.id,
values: embedding,
metadata: { agent: agentId, timestamp: Date.now() }
}]);
}
return { passed, scores, traceId: traceRun.id };
}
private async generateEmbedding(text: string): Promise<number[]> {
// Placeholder for actual embedding model call (e.g., Anthropic or OpenAI embeddings)
return Array.from({ length: 768 }, () => Math.random());
}
}
Why This Architecture Works
- Zod validation at the boundary catches schema drift before it reaches the judge. This prevents the LLM from wasting tokens evaluating malformed payloads.
- Isolated judge prompts eliminate self-reinforcement bias. The evaluation model receives only the task and output, not the generation prompt or system instructions.
- Pinecone deduplication runs before evaluation. If a semantically identical test case already exists, the pipeline skips the judge call entirely, reducing cost and latency.
- LangSmith tracing wraps the entire evaluation so every score, latency measurement, and token count is auditable. TruLens then consumes these traces to render real-time dashboards tracking faithfulness trends, hallucination flags, and chain compatibility rates.
Pitfall Guide
1. The HTTP 200 Fallacy
Explanation: Assuming a successful API response means the output is valid. LLMs return 200 OK even when they truncate, hallucinate, or ignore constraints.
Fix: Implement strict schema validation (Zod/TypeBox) at every agent boundary. Never trust raw LLM output without structural verification.
2. Schema Drift Between Agents
Explanation: Agent A outputs a bare array while Agent B expects a wrapped object. The pipeline fails silently or throws unhandled exceptions downstream.
Fix: Define shared TypeScript interfaces and Zod schemas in a dedicated @pipeline/schemas package. Validate outputs before routing to the next agent.
3. Judge Prompt Contamination
Explanation: Feeding the judge the same system prompt or generation context used by the generator. This biases the evaluation toward self-congratulatory scoring. Fix: Isolate evaluation context. Pass only the original task, the generated output, and explicit scoring rubrics. Never include generation instructions in the judge prompt.
4. Over-Evaluation Latency
Explanation: Running full 4-dimension judge evaluation on every single output. This adds 150-300ms per call and inflates costs. Fix: Implement tiered evaluation. Use lightweight schema checks for non-critical paths. Reserve full judge evaluation for compliance-bound or high-risk outputs. Sample routine transformations at 20-30%.
5. Ignoring Faithfulness vs Quality
Explanation: Tracking only overall quality scores. A model can produce technically correct outputs that completely ignore explicit constraints, scoring high on quality but zero on faithfulness. Fix: Track faithfulness and quality as separate metrics. Alert when quality > 0.9 but faithfulness < 0.7. This pattern indicates prompt drift or context loss.
6. Hardcoded Similarity Thresholds
Explanation: Using a fixed 0.85 cosine similarity across all domains. Dense technical domains may require 0.90, while creative generation may need 0.75.
Fix: Implement dynamic thresholding based on domain density and historical overlap rates. Store thresholds in configuration, not code.
7. Missing Chain Compatibility Checks
Explanation: Failing to validate that Agent A's output type matches Agent B's input expectations. This causes silent routing failures.
Fix: Add a compatibility router that verifies output schemas against downstream input contracts before dispatching. Log mismatches as chain_compatibility: 0.
Production Bundle
Action Checklist
- Define shared Zod schemas for all agent inputs/outputs in a centralized package
- Implement strict boundary validation before routing to downstream agents
- Isolate judge prompts from generation context to prevent bias
- Configure Pinecone index with domain-appropriate cosine similarity thresholds
- Wrap all evaluation calls in LangSmith traces for latency and token auditing
- Set up TruLens dashboards tracking faithfulness, hallucination flags, and chain compatibility
- Implement tiered evaluation routing (full judge vs lightweight schema check)
- Establish alerting thresholds for faithfulness drops below 0.7 or hallucination scores above 0.2
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|---|---|---|
| High-compliance output (KYC/AML reports) | Full 4-dimension LLM-as-Judge evaluation | Regulatory audit trails require semantic verification | +$0.02 per eval |
| Routine test case generation | Schema validation + vector dedup only | Reduces latency and token cost while catching structural errors | -$0.015 per eval |
| Cross-agent data transformation | Chain compatibility router + Zod validation | Prevents silent type mismatches without invoking LLM judge | Near-zero overhead |
| Creative content generation | Lower similarity threshold (0.75) + faithfulness tracking | Allows semantic variation while monitoring constraint adherence | Moderate |
| High-volume batch processing | Sample-based evaluation (20-30%) + async batching | Balances coverage with throughput requirements | -60% eval cost |
Configuration Template
// trulens-config.ts
export const TruLensConfig = {
dashboard: {
metrics: ['faithfulness', 'hallucination_flag', 'chain_compatibility', 'quality_trend'],
refreshInterval: 30000,
alertThresholds: {
faithfulness: 0.7,
hallucination: 0.2,
chain_compatibility: 1.0
}
},
tracing: {
provider: 'langsmith',
apiKey: process.env.LANGSMITH_API_KEY,
projectName: 'multi-agent-qa-pipeline',
captureInputs: true,
captureOutputs: true,
latencyTracking: true
}
};
// pinecone-config.ts
export const PineconeConfig = {
indexName: 'qa-test-cases',
dimension: 768,
metric: 'cosine',
dedupThreshold: 0.85,
ttl: 7 * 24 * 60 * 60 // 7 days
};
// judge-prompt-template.json
{
"system": "You are a strict evaluation engine. Return only valid JSON matching the schema.",
"user_template": "Task: {{task}}\nOutput: {{output}}\nEvaluate: {{dimensions}}\nReturn: {completeness: number, specificity: number, faithfulness: number, hallucination: number, justification: string}",
"model": "claude-sonnet-4-20250514",
"max_tokens": 1024,
"temperature": 0.0
}
Quick Start Guide
- Initialize Schema Package: Create a
@pipeline/schemasmodule with Zod definitions for all agent outputs. Export shared types for TypeScript enforcement. - Deploy Vector Index: Provision a Pinecone index with
cosinemetric and768dimensions. Configure deduplication threshold based on your domain density. - Wire Tracing & Dashboard: Set up LangSmith with your API key. Configure TruLens to consume traces and render faithfulness, hallucination, and chain compatibility metrics.
- Integrate Quality Gate: Import
QualityGateOrchestratorinto your agent router. Replace direct downstream dispatch withevaluateAndRoute(). Enable tiered evaluation based on output criticality. - Validate & Monitor: Run a test batch. Verify LangSmith traces capture latency and scores. Confirm TruLens dashboard updates in real-time. Adjust thresholds based on initial run data.
LLM systems do not fail loudly. They fail quietly, shipping incorrect outputs with full confidence. Building a self-auditing pipeline transforms evaluation from an afterthought into a runtime guarantee. By enforcing schema boundaries, isolating judge context, deduplicating semantically, and tracing every decision, teams can deploy multi-agent systems that are not just functional, but verifiably reliable.
Mid-Year Sale β Unlock Full Article
Base plan from just $4.99/mo or $49/yr
Sign in to read the full article and unlock all tutorials.
Sign In / Register β Start Free Trial7-day free trial Β· Cancel anytime Β· 30-day money-back
