ContextCast

Predict what engineers will need before they ask.

ContextCast is an AI-powered proactive context prediction engine built on Splunk. It watches your operational data stream, builds a live knowledge graph of your systems, and the moment an alert fires or a deployment lands it predicts exactly what the responding engineer will need next: the right runbook, the dependent service dashboard, the last three deployments, the colleague who resolved the same incident six weeks ago. All of it surfaces before the engineer opens a single tab.

Built for the Splunk Agentic Ops Hackathon 2026. Tracks: Observability and Platform and Developer Experience. Splunk AI used: MCP Server, foundation-sec-1.1-8b-instruct, CDTSM, Splunk SDK, Custom SPL Command, HEC.


The Problem

When a production alert fires, engineers do not lack intelligence. They lack context. The sequence is always the same: Splunk fires an alert, the engineer opens Jira to find related tickets, then GitHub for recent commits, then Slack to find who was oncall last time, then Confluence for the runbook, then back to Splunk for the right dashboard. Studies show engineers spend 40 to 60 percent of incident time just gathering information, not analyzing it. The average recovery time from a single context switch is 23 minutes (Gloria Mark, UC Irvine). During a SEV-1 engineers switch between 8 to 12 tools. Total cognitive cost: 70 percent of MTTR is spent on diagnosis, not resolution.

The root cause is not tooling. It is that every tool waits to be asked. None of them predict.

Weather forecasts do not wait for you to notice it is raining. ContextCast does not wait for you to ask what is relevant. It tells you before you realize you need it.


The Solution

ContextCast introduces the concept of a Context Pack: a pre-assembled, confidence-ranked bundle of everything an engineer needs for a given trigger. A Context Pack contains:

  • Top-k predicted context items ranked by confidence score
  • Pre-built SPL queries ready to run against live Splunk data
  • AI-generated root cause summary via Splunk hosted foundation-sec-1.1-8b-instruct
  • Runbook links extracted from the knowledge graph
  • Related incident timeline with resolution history
  • Engineer-personalized context based on past work patterns

Context Packs are generated automatically when Splunk saved searches detect anomalies, when deployments land, or when incidents are created. They are delivered to engineers via the ContextCast dashboard and via MCP agent tool calls.


How We Built It

Layer 1: Data Ingestion

We started by defining a canonical event schema called CCEvent. Every external signal, whether a GitHub push, a Jira ticket update, or a Slack message in an incident channel, gets normalized into this schema and forwarded to Splunk via HEC.

ingestion/hec_client.py handles single events and batches with proper error handling and health checks. ingestion/ingestors.py contains three ingestor classes (GitHubIngestor, JiraIngestor, SlackIngestor) that each accept webhook payloads, extract the relevant fields, wrap them in a CCEvent, and send to HEC. We also wrote ingestion/contextcast_input.py as a proper Splunk modular input so the app can poll GitHub and Jira directly from inside Splunk without the external server.

Sourcetypes: contextcast:github, contextcast:jira, contextcast:slack, contextcast:pack.

Layer 2: Knowledge Graph

The central insight of ContextCast is that raw logs are not enough. What matters is the relationships: this service depends on that one, this deployment caused this incident, this engineer resolved it using this runbook. A flat index cannot answer that. A knowledge graph can.

knowledge_graph/graph.py implements ContextGraph on top of NetworkX MultiDiGraph. Nodes represent six entity types: service, incident, engineer, deployment, runbook, alert. Edges carry semantic types: DEPENDS_ON, CAUSED, RESOLVED_BY, WORKED_BY, DEPLOYED_TO, SIMILAR_TO, AFFECTED, MENTIONED. All writes go through typed upsert methods so the schema stays consistent.

knowledge_graph/builder.py implements GraphBuilder, which reads CCEvents from the normalized stream and calls the correct upsert methods. It also exposes build_from_splunk() which uses the Splunk Python SDK to backfill the graph from historical index data. The graph persists to disk as a JSON node-link file so state survives restarts.

Layer 3: Prediction Engine

Given a trigger (an alert, a service name, an incident key), the prediction engine returns a ranked list of context items the engineer will most likely need next. We combined four signals:

Signal 1: Graph Traversal. BFS from the trigger node up to 2 hops, with exponential confidence decay by depth. A direct dependency (depth 1) starts at 0.9 confidence. A 2-hop neighbor starts at 0.5. This captures structural relationships: if checkout is the trigger, payment and inventory surface immediately because they are direct dependencies.

