Skip to content

Knowledge Graph & Realms

The knowledge graph is the core data structure in Agentcy. Every entity a connector discovers — a GitHub repo, an EC2 instance, a Kubernetes pod, a Salesforce account, a Figma file — becomes a node. Relationships between them become edges. Queries — whether Cypher, semantic search, or agent tool calls — read the same graph.

The graph is stored in Neo4j 5. Three Rust crates work on it:

CrateRole
agentcy-graphReads (search, traversal, Cypher), writes coming from API handlers.
agentcy-ingestBulk writes from ingestion pipelines. Owns RealmWriter.
agentcy-ragEmbeddings + vector search layered over the graph.

Nodes and relationships

Nodes carry labels (like Repository, Service, Incident) and properties (like name, url, created_at). Edges are directed and typed.

Typical shape:

(:Repository {name:"monolith"})-[:HAS_PR]->(:PullRequest {number:412})
(:Service {name:"checkout"})-[:DEPLOYED_ON]->(:Cluster {name:"prod-us"})
(:User {email:"alice@…"})-[:OWNS]->(:Repository)
(:Incident {id:"INC-42"})-[:AFFECTS]->(:Service)

You don't need a schema up front — Neo4j is schema-optional and new node/edge types appear organically as connectors evolve. agentcy-graph applies idempotent constraints at first-write for the properties that should be unique (source_id, realm, canonical URLs).

Realms

Knowledge graph partitioned into realms (infrastructure, development, crm). Queries are scoped by default; cross-realm edges are explicit and rare.

Realms are the partition key. Every node and edge carries a realm: string property. A realm groups data by domain so multi-tenant users can run many concurrent pipelines without collision.

Built-in realms (you can add your own):

RealmTypical use
infrastructureCloud, Kubernetes, CI/CD, observability
developmentGitHub, Jenkins, code intel
crmHubSpot, Google Workspace, Slack, Read.ai
designFigma, Remotion
dataSQL, MongoDB, Power BI, CSV/JSON

Queries are realm-scoped by default. A chat in a conversation tagged realm: "crm" will not see :Service nodes written by the infrastructure pipeline, even if they share the same Neo4j database. To cross realms, pass realms: ["crm","infrastructure"] or realms: ["*"] to the query.

Realms are enforced in three places:

  1. Graph writesRealmWriter injects realm on every node and rejects writes missing it.
  2. Graph reads — all search and traversal endpoints filter by realms from the request context.
  3. Agent tool calls — the agent loop forwards the conversation's realm to tools that accept one.

API

bash
# List realms this org has data in
curl http://localhost:8080/api/v1/realms \
  -H "authorization: Bearer $TOKEN" | jq

# Create / edit
curl -X POST http://localhost:8080/api/v1/realms \
  -H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
  -d '{"name":"customer-success","description":"HubSpot + ReadAI + Slack for CS team"}'

Tenancy

Every node has both org_id and realm. Cross-org queries are architecturally impossible — agentcy-graph composes a WHERE n.org_id = $org_id AND n.realm IN $realms filter on every query it builds. Raw Cypher passes through a safety-check layer that injects the same filter if missing.

Multiple orgs sharing one Neo4j cluster is supported and is how the Cloud deployment works.

Three kinds:

bash
curl "http://localhost:8080/api/v1/graph/search?q=checkout&labels=Service,Repository&realms=development" \
  -H "authorization: Bearer $TOKEN"

Powered by Neo4j full-text indexes. Returns ranked nodes with highlighted fields.

2. Semantic / vector

agentcy-rag embeds every node's text representation using fastembed-rs (local, no external API). Vectors live in the node itself as embedding: [f32] and are indexed using Neo4j 5 vector indexes (HNSW).

bash
curl -X POST http://localhost:8080/api/v1/rag/search \
  -H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
  -d '{"query":"why is the payment service flaky","top_k":10,"realms":["infrastructure","development"]}'

3. Cypher

Power users can run Cypher directly (subject to policies and the realm filter). The UI graph explorer uses this path.

bash
curl -X POST http://localhost:8080/api/v1/graph/cypher \
  -H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
  -d '{
    "query": "MATCH (p:PullRequest)-[:CLOSES]->(i:Incident {status:\"open\"}) RETURN p,i LIMIT 25",
    "realms": ["development","infrastructure"]
  }'

Subgraph expansion

GET /api/v1/graph/expand?node_id=<id>&depth=2 returns a breadth-first expansion — the payload the UI uses to render the React Flow graph explorer. Edge kinds can be filtered (&edges=DEPENDS_ON,DEPLOYS_TO).

Writes from chat

Agents occasionally need to record new facts (an incident, a decision). Use graph.write_node and graph.write_edge via the catalog, or write directly from a tool implementation. Both are policy-gated (graph.write).

Visualization

Graph explorer — a force-directed React Flow canvas of nodes grouped by label with a realm toggle in the left rail.

The /graph page in the frontend is a React Flow canvas with:

  • Category-aware layouts (dagre for DAG-like edges, force for mesh).
  • Realm toggles on the left rail.
  • Saved views (persist as a query + layout).
  • Node detail panel with backlink to source (GitHub URL, AWS console, etc.).

Schema evolution

Connectors write nodes with the fields their upstream provider exposes. When a provider adds a field, the connector starts writing it on next sync. agentcy-graph migrates nothing — missing fields simply appear over time. Soft-deletes mark nodes as archived_at rather than removing them, so history is preserved.

Gotchas

  • Large writes are chunked. Pipelines write in batches of PIPELINE_BATCH_SIZE (default 500 nodes). Increase for first-time bulk imports.
  • Neo4j Community edition is what we test against. Enterprise works but we don't use role mappings, fine-grained access, or causal clustering features.
  • Vector search requires Neo4j ≥ 5.13. We enable the vector index on a per-label basis on first write.
  • Cross-realm Cypher is powerful but easy to misuse. Consider adding a policy (deny[msg] { input.action == "graph.cypher.cross_realm" … }) that audits or blocks it.

Next

Built by AgentcyLabs. For in-house deployment or Agentcy Cloud (PaaS) access, visit agentcylabs.com.