AGENTIC AI · GENERALIZED FOR CONFIDENTIALITY
AI Recipe Authoring Agent
Production-grade agentic AI platform that reduced pharmaceutical recipe authoring from 4 months to 10 days, with human-in-the-loop validation and full traceability.
LangGraphAmazon BedrockRAGMCPLangSmithFastAPIReactPostgreSQLpgVectorAWS
Overview
A pharmaceutical manufacturing execution (MES) environment depends on recipes — heavily regulated process definitions that govern how drugs are produced on the shop floor. Authoring them is slow, expert-bound work: an engineer translates an approved manufacturing recipe into a structured system configuration, validates it against site standards, and iterates with reviewers. This platform uses an agentic AI workflow to draft, validate, and refine those recipes with a human-in-the-loop (HITL) approval gate at every critical step.
The architecture below is generalized. Company-specific system names and internal URLs are intentionally omitted.
The engineering problem
Recipe authoring took ~4 months per recipe. The bottleneck was not typing — it was assembling knowledge: historical recipes, site-specific rules, global standards, and validation requirements scattered across enterprise systems. A pure “LLM writes the recipe” approach fails here for three reasons: regulated outputs demand auditability, model
Architecture
<rect x="250" y="40" width="150" height="56" style="fill:var(--paper);stroke:var(--ink)"></rect>
<text x="325" y="64" text-anchor="middle" style="fill:var(--ink)">FastAPI</text>
<text x="325" y="80" text-anchor="middle" style="fill:var(--dim)">Orchestration API</text>
<rect x="480" y="20" width="270" height="96" style="fill:var(--paper);stroke:var(--red)"></rect>
<text x="615" y="42" text-anchor="middle" style="fill:var(--red)">LangGraph Agent</text>
<text x="615" y="60" text-anchor="middle" style="fill:var(--ink)">draft → validate → retrieve</text>
<text x="615" y="76" text-anchor="middle" style="fill:var(--ink)">→ HITL review → refine</text>
<text x="615" y="92" text-anchor="middle" style="fill:var(--ink)">→ emit recipe</text>
<text x="615" y="108" text-anchor="middle" style="fill:var(--dim)">stateful, resumable workflow</text>
<rect x="250" y="170" width="150" height="56" style="fill:var(--paper);stroke:var(--ink)"></rect>
<text x="325" y="194" text-anchor="middle" style="fill:var(--ink)">MCP Tools</text>
<text x="325" y="210" text-anchor="middle" style="fill:var(--dim)">FastMCP server</text>
<rect x="480" y="170" width="270" height="56" style="fill:var(--paper);stroke:var(--ink)"></rect>
<text x="615" y="194" text-anchor="middle" style="fill:var(--ink)">Aurora PostgreSQL + pgvector</text>
<text x="615" y="210" text-anchor="middle" style="fill:var(--dim)">site-specific → global knowledge tiers</text>
<rect x="20" y="170" width="150" height="56" style="fill:var(--paper);stroke:var(--ink)"></rect>
<text x="95" y="194" text-anchor="middle" style="fill:var(--ink)">Amazon Bedrock</text>
<text x="95" y="210" text-anchor="middle" style="fill:var(--dim)">model access layer</text>
<rect x="250" y="260" width="150" height="50" style="fill:var(--paper);stroke:var(--ink)"></rect>
<text x="325" y="281" text-anchor="middle" style="fill:var(--ink)">HITL Queue</text>
<text x="325" y="297" text-anchor="middle" style="fill:var(--dim)">domain expert review</text>
<rect x="480" y="260" width="270" height="50" style="fill:var(--paper);stroke:var(--ink)"></rect>
<text x="615" y="281" text-anchor="middle" style="fill:var(--ink)">LangSmith</text>
<text x="615" y="297" text-anchor="middle" style="fill:var(--dim)">traces · evals · prompt versions</text>
<path d="M170,68 L250,68" style="stroke:var(--ink);fill:none;marker-end:url(#ah)"></path>
<path d="M400,68 L480,68" style="stroke:var(--ink);fill:none;marker-end:url(#ah)"></path>
<path d="M615,116 L615,170" style="stroke:var(--red);fill:none;marker-end:url(#ah)"></path>
<path d="M480,198 L400,198" style="stroke:var(--ink);fill:none;marker-end:url(#ah)"></path>
<path d="M250,198 L170,198" style="stroke:var(--ink);fill:none;marker-end:url(#ah)"></path>
<path d="M325,226 L325,260" style="stroke:var(--ink);fill:none;marker-end:url(#ah)"></path>
<path d="M615,226 L615,260" style="stroke:var(--ink);fill:none;marker-end:url(#ah)"></path>
<path d="M325,116 L615,40" style="stroke:var(--red);fill:none;marker-end:url(#ah)"></path>
Technical design
- Agent layer — a stateful LangGraph workflow (draft → validate → retrieve → review → refine) where every transition is a persisted checkpoint. Long-running authoring sessions survive restarts and can be resumed or audited.
- Models — Amazon Bedrock for model access. Model choice is a configuration concern, not a code concern: prompts are versioned and evaluated independently of deployments.
- Retrieval — MCP tool servers expose a three-tier retrieval strategy: site-specific knowledge first, then global standards, then historical recipes — with pgvector similarity search over vectorized enterprise configurations (fed by a dedicated ETL pipeline).
- HITL gates — domain experts approve or reject agent output at defined checkpoints. Every decision is captured as workflow state, giving a complete audit trail.
- Observability — LangSmith traces every run; prompt and model changes ship through an evaluation harness before touching production flows.
Key engineering decisions
- Why agentic, not a single prompt? The task has real control flow: validation failures must loop back into drafting with new context. A graph with typed state beats prompt-fu.
- Why MCP for tools? Tool interfaces outlive agent frameworks. A standards-based tool layer let agents — and later, other AI systems — reuse the same retrieval surface.
- Why pgvector over a dedicated vector DB? Configurations already lived in PostgreSQL; keeping vectors beside the relational source of truth removed a sync problem and met enterprise operational requirements (backup, access control, HA) out of the box.
- Why HITL instead of full automation? In a regulated domain, trust is earned incrementally. The HITL gate is what made adoption possible — experts only accept what they can inspect.
Challenges & solutions
- Retrieval precision across sites — site-specific rules sometimes conflicted with global standards. Solved with the tiered retrieval strategy and explicit precedence rules.
- Non-determinism in regulated output — structured output schemas plus validation nodes in the graph; anything failing schema or business rules never reaches a reviewer.
- Evaluation drift — prompts changed frequently early on; versioned prompts plus LangSmith eval sets turned “it seems better” into a measurable regression gate.
Results
- Recipe authoring effort reduced from 4 months to 10 days.
- Expert review time became the primary constraint — the system shifted human effort from assembly to judgment.
- The MCP retrieval layer was subsequently reused by other AI platforms in the organization.
What I learned
The hard problems were not model problems. Retrieval quality, state modeling, and review ergonomics determined the outcome; the LLM was the easy part.
What I would change today
I would invest in automated evaluation before the first production deployment rather than after, and push more validation logic into deterministic tool calls instead of asking the model to self-check.
Technologies
LangGraph · Amazon Bedrock · MCP (FastMCP) · RAG · pgVector · Aurora PostgreSQL · FastAPI · React · LangSmith · Docker · ECS · GitHub Actions
knowledge goes stale, and hallucinated parameters are unacceptable in GxP manufacturing.
My role
I architected the platform end to end: the agentic graph design, the retrieval architecture, the MCP-based tool layer, the HITL checkpoint model, and the observability stack — and led the technical design reviews with senior leadership and site stakeholders.