Signal 2: Co-occurrence. We scan the incident history in the graph and count how often pairs of nodes appear together in the same incident subgraph. Nodes that have co-occurred in many past incidents get a co-occurrence boost capped at 0.7. This captures patterns the graph structure alone cannot express.

Signal 3: Engineer Markov Chain. For each engineer we build a transition matrix from their past activity: which nodes they pushed to, worked on, or mentioned. When an engineer is specified in the predict request, their personal transition counts boost confidence for nodes they have touched before. This is the personalization layer.

Signal 4: PageRank Boost. After the three primary signals are combined, we run PageRank on the full graph and add a small structural importance boost (up to 0.15) for nodes that are central to the dependency topology. This prevents low-traffic but structurally critical nodes from being buried.

The four signals are merged by taking the maximum confidence per node (not additive), then all predictions are sorted by final confidence and the top-k are returned.

Layer 4: Context Pack Generator

context_pack/generator.py takes the raw prediction list and assembles a full Context Pack. For each trigger type it generates a set of relevant SPL queries: error rate timechart, deployment history, incident timeline, plus a prediction-specific query per top-5 predicted nodes. It also appends two special queries: a CDTSM zero-shot anomaly forecast and a foundation-sec-1.1-8b-instruct incident summary query that runs entirely inside Splunk. If a live Splunk service is connected it executes the top 3 queries and attaches the results.

Layer 5: MCP Server Integration

We registered five tools with the Splunk MCP Server so AI agents can drive ContextCast as a tool in an agentic loop:

  • contextcast_predict: returns top-k predictions for a trigger
  • contextcast_graph_query: traverses the knowledge graph for a node
  • contextcast_get_pack: generates and returns a full Context Pack
  • contextcast_run_spl: executes a SPL query and returns results
  • contextcast_graph_stats: returns graph statistics and top nodes by PageRank

mcp_server/mcp_tools.py is the single handler file. It reads a JSON payload from stdin, dispatches to the correct function, and writes JSON to stdout, which is exactly how Splunk MCP Server invokes custom tools. mcp_server/tools.conf registers all five tools. mcp_server/tool_input_payload_signatures.json defines their parameter schemas so the MCP Server can validate inputs and surface them in the AI Assistant UI.

Custom SPL Search Command

contextcast_app/bin/contextcast_predict.py implements a Splunk streaming search command so any SPL pipeline can invoke the prediction engine inline. It adds fields to each event: cc_predictions (JSON array), cc_top_node, cc_top_label, cc_top_reason, cc_top_confidence, cc_top_spl. With generate_pack=true it attaches the full Context Pack as cc_pack_json. Engineers can use it in saved searches, alerts, and real-time searches without leaving SPL.

FastAPI Webhook Server

main.py is the external-facing server. It receives webhooks from GitHub, Jira, and Slack, normalizes them, sends to HEC, and updates the knowledge graph in background tasks. It also exposes the prediction and Context Pack REST API for direct integration. A /webhook/splunk_alert endpoint receives forwarded Splunk alert payloads, triggers Context Pack generation, and writes the result back to HEC as contextcast:pack.

Splunk App and Dashboard

The contextcast_app directory is a complete, installable Splunk app. savedsearches.conf defines four scheduled searches: anomaly detection using CDTSM zero-shot forecasting, AI incident summaries using foundation-sec-1.1-8b-instruct, high-risk deployment detection, and a graph rebuild trigger. The dashboard (contextcast_dashboard.xml) has six panels: KPI row, predictions confidence heatmap table, event activity timechart, CDTSM anomaly chart, AI incident analysis table, and engineer activity heatmap.


Architecture

