A personal, Information Security-focused multi-agent AI platform built on LangChain and LangGraph. A Supervisor agent autonomously routes tasks to a team of specialist sub-agents equipped with InfoSec tools, surfacing results through a cyberpunk React UI or a terminal TUI.
- SOC agent team — 14 config-driven agents covering incident investigation, threat intelligence, vulnerability management, compliance, and KQL analytics
- Hierarchical specialist pattern — agents call other agents as tools; the full call chain is visualised in real time
- Azure Sentinel integration — KQL specialist queries a connected Log Analytics workspace, with a self-improving knowledge base of working queries
- Automatic tool discovery — agents are injected with a live tool catalogue at runtime; adding a new tool to a group requires no YAML or prompt edits
- Full conversation transparency — every agent prompt and response is shown inline as collapsible handoff/response blocks
- Multi-provider LLM support — Azure OpenAI, Anthropic Claude, Ollama (local/cloud), LM Studio; switch via
config.yaml - React frontend — live animated node graph (React Flow) showing real-time agent and tool data flow, multi-session tabs, cyberpunk dark theme, command palette
- Stop button — cancel a running task and return all agents to idle with a single click
- Textual TUI — full-featured terminal interface with split-pane layout and colour-coded agent status
- Structured logging — per-agent and per-API log files in JSON format, rotating at 10 MB
- Session persistence — SQLite-backed sessions with 7-day auto-pruning
| Agent | Purpose |
|---|---|
security_incident_manager_agent |
End-to-end incident investigation — retrieves Sentinel data, coordinates domain analysts, synthesises report |
security_threat_intel_agent |
OSINT enrichment of IPs, domains, hashes, and URLs via AbuseIPDB, VirusTotal, AlienVault OTX |
security_vulnerability_manager_agent |
Prioritised vulnerability reports from Qualys (Sentinel) + NVD CVE data |
security_compliance_manager_agent |
Security posture assessment against NIST CSF 2.0 and ISO 27001 Annex A |
| Agent | Focus |
|---|---|
security_incident_planner_agent |
Analyses incident context and entity list; produces a structured investigation plan specifying which analysts to engage and what each should focus on. Called before the coordinator. |
security_investigation_coordinator_agent |
Receives the approved plan from the incident manager; dispatches domain analysts in two phases and consolidates their findings |
security_investigation_network_analyst |
Firewall, proxy, DNS logs (Palo Alto, Check Point, Zscaler, BlueCat, CEF) |
security_investigation_identity_analyst |
Entra ID sign-ins, UEBA anomalies, MFA fatigue, admin changes |
security_investigation_endpoint_analyst |
Windows Security Events, MDE/XDR device telemetry |
security_investigation_m365_analyst |
Exchange, SharePoint, OneDrive, Teams, Entra ID — BEC, exfiltration, OAuth abuse detection |
security_investigation_threat_intel_analyst |
IOC enrichment during active investigations |
| Agent | Purpose |
|---|---|
kql_agent |
Translates natural language to KQL, executes against Azure Log Analytics, maintains query knowledge base |
log_analytics_agent |
Schema reference for all workspace tables, loaded from knowledge/sentineltables.yaml |
Tools are organised into named groups in core/tool_registry.py. Agents reference a group name in their YAML rather than individual tool names — adding a tool to a group makes it available to every agent using that group automatically.
| Group | Tools |
|---|---|
threat_intel |
ip_reputation, domain_whois, virustotal_lookup, alienvault_lookup |
kql |
run_kql_query, recall_kql, save_kql, list_sentinel_tables |
cve |
cve_lookup, cvss_scoring |
monitoring |
ioc_extractor, log_pattern_analyser |
At runtime, each agent's system prompt is automatically extended with an == AVAILABLE TOOLS == section listing every tool it has access to, built from the tool's own docstring. The agent always has an accurate, up-to-date tool reference without manual prompt maintenance.
┌──────────────────────────────────────────────────────┐
│ React Frontend │
│ Node graph · Tool nodes · Multi-session tabs │
└────────────────────────┬─────────────────────────────┘
│ WebSocket / REST
┌────────────────────────▼─────────────────────────────┐
│ FastAPI Backend │
│ POST /tasks · POST /tasks/{id}/cancel │
│ GET /sessions · WS /ws/{id} · GET /health │
└────────────────────────┬─────────────────────────────┘
│
┌────────────────────────▼─────────────────────────────┐
│ Supervisor │
│ LLM-based routing · parallel dispatch │
└──────┬────────────┬──────────────┬───────────────────┘
│ │ │
Incident Threat Vulnerability /
Manager Intel Compliance
│
├── kql_agent (Sentinel queries)
├── Investigation Planner (plan only — no tool calls)
└── Investigation Coordinator (executes approved plan)
├── Network Analyst → kql_agent
├── Identity Analyst → kql_agent
├── Endpoint Analyst → kql_agent
├── Email Analyst → kql_agent
└── Threat Intel Analyst (AbuseIPDB · VT · OTX)
All agent→agent calls, tool invocations, prompts, and responses are streamed to the frontend via WebSocket. The node graph shows agents (blue/green/yellow/red), live tool nodes (amber), and infrastructure nodes (LLM provider, Internet) with animated edges colour-coded by state.
Edge colours:
- Green — agent actively processing or returning a result
- Yellow — agent waiting for a specialist sub-agent response
- Amber — agent calling an external tool
MyClaw/
├── agents/ # Agent YAML config files (add new agents here)
│ ├── supervisor.yaml
│ ├── kql_agent.yaml
│ ├── log_analytics_agent.yaml
│ ├── security_incident_manager_agent.yaml
│ ├── security_incident_planner_agent.yaml
│ ├── security_investigation_coordinator_agent.yaml
│ ├── security_investigation_network_analyst.yaml
│ ├── security_investigation_identity_analyst.yaml
│ ├── security_investigation_endpoint_analyst.yaml
│ ├── security_investigation_m365_analyst.yaml
│ ├── security_investigation_threat_intel_analyst.yaml
│ ├── security_threat_intel_agent.yaml
│ ├── security_vulnerability_manager_agent.yaml
│ └── security_compliance_manager_agent.yaml
├── api/ # FastAPI backend
│ ├── main.py # App factory, /health, /knowledge endpoints
│ └── routes/
│ ├── tasks.py # POST /tasks · POST /tasks/{id}/cancel
│ ├── sessions.py # GET/DELETE /sessions
│ └── ws.py # WebSocket /ws/{session_id}
├── core/ # Shared Python library
│ ├── config.py # Pydantic AppConfig loader
│ ├── logging.py # Structured JSON logging
│ ├── agent_config.py # Agent YAML schema + registry loader
│ ├── base_agent.py # LangGraph ReAct agent wrapper + specialist pattern
│ ├── supervisor.py # LLM-based task router
│ ├── event_bus.py # Async pub/sub with buffering for late subscribers
│ ├── tool_registry.py # TOOL_GROUPS · BaseTool registry · group resolution
│ ├── llm_provider.py # Multi-provider LLM abstraction
│ ├── session_store.py # SQLite session persistence
│ ├── kql_knowledge.py # SQLite KQL query knowledge base
│ └── tools/ # One file per tool action
│ ├── ip_reputation.py # AbuseIPDB IP abuse confidence lookup
│ ├── domain_whois.py # WHOIS domain registration details
│ ├── virustotal_lookup.py # VirusTotal multi-indicator scan
│ ├── alienvault_lookup.py # AlienVault OTX threat pulse lookup
│ ├── cve_lookup.py # NVD CVE search by ID or keyword
│ ├── cvss_scoring.py # Full CVSS v3 breakdown for a CVE
│ ├── ioc_extractor.py # Regex IOC extraction (IPs, domains, hashes, URLs)
│ ├── log_pattern_analyser.py # LLM-powered log anomaly analysis
│ ├── run_kql_query.py # Execute KQL against Log Analytics
│ ├── recall_kql.py # Semantic search of KQL knowledge base
│ ├── save_kql.py # Persist validated KQL queries to knowledge base
│ └── list_sentinel_tables.py # Categorised Sentinel table catalogue
├── knowledge/
│ ├── sentineltables.yaml # Workspace table reference (categories, descriptions)
│ └── kql_knowledge.db # Auto-created SQLite store of working KQL queries
├── frontend/ # React + Vite + TypeScript
│ └── src/
│ ├── App.tsx
│ ├── components/
│ │ ├── AgentGraph.tsx # React Flow canvas
│ │ ├── AgentNode.tsx # Per-agent status node (idle/thinking/waiting/done/error)
│ │ ├── ToolNode.tsx # Live tool invocation node (per tool call)
│ │ ├── AnimatedEdge.tsx # Green/yellow/amber animated edge
│ │ ├── InternetNode.tsx # Spinning globe infrastructure node
│ │ ├── LLMNode.tsx # Provider node with active-agent display
│ │ ├── SidePanel.tsx # Conversation + handoff/response blocks
│ │ ├── SessionTabs.tsx # Multi-session tab bar
│ │ └── TaskInput.tsx # Input · command palette · Stop button
│ ├── hooks/
│ │ └── useAgentSocket.ts # WebSocket event subscriber
│ ├── store/
│ │ └── sessionStore.ts # Zustand state (sessions, messages, graph nodes)
│ └── styles/theme.css # Cyberpunk CSS variables
├── tui/ # Textual TUI
│ ├── app.py
│ ├── client.py # httpx + websockets API client
│ ├── main.py
│ └── widgets/
│ ├── chat_output.py
│ ├── agent_status.py
│ └── task_input.py # Command picker with /commands
├── sessions/ # SQLite session database (auto-created)
├── logs/ # Rotating log files (auto-created)
├── config.yaml # Global application settings
├── .env.example # Environment variable template
├── requirements.txt
└── Team.MD # Agent team design document
- Python 3.11+
- Node.js 18+
- One configured LLM provider (see below)
cp .env.example .env
# Edit .env with your provider credentials and API keysSet llm.provider in config.yaml, then fill in the matching .env variables:
| Provider | config.yaml value |
Required .env vars |
|---|---|---|
| Azure OpenAI | azure_openai |
AZURE_OPENAI_API_KEY, AZURE_OPENAI_ENDPOINT, AZURE_OPENAI_DEPLOYMENT, AZURE_OPENAI_API_VERSION |
| Anthropic | anthropic |
ANTHROPIC_API_KEY |
| Ollama (local) | ollama_local |
(none — defaults to http://localhost:11434) |
| LM Studio | lm_studio |
(none — defaults to http://localhost:1234/v1) |
Tools degrade gracefully if a key is absent — they return a clear error rather than crashing.
| Variable | Service | Used by |
|---|---|---|
ABUSEIPDB_API_KEY |
AbuseIPDB | IP reputation |
VIRUSTOTAL_API_KEY |
VirusTotal | File hash / IP / domain / URL analysis |
ALIENVAULT_OTX_API_KEY |
AlienVault OTX | Threat intelligence pulses |
NVD_API_KEY |
NVD | CVE research (higher rate limits) |
Required for KQL-based investigation agents:
| Variable | Purpose |
|---|---|
AZURE_TENANT_ID |
Azure AD tenant |
AZURE_CLIENT_ID |
Service principal client ID |
AZURE_CLIENT_SECRET |
Service principal secret |
AZURE_WORKSPACE_ID |
Log Analytics workspace ID |
pip install -r requirements.txt
uvicorn api.main:app --reload
# API at http://localhost:8000
# Swagger docs at http://localhost:8000/docscd frontend
npm install
npm run dev
# Open http://localhost:5173python -m tui.mainType / in either frontend to open the command palette:
| Command | Action |
|---|---|
/clear |
Clear conversation history |
/agents |
List all available agents and capabilities |
/knowledge |
Show KQL knowledge base summary |
/cve <id> |
CVE research lookup |
/threat <indicator> |
Threat intelligence on an IP, domain, or hash |
/monitor <query> |
Security monitoring / log query |
/exit |
Close the application |
Every agent handoff and response is shown inline in the conversation panel:
| Block | Colour | Content |
|---|---|---|
| HANDOFF | Purple | Collapsible — the exact prompt one agent sent to another |
| RESPONSE | Teal | Collapsible — the exact response an agent returned |
| ASSISTANT | Green bar | Final synthesised output shown in full |
Create a YAML file in agents/:
name: my_analyst_agent
description: >
One-paragraph description used by the supervisor for routing decisions.
system_prompt: >
You are a specialist in X. Follow this workflow: ...
tools:
- threat_intel # use a group name to get all tools in that group
- cve # or mix groups with individual tool names
callable_specialists: []For a specialist agent (called by other agents, hidden from the supervisor):
name: my_specialist_agent
description: >
What this specialist does.
system_prompt: >
You are a specialist in Y...
tools:
- monitoring
callable_specialists:
- kql_agent
extra:
specialist: true # hides from supervisor routingRestart the API server — agents are loaded automatically from the agents/ directory.
- Create
core/tools/my_new_tool.pywith a single@toolfunction and a clear docstring (this becomes the agent's tool reference). - In
core/tool_registry.py:- Import and add it to
register_all_tools() - Add its name to the relevant group in
TOOL_GROUPS
- Import and add it to
That's it. Every agent using that group will automatically receive the new tool and see its description in their system prompt — no YAML edits required.
# core/tool_registry.py
TOOL_GROUPS = {
"threat_intel": ["ip_reputation", "domain_whois", "virustotal_lookup", "alienvault_lookup", "my_new_tool"],
...
}Edit config.yaml for global settings:
llm:
provider: azure_openai # anthropic | ollama_local | ollama_cloud | lm_studio
logging:
level: INFO # DEBUG for verbose output
dir: logs
sessions:
expiry_days: 7
api:
host: 127.0.0.1
port: 8000| Layer | Technology |
|---|---|
| Agent framework | LangChain + LangGraph |
| LLM providers | Azure OpenAI · Anthropic Claude · Ollama · LM Studio |
| API server | FastAPI + uvicorn |
| SIEM integration | Azure Log Analytics REST API (KQL) |
| Session store | SQLite (sqlite3 stdlib) |
| React frontend | Vite + React Flow + Zustand + Tailwind CSS |
| TUI | Textual + Rich |
| Config | Pydantic + PyYAML |
| Threat intel | AbuseIPDB · VirusTotal v3 · AlienVault OTX · python-whois |
| Vulnerability data | Qualys (via Sentinel) · NVD REST API v2 |