Skip to main content
Intermediate7 min read3 of 5

Context Graphs and Agentic AI

A biomedical AI agent that can answer 'Is there a quality issue with this drug?' must route across three separate graph databases, apply business rules, and synthesise a grounded answer — all in one turn. That is what a context graph enables.

Context Graphs and Agentic AI

A researcher asks an AI assistant: "Is there a quality issue with the aspirin batches currently supplying Trial NCT-4421?"

To answer this correctly, the AI agent needs to:

  1. Find the drug in the clinical knowledge graph (Foundation module — Neo4j)
  2. Find the batches in the supply chain graph (Supply/Quality module — PostgreSQL graph)
  3. Check quality events against the compliance graph (Governance module — Neptune RDF)
  4. Apply the policy: "Batches with Grade 2+ quality events must trigger a pharmacovigilance review before trial continuation"
  5. Return a grounded answer with source attribution

No single database has all of this. The context graph assembles the right slice of knowledge from across all three systems, guided by what the task actually needs.


Multi-Database Routing: The Agent's First Decision

A production biomedical knowledge graph is not a monolith. Different modules live in different stores optimised for different query patterns:

flowchart TD
  AGENT["AI Agent — receives natural language query"] --> ROUTE{Query classifier\nmax_tokens: 10}

  ROUTE -- "drugs, diseases, genes,\nproteins, trials, patients" --> NEO4J["Neo4j Aura\nProperty graph\nFast traversal\nCommunity detection"]
  ROUTE -- "batch, manufacturing,\nquality, GMP, site" --> PG["pgGraph\nPostgreSQL graph\nSupply chain traceability\nFK-based relationships"]
  ROUTE -- "provenance, derived from,\nontology, RDF, SPARQL,\nregulatory" --> NEPTUNE["AWS Neptune\nRDF + SPARQL\nCross-module reasoning\nSemantic web queries"]
  ROUTE -- "sync, validate,\nalign vocabularies" --> SYNC["Graph Sync Server\nBidirectional sync\nSHACL validation\nConflict resolution"]

The routing decision is made by a lightweight classifier, not by examining the full data. Once routed, the agent executes the appropriate tool:

ToolWhat it does
neo4j_queryCypher query on Foundation/Clinical/Patient/Medical Affairs data
neo4j_expandK-hop subgraph expansion from a seed entity
neo4j_communityLouvain community detection across entity clusters
neo4j_pathfindShortest path between two entities
pggraph_batch_lineageFull lineage: drug → batches → manufacturing sites → quality events
pggraph_site_impactAll batches and quality events from a specific site
neptune_sparqlSPARQL query for semantic/provenance/cross-module reasoning
neptune_cypheropenCypher on Neptune for hybrid queries
sync_validate_graphSHACL validation before publishing to production Neptune

Multi-Step Reasoning: Chaining Tools Across Databases

The real power of the context graph pattern is chaining tools — where each step's result informs the next query.

flowchart TD
  Q["'Is there a quality issue with the\naspirin batches in Trial NCT-4421?'"]

  Q --> S1["Step 1: neo4j_query\nFind aspirin drug_id and\nactive trials it appears in\n→ drug_id: DRG-0007\nTrial NCT-4421: Active, Phase II"]

  S1 --> S2["Step 2: pggraph_batch_lineage\nFind all batches of DRG-0007\nproduced in last 180 days\n→ 3 batches from Site_Mumbai\n→ Batch B-2024-0091: QE-grade2\n→ Batch B-2024-0093: released"]

  S2 --> S3["Step 3: neptune_sparql\nCheck compliance records:\nDoes QE-grade2 trigger\npharmacovigil policy?\n→ Policy P-0023 applies:\nGrade 2+ events require review"]

  S3 --> SYNTH["Synthesise:\nBatch B-2024-0091 has a Grade 2 quality\nevent. Policy P-0023 requires\npharmacovigilance review before\nTrial NCT-4421 can continue supply.\nSource: DRG-0007, Batch B-2024-0091,\nPolicy P-0023"]

Each step produces structured output that the next step can use as a precise filter. This is fundamentally different from asking an LLM to "figure it out from text" — every piece of evidence is sourced from a specific, versioned graph node.


The Context Graph: Assembling the Right Slice

A context graph is not the full knowledge graph — it is the subgraph assembled for a specific task, user, and moment. The same knowledge graph produces different context slices for different queries.

Same knowledge graph, different context slices:

flowchart LR
  KG[(Full Knowledge Graph\n31 entity types\n37 relationship types)]

  KG --> CL1["Oncologist context:\nDrug mechanism\nClinical trial results\nPatient outcomes\nBiomarker associations"]

  KG --> CL2["Pharmacovigilance context:\nAdverse events per drug\nIncidence rates\nMedDRA codes\nGrade severity distribution"]

  KG --> CL3["Supply chain context:\nBatch lineage\nManufacturing site GMP status\nQuality events\nRegulatory submissions"]

  KG --> CL4["Regulatory context:\nCompliance records\nSubmission status\nPolicy applicability\nAudit trail provenance"]

