An autonomous Security Operations Center agent that connects to a Cortex XSIAM tenant, polls for new cases every 5 minutes, auto-triages and investigates each case using Gemini AI, and writes findings back to XSIAM as case comments and notepad entries.
Cron (5 min)
│
▼
Poll Agent ── XSIAM REST API (/public_api/v1/case/search)
│
▼
For each new/updated case:
├── Triage Agent → severity, category, false positive likelihood
└── Investigation Agent → root cause, IoCs, MITRE ATT&CK, timeline
│
├── Issue enrichment ── Cortex MCP Server (read-only)
│
▼
Writer Agent → XSIAM Case Discussion + Notepad
│
▼
SQLite state store → Streamlit Dashboard
The agent applies NIST SP 800-53, NIST CSF 2.0, and ISO/IEC 27001 frameworks in its analysis and maps findings to MITRE ATT&CK tactics and techniques.
- Server-side filtering — filter cases by status, severity, domain, assignee (email or display name), and time window directly via the XSIAM REST API
- Hot-reload config — edit
.envand changes are picked up on the next poll cycle without restarting - False positive detection — cases with high FP likelihood are flagged and skipped
- Adaptive thinking depth — uncapped Gemini reasoning for CRITICAL/HIGH cases, bounded for lower severity
- Streamlit dashboard — live poll status, case table with severity badges, expandable findings
- Deduplication — SQLite state store prevents reprocessing cases unless they've been updated
- Python 3.11+
- A Cortex XSIAM tenant with API access (API key with
Responderrole) - A running Cortex MCP Server v2.13.1 (see below)
- A Google Gemini API key
The agent uses the Cortex MCP Server v2.13.1 for read-only data enrichment — fetching issues, assets, vulnerabilities, and playbooks linked to each case. Case retrieval and all write operations go directly through the XSIAM REST API; the MCP server handles enrichment only.
| MCP Tool | Purpose |
|---|---|
get_issues |
Fetch alerts/incidents linked to a case |
get_assets / get_asset_by_id |
Asset context for affected hosts |
get_filtered_endpoints |
Endpoint details (OS, status, isolation state) |
get_vulnerabilities |
Known CVEs on affected assets |
get_correlation_rules |
Detection rule definitions that fired |
get_playbook |
Retrieve the playbook associated with a case |
The MCP server uses the Streamable HTTP transport (MCP protocol 2024-11-05). Each agent run opens a session via a POST /initialize request and receives an Mcp-Session-Id header that is passed in all subsequent tool calls.
POST http://localhost:8888/api/v1/stream/mcp
Accept: application/json, text/event-stream
Responses are Server-Sent Events (SSE) — the agent reads data: lines and parses the JSON payload.
Download and run the Cortex MCP Server from your XSIAM tenant's integrations page. The default port is 8888. Once running, set MCP_SERVER_URL in your .env:
MCP_SERVER_URL=http://localhost:8888/api/v1/stream/mcpIf the MCP server is unavailable at startup, the agent logs a warning and continues — case triage and investigation will proceed without issue enrichment.
# Install dependencies
pip install -r requirements.txt
# Configure secrets
cp .env.example .env
# Edit .env with your credentials and filters
# Initialize the state database
python -c "from scheduler.state import init_db; init_db()"All configuration is via .env:
GEMINI_API_KEY=<your-key>
CORTEX_URL=https://<your-xsiam-api-url>
CORTEX_API_KEY=<api-key-value>
CORTEX_API_ID=<api-key-id>
GEMINI_MODEL=gemini-3.5-flash
MCP_SERVER_URL=http://localhost:8888/api/v1/stream/mcp
STATE_DB_PATH=./data/processed_cases.db
POLL_INTERVAL_SECONDS=300
MAX_CASES_PER_POLL=50
LOG_LEVEL=INFO
CASE_STATUSES=New,Under Investigation
CASE_SEVERITIES=low, medium, high, critical
CASE_DOMAIN=SECURITY
CASE_LAST_UPDATE_HOURS=24
CASE_ASSIGNEE_EMAIL=analyst@company.com
CASE_ASSIGNEE_NAME=
CASE_LOOKBACK_HOURS=Note: The XSIAM API key must have the
Responderrole to write case comments and notepad entries.
Every case filter is opt-in — if a variable is blank or omitted, that filter is not applied and no restriction is placed on that field. This means:
- To process all cases regardless of assignee: leave
CASE_ASSIGNEE_EMAILandCASE_ASSIGNEE_NAMEblank - To process only your cases: set
CASE_ASSIGNEE_EMAILto your XSIAM user email - To process all severities: leave
CASE_SEVERITIESblank - To remove the time window: leave both
CASE_LAST_UPDATE_HOURSandCASE_LOOKBACK_HOURSblank
The only filter with a built-in default is CASE_STATUSES — if not set at all, it defaults to New,Under Investigation. Set it explicitly to a different value, or leave it blank to process cases of any status.
All filters are re-evaluated on every poll cycle, so changes to .env take effect at the next tick without restarting the agent.
# Continuous polling (every 5 min)
python main.py
# Single poll cycle and exit
python main.py --run-once
# Process a specific case (writes to XSIAM)
python main.py --case-id 88921
# Dry run — prints findings to stdout, no XSIAM write
python main.py --case-id 88921 --dry-runpython -m streamlit run dashboard/app.pyOpens at http://localhost:8501. Shows agent status, active filters, per-severity case counts, a case table with colour-coded severity badges, and expandable investigation findings per case. Auto-refreshes every 30 seconds and picks up .env filter changes live.
| Component | Technology |
|---|---|
| LLM | Gemini 3.5 Flash (dynamic thinking) |
| Case retrieval | XSIAM REST API /public_api/v1/case/search |
| Issue/asset enrichment | Cortex MCP Server v2.13.1 (Streamable HTTP) |
| Write back | XSIAM REST API /public_api/v1/incidents/update_incident |
| State store | SQLite |
| Dashboard | Streamlit |
Each processed case receives a structured markdown comment posted to the XSIAM Case Discussion:
- Triage summary (severity, category, false positive assessment)
- Root cause analysis
- Reconstructed timeline
- Extracted IoCs (IPs, domains, hashes, accounts)
- MITRE ATT&CK mapping (tactic + technique)
- Containment, eradication, and recovery recommendations
- ISO 27001 Annex A control references
- NIST CSF function alignment
A condensed version is also written to the Case Notepad for quick reference.
- Never commit
.env— it is gitignored - The agent has read + comment/notepad write access only; it cannot close, reassign, or modify case status
- Raw case data (alerts, logs, IoCs) is only logged at DEBUG level — do not set
LOG_LEVEL=DEBUGin production