Stage 7 · Master
Incident Response With AI
Closing the Knowledge Loop
Feeding resolved incidents back into the RAG index automatically.
Why Close the Loop?
Every resolved incident is a learning opportunity. If that knowledge is trapped in a postmortem that nobody reads, it is wasted. By feeding resolved incidents back into your RAG index, the next engineer facing a similar issue gets the benefit of past experience.
The Ingestion Pipeline
class IncidentKnowledgePipeline:
def __init__(self, vector_db, embedding_model):
self.vector_db = vector_db
self.embedding_model = embedding_model
def ingest_resolved_incident(self, postmortem, metadata):
"""Ingest a resolved incident into the knowledge base."""
# Step 1: Validate the postmortem is complete
if not self.quality_gate(postmortem):
return {"status": "rejected", "reason": "Incomplete postmortem"}
# Step 2: Extract key sections
sections = self.extract_sections(postmortem)
# Step 3: Chunk and embed each section
for section_name, content in sections.items():
chunks = self.chunk_text(content)
for chunk in chunks:
embedding = self.embedding_model.embed(chunk)
self.vector_db.insert(
text=chunk,
embedding=embedding,
metadata={
**metadata,
"section": section_name,
"doc_type": "postmortem",
}
)
return {"status": "ingested", "sections": len(sections)}
def quality_gate(self, postmortem):
"""Check that the postmortem has required sections."""
required = ["Summary", "Root Cause", "Timeline", "Action Items"]
return all(section in postmortem for section in required)The pipeline validates quality, extracts sections, chunks them, and indexes them with metadata.
Quality Gates
- Postmortem must have all required sections (summary, root cause, timeline, actions).
- Root cause must be specific, not vague like human error.
- Action items must have owners and due dates.
- Postmortem must be reviewed and approved by the incident commander.
Keeping the Index Fresh
from croniter import croniter
from datetime import datetime
class IndexManager:
def __init__(self, pipeline, schedule="0 2 * * 0"): # Weekly on Sunday at 2 AM
self.pipeline = pipeline
self.schedule = schedule
def should_reindex(self):
"""Check if it is time to reindex."""
cron = croniter(self.schedule, datetime.now())
next_run = cron.get_next(datetime)
return (next_run - datetime.now()).total_seconds() < 3600
def reindex_changed_documents(self):
"""Reindex only documents that changed since last index."""
changed = self.get_changed_documents()
for doc in changed:
# Remove old chunks
self.vector_db.delete_by_source(doc["source"])
# Ingest new version
self.pipeline.ingest_resolved_incident(doc["content"], doc["metadata"])
return len(changed)Reindex only changed documents to keep the knowledge base current without rebuilding the entire index.
Measuring Knowledge Value
def measure_knowledge_value(vector_db):
"""Measure how the knowledge base is being used."""
stats = {
"total_documents": vector_db.count(),
"documents_by_type": vector_db.count_by_metadata("doc_type"),
"recent_queries": get_recent_queries(days=30),
"queries_with_citations": count_cited_queries(days=30),
"answer_accuracy": measure_answer_accuracy(days=30),
}
# Value metric: percentage of queries that cite a source
citation_rate = (
stats["queries_with_citations"] / stats["total_queries"]
if stats["total_queries"] > 0 else 0
)
return {
**stats,
"citation_rate": citation_rate,
"value_assessment": "high" if citation_rate > 0.7 else "medium" if citation_rate > 0.4 else "low"
}Track citation rate — how often answers cite a source document. High citation rate means the knowledge base is useful.
After ingesting 50+ postmortems, the RAG system can answer questions like this happened before, what did we do last time. This compounds over time.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.