Each context slice is assembled dynamically based on:

  • Who is asking — their role and permissions
  • What they are doing — the task type triggers different module routing
  • What state exists — prior conversation turns, prior agent actions
  • What policies apply — governance rules stored as graph nodes

Agent Memory: Persistent Context Across Turns

One of the hardest problems in agentic AI is memory — making an agent aware of what happened in prior turns without forcing it to hold the entire conversation history in context.

A context graph solves this by storing conversation turns as graph nodes linked to the entities they reference:

flowchart TD
  T1["Turn 1:\n'Find trials investigating pembrolizumab\nfor lung cancer'"] --> KG_T1[(Graph stores:\nTurn_1 → Drug: Pembrolizumab\nTurn_1 → Disease: Lung Cancer\nTurn_1 → 4 trial nodes surfaced)]

  T2["Turn 2:\n'Which of those have Grade 3 adverse events?'"] --> KG_T1
  KG_T1 --> |"Recall: 4 trials from Turn_1"| FILTER["Filter: TRIAL_REPORTS_ADVERSE_EVENT\n[severity: Grade 3+]\n→ 2 trials match"]

  T3["Turn 3:\n'What is the enrollment status?'"] --> KG_T1
  KG_T1 --> |"Recall: 2 trials from Turn_2"| STATUS["neo4j_query:\nClinicalTrial.status\n→ 1 recruiting, 1 completed"]

Pronouns and implicit references ("those", "that trial", "the drug") are resolved by traversing the conversation history nodes — not by scanning raw text. This is semantic recall: the agent retrieves the relevant prior context by traversing typed relationships, not by reading a conversation log.


Business Rules as Graph Nodes

The most underappreciated challenge in production AI is enforcing business rules. Rules like "Grade 2+ quality events require pharmacovigilance review before trial continuation" exist in policy documents and institutional knowledge — not in any queryable database field.

A knowledge graph makes these rules explicit and traversable:

flowchart TD
  POL["Policy: P-0023\nDataGovernancePolicy\ncategory: PharmacovigilanceReview\nscope: ClinicalSupply\nstatus: Active\neffective_date: 2024-01-01"]
  POL -- "POLICY_GOVERNS_ENTITY\n[enforcement_level: Required]" --> QE["QualityEvent\n[severity: Grade2+]"]
  QE -- "triggers" --> ACT["Required Action:\nBlock trial supply release\nNotify: PV team + Medical Affairs\nCreate: ComplianceRecord"]

  AGENT["AI Agent detects\nBatch B-2024-0091 QE Grade2"] --> TR["Traverse:\nBatch → QualityEvent → Policy"]
  TR --> POL
  POL --> RESP["Agent applies rule:\n'Policy P-0023 requires review\nbefore Trial NCT-4421 supply'"]

When the agent traverses the context graph and finds Policy P-0023 governing QualityEvent [Grade2+], it applies the rule correctly — without the rule needing to be in the prompt or the model needing to have learned it from training data.


The MCP Protocol: How Agents Connect to the Context Graph

The Model Context Protocol (MCP) is the interface between an AI agent and the knowledge graph layer. Each database exposes its capabilities as MCP tools — structured, schema-validated function calls that the agent can invoke.

flowchart LR
  AGENT2["AI Agent"] -- "JSON-RPC 2.0 / MCP" --> MCP["MCP Server Layer"]
  MCP --> T1["neo4j_query\n{cypher, params}"]
  MCP --> T2["pggraph_batch_lineage\n{drug_id, days_back}"]
  MCP --> T3["neptune_sparql\n{sparql_query}"]
  MCP --> T4["sync_validate_graph\n{source, target, mode}"]
  T1 --> DB1["Neo4j Aura\n(Foundation/Clinical)"]
  T2 --> DB2["pgGraph\n(Supply/Quality)"]
  T3 --> DB3["AWS Neptune\n(RDF/Governance)"]
  T4 --> DB1 & DB3

Each MCP tool call:

  • Validates inputs against a JSON Schema before execution
  • Authenticates to the database (Neo4j: bolt+s, Neptune: SigV4, pgGraph: SSL)
  • Checks cache (Redis, TTL 300s for queries, 3600s for entities)
  • Returns structured results the agent can use in the next reasoning step

The agent does not write raw database queries — it calls tools. This means the knowledge graph owner controls what queries are possible, what data is accessible, and what audit trail is maintained.

[Key Insight] The MCP pattern inverts the traditional AI architecture: instead of the AI model having direct database access, the knowledge graph exposes a curated set of tools. The knowledge graph owner controls the schema, the access rules, and the audit trail. The AI reasons over what it is given — not over everything it can reach.


From Prompt to Production

The pattern that consistently holds across biomedical AI deployments:

StageWhat the context graph enables
Single-domain queriesRoute to correct database, return structured results
Cross-domain queriesChain tools across Neo4j + pgGraph + Neptune
Agentic workflowsMulti-step reasoning with memory between steps
Compliance queriesTraverse policy nodes, enforce rules, generate audit records
Reproducible answersEvery answer traceable to specific, versioned graph nodes

The context graph does not make the AI smarter. It makes the AI's environment trustworthy — structured, complete, governed, and auditable.

Next: GraphRAG Explained — how the graph traversal that powers context assembly works technically, from entity extraction through community detection.