Writing
Graph Memory: Why Relationships Matter

Graph Memory for Construction: Why Relationships Matter More Than Keywords

The Question That Exposes the Problem

Ask your AI agent: "If the steel delivery from Allied is delayed 5 days, what else is affected?"

To answer correctly, the agent needs to understand a chain of relationships:

  1. Steel delivery → 4th floor framing (can't frame without steel)
  2. 4th floor framing → 4th floor deck pour (can't pour without framing)
  3. 4th floor deck pour → 4th floor MEP rough-in (can't rough-in until deck is cured)
  4. 4th floor MEP rough-in → Drywall (can't close walls until MEP is inspected)
  5. Vendor X (Allied) has delayed before → reliability pattern
  6. Crane rental → scheduled for framing week → needs to be extended
  7. Framing crew → needs to be rescheduled → affects their next project

This isn't one fact. It's a network of connected facts — and the connections are what matter. Knowing that "Allied delivers steel" is a fact. Knowing that "Allied's steel delay cascades through framing → decking → MEP → drywall and also affects the crane rental and the framing crew's other commitments" is a relationship map.

Most AI memory systems store facts like entries in a dictionary — flat, disconnected, searchable by keyword. That works for "what's the specified concrete strength?" It fails catastrophically for "what happens if this one thing changes?"

Graph memory stores facts and their relationships — like a web of connected nodes. It's the difference between a phone book and a social network.


Flat Memory vs. Graph Memory

What's a "Graph" in This Context?

Not a chart or a bar graph. In computer science, a graph is a network of dots (called "nodes") connected by lines (called "edges"). Your social media friend network is a graph: each person is a node, each friendship is an edge. A construction project is also a graph: each task, person, material, and date is a node, and the relationships between them (depends on, supplied by, managed by, scheduled for) are edges.

Flat memory stores five disconnected facts. If you ask "what happens if steel is delayed?", the AI has to guess the connections based on proximity and keyword matching. It might find facts 1-3 but miss the crane rental and the framing crew.

Graph memory stores the same information as a web of connected nodes. Ask "what happens if steel is delayed?" and the system traverses the graph — following every connection outward from the steel delivery node — and finds all affected entities automatically: framing, deck pour, MEP, crane rental, framing crew, and Allied's reliability history.


Neo4j create-context-graph: Building Graph Memory

create-context-graph (opens in a new tab) from Neo4j Labs is a tool that scaffolds a complete graph-based memory system for AI agents. It supports 22 industry verticals and 8 agent frameworks out of the box.

What's Neo4j?

Neo4j is the world's most popular graph database — a database specifically designed to store and query relationships between things. Instead of rows and columns (like Excel or SQL), it stores nodes and edges (like a network diagram). It's been used for decades by companies like NASA, Walmart, and the FBI for exactly this kind of relationship analysis. The "create-context-graph" tool is a starter kit that generates a full application on top of Neo4j.

The POLE+O Memory Model

create-context-graph uses a memory model called POLE+O (Person, Organization, Location, Event, Object). This maps perfectly to construction:

POLE+O CategoryConstruction Examples
PersonJohn (superintendent), Sarah (architect), Mike (plumber foreman)
OrganizationAllied Steel (vendor), Henderson Design (architect), Your GC Company
LocationBuilding C, 4th Floor, Zone B, Staging Area North
EventSteel delivery, concrete pour, inspection, RFI submission, delay
ObjectSteel beams, concrete mix, crane, pump truck, RFI #247

Plus three types of memory:

Memory TypeWhat It StoresConstruction Example
Short-termCurrent conversations and active tasksToday's daily log, current discussion about the steel delay
Long-term (Knowledge Graph)Permanent entity relationshipsAllied Steel → delivers to → 4th Floor Framing → depends on → Crane Rental
Reasoning MemoryDecision traces with provenance"On March 28, we decided to extend the crane rental because: steel delay (5 days) → framing pushed → crane needed longer. Decision made by PM Agent, approved by Board."

Quick Start: Building a Construction Context Graph

Scaffold the Application

npx create-context-graph@latest my-construction-graph \
  --framework paperclip \
  --industry construction \
  --db neo4j

This generates a full application with:

  • Neo4j database schema pre-configured for POLE+O
  • API endpoints for adding/querying entities and relationships
  • Integration hooks for your agent framework

Start Neo4j

# Using Docker (easiest)
docker run -d --name neo4j \
  -p 7474:7474 -p 7687:7687 \
  -e NEO4J_AUTH=neo4j/password \
  neo4j:latest

Populate Your Project Graph

from context_graph import ContextGraph
 
graph = ContextGraph(uri="bolt://localhost:7687", auth=("neo4j", "password"))
 
# Create entities (nodes)
allied = graph.create_entity("Organization", {
    "name": "Allied Steel",
    "type": "vendor",
    "reliability_score": 0.60,
    "avg_delay_days": 2.3
})
 
steel_delivery = graph.create_entity("Event", {
    "name": "Steel Delivery - 4th Floor Package",
    "scheduled_date": "2026-04-15",
    "status": "delayed",
    "delay_days": 5
})
 
framing = graph.create_entity("Event", {
    "name": "4th Floor Framing",
    "scheduled_start": "2026-04-18",
    "scheduled_end": "2026-04-29",
    "crew_size": 12
})
 
deck_pour = graph.create_entity("Event", {
    "name": "4th Floor Deck Pour",
    "scheduled_date": "2026-05-01",
    "concrete_cy": 65
})
 
mep_roughin = graph.create_entity("Event", {
    "name": "4th Floor MEP Rough-In",
    "scheduled_start": "2026-05-05",
    "scheduled_end": "2026-05-16"
})
 
crane = graph.create_entity("Object", {
    "name": "Tower Crane Rental",
    "vendor": "Maxim Crane",
    "scheduled_end": "2026-04-29",
    "daily_rate": 2500
})
 
john = graph.create_entity("Person", {
    "name": "John",
    "role": "Superintendent",
    "communication_preference": "brief, action-oriented"
})
 
# Create relationships (edges)
graph.create_relationship(allied, "DELIVERS", steel_delivery)
graph.create_relationship(steel_delivery, "REQUIRED_FOR", framing)
graph.create_relationship(framing, "FOLLOWED_BY", deck_pour)
graph.create_relationship(deck_pour, "FOLLOWED_BY", mep_roughin)
graph.create_relationship(framing, "REQUIRES_RESOURCE", crane)
graph.create_relationship(john, "MANAGES", framing)

Query the Impact of a Change

# THE KILLER QUERY: "What's affected by the steel delay?"
impact = graph.cascade_impact(
    entity=steel_delivery,
    change={"delay_days": 5}
)
 
print(impact.summary)
# {
#   "directly_affected": [
#     {"entity": "4th Floor Framing", "impact": "Start delayed 5 days to April 23"},
#     {"entity": "Tower Crane Rental", "impact": "Extension needed: 5 days × $2,500 = $12,500"}
#   ],
#   "indirectly_affected": [
#     {"entity": "4th Floor Deck Pour", "impact": "Pushed to May 6 (from May 1)"},
#     {"entity": "4th Floor MEP Rough-In", "impact": "Pushed to May 10 (from May 5)"}
#   ],
#   "schedule_impact": "5 days added to critical path",
#   "cost_impact": "$12,500 (crane extension)",
#   "people_to_notify": ["John (Superintendent)", "Maxim Crane (vendor)"],
#   "decision_needed": "Approve crane extension or find alternative lifting plan"
# }

That single query — "what's affected by the steel delay?" — traversed the graph, followed every relationship, calculated the cascade, identified the cost impact, and listed who needs to be notified. With flat memory, your agent would have given you a partial answer at best.


Visualization: Seeing the Project as a Graph

One of the most powerful features of graph memory is visualization. You can literally see your project as a network of connected entities:

This visualization immediately shows things that would take an experienced PM minutes to piece together:

  • The steel delay cascades through framing → pour → MEP → drywall
  • RFI #247 also blocks MEP — so MEP is now doubly blocked (delay AND open RFI)
  • The crane cost impact is $12,500
  • John needs to be notified about the framing delay
  • The electrical sub needs to be notified about the MEP push

Graph Memory + Honcho: Complementary, Not Competing

This is important: graph memory doesn't replace Honcho. They solve different problems.

CapabilityHonchoGraph Memory (Neo4j)
Remembers conversations✅ Full session history❌ Not its job
Models people's preferences✅ Deep behavioral modeling⚠️ Basic attributes only
Background reasoning✅ Asynchronous analysis❌ Not built-in
Relationship mapping❌ Stores facts, not connections✅ Primary purpose
Cascade/impact analysis❌ Can't traverse relationships✅ Core capability
"What-if" scenarios✅ "If X changes, what's affected?"
Visual project mapping✅ Graph visualization

The ideal setup: Use Honcho for people memory (how does John like to communicate? How fast does Sarah respond to RFIs?) and graph memory for project structure (what depends on what? If this changes, what cascades?).

When the PM agent needs to handle the steel delay, it asks:

  • Graph memory: "What's affected by this delay?" → Gets the full cascade
  • Honcho: "How should I notify John?" → "Brief, action-oriented. Text, not email."

Both answers are needed. Neither alone is sufficient.


Connecting to Your Agent Stack

Graph memory plugs into the full agent stack as an additional memory layer:

# In a Hermes agent's heartbeat (managed by Paperclip)
from context_graph import ContextGraph
import honcho
import os
 
# Connect to both memory systems
graph = ContextGraph(uri="bolt://localhost:7687")
workspace = honcho.Workspace.get(name="harbor-view-mixed-use")
 
# Get the current task from Paperclip
task_id = os.environ["PAPERCLIP_TASK_ID"]
 
# Ask graph memory: what entities are related to this task?
task_context = graph.query(
    "MATCH (t:Event {task_id: $id})-[r*1..3]-(related) "
    "RETURN related, type(r), r",
    id=task_id
)
 
# Ask Honcho: what do I need to know about the people involved?
people_context = workspace.chat(
    query=f"Who is involved in task {task_id} and what are their preferences?"
)
 
# Now the agent has BOTH:
# - Structural knowledge (what depends on what)
# - People knowledge (how to communicate)

When to Add Graph Memory

Graph memory adds the most value when your projects have high complexity — many interdependent tasks, many stakeholders, and frequent changes that cascade.

Project CharacteristicsFlat Memory SufficientGraph Memory Adds Value
Simple renovation, 5 subs, 3 monthsOverkill
Commercial build, 20 subs, 12 monthsMaybe✅ Cascading impacts matter
Multi-building campus, 50+ subs✅ Essential for impact analysis
Highway/infrastructure, long duration✅ Relationship complexity is extreme

Rule of thumb: If your project has more than 15 active subcontractors or more than 200 schedule activities, graph memory will materially improve your agents' ability to reason about changes and cascading impacts.


Conclusion

Construction projects are networks of relationships. Tasks depend on deliveries. Deliveries come from vendors. Vendors have reliability patterns. Tasks require resources. Resources have schedules. Changes cascade.

Flat memory systems treat all of this as disconnected facts. Graph memory systems treat it as what it actually is: a connected web where everything affects everything else.

When your AI agent can answer "if this one thing changes, show me everything that's affected" — not by guessing, but by actually traversing the relationship map — that's when AI starts to think like an experienced project manager.

Honcho remembers the people. Graph memory remembers the project. Together, your agents understand both.