Martin Fowler's blog (by Sarang Kulkarni, Thoughtworks)
ai-engineering
Original source

Building Reliable Agentic AI Systems — Bayer PRINCE Case Study

Summary

A detailed case study of PRINCE (Preclinical Information Center) — a production agentic RAG system built by Bayer AG with Thoughtworks for preclinical drug discovery. Demonstrates how to build reliable, trustworthy LLM systems in a regulated enterprise environment.

Key Concepts

Two Engineering Disciplines

  1. Context Engineering — shaping what information each model receives, routing the right context to the right agent at the right time
  2. Harness Engineering — orchestration, tool boundaries, state persistence, retries, fallbacks, validation, reflection loops, observability, and human review around the models

PRINCE Evolution (Search → Ask → Do)

  • Search: Unified gateway to structured metadata across data silos
  • Ask: RAG-powered natural language Q&A over unstructured PDF study reports
  • Do: Multi-agent research assistant that drafts regulatory documents

Architecture

Built with LangGraph + FastAPI, React UI. Multi-agent workflow:

  1. Clarify User Intent — proactive disambiguation, domain/tool selection
  2. Think & Plan (Process Reflection) — metacognitive step inspired by Anthropic’s “Think tool”; evaluates whether workflow is on right trajectory, selects appropriate tools
  3. Researcher Agent — dual strategy:
    • RAG for unstructured data (PDFs in OpenSearch)
    • Text-to-SQL for structured data (Amazon Athena)
  4. Reflection Agent (Data Reflection) — evaluates if retrieved data is sufficient/relevant; generates follow-up questions if gaps exist
  5. Writer Agent (Draft Reflection) — synthesizes answer with citations; internal review loop for completeness

Three Complementary Reflection Loops

  • Process reflection (Think & Plan): right trajectory?
  • Data reflection (Reflection Agent): sufficient evidence?
  • Draft reflection (Writer Agent): complete output?

RAG Pipeline Details

  • Keyword extraction + metadata filter generation + query expansion (5 variants)
  • Hybrid search: 0.7 semantic + 0.3 keyword weighting
  • Reranking with bge-reranker-large (top 7 from ~20 chunks)
  • Citations linked to exact page/quote in source documents

Text-to-SQL

  • Dynamic few-shot prompting (examples stored in vector DB as “semantic layer”)
  • Schema injection (only relevant parts)
  • Up to 3 retry iterations on SQL errors
  • Limited to SELECT only, max 50 records

Resilience Engineering

  • State persistence: Agent state in Postgres (LangGraph checkpointer), app state in DynamoDB
  • Built-in retries at LLM call level AND node level
  • LLM fallbacks across providers (OpenAI, Anthropic, Google, open-source via unified endpoint)
  • User-initiated retries resume from failure point (skip successful steps)
  • Error context passed back to agents for alternative planning

Trust & Evaluation

  • Transparency: Intermediate steps shown to user, source chunk links displayed
  • Citations: Hover over any sentence → see exact quote + page from source document
  • Dataset Evaluations: Faithfulness, Answer Relevancy, Context Relevancy, Answer Accuracy, Semantic Similarity (RAGAS framework)
  • Live Traffic Evaluations: Daily batch on real queries (no reference answers)
  • Monitoring: Langfuse for traces, CloudWatch for system health

Data Quality

  • NER system extracts entities from PDFs to correct/enrich structured metadata
  • Confidence scoring: high confidence → auto-update; low confidence → human review

Key Lessons

  • Larger context windows don’t remove need for selective context — “context discipline”
  • Don’t optimize cost prematurely; focus on accuracy first
  • Production LLM apps are iterative — ship early, refine with real feedback
  • Reliability = context engineering + harness engineering (not just better models/prompts)
  • Explicit control over workflow state, recovery, and verification remains essential even as models improve