IntentGuard
Agentic AI reverse engineering and semantic intent security platform
IntentGuard is a multi-agent security framework designed to perform automated static inspection and reverse engineering on agentic AI skills, repositories, and Model Context Protocol (MCP) tool definitions. By orchestrating deterministic Abstract Syntax Tree (AST) tracing with LLM-driven semantic analysis, it bridges the gap between raw code and human understanding — exposing the true intent of AI agents for both technical and non-technical users.
Table of contents
- Architecture
- Vulnerability coverage
- Prerequisites
- Setup
- Running
- Project structure
- API endpoints
- Environment variables
- License
Architecture
┌─────────────────────────────────────┐
│ IntentGuard Orchestrator │
│ (Pipeline & Risk Scoring Core) │
└────────────┬────────────────────────┘
│
┌─────────────────────┴──────────────────────┐
│ STATIC TRACK │ DYNAMIC TRACK
▼ ▼
AST & Dataflow Tracer Sandbox Runner
· Parses .md/Python/JSON/manifests · Dry-runs agent logic
· Builds deterministic syntax tree · Injects adversarial inputs
· Maps data origins to destinations · Identifies runtime-only bugs
· Pushes topology to Neo4j graph · Runs in isolated Docker container
Semantic Intent Analyzer
· LLM reads Neo4j graph data
· Deduces combined behavioral intent
(e.g., benign read + external tool call)
OWASP Mapper
· Classifies semantic findings against
OWASP Agentic Top 10 standard taxonomy
Data flow
Target Input (GitHub Repo URL / .md Skill File)
→ Ingestion Agent → Normalized workspace representation
→ AST & Dataflow Tracer → Graph nodes/edges injected into Neo4j
→ Semantic Analyzer → Intent descriptions and confidence scores
→ OWASP Mapper → Standardized vulnerability classifications
→ Sandbox Runner → Runtime anomaly logs (e.g., retry loops)
→ Risk Orchestrator → Aggregated Risk Score + JSON "Nutrition Label"
→ Flask API + React UI → Visual Graph Topology & Non-Tech Summary Views
Semantic intent analysis — how it works
Because traditional antivirus relies on static signatures, it fails against dynamic, prompt-driven AI skills. IntentGuard uses semantic reverse engineering as its primary detection mechanism:
trace_dataflow()— The AST Tracer deterministically maps the flow of data. If an agent reads a local system file and later passes that variable to an LLM prompt which triggers an externalrequests.post(), this path is mapped in Neo4j.evaluate_intent()— The LLM core is fed this specific path. It is asked to determine the combined goal of these operations. Instead of flagging syntax, it flags the behavior (e.g., "Unauthorized Data Exfiltration").map_to_taxonomy()— The finding is tagged with an OWASP Agentic Top 10 label and routed to the UI. The frontend visualizes this exact path in the Graph Topology view, allowing developers to see the exact chain of events.
Vulnerability coverage
| Type | Detection method |
|---|---|
| Prompt injection | Semantic Analyzer + Sandbox Runner |
| Unauthorized tool usage | AST Tracer + Semantic Analyzer |
| Data exfiltration | Graph Topology Dataflow + LLM |
| Destructive retry loops | Sandbox Runner (dynamic analysis) |
| Insecure output handling | Semantic Analyzer |
| API rate-limit abuse | Sandbox Runner |
Supply chain / malicious .md |
Ingestion Agent + AST Tracer |
| Over-privileged agent scope | Static Parsing + Semantic Analyzer |
Prerequisites
- Python 3.10+
- Docker — for Neo4j, MongoDB, and the execution sandbox
- Node.js 18+ — for the React frontend
- An LLM API key from one provider: OpenAI (
OPENAI_API_KEY) or Anthropic Claude (ANTHROPIC_API_KEY), selected withLLM_PROVIDER(see Environment variables)
Setup
# 1. Clone the repo
git clone https://github.com/your-org/intent-guard
cd intent-guard
# 2. Install backend dependencies
pip install -r requirements.txt
# 3. Configure environment
cp .env.example .env
# Edit .env — set LLM_PROVIDER and the matching API key (OpenAI or Anthropic),
# plus database URIs (see Environment Variables below)
# 4. Start Neo4j and MongoDB
docker-compose up -d db-neo4j db-mongo
# 5. Build the Sandbox Docker image
docker build -t intentguard-sandbox -f sandbox.Dockerfile .
Running
Backend (Flask API)
python run_server.py --host 0.0.0.0 --port 5000
Frontend (React / Tailwind)
cd frontend
npm install
npm start
# → http://localhost:3000
The frontend proxies /api/* to http://localhost:5000.
Demo (mock dashboard)
The repository includes a static preview of the IntentGuard UI (no API keys or databases). The demo app starts with an interactive mock pipeline (ingestion → AST → Neo4j → LLM → MongoDB → UI) that emits a fake Scan ID and then loads the mock dashboard. See demo/README.md: npm install && npm run dev in demo/ui, and npm test for Vitest coverage of the mock pipeline.
CLI (no frontend)
# Scan a public GitHub repository
python main.py scan https://github.com/user/agent-repo
# Scan a local skill file
python main.py scan ./skills/research_agent.md
# Quick smoke scan using bundled demo samples (see demo/README.md)
python main.py scan ./demo/sample_skill.md
Project structure
intent-guard/
├── .env.example # Sample configuration (copy to .env; never commit secrets)
├── LICENSE
├── README.md
├── requirements.txt # Python dependencies (Flask, drivers, OpenAI & Anthropic SDKs)
├── docker-compose.yml # Neo4j, MongoDB, and optional local service wiring
├── sandbox.Dockerfile # Image built as intentguard-sandbox for dynamic analysis
├── run_server.py # Flask API entry point (`python run_server.py …`)
├── main.py # CLI entry point (`python main.py scan …`)
├── config.py # Settings, .env loader, LLM provider selection
│
├── api/ # Flask application package
│ ├── __init__.py
│ ├── app.py # Application factory / extensions
│ └── routes.py # REST endpoints (`/api/scans`, …)
│
├── engine/ # Core analysis pipeline
│ ├── __init__.py
│ ├── orchestrator.py # Pipeline coordinator and risk aggregation
│ ├── agents/
│ │ ├── ingestion.py # Input normalization (repo URL, skill files, MCP JSON)
│ │ ├── ast_tracer.py # Deterministic parsing and graph construction
│ │ ├── semantic.py # LLM intent analysis (uses engine/llm clients)
│ │ ├── owasp.py # OWASP Agentic Top 10 mapping
│ │ └── sandbox.py # Dynamic dry-run execution in Docker
│ ├── database/
│ │ ├── neo4j_client.py # Graph read/write for topology
│ │ └── mongo_client.py # Persisted scan reports and metadata
│ ├── agent_runtime/ # LangGraph scan pipeline + LangSmith tracing hooks
│ │ ├── tracing.py # LANGCHAIN_* / LangSmith env wiring
│ │ ├── langchain_llm.py # ChatOpenAI / ChatAnthropic via Helicone when configured
│ │ └── scan_graph.py # Static semantic node (cache-friendly) → optional dynamic log merge
│ └── llm/ # Chat completions: OpenAI and Anthropic Claude
│ ├── __init__.py
│ ├── base.py # Shared protocol / response normalization
│ ├── helicone.py # Helicone-Auth / cache / property headers
│ ├── openai_client.py # OpenAI-compatible chat API
│ └── anthropic_client.py # Messages API (Claude)
│
├── prompts/ # Prompt templates for the Semantic Engine
│ └── intent_analysis.md
│
├── schemas/ # Pydantic (or similar) models shared across API and engine
│ ├── graph_nodes.py
│ └── report_schema.py # "Nutrition Label" JSON shape
│
├── tests/ # pytest: unit and integration tests
│ ├── conftest.py
│ └── test_orchestrator.py
│
├── demo/ # Bundled samples + interactive UI preview (no backend required)
│ ├── README.md # How to run the mock dashboard and where mock data lives
│ ├── mock/scan-preview.json # Shared JSON model for the demo UI (risk, graph, OWASP, code)
│ ├── sample_skill.md # Tiny agent skill file for future `main.py scan` smoke tests
│ ├── sample_mcp_tools.json # Example MCP-style tool definitions for ingestion tests
│ ├── samples/ # Example `.py` / `.md` snippets aligned with the UI storyboard
│ └── ui/ # Vite + React + Tailwind demo app (`npm install && npm run dev`)
│
└── frontend/ # React + Tailwind dashboard
├── package.json
├── public/
│ └── index.html
├── tailwind.config.js
└── src/
├── App.jsx
├── index.js
├── setupProxy.js # Dev-only: proxy /api → Flask (localhost:5000)
├── components/
│ ├── NutritionLabel.jsx # Non-technical summary view
│ └── TopologyGraph.jsx # Cytoscape / D3 graph view
├── pages/
│ ├── Dashboard.jsx
│ └── ScanDetails.jsx
└── utils/
└── api.js # fetch helpers for `/api/*`
API endpoints
| Method | Path | Description |
|---|---|---|
POST |
/api/scans |
Submit a target (URL/file). JSON body may include optional dynamic_logs (string or JSON) for LangGraph dynamic merge after static analysis |
GET |
/api/scans |
List historical scan reports |
GET |
/api/scans/{id}/report |
Retrieve the structured JSON "Nutrition Label" |
GET |
/api/scans/{id}/topology |
Retrieve the Neo4j node/edge data for frontend visualization |
GET |
/api/scans/{id}/telemetry |
Return ready-made LangSmith / Helicone deep-link URLs for this scan (based on scan metadata) |
Environment variables
IntentGuard’s Semantic Intent Analyzer talks to either the OpenAI API or the Anthropic Messages API (Claude). Set LLM_PROVIDER to choose which client config.py / engine/llm loads, and provide the matching secret.
| Variable | Default | Description |
|---|---|---|
LLM_PROVIDER |
openai |
openai or anthropic — which vendor backs semantic analysis |
OPENAI_API_KEY |
— | Required when LLM_PROVIDER=openai |
ANTHROPIC_API_KEY |
— | Required when LLM_PROVIDER=anthropic |
LLM_MODEL |
(provider default) | Chat model id for the active provider (e.g. OpenAI gpt-4o, Anthropic claude-sonnet-4-20250514) |
NEO4J_URI |
bolt://localhost:7687 |
Connection string for the graph database |
NEO4J_USER |
neo4j |
Neo4j username |
NEO4J_PASSWORD |
password |
Neo4j password |
MONGO_URI |
mongodb://localhost:27017 |
Connection string for the document database |
SANDBOX_IMAGE |
intentguard-sandbox |
Docker image name for dynamic analysis |
SANDBOX_TIMEOUT |
45 |
Execution timeout for the dry-run in seconds |
SANDBOX_NETWORK_NONE |
true |
Adds --network none to sandbox dry-runs (recommended for untrusted third-party agent repos) |
LOG_LEVEL |
INFO |
Logging verbosity (DEBUG, INFO, WARNING, ERROR) |
MONGO_DB |
intentguard |
MongoDB database name for scan documents |
LANGCHAIN_TRACING_V2 |
false |
Set true to send LangGraph / LangChain traces to LangSmith |
LANGCHAIN_API_KEY |
— | LangSmith API key (required when tracing is enabled) |
LANGCHAIN_PROJECT |
intent-guard |
LangSmith project name |
LANGSMITH_BASE_URL |
https://smith.langchain.com |
Base URL for LangSmith deep-link generation |
HELICONE_API_KEY |
— | Optional Helicone key; when set, OpenAI/Anthropic SDKs and LangGraph LLM steps use the Helicone gateway |
HELICONE_CACHE_ENABLED |
true |
When using Helicone, enable response caching (strongest on identical static prompts) |
HELICONE_APP_URL |
https://app.helicone.ai |
Base URL for Helicone deep-link generation |
USE_LANGGRAPH_RUNTIME |
true |
Use LangGraph for semantic analysis (static pass + optional dynamic log node); set false to force the legacy single-call path |
Real-world test targets
Suggested scan targets to stress the parser and semantic mapper:
https://github.com/modelcontextprotocol/servershttps://github.com/Significant-Gravitas/AutoGPThttps://github.com/openai/swarm./demo/samples/devops_troubleshooter.md(intentional exfiltration-like honeypot)
If you want dynamic behavior checks, post a dynamic_logs payload with POST /api/scans:
{
"target": "./demo/samples/devops_troubleshooter.md",
"dynamic_logs": [
{"ts":"2026-04-21T10:00:00Z","tool":"fetch_env_vars","keys":["AWS_ACCESS_KEY_ID","DATABASE_URL"]},
{"ts":"2026-04-21T10:00:03Z","tool":"post_to_dashboard","url":"https://api.external-monitoring-dashboard.com/alerts/critical"}
]
}
With LANGCHAIN_TRACING_V2=true, these semantic calls are traceable in LangSmith.
With HELICONE_API_KEY set, LLM traffic flows through the Helicone gateway with scan metadata (Helicone-Property-ScanId, Helicone-Property-Target) and static-cache properties.
License
MIT
Built With
- css
- dockerfile
- html
- javascript
- python
Log in or sign up for Devpost to join the conversation.