From Knowledge Graphs to Context Graphs: The Next Evolution for AI Agents
Knowledge graphs have proven their value as a context layer for AI agents. Hybrid search β lexical, semantic, and structural β is now a production pattern at scale. Organisations run 45,000-node graphs on Community Edition instances, and every major platform ships a graph-backed offering for agent retrieval.
But retrieval of what exists is not the same as governing what is allowed, what was true at decision time, or what an agent actually did. The knowledge graph maps entities and relationships. The context graph adds four dimensions that production AI agents require: temporal validity windows, policy nodes, decision traces, and event-driven subgraph activation.
What Knowledge Graphs Do Today
A knowledge graph is fundamentally a map of facts. It answers "what is related to what":
// Find all products affected by a vulnerability
MATCH (v:Vulnerability {cve: "CVE-2026-1234"})-[:AFFECTS]->(p:Product)
RETURN p.name, p.version
This query works because the graph has been populated with entities and relationships extracted from documents, databases, or manual curation. The graph is a snapshot β it reflects the state of knowledge at the time of ingestion. Timestamps may exist as properties, but the graph model itself is static. Every edge asserts "this relationship holds" without necessarily specifying when it started, when it expired, or under what conditions it applies.
Vector RAG retrieves semantically similar text chunks. Graph-enhanced RAG traverses relationships to surface connected entities. Both operate over a frozen knowledge base. Neither encodes permissions, temporal scoping, or the provenance of past decisions. For a question-answering bot that references documentation, this is sufficient. For an autonomous agent that executes actions against live systems, it is dangerously incomplete.
What Context Graphs Add
A context graph extends the property graph model with four primitives that mirror the requirements of production agent systems:
Temporal Validity Windows
Every relationship carries an interval β a half-open range [valid_from, valid_until) that defines when the relationship was active in the real world:
An agent querying this graph at runtime must include the current timestamp in its traversal. The graph engine filters out expired and not-yet-active edges automatically. This prevents an agent from acting on stale authorisations or attempting to use a service that has been decommissioned.
Policy Nodes
Policies are first-class nodes, not edge properties. They encode what is permitted, prohibited, or required for a given action on a given resource:
CREATE (p:Policy {
id: "pol-pci-dss-11",
type: "restriction",
action: "EXFILTRATE",
resource_pattern: "database:customers/*",
condition: "env != 'prod-dr' AND NOT user.role IN ['sre', 'compliance']",
priority: 100,
enforcement: "HARD_BLOCK"
})
Context graph queries are rewritten at traversal time to intersect results with applicable policies. The agent never sees forbidden paths β the graph simply does not return them. This is the difference between asking "may I access this?" and having the graph enforce boundaries silently.
Decision Traces
Every agent action that produces a side effect is reified as a decision node with full provenance:
These nodes create an auditable chain of causation. Every agent decision is linked to the context that informed it β the policies that allowed it, the evidence that supported it, and the state of the world when it was taken.
Event-Driven Subgraph Activation
A context graph is not queried in isolation at a single point in time. It listens for events β deployment completed, vulnerability published, policy revoked β and activates or deactivates subgraphs accordingly. An edge with valid_until in the past is pruned from query results. A new ACCESSES edge created by an IAM event handler becomes visible to agents within seconds.
This dynamic activation enables the graph to serve as a live control plane rather than a static index. AWS launch notifications, Kubernetes admission webhooks, and CI/CD pipeline events all feed into the graph, which in turn re-shapes the context available to every agent in the system.
Architecture Overview
The following diagram shows how the four primitives fit together in a running system:
flowchart TB
subgraph Events["Event Sources"]
K8S["K8s Admission Webhook"]
CI["CI/CD Pipeline"]
IAM["IAM Role Changes"]
VULN["Vulnerability Feed"]
end
subgraph ContextGraph["Context Graph (Neo4j)"]
TEMP["Temporal Edges<br/>valid_from / valid_until"]
POLICY["Policy Nodes<br/>HARD_BLOCK / SOFT_WARN"]
DECISION["Decision Traces<br/>Action β Evidence β Policy"]
ACTIVE["Active Subgraph<br/>(current timestamp filter)"]
end
subgraph Agents["AI Agents"]
AGENT1["Deploy Agent"]
AGENT2["Data Query Agent"]
AGENT3["Incident Response"]
end
subgraph MCP["MCP Transport Layer"]
GET["get_context"]
TRAV["traverse_at_time"]
SUB["subscribe_context"]
end
Events -->|"event-driven updates"| ContextGraph
ContextGraph -->|"current view"| ACTIVE
Agents -->|"MCP tools"| MCP
MCP -->|"policy-mediated<br/>traversal"| ACTIVE
ACTIVE -->|"allowed paths only"| Agents
The event sources feed into the context graph, which maintains temporal edges and policy constraints. Agents query through the MCP transport layer, which enforces policy-mediated traversal. The agent only sees the subgraph that is temporally valid, policy-permitted, and relevant to its current operation.
Building a Context Graph: Practical Walkthrough
To make these concepts concrete, here is a worked example: a context graph that governs a deployment agent across a full release cycle.
Step 1: Seed the Ontology
The context graph needs node labels and constraints that support temporal traversal and policy mediation:
CREATE CONSTRAINT IF NOT EXISTS FOR (a:Agent) REQUIRE a.id IS UNIQUE;
CREATE CONSTRAINT IF NOT EXISTS FOR (s:Service) REQUIRE (s.id, s.version) IS NODE KEY;
CREATE CONSTRAINT IF NOT EXISTS FOR (p:Policy) REQUIRE p.id IS UNIQUE;
CREATE INDEX IF NOT EXISTS FOR ()-[r:ACCESSES]-() ON (r.valid_from, r.valid_until);
CREATE INDEX IF NOT EXISTS FOR ()-[r:DEPLOYS]-() ON (r.timestamp);
The composite index on ACCESSES.valid_from and ACCESSES.valid_until is critical. Every agent query filters on these columns, and without the index the graph engine performs a full scan on every traversal.
Step 2: Define Initial Policies
The deployment agent is governed by two policies β one that restricts deployment targets and one that enforces approval workflow:
CREATE (p1:Policy {
id: "pol-deploy-target",
type: "restriction",
action: "DEPLOY",
resource_pattern: "service:*",
condition: "target_env IN ['staging', 'prod-canary'] OR ticket.status = 'approved'",
priority: 100,
enforcement: "HARD_BLOCK"
});
CREATE (p2:Policy {
id: "pol-deploy-time-window",
type: "restriction",
action: "DEPLOY",
resource_pattern: "service:prod*",
condition: "hour_of_day BETWEEN 6 AND 22 AND day_of_week NOT IN [6, 7]",
priority: 90,
enforcement: "HARD_BLOCK"
});
Step 3: Grant Temporal Access
The agent receives access to the staging environment with a temporal validity window. The access expires automatically when the window closes:
Step 4: Query with Temporal and Policy Constraints
At runtime, the agent queries its context. The query must include the current timestamp to filter temporally valid edges, and it must intersect with applicable policies:
// Agent queries: "What can I deploy and where, right now?"
MATCH (a:Agent {id: "deploy-bot-v2"})
MATCH (a)-[acc:ACCESSES]->(s:Service)
WHERE acc.valid_from <= datetime()
AND acc.valid_until > datetime()
MATCH (pol:Policy {action: "DEPLOY"})
WHERE pol.enforcement <> "HARD_BLOCK"
OR (pol.resource_pattern CONTAINS s.id)
RETURN s.id AS service, s.version, acc.environment,
collect(DISTINCT pol.id) AS applicable_policies
The query returns only services with currently valid access that pass policy evaluation. If the deployment window has expired or a policy has been updated (e.g., pol-deploy-time-window now blocks the current hour), the agent receives an empty result set.
Step 5: Record the Decision
After a successful deployment, the agent records a decision trace:
The decision node links back to the policies that allowed it and the service it affected. This creates an auditable chain: any compliance auditor can walk from (d)-[:AFFECTED]->(s) to verify that the deployment was governed by the correct policies at the time of execution.
Step 6: React to Events
When a new vulnerability is published affecting payment-api, an event handler creates a policy update that immediately blocks further deployments:
MATCH (s:Service {id: "payment-api"})
MATCH (v:Vulnerability {cve: "CVE-2026-5678"})
CREATE (v)-[:AFFECTS]->(s);
CREATE (p:Policy {
id: "pol-vuln-block-5678",
type: "restriction",
action: "DEPLOY",
resource_pattern: "service:payment-api",
condition: "false", // Always block
priority: 999, // Overrides all other policies
enforcement: "HARD_BLOCK"
});
The next time the deployment agent queries its context, the query intersects with the new pol-vuln-block-5678 policy. The agent receives an empty result set, and the deployment pipeline halts without any code change to the agent itself.
Why Agents Need This
The hallucination problem is often framed as a retrieval problem β give the model better documents and it will answer correctly. In practice, production AI agents fail for a different reason: they operate outside their permitted context.
An agent that can read any document, access any service, and act on any relationship will, given enough steps, attempt something the organisation did not intend. The boundary is not one of knowledge but of permission and temporal relevance.
Context graphs encode this boundary structurally. An agent traversing a context graph cannot reach a node or edge that is forbidden, expired, or irrelevant to the current operation. The graph does not return unauthorised paths, so the agent never picks them. There is no prompt engineering, no runtime guardrail, no post-hoc filter β the constraint is baked into the retrieval layer itself.
MCP as the Interface
The Model Context Protocol (MCP) is emerging as the natural transport layer for context graphs. Each context graph node can be exposed as an MCP resource with a URI pattern like context-graph://agents/agent-iota/decisions/{id} or context-graph://policies/pol-pci-dss-11.
MCP tools provide the temporal traversal operations that agents need:
MCP Tool
Purpose
get_context
Retrieve active context for an agent at a point in time
traverse_at_time
Graph walk constrained by a temporal validity window
query_decision_chain
Trace provenance from action to evidence to policy
subscribe_context
Receive real-time push when context subgraph changes
Streamable HTTP transport β the recently adopted MCP transport specification β supports server-sent events for the subscribe_context tool. When a deployment completes or a policy updates, the context graph pushes the delta to every subscribed agent. The agent's context window stays current without polling.
Real-World Convergence
The industry is already moving in this direction. Atlan ships a "data context graph" that maps relationships across enterprise data assets with lineage and ownership. DataHub extends metadata graphs with assertion-based lineage and access policies as first-class graph nodes. TrustGraph models permissions, data sensitivity labels, and agent capabilities as graph nodes where every traversal is mediated by policy evaluation β the closest production system to the context graph model described here.
Kore.ai and Tekst maintain per-session agent context stores tracking conversation state, retrieved evidence, and action history. Neither exposes the temporal and policy dimensions in the graph model itself, but the direction is clear.
Implementation Trade-Offs
Building a context graph introduces costs that deserve honest discussion:
Query latency. Temporal filtering on every traversal adds overhead. A traversal that takes 5ms in a standard knowledge graph can take 15β50ms in a context graph because every edge requires an interval check and policy intersection. Mitigation: composite indexes (as shown in Step 1) and caching common query patterns.
Eventual consistency. Event sources update the graph asynchronously. There is a window β typically 2β5 seconds β between a policy being revoked and the graph reflecting the change. For HARD_BLOCK policies, this window is a risk. Mitigation: two-phase updates β first write the policy with immediate effect in a fast-path cache, then persist to the graph.
Graph complexity. A context graph has more node types and relationship categories than an equivalent knowledge graph. The ontology grows from 5β10 labels to 15β25 as policies, decisions, and temporal metadata are added. Mitigation: schema-as-code tooling and automated constraint validation in CI/CD.
Token budget for provenance. Decision traces carry evidence arrays, context hashes, and policy references. Over thousands of decisions, the graph grows large. Mitigation: archive decision nodes older than 90 days to cold storage, keeping only the most recent provenance chain hot.
Knowledge Graph vs Context Graph
Dimension
Knowledge Graph
Context Graph
Query model
"What entities are related?"
"What is relevant, permitted, and temporally valid now?"
Temporal modelling
Timestamps as optional properties
Half-open validity intervals as first-class edge attributes
Policy enforcement
External β applied via middleware or post-query
Structural β policies are nodes, traversal is policy-mediated
Event-driven edge activation/deactivation via Streamable HTTP
Decision audit
Logs outside the graph (if at all)
Reified decision nodes with provenance links within the graph
Consistency model
Eventual β snapshots reflect last batch
Near-real-time β state changes propagate to subscribed agents
Query latency
2β10ms typical
15β50ms (with policy mediation overhead)
The knowledge graph is not going away. It becomes the base layer β the map of entities and relationships that the context graph annotates with temporal validity, policy constraints, and decision provenance. The context graph is the control plane that rides on top. One maps what exists. The other governs what happens.