EXTERNAL SOURCES                LAYER 1: INGESTION
  GitHub webhooks  ------>      FastAPI Webhook Server (main.py)
  Jira webhooks    ------>        GitHubIngestor / JiraIngestor / SlackIngestor
  Slack events     ------>        HECClient  ------>  Splunk index=contextcast
  Splunk alerts    <------      /webhook/splunk_alert

  SPLUNK ENTERPRISE
    index=contextcast  (sourcetypes: github, jira, slack, pack)
      |
    Saved Searches
      - Service Anomaly Detection  (CDTSM zero-shot forecasting)
      - Incident AI Summary        (foundation-sec-1.1-8b-instruct)
      - High-Risk Deployments
      |
    Splunk Hosted Models
      foundation-sec-1.1-8b-instruct  ->  incident summarization
      CDTSM (Cisco Deep Time Series)  ->  anomaly detection
      |
    Splunk MCP Server
      tools.conf + tool_input_payload_signatures.json
        contextcast_predict
        contextcast_graph_query
        contextcast_get_pack
        contextcast_run_spl
        contextcast_graph_stats
      |
    Custom SPL Command
      | contextcast_predict trigger=svc:checkout top_k=5
      adds cc_predictions, cc_top_* fields to pipeline

  CONTEXTCAST PREDICTION STACK (Python)
    Layer 5: MCP Tool Handler     (mcp_server/mcp_tools.py)
      |
    Layer 4: Context Pack Generator (context_pack/generator.py)
      assembles predictions + SPL queries + AI summary + runbooks
      |
    Layer 3: Prediction Engine    (prediction_engine/predictor.py)
      Signal 1: Graph traversal   (BFS, depth-weighted decay)
      Signal 2: Co-occurrence     (past incident patterns)
      Signal 3: Markov chain      (per-engineer personalization)
      Signal 4: PageRank boost    (structural importance)
      |
    Layer 2: Knowledge Graph      (knowledge_graph/graph.py)
      Nodes: service, incident, engineer, deployment, runbook, alert
      Edges: DEPENDS_ON, CAUSED, RESOLVED_BY, WORKED_BY, DEPLOYED_TO, SIMILAR_TO
      |
    Layer 1: Graph Builder        (knowledge_graph/builder.py)
      reads CCEvents, upserts nodes and edges
      build_from_splunk() backfills from historical index

  DASHBOARD  contextcast_dashboard.xml
    KPI row | Predictions heatmap | Anomaly chart
    AI Incident Analysis | Deployment risk | Engineer heatmap

Splunk AI Capabilities

Capability Where Used Prize Target
Splunk MCP Server mcp_server/tools.conf and mcp_tools.py, 5 registered tools Best MCP Server $1K
foundation-sec-1.1-8b-instruct savedsearches.conf AI Summary, Context Pack SPL queries Best Hosted Models $1K
CDTSM Cisco Deep Time Series savedsearches.conf anomaly detection, dashboard anomaly panel Best Hosted Models
Splunk AI Assistant NL to SPL translation, SPL explanation in dashboard Platform track
Splunk SDK splunklib contextcast_input.py modular input, contextcast_predict.py command, builder.py Best Developer Tools $1K
Custom SPL Streaming Command contextcast_predict adds cc_predictions fields to any pipeline Best Developer Tools
HEC HTTP Event Collector hec_client.py, all event ingestion from GitHub Jira Slack Core platform

Project Structure

contextcast/
  main.py                            FastAPI server, webhooks and REST API
  requirements.txt
  Dockerfile
  docker-compose.yml
  .env.example
  architecture.md
  ingestion/
    hec_client.py                    Splunk HEC client, single and batch
    ingestors.py                     GitHub, Jira, Slack event normalizers
    contextcast_input.py             Splunk modular input for polling
  knowledge_graph/
    graph.py                         ContextGraph NetworkX MultiDiGraph
    builder.py                       CCEvent to graph node and edge builder
  prediction_engine/
    predictor.py                     4-signal prediction engine
  context_pack/
    generator.py                     Context Pack assembler
  mcp_server/
    mcp_tools.py                     MCP tool handler, stdin/stdout JSON dispatch
    tools.conf                       Splunk MCP tool registry
    tool_input_payload_signatures.json  Tool parameter schemas
  contextcast_app/
    bin/
      contextcast_predict.py         Custom Splunk SPL streaming command
    default/
      app.conf
      inputs.conf
      transforms.conf
      savedsearches.conf             4 scheduled searches with hosted AI models
      data/ui/views/
        contextcast_dashboard.xml    Dark theme, 6-panel dashboard
  tests/
    test_graph.py                    9 graph tests
    test_predictor.py                12 predictor tests
    test_api.py                      13 API and webhook tests

Setup

Prerequisites

  • Python 3.11 or higher
  • Splunk Enterprise free trial with Developer License, or Splunk Cloud
  • HEC enabled on your Splunk instance (Settings, Data Inputs, HTTP Event Collector)

1. Clone and install

git clone https://github.com/Tasfia-17/ContextCast
cd ContextCast
pip install -r requirements.txt

2. Configure environment

cp .env.example .env

Edit .env and fill in:

SPLUNK_HEC_HOST=localhost
SPLUNK_HEC_PORT=8088
SPLUNK_HEC_TOKEN=your-hec-token
SPLUNK_HOST=localhost
SPLUNK_PORT=8089
SPLUNK_USERNAME=admin
SPLUNK_PASSWORD=your-password
GITHUB_WEBHOOK_SECRET=your-secret

3. Create the Splunk index

In Splunk: Settings > Indexes > New Index. Name it contextcast.

4. Run the API server

uvicorn main:app --host 0.0.0.0 --port 8000 --reload

Or with Docker:

docker-compose up

5. Install the Splunk app

cp -r contextcast_app $SPLUNK_HOME/etc/apps/contextcast
$SPLUNK_HOME/bin/splunk restart

6. Configure webhooks

Point your GitHub repo webhooks to:

POST http://your-server:8000/webhook/github
Header: X-GitHub-Event  (set automatically by GitHub)

Jira webhooks:

POST http://your-server:8000/webhook/jira

Slack Event Subscriptions:

POST http://your-server:8000/webhook/slack

Splunk saved search alert action webhook:

POST http://your-server:8000/webhook/splunk_alert

7. Install MCP Server tools

cp mcp_server/tools.conf $SPLUNK_HOME/etc/apps/contextcast/default/
cp mcp_server/tool_input_payload_signatures.json $SPLUNK_HOME/etc/apps/contextcast/default/
cp mcp_server/mcp_tools.py $SPLUNK_HOME/etc/apps/contextcast/bin/
$SPLUNK_HOME/bin/splunk restart

API Reference

Endpoint Method Description
/health GET Health check, graph stats, HEC status
/api/predict POST Get top-k predictions for a trigger
/api/context-pack POST Get full Context Pack
/api/graph/stats GET Knowledge graph node and edge counts
/api/graph/node/{node_id} GET Node data and neighbors

Predict request:

{
  "trigger": "svc:checkout",
  "engineer": "alice",
  "top_k": 8
}

Prediction response:

{
  "trigger": "svc:checkout",
  "predictions": [
    {
      "node_id": "svc:payment",
      "node_type": "service",
      "label": "payment",
      "reason": "Graph neighbor (depth 1, via DEPENDS_ON)",
      "confidence": 0.9,
      "spl_hint": "index=contextcast entity_id=\"svc:payment\" | timechart span=5m count by cc_type"
    }
  ]
}

Node ID prefixes: svc: for services, inc: for incidents, eng: for engineers, deploy: for deployments, rb: for runbooks, alert: for alerts.


SPL Usage

Add predictions to any search pipeline:

index=main alert_name=*
| contextcast_predict trigger_field=service engineer=alice top_k=5

Generate a full Context Pack inline:

index=contextcast cc_type=deployment
| contextcast_predict trigger="svc:checkout" generate_pack=true

AI incident summary using Splunk hosted model:

index=contextcast sourcetype="contextcast:jira"
| spath
| ai model="foundation-sec-1.1-8b-instruct"
    prompt="SRE analysis, summarize this incident and identify root cause in 2 sentences: {attributes.summary}"
    input_field=attributes.summary
    output_field=ai_analysis
| table _time, attributes.key, attributes.priority, summary, ai_analysis

Zero-shot anomaly detection using CDTSM:

index=main service="checkout"
| timechart span=5m count as requests
| apply CDTSM requests mode=anomaly conf_interval=90 method=quantile

MCP Agent Tool Usage

{"function": "predict_context", "params": {"trigger": "svc:checkout", "engineer": "alice"}}

{"function": "get_context_pack", "params": {"trigger": "inc:INC-1234", "include_live_data": true}}

{"function": "graph_query", "params": {"node_id": "svc:checkout", "edge_type": "DEPENDS_ON"}}

{"function": "run_contextual_spl", "params": {"spl": "index=contextcast | stats count by cc_type", "earliest": "-1h"}}

{"function": "graph_stats", "params": {"node_type": "service"}}

Tests

pytest tests/ -q

Expected output: 34 passed.

Test coverage:

  • test_graph.py: node upsert idempotency, dependency edges, BFS traversal, incident context, service context, PageRank, save/load persistence, stub node creation
  • test_predictor.py: sorted confidence, confidence range, trigger exclusion, incident triggers, engineer personalization, SPL hint generation, to_dict schema
  • test_api.py: all REST endpoints, webhook handlers for GitHub/Jira/Slack/Splunk, Slack URL challenge, response schema validation

Built With

Share this project:

Updates