Writing incident retrospectives (post-mortems) and debugging recurring production outages are two of the most time-consuming responsibilities for Site Reliability Engineers (SREs).
Engineers often spend hours cross-referencing PagerDuty timelines, responder notes, service dependencies, and past incident histories. When teams attempt to solve this with standard LLMs, they quickly run into context window limits or hallucinated timelines because incidents are tightly bound to time, services, and escalation hierarchies.
With GraphRAG (Knowledge Graph Retrieval-Augmented Generation), an AI system can traverse:
Incident $\rightarrow$ AFFECTS $\rightarrow$ Service $\rightarrow$ ESCALATES_TO $\rightarrow$ Escalation Policy $\rightarrow$ RESOLVED_BY $\rightarrow$ Responder
As part of the WeMakeDevs × Cognee Mergetober Hackathon, I built and submitted the PagerDuty data-source connector (cognee-community-connector-pagerduty) for Cognee.
Here is an architectural walkthrough of how we bridged PagerDuty incidents and service topologies into Cognee.
Architectural Workflow
The connector extracts live incident streams and service architecture from PagerDuty's v2 REST API, cleans and redacts the payloads, and routes them into Cognee's document ingestion pipeline:
flowchart TD
subgraph PagerDutyAPI ["PagerDuty REST API v2"]
A["/incidents (Urgencies, Statuses, Timelines)"]
B["/incidents/{id}/notes (Responder Chronology)"]
C["/services (Service Catalogs & Dependencies)"]
end
subgraph ConnectorCore ["Security & Normalization Core"]
D["Rate-Limit Backoff (HTTP 429 & Retry-After)"]
E["Secret Redaction (API Tokens, Keys, PATs)"]
F["Structured Markdown Serializer"]
end
subgraph CogneeCore ["Cognee GraphRAG Layer"]
G["dlt Resource (cognee_document_source='pagerduty')"]
H["Cognify Pipeline (LLM Relationship Extraction)"]
I["Service & Incident Graph (FalkorDB / NetworkX)"]
J["Semantic Memory (Vector Search)"]
end
A & B & C --> D --> E --> F --> G --> H --> I & J
1. Dual-Resource Ingestion: Incidents & Service Catalogs
Incidents in isolation lack critical context without knowing the service topology. The connector ingests two synchronized resources:
A. Live & Historical Incidents (pagerduty_incidents)
Captures incident IDs, numbers, titles, urgency levels (high, low), lifecycle statuses (triggered, acknowledged, resolved), created and resolved timestamps, assignees, and crucially, responder notes:
# PagerDuty Incident #48291: Payment Gateway Timeout Surge
- **Urgency:** high | **Status:** resolved
- **Service:** Checkout-API
- **Escalation Policy:** Payments-Primary-Tier1
- **Created At:** 2026-10-31T18:20:00Z
- **Resolved At:** 2026-10-31T18:45:00Z
- **Assignees:** Alex Chen, Maria Garcia
### Responder Timeline & Notes
- **2026-10-31T18:25:00Z (Alex Chen):** Identified 504 gateway timeouts originating from payment vendor webhook endpoint.
- **2026-10-31T18:35:00Z (Maria Garcia):** Toggled circuit breaker to secondary gateway; error rates normalized.
B. Service Topologies (pagerduty_services)
Ingests registered microservices, descriptions, alert creation configurations, auto-resolve timeout limits, and team ownership.
2. Production Security & Pre-Ingestion Redaction
Incident titles, descriptions, and responder notes frequently contain sensitive diagnostic payloads pasted during live triage—such as database connection strings, bearer tokens, or AWS credentials.
The PagerDuty connector applies strict pre-ingestion regex redaction across all incident fields before emitting records:
import re
PATTERNS = [
(re.compile(r"Bearer\s+[A-Za-z0-9\-._~+/]+=*", re.IGNORECASE), "Bearer [REDACTED_TOKEN]"),
(re.compile(r"AKIA[0-9A-Z]{16}"), "[REDACTED_AWS_KEY]"),
(re.compile(r"sk-[A-Za-z0-9]{20,}"), "[REDACTED_API_KEY]"),
(re.compile(r"ghp_[A-Za-z0-9]{36}"), "[REDACTED_GITHUB_PAT]"),
]
def redact_secrets(text: str) -> str:
for pattern, repl in PATTERNS:
text = pattern.sub(repl, text)
return text
3. Cognitive Integration with Cognee
By tagging the source with:
setattr(source, DOCUMENT_SOURCE_ATTR, "pagerduty")
Cognee bypasses generic relational flattening and feeds the Markdown summaries into its entity extraction pipeline.
Querying Incident Memory in Python
import asyncio
import os
import cognee
from cognee_community_connector_pagerduty import pagerduty_source
async def main():
# 1. Initialize PagerDuty connector
source = pagerduty_source(
api_key=os.environ["PAGERDUTY_API_KEY"],
resources=["incidents", "services"],
urgencies=["high"],
)
# 2. Add to Cognee and run Cognify
print("Ingesting PagerDuty incidents and service topologies...")
await cognee.add(source)
print("Building incident knowledge graph...")
await cognee.cognify()
# 3. Query past incidents to automate post-mortems
query = "What caused the high urgency Checkout-API incident and how did Maria resolve it?"
print(f"\nQuerying: '{query}'")
results = await cognee.search(query)
for res in results:
print(f"\n[Incident Memory]:\n{res}")
if __name__ == "__main__":
asyncio.run(main())
Verification & Compliance
-
Complete Test Coverage: Offline test suite mocking PagerDuty REST API endpoints with zero network dependencies (
tests/test_source.py,tests/test_client.py,tests/test_redaction.py). -
Resilient Rate-Limiting: Exponential backoff with
Retry-Aftercapping to avoid thread locks. - DCO Certified: Clean commit history with Developer Certificate of Origin sign-off.
Check Out the Code
- Pull Request: topoteretes/cognee-community#429
- Repository: topoteretes/cognee
Have questions about integrating incident response into AI workflows? Feel free to connect in the comments!
Top comments (0)