Timothy Eastridge commited on
Commit Β·
28e46ad
1
Parent(s): 5d556b0
commit 9
Browse files- .gitignore +2 -0
- Makefile +79 -1
- README.md +266 -47
- agent/Dockerfile +3 -2
- docker-compose.yml +53 -23
- frontend/next-env.d.ts +5 -0
- frontend/tsconfig.json +24 -5
- mcp/Dockerfile +4 -2
- mcp/__pycache__/main.cpython-311.pyc +0 -0
- ops/scripts/seed.py +191 -74
.gitignore
CHANGED
|
@@ -1,3 +1,5 @@
|
|
| 1 |
*.db
|
| 2 |
/graph-agentic-system/neo4j/data
|
| 3 |
/neo4j/data
|
|
|
|
|
|
|
|
|
| 1 |
*.db
|
| 2 |
/graph-agentic-system/neo4j/data
|
| 3 |
/neo4j/data
|
| 4 |
+
/postgres/data
|
| 5 |
+
/neo4j/logs
|
Makefile
CHANGED
|
@@ -1,11 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
| 1 |
up:
|
| 2 |
docker-compose up -d
|
|
|
|
|
|
|
|
|
|
| 3 |
|
|
|
|
| 4 |
down:
|
| 5 |
docker-compose down
|
| 6 |
|
|
|
|
| 7 |
logs:
|
| 8 |
docker-compose logs -f
|
| 9 |
|
|
|
|
| 10 |
seed:
|
| 11 |
-
docker-compose exec mcp python /app/ops/scripts/seed.py
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.PHONY: up down logs seed clean health test demo
|
| 2 |
+
|
| 3 |
+
# Start all services
|
| 4 |
up:
|
| 5 |
docker-compose up -d
|
| 6 |
+
@echo "Waiting for services to be healthy..."
|
| 7 |
+
@sleep 10
|
| 8 |
+
@make health
|
| 9 |
|
| 10 |
+
# Stop all services
|
| 11 |
down:
|
| 12 |
docker-compose down
|
| 13 |
|
| 14 |
+
# View logs
|
| 15 |
logs:
|
| 16 |
docker-compose logs -f
|
| 17 |
|
| 18 |
+
# Seed initial data
|
| 19 |
seed:
|
| 20 |
+
docker-compose exec mcp python /app/ops/scripts/seed.py
|
| 21 |
+
|
| 22 |
+
# Clean everything (including volumes)
|
| 23 |
+
clean:
|
| 24 |
+
docker-compose down -v
|
| 25 |
+
docker system prune -f
|
| 26 |
+
@if [ -d "neo4j/data" ]; then rm -rf neo4j/data; fi
|
| 27 |
+
@if [ -d "postgres/data" ]; then rm -rf postgres/data; fi
|
| 28 |
+
@if [ -d "frontend/.next" ]; then rm -rf frontend/.next; fi
|
| 29 |
+
@if [ -d "frontend/node_modules" ]; then rm -rf frontend/node_modules; fi
|
| 30 |
+
|
| 31 |
+
# Health check all services
|
| 32 |
+
health:
|
| 33 |
+
@echo "Checking service health..."
|
| 34 |
+
@docker-compose exec neo4j cypher-shell -u neo4j -p password "MATCH (n) RETURN count(n) LIMIT 1" > /dev/null 2>&1 && echo "β
Neo4j: Healthy" || echo "β Neo4j: Unhealthy"
|
| 35 |
+
@docker-compose exec postgres pg_isready -U postgres > /dev/null 2>&1 && echo "β
PostgreSQL: Healthy" || echo "β PostgreSQL: Unhealthy"
|
| 36 |
+
@curl -s http://localhost:8000/health > /dev/null && echo "β
MCP Server: Healthy" || echo "β MCP Server: Unhealthy"
|
| 37 |
+
@curl -s http://localhost:3000 > /dev/null && echo "β
Frontend: Healthy" || echo "β Frontend: Unhealthy"
|
| 38 |
+
@docker-compose ps agent | grep -q "Up" && echo "β
Agent: Running" || echo "β Agent: Not running"
|
| 39 |
+
|
| 40 |
+
# Run integration test
|
| 41 |
+
test: health
|
| 42 |
+
@echo "Running integration test..."
|
| 43 |
+
@make seed
|
| 44 |
+
@sleep 5
|
| 45 |
+
@echo "Check http://localhost:3000 and Neo4j Browser at http://localhost:7474"
|
| 46 |
+
|
| 47 |
+
# Demo workflow
|
| 48 |
+
demo:
|
| 49 |
+
@echo "Starting demo workflow..."
|
| 50 |
+
@make clean
|
| 51 |
+
@make up
|
| 52 |
+
@make seed
|
| 53 |
+
@echo ""
|
| 54 |
+
@echo "π Demo Ready!"
|
| 55 |
+
@echo "1. Open http://localhost:3000 in your browser"
|
| 56 |
+
@echo "2. Ask a question like: 'Show me all customers who have placed orders'"
|
| 57 |
+
@echo "3. Watch the agent process through the workflow"
|
| 58 |
+
@echo "4. Check Neo4j Browser at http://localhost:7474 (neo4j/password)"
|
| 59 |
+
@echo ""
|
| 60 |
+
@echo "During 5-minute pauses, you can edit instructions in Neo4j Browser:"
|
| 61 |
+
@echo "MATCH (i:Instruction {status: 'pending'}) SET i.parameters = '{\"question\": \"new question\"}'"
|
| 62 |
+
|
| 63 |
+
# Build all services
|
| 64 |
+
build:
|
| 65 |
+
docker-compose build
|
| 66 |
+
|
| 67 |
+
# Restart specific service
|
| 68 |
+
restart-agent:
|
| 69 |
+
docker-compose restart agent
|
| 70 |
+
|
| 71 |
+
restart-mcp:
|
| 72 |
+
docker-compose restart mcp
|
| 73 |
+
|
| 74 |
+
restart-frontend:
|
| 75 |
+
docker-compose restart frontend
|
| 76 |
+
|
| 77 |
+
# Debug commands
|
| 78 |
+
debug-agent:
|
| 79 |
+
docker-compose logs agent
|
| 80 |
+
|
| 81 |
+
debug-mcp:
|
| 82 |
+
docker-compose logs mcp
|
| 83 |
+
|
| 84 |
+
debug-frontend:
|
| 85 |
+
docker-compose logs frontend
|
| 86 |
+
|
| 87 |
+
# Quick status check
|
| 88 |
+
status:
|
| 89 |
+
docker-compose ps
|
README.md
CHANGED
|
@@ -1,80 +1,299 @@
|
|
| 1 |
-
# Agentic
|
| 2 |
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
## Architecture
|
| 6 |
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
|
| 13 |
## Quick Start
|
| 14 |
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
```bash
|
| 17 |
git clone <repository-url>
|
| 18 |
-
cd
|
| 19 |
cp .env.example .env
|
| 20 |
```
|
| 21 |
|
| 22 |
-
2. **
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
-
|
|
|
|
| 26 |
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
```bash
|
| 29 |
make up
|
| 30 |
```
|
| 31 |
|
| 32 |
-
4. **
|
| 33 |
```bash
|
| 34 |
-
make
|
| 35 |
-
make logs
|
| 36 |
```
|
| 37 |
|
| 38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
|
| 55 |
## Development
|
| 56 |
|
| 57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
```
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
|
|
|
| 67 |
```
|
| 68 |
|
| 69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
|
| 78 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
|
| 80 |
-
|
|
|
|
| 1 |
+
# Graph-Driven Agentic System MVP
|
| 2 |
|
| 3 |
+
## Overview
|
| 4 |
+
An intelligent agent system that reads instructions from Neo4j, queries PostgreSQL databases, pauses for human review, and maintains a complete audit trail. The system demonstrates agentic workflow orchestration with human-in-the-loop controls.
|
| 5 |
+
|
| 6 |
+
## Key Features
|
| 7 |
+
|
| 8 |
+
π€ **Autonomous Agent**: Processes instructions sequentially with configurable pause durations
|
| 9 |
+
π **Graph Database**: All workflow metadata stored in Neo4j for complete traceability
|
| 10 |
+
π **Natural Language SQL**: Converts questions to SQL using LLM integration
|
| 11 |
+
βΈοΈ **Human-in-the-Loop**: 5-minute pauses allow instruction editing during execution
|
| 12 |
+
π― **Single API Gateway**: All Neo4j operations routed through MCP server
|
| 13 |
+
π **Real-time Visualization**: Live workflow progress in browser interface
|
| 14 |
+
π **Complete Audit Trail**: Every action logged with timestamps and relationships
|
| 15 |
|
| 16 |
## Architecture
|
| 17 |
|
| 18 |
+
```
|
| 19 |
+
βββββββββββββββ βββββββββββββββ βββββββββββββββ
|
| 20 |
+
β Frontend ββββββ MCP Server ββββββ Neo4j β
|
| 21 |
+
β (Next.js) β β (FastAPI) β β (Graph) β
|
| 22 |
+
βββββββββββββββ βββββββββββββββ βββββββββββββββ
|
| 23 |
+
β
|
| 24 |
+
βββββββββββββββ βββββββββββββββ
|
| 25 |
+
β Agent ββββββ PostgreSQL β
|
| 26 |
+
β (Python) β β (Data) β
|
| 27 |
+
βββββββββββββββ βββββββββββββββ
|
| 28 |
+
```
|
| 29 |
+
|
| 30 |
+
### Components
|
| 31 |
+
|
| 32 |
+
- **Neo4j**: Graph database storing workflows, instructions, and execution metadata
|
| 33 |
+
- **MCP Server**: Single gateway for all Neo4j operations with parameter fixing
|
| 34 |
+
- **Agent**: Executes instructions with configurable pause periods for human review
|
| 35 |
+
- **PostgreSQL**: Sample data source for testing SQL generation
|
| 36 |
+
- **Frontend**: React/Next.js chat interface with real-time workflow visualization
|
| 37 |
|
| 38 |
## Quick Start
|
| 39 |
|
| 40 |
+
### Prerequisites
|
| 41 |
+
- Docker & Docker Compose
|
| 42 |
+
- OpenAI or Anthropic API key (for LLM integration)
|
| 43 |
+
|
| 44 |
+
### Setup
|
| 45 |
+
1. **Clone and configure**:
|
| 46 |
```bash
|
| 47 |
git clone <repository-url>
|
| 48 |
+
cd <repository-name>
|
| 49 |
cp .env.example .env
|
| 50 |
```
|
| 51 |
|
| 52 |
+
2. **Add your LLM API key** to `.env`:
|
| 53 |
+
```bash
|
| 54 |
+
# For OpenAI
|
| 55 |
+
LLM_API_KEY=sk-your-openai-key-here
|
| 56 |
+
LLM_MODEL=gpt-4
|
| 57 |
|
| 58 |
+
# For Anthropic
|
| 59 |
+
LLM_API_KEY=your-anthropic-key-here
|
| 60 |
+
LLM_MODEL=claude-3-sonnet-20240229
|
| 61 |
+
```
|
| 62 |
+
|
| 63 |
+
3. **Start the system**:
|
| 64 |
```bash
|
| 65 |
make up
|
| 66 |
```
|
| 67 |
|
| 68 |
+
4. **Seed demo data**:
|
| 69 |
```bash
|
| 70 |
+
make seed
|
|
|
|
| 71 |
```
|
| 72 |
|
| 73 |
+
5. **Open the interface**:
|
| 74 |
+
- Frontend: http://localhost:3000
|
| 75 |
+
- Neo4j Browser: http://localhost:7474 (neo4j/password)
|
| 76 |
+
|
| 77 |
+
## Usage
|
| 78 |
+
|
| 79 |
+
### Basic Workflow
|
| 80 |
+
1. **Ask a question** in the chat interface:
|
| 81 |
+
- "How many customers do we have?"
|
| 82 |
+
- "Show me all customers who have placed orders"
|
| 83 |
+
- "What's the total revenue?"
|
| 84 |
+
|
| 85 |
+
2. **Watch the agent process**:
|
| 86 |
+
- Creates workflow with 3 instructions
|
| 87 |
+
- Discovers database schema
|
| 88 |
+
- Generates SQL from your question
|
| 89 |
+
- Reviews and formats results
|
| 90 |
+
|
| 91 |
+
3. **Human intervention** (during 5-minute pauses):
|
| 92 |
+
- Edit instructions in Neo4j Browser
|
| 93 |
+
- Change parameters or questions
|
| 94 |
+
- Stop workflows if needed
|
| 95 |
+
|
| 96 |
+
### Editing Instructions During Pause
|
| 97 |
+
|
| 98 |
+
When the agent pauses, you can modify instructions in Neo4j Browser:
|
| 99 |
+
|
| 100 |
+
```cypher
|
| 101 |
+
// Change the question being asked
|
| 102 |
+
MATCH (i:Instruction {status: 'pending'})
|
| 103 |
+
SET i.parameters = '{"question": "Show me customers from the last month"}'
|
| 104 |
|
| 105 |
+
// Stop the entire workflow
|
| 106 |
+
MATCH (w:Workflow {status: 'active'})
|
| 107 |
+
SET w.status = 'stopped'
|
| 108 |
+
```
|
| 109 |
+
|
| 110 |
+
### Monitoring
|
| 111 |
+
|
| 112 |
+
Check system health:
|
| 113 |
+
```bash
|
| 114 |
+
make health
|
| 115 |
+
```
|
| 116 |
+
|
| 117 |
+
View real-time logs:
|
| 118 |
+
```bash
|
| 119 |
+
make logs
|
| 120 |
+
```
|
| 121 |
+
|
| 122 |
+
Check specific service:
|
| 123 |
+
```bash
|
| 124 |
+
make debug-agent # Agent logs
|
| 125 |
+
make debug-mcp # MCP server logs
|
| 126 |
+
make debug-frontend # Frontend logs
|
| 127 |
+
```
|
| 128 |
+
|
| 129 |
+
## Commands Reference
|
| 130 |
|
| 131 |
+
| Command | Description |
|
| 132 |
+
|---------|-------------|
|
| 133 |
+
| `make up` | Start all services |
|
| 134 |
+
| `make down` | Stop all services |
|
| 135 |
+
| `make clean` | Remove all data and containers |
|
| 136 |
+
| `make health` | Check service health |
|
| 137 |
+
| `make seed` | Create demo data |
|
| 138 |
+
| `make logs` | View all logs |
|
| 139 |
+
| `make demo` | Full clean + setup + seed |
|
| 140 |
+
| `make test` | Run integration test |
|
| 141 |
|
| 142 |
+
## Configuration
|
| 143 |
+
|
| 144 |
+
### Environment Variables
|
| 145 |
+
|
| 146 |
+
All configuration is in `.env` file:
|
| 147 |
+
|
| 148 |
+
- **Neo4j**: Database connection and auth
|
| 149 |
+
- **PostgreSQL**: Sample data source
|
| 150 |
+
- **MCP**: API keys and server settings
|
| 151 |
+
- **Agent**: Polling interval and pause duration
|
| 152 |
+
- **LLM**: API key and model selection
|
| 153 |
+
|
| 154 |
+
### Pause Duration
|
| 155 |
+
|
| 156 |
+
Default: 5 minutes (300 seconds)
|
| 157 |
+
Configurable via `PAUSE_DURATION` in `.env`
|
| 158 |
+
|
| 159 |
+
### Polling Interval
|
| 160 |
+
|
| 161 |
+
Default: 30 seconds
|
| 162 |
+
Configurable via `AGENT_POLL_INTERVAL` in `.env`
|
| 163 |
|
| 164 |
## Development
|
| 165 |
|
| 166 |
+
### File Structure
|
| 167 |
+
```
|
| 168 |
+
βββ agent/ # Python agent that executes instructions
|
| 169 |
+
βββ frontend/ # Next.js chat interface
|
| 170 |
+
βββ mcp/ # FastAPI server for Neo4j operations
|
| 171 |
+
βββ neo4j/ # Neo4j configuration and data
|
| 172 |
+
βββ postgres/ # PostgreSQL setup and sample data
|
| 173 |
+
βββ ops/ # Operational scripts (seeding, etc.)
|
| 174 |
+
βββ docker-compose.yml
|
| 175 |
+
βββ Makefile
|
| 176 |
+
βββ README.md
|
| 177 |
+
```
|
| 178 |
+
|
| 179 |
+
### Adding New Instruction Types
|
| 180 |
+
|
| 181 |
+
1. **Define handler in agent**:
|
| 182 |
+
```python
|
| 183 |
+
def handle_new_instruction_type(instruction):
|
| 184 |
+
# Implementation
|
| 185 |
+
return {"status": "success", "result": "..."}
|
| 186 |
+
```
|
| 187 |
+
|
| 188 |
+
2. **Add to agent main loop**:
|
| 189 |
+
```python
|
| 190 |
+
elif instruction['type'] == 'new_instruction_type':
|
| 191 |
+
exec_result = handle_new_instruction_type(instruction)
|
| 192 |
+
```
|
| 193 |
+
|
| 194 |
+
3. **Update frontend** to create new instruction types in workflows.
|
| 195 |
+
|
| 196 |
+
### Database Schema
|
| 197 |
+
|
| 198 |
+
The system uses two databases:
|
| 199 |
+
|
| 200 |
+
**Neo4j** (Workflow metadata):
|
| 201 |
+
- `Workflow` nodes with status and metadata
|
| 202 |
+
- `Instruction` nodes with type, sequence, parameters
|
| 203 |
+
- `Execution` nodes with results and timestamps
|
| 204 |
+
- Relationships: `HAS_INSTRUCTION`, `EXECUTED_AS`, `NEXT_INSTRUCTION`
|
| 205 |
+
|
| 206 |
+
**PostgreSQL** (Sample data):
|
| 207 |
+
- `customers` table
|
| 208 |
+
- `orders` table
|
| 209 |
+
- Sample data for testing SQL generation
|
| 210 |
+
|
| 211 |
+
## Troubleshooting
|
| 212 |
+
|
| 213 |
+
### Common Issues
|
| 214 |
+
|
| 215 |
+
**Services not starting**:
|
| 216 |
+
```bash
|
| 217 |
+
make down
|
| 218 |
+
make clean
|
| 219 |
+
make up
|
| 220 |
+
```
|
| 221 |
+
|
| 222 |
+
**Agent not processing**:
|
| 223 |
+
```bash
|
| 224 |
+
make restart-agent
|
| 225 |
+
make debug-agent
|
| 226 |
+
```
|
| 227 |
+
|
| 228 |
+
**Frontend not loading**:
|
| 229 |
+
```bash
|
| 230 |
+
make restart-frontend
|
| 231 |
+
make debug-frontend
|
| 232 |
+
```
|
| 233 |
|
| 234 |
+
**Database connection issues**:
|
| 235 |
+
```bash
|
| 236 |
+
make health
|
| 237 |
+
# Check .env configuration
|
| 238 |
```
|
| 239 |
+
|
| 240 |
+
### Debug Mode
|
| 241 |
+
|
| 242 |
+
For detailed logging, check individual service logs:
|
| 243 |
+
```bash
|
| 244 |
+
docker-compose logs -f agent
|
| 245 |
+
docker-compose logs -f mcp
|
| 246 |
+
docker-compose logs -f frontend
|
| 247 |
```
|
| 248 |
|
| 249 |
+
### Reset Everything
|
| 250 |
+
|
| 251 |
+
Complete clean slate:
|
| 252 |
+
```bash
|
| 253 |
+
make clean
|
| 254 |
+
cp .env.example .env
|
| 255 |
+
# Edit .env with your API key
|
| 256 |
+
make demo
|
| 257 |
+
```
|
| 258 |
+
|
| 259 |
+
## Contributing
|
| 260 |
+
|
| 261 |
+
1. Fork the repository
|
| 262 |
+
2. Create a feature branch
|
| 263 |
+
3. Test with `make demo`
|
| 264 |
+
4. Submit a pull request
|
| 265 |
+
|
| 266 |
+
## License
|
| 267 |
|
| 268 |
+
MIT License - see LICENSE file for details.
|
| 269 |
+
|
| 270 |
+
---
|
| 271 |
+
|
| 272 |
+
## Quick Demo
|
| 273 |
+
|
| 274 |
+
Want to see it in action immediately?
|
| 275 |
+
|
| 276 |
+
```bash
|
| 277 |
+
# 1. Clone repo
|
| 278 |
+
git clone <repo-url> && cd <repo-name>
|
| 279 |
+
|
| 280 |
+
# 2. Add your API key
|
| 281 |
+
cp .env.example .env
|
| 282 |
+
# Edit .env: LLM_API_KEY=your-key-here
|
| 283 |
+
|
| 284 |
+
# 3. Start everything
|
| 285 |
+
make demo
|
| 286 |
+
|
| 287 |
+
# 4. Open http://localhost:3000
|
| 288 |
+
# 5. Ask: "How many records are in the database?"
|
| 289 |
+
# 6. Watch the magic happen! β¨
|
| 290 |
+
```
|
| 291 |
|
| 292 |
+
The system will:
|
| 293 |
+
- Create a workflow with 3 instructions
|
| 294 |
+
- Pause for 5 minutes before each step (editable in Neo4j Browser)
|
| 295 |
+
- Generate SQL from your natural language question
|
| 296 |
+
- Execute the query and return formatted results
|
| 297 |
+
- Show the entire process in a visual graph
|
| 298 |
|
| 299 |
+
π **Welcome to the future of human-AI collaboration!**
|
agent/Dockerfile
CHANGED
|
@@ -5,6 +5,7 @@ WORKDIR /app
|
|
| 5 |
COPY requirements.txt .
|
| 6 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 7 |
|
| 8 |
-
COPY
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
| 5 |
COPY requirements.txt .
|
| 6 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 7 |
|
| 8 |
+
COPY . .
|
| 9 |
|
| 10 |
+
# Use unbuffered output to see logs in real-time
|
| 11 |
+
CMD ["python", "-u", "main.py"]
|
docker-compose.yml
CHANGED
|
@@ -4,63 +4,86 @@ services:
|
|
| 4 |
neo4j:
|
| 5 |
build: ./neo4j
|
| 6 |
ports:
|
| 7 |
-
- "7474:7474"
|
| 8 |
-
- "7687:7687"
|
| 9 |
environment:
|
| 10 |
-
- NEO4J_AUTH
|
| 11 |
volumes:
|
| 12 |
- ./neo4j/data:/data
|
|
|
|
| 13 |
healthcheck:
|
| 14 |
test: ["CMD", "cypher-shell", "-u", "neo4j", "-p", "password", "MATCH (n) RETURN count(n) LIMIT 1"]
|
| 15 |
interval: 10s
|
| 16 |
timeout: 5s
|
| 17 |
retries: 5
|
|
|
|
|
|
|
| 18 |
|
| 19 |
postgres:
|
| 20 |
image: postgres:15
|
| 21 |
-
container_name: postgres
|
| 22 |
-
ports:
|
| 23 |
-
- "5432:5432"
|
| 24 |
environment:
|
| 25 |
- POSTGRES_DB=testdb
|
| 26 |
- POSTGRES_USER=postgres
|
| 27 |
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
|
|
|
|
|
|
| 28 |
volumes:
|
| 29 |
-
-
|
| 30 |
- ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
|
| 31 |
healthcheck:
|
| 32 |
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
| 33 |
interval: 10s
|
| 34 |
timeout: 5s
|
| 35 |
retries: 5
|
|
|
|
|
|
|
| 36 |
|
| 37 |
mcp:
|
| 38 |
build: ./mcp
|
| 39 |
-
container_name: mcp
|
| 40 |
ports:
|
| 41 |
- "8000:8000"
|
| 42 |
environment:
|
| 43 |
-
-
|
| 44 |
-
-
|
| 45 |
-
-
|
| 46 |
-
-
|
| 47 |
-
-
|
| 48 |
depends_on:
|
| 49 |
-
|
| 50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
|
| 52 |
agent:
|
| 53 |
build: ./agent
|
| 54 |
-
container_name: agent
|
| 55 |
environment:
|
| 56 |
- MCP_URL=http://mcp:8000/mcp
|
| 57 |
- MCP_API_KEY=dev-key-123
|
| 58 |
-
- AGENT_POLL_INTERVAL=${AGENT_POLL_INTERVAL
|
|
|
|
| 59 |
- LLM_API_KEY=${LLM_API_KEY}
|
| 60 |
-
- LLM_MODEL=${LLM_MODEL
|
|
|
|
| 61 |
depends_on:
|
| 62 |
-
|
| 63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
|
| 65 |
frontend:
|
| 66 |
build: ./frontend
|
|
@@ -70,7 +93,14 @@ services:
|
|
| 70 |
- NEXT_PUBLIC_MCP_URL=http://localhost:8000
|
| 71 |
depends_on:
|
| 72 |
- mcp
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
|
|
|
| 4 |
neo4j:
|
| 5 |
build: ./neo4j
|
| 6 |
ports:
|
| 7 |
+
- "7474:7474"
|
| 8 |
+
- "7687:7687"
|
| 9 |
environment:
|
| 10 |
+
- NEO4J_AUTH=${NEO4J_AUTH}
|
| 11 |
volumes:
|
| 12 |
- ./neo4j/data:/data
|
| 13 |
+
- ./neo4j/logs:/logs
|
| 14 |
healthcheck:
|
| 15 |
test: ["CMD", "cypher-shell", "-u", "neo4j", "-p", "password", "MATCH (n) RETURN count(n) LIMIT 1"]
|
| 16 |
interval: 10s
|
| 17 |
timeout: 5s
|
| 18 |
retries: 5
|
| 19 |
+
networks:
|
| 20 |
+
- agent-network
|
| 21 |
|
| 22 |
postgres:
|
| 23 |
image: postgres:15
|
|
|
|
|
|
|
|
|
|
| 24 |
environment:
|
| 25 |
- POSTGRES_DB=testdb
|
| 26 |
- POSTGRES_USER=postgres
|
| 27 |
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
| 28 |
+
ports:
|
| 29 |
+
- "5432:5432"
|
| 30 |
volumes:
|
| 31 |
+
- ./postgres/data:/var/lib/postgresql/data
|
| 32 |
- ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
|
| 33 |
healthcheck:
|
| 34 |
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
| 35 |
interval: 10s
|
| 36 |
timeout: 5s
|
| 37 |
retries: 5
|
| 38 |
+
networks:
|
| 39 |
+
- agent-network
|
| 40 |
|
| 41 |
mcp:
|
| 42 |
build: ./mcp
|
|
|
|
| 43 |
ports:
|
| 44 |
- "8000:8000"
|
| 45 |
environment:
|
| 46 |
+
- NEO4J_BOLT_URL=${NEO4J_BOLT_URL}
|
| 47 |
+
- NEO4J_AUTH=${NEO4J_AUTH}
|
| 48 |
+
- POSTGRES_CONNECTION=${POSTGRES_CONNECTION}
|
| 49 |
+
- MCP_API_KEYS=${MCP_API_KEYS}
|
| 50 |
+
- MCP_PORT=${MCP_PORT}
|
| 51 |
depends_on:
|
| 52 |
+
neo4j:
|
| 53 |
+
condition: service_healthy
|
| 54 |
+
postgres:
|
| 55 |
+
condition: service_healthy
|
| 56 |
+
volumes:
|
| 57 |
+
- ./mcp:/app
|
| 58 |
+
- ./ops/scripts:/app/ops/scripts
|
| 59 |
+
command: uvicorn main:app --host 0.0.0.0 --port 8000 --reload
|
| 60 |
+
healthcheck:
|
| 61 |
+
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
| 62 |
+
interval: 10s
|
| 63 |
+
timeout: 5s
|
| 64 |
+
retries: 5
|
| 65 |
+
networks:
|
| 66 |
+
- agent-network
|
| 67 |
|
| 68 |
agent:
|
| 69 |
build: ./agent
|
|
|
|
| 70 |
environment:
|
| 71 |
- MCP_URL=http://mcp:8000/mcp
|
| 72 |
- MCP_API_KEY=dev-key-123
|
| 73 |
+
- AGENT_POLL_INTERVAL=${AGENT_POLL_INTERVAL}
|
| 74 |
+
- PAUSE_DURATION=${PAUSE_DURATION}
|
| 75 |
- LLM_API_KEY=${LLM_API_KEY}
|
| 76 |
+
- LLM_MODEL=${LLM_MODEL}
|
| 77 |
+
- POSTGRES_CONNECTION=${POSTGRES_CONNECTION}
|
| 78 |
depends_on:
|
| 79 |
+
mcp:
|
| 80 |
+
condition: service_healthy
|
| 81 |
+
volumes:
|
| 82 |
+
- ./agent:/app
|
| 83 |
+
command: python -u main.py
|
| 84 |
+
restart: unless-stopped
|
| 85 |
+
networks:
|
| 86 |
+
- agent-network
|
| 87 |
|
| 88 |
frontend:
|
| 89 |
build: ./frontend
|
|
|
|
| 93 |
- NEXT_PUBLIC_MCP_URL=http://localhost:8000
|
| 94 |
depends_on:
|
| 95 |
- mcp
|
| 96 |
+
volumes:
|
| 97 |
+
- ./frontend:/app
|
| 98 |
+
- /app/node_modules
|
| 99 |
+
- /app/.next
|
| 100 |
+
command: npm run dev
|
| 101 |
+
networks:
|
| 102 |
+
- agent-network
|
| 103 |
|
| 104 |
+
networks:
|
| 105 |
+
agent-network:
|
| 106 |
+
driver: bridge
|
frontend/next-env.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/// <reference types="next" />
|
| 2 |
+
/// <reference types="next/image-types/global" />
|
| 3 |
+
|
| 4 |
+
// NOTE: This file should not be edited
|
| 5 |
+
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
frontend/tsconfig.json
CHANGED
|
@@ -1,7 +1,11 @@
|
|
| 1 |
{
|
| 2 |
"compilerOptions": {
|
| 3 |
"target": "es5",
|
| 4 |
-
"lib": [
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
"allowJs": true,
|
| 6 |
"skipLibCheck": true,
|
| 7 |
"strict": true,
|
|
@@ -16,9 +20,24 @@
|
|
| 16 |
"incremental": true,
|
| 17 |
"baseUrl": ".",
|
| 18 |
"paths": {
|
| 19 |
-
"@/*": [
|
| 20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
},
|
| 22 |
-
"include": [
|
| 23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"compilerOptions": {
|
| 3 |
"target": "es5",
|
| 4 |
+
"lib": [
|
| 5 |
+
"dom",
|
| 6 |
+
"dom.iterable",
|
| 7 |
+
"esnext"
|
| 8 |
+
],
|
| 9 |
"allowJs": true,
|
| 10 |
"skipLibCheck": true,
|
| 11 |
"strict": true,
|
|
|
|
| 20 |
"incremental": true,
|
| 21 |
"baseUrl": ".",
|
| 22 |
"paths": {
|
| 23 |
+
"@/*": [
|
| 24 |
+
"./*"
|
| 25 |
+
]
|
| 26 |
+
},
|
| 27 |
+
"plugins": [
|
| 28 |
+
{
|
| 29 |
+
"name": "next"
|
| 30 |
+
}
|
| 31 |
+
]
|
| 32 |
},
|
| 33 |
+
"include": [
|
| 34 |
+
"next-env.d.ts",
|
| 35 |
+
"**/*.ts",
|
| 36 |
+
"**/*.tsx",
|
| 37 |
+
"types/**/*.d.ts",
|
| 38 |
+
".next/types/**/*.ts"
|
| 39 |
+
],
|
| 40 |
+
"exclude": [
|
| 41 |
+
"node_modules"
|
| 42 |
+
]
|
| 43 |
}
|
mcp/Dockerfile
CHANGED
|
@@ -2,11 +2,13 @@ FROM python:3.11-slim
|
|
| 2 |
|
| 3 |
WORKDIR /app
|
| 4 |
|
|
|
|
|
|
|
|
|
|
| 5 |
COPY requirements.txt .
|
| 6 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 7 |
|
| 8 |
COPY . .
|
| 9 |
|
| 10 |
EXPOSE 8000
|
| 11 |
-
|
| 12 |
-
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
|
|
|
| 2 |
|
| 3 |
WORKDIR /app
|
| 4 |
|
| 5 |
+
# Install curl for healthcheck
|
| 6 |
+
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
|
| 7 |
+
|
| 8 |
COPY requirements.txt .
|
| 9 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 10 |
|
| 11 |
COPY . .
|
| 12 |
|
| 13 |
EXPOSE 8000
|
| 14 |
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
|
|
mcp/__pycache__/main.cpython-311.pyc
ADDED
|
Binary file (10.3 kB). View file
|
|
|
ops/scripts/seed.py
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import requests
|
| 2 |
import json
|
|
|
|
|
|
|
| 3 |
|
| 4 |
-
|
| 5 |
-
|
|
|
|
| 6 |
|
| 7 |
def call_mcp(tool, params=None):
|
|
|
|
| 8 |
response = requests.post(
|
| 9 |
MCP_URL,
|
| 10 |
headers={"X-API-Key": API_KEY, "Content-Type": "application/json"},
|
|
@@ -12,83 +22,190 @@ def call_mcp(tool, params=None):
|
|
| 12 |
)
|
| 13 |
return response.json()
|
| 14 |
|
| 15 |
-
|
| 16 |
-
workflow
|
| 17 |
-
"
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
"name": "Entity Resolution Demo",
|
| 22 |
-
"status": "active",
|
| 23 |
-
"max_iterations": 10,
|
| 24 |
-
"current_iteration": 0
|
| 25 |
-
}
|
| 26 |
-
})
|
| 27 |
-
print(f"Created workflow: {workflow}")
|
| 28 |
-
|
| 29 |
-
# Create three instructions
|
| 30 |
-
instructions = [
|
| 31 |
-
{
|
| 32 |
-
"id": "inst-1",
|
| 33 |
-
"sequence": 1,
|
| 34 |
-
"type": "discover_schema",
|
| 35 |
-
"status": "pending",
|
| 36 |
-
"pause_duration": 300,
|
| 37 |
-
"parameters": "{}"
|
| 38 |
-
},
|
| 39 |
-
{
|
| 40 |
-
"id": "inst-2",
|
| 41 |
-
"sequence": 2,
|
| 42 |
-
"type": "generate_sql",
|
| 43 |
-
"status": "pending",
|
| 44 |
-
"pause_duration": 300,
|
| 45 |
-
"parameters": json.dumps({"question": "Show all customers who have placed orders"})
|
| 46 |
-
},
|
| 47 |
-
{
|
| 48 |
-
"id": "inst-3",
|
| 49 |
-
"sequence": 3,
|
| 50 |
-
"type": "review_results",
|
| 51 |
-
"status": "pending",
|
| 52 |
-
"pause_duration": 300,
|
| 53 |
-
"parameters": "{}"
|
| 54 |
-
}
|
| 55 |
-
]
|
| 56 |
-
|
| 57 |
-
for inst in instructions:
|
| 58 |
-
result = call_mcp("write_graph", {
|
| 59 |
"action": "create_node",
|
| 60 |
-
"label": "
|
| 61 |
-
"properties":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
})
|
| 63 |
-
print(f"Created instruction: {inst['id']}")
|
| 64 |
|
| 65 |
-
|
| 66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
"query": """
|
| 68 |
-
MATCH (w:Workflow {id:
|
| 69 |
-
|
| 70 |
""",
|
| 71 |
-
"parameters": {
|
| 72 |
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
}
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
|
| 94 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Seed script to create demo data for the agentic system.
|
| 4 |
+
Creates a sample workflow with instructions for testing.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
import requests
|
| 8 |
import json
|
| 9 |
+
import time
|
| 10 |
+
import os
|
| 11 |
|
| 12 |
+
# Configuration
|
| 13 |
+
MCP_URL = os.getenv("MCP_URL", "http://localhost:8000/mcp")
|
| 14 |
+
API_KEY = os.getenv("MCP_API_KEY", "dev-key-123")
|
| 15 |
|
| 16 |
def call_mcp(tool, params=None):
|
| 17 |
+
"""Call the MCP API"""
|
| 18 |
response = requests.post(
|
| 19 |
MCP_URL,
|
| 20 |
headers={"X-API-Key": API_KEY, "Content-Type": "application/json"},
|
|
|
|
| 22 |
)
|
| 23 |
return response.json()
|
| 24 |
|
| 25 |
+
def create_demo_workflow():
|
| 26 |
+
"""Create a demo workflow for testing"""
|
| 27 |
+
print("π± Seeding demo data...")
|
| 28 |
+
|
| 29 |
+
# Create demo workflow
|
| 30 |
+
workflow_result = call_mcp("write_graph", {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
"action": "create_node",
|
| 32 |
+
"label": "Workflow",
|
| 33 |
+
"properties": {
|
| 34 |
+
"id": "demo-workflow-1",
|
| 35 |
+
"name": "Entity Resolution Demo",
|
| 36 |
+
"description": "Demo workflow showing SQL generation and execution",
|
| 37 |
+
"status": "active",
|
| 38 |
+
"created_at": time.strftime("%Y-%m-%dT%H:%M:%SZ")
|
| 39 |
+
}
|
| 40 |
})
|
|
|
|
| 41 |
|
| 42 |
+
if 'created' not in workflow_result:
|
| 43 |
+
print(f"β Failed to create workflow: {workflow_result}")
|
| 44 |
+
return False
|
| 45 |
+
|
| 46 |
+
print("β
Created demo workflow")
|
| 47 |
+
|
| 48 |
+
# Create demo instructions
|
| 49 |
+
instructions = [
|
| 50 |
+
{
|
| 51 |
+
"id": "demo-inst-1",
|
| 52 |
+
"type": "discover_schema",
|
| 53 |
+
"sequence": 1,
|
| 54 |
+
"description": "Discover database schema",
|
| 55 |
+
"parameters": "{}"
|
| 56 |
+
},
|
| 57 |
+
{
|
| 58 |
+
"id": "demo-inst-2",
|
| 59 |
+
"type": "generate_sql",
|
| 60 |
+
"sequence": 2,
|
| 61 |
+
"description": "Generate SQL for customer orders",
|
| 62 |
+
"parameters": json.dumps({
|
| 63 |
+
"question": "Show me all customers who have placed orders, including their order details"
|
| 64 |
+
})
|
| 65 |
+
},
|
| 66 |
+
{
|
| 67 |
+
"id": "demo-inst-3",
|
| 68 |
+
"type": "review_results",
|
| 69 |
+
"sequence": 3,
|
| 70 |
+
"description": "Review and format results",
|
| 71 |
+
"parameters": "{}"
|
| 72 |
+
}
|
| 73 |
+
]
|
| 74 |
+
|
| 75 |
+
for inst in instructions:
|
| 76 |
+
inst_result = call_mcp("write_graph", {
|
| 77 |
+
"action": "create_node",
|
| 78 |
+
"label": "Instruction",
|
| 79 |
+
"properties": {
|
| 80 |
+
"id": inst["id"],
|
| 81 |
+
"type": inst["type"],
|
| 82 |
+
"sequence": inst["sequence"],
|
| 83 |
+
"description": inst["description"],
|
| 84 |
+
"status": "pending",
|
| 85 |
+
"pause_duration": 300, # 5 minutes
|
| 86 |
+
"parameters": inst["parameters"],
|
| 87 |
+
"created_at": time.strftime("%Y-%m-%dT%H:%M:%SZ")
|
| 88 |
+
}
|
| 89 |
+
})
|
| 90 |
+
|
| 91 |
+
if 'created' not in inst_result:
|
| 92 |
+
print(f"β Failed to create instruction {inst['id']}: {inst_result}")
|
| 93 |
+
continue
|
| 94 |
+
|
| 95 |
+
# Link instruction to workflow
|
| 96 |
+
link_result = call_mcp("query_graph", {
|
| 97 |
+
"query": "MATCH (w:Workflow), (i:Instruction) WHERE w.id = wid AND i.id = iid CREATE (w)-[:HAS_INSTRUCTION]->(i)",
|
| 98 |
+
"parameters": {"wid": "demo-workflow-1", "iid": inst["id"]}
|
| 99 |
+
})
|
| 100 |
+
|
| 101 |
+
print(f"β
Created instruction: {inst['type']}")
|
| 102 |
+
|
| 103 |
+
# Create instruction chain
|
| 104 |
+
for i in range(len(instructions) - 1):
|
| 105 |
+
current_id = instructions[i]["id"]
|
| 106 |
+
next_id = instructions[i + 1]["id"]
|
| 107 |
+
|
| 108 |
+
chain_result = call_mcp("query_graph", {
|
| 109 |
+
"query": "MATCH (i1:Instruction), (i2:Instruction) WHERE i1.id = id1 AND i2.id = id2 CREATE (i1)-[:NEXT_INSTRUCTION]->(i2)",
|
| 110 |
+
"parameters": {"id1": current_id, "id2": next_id}
|
| 111 |
+
})
|
| 112 |
+
|
| 113 |
+
print("β
Created instruction chain")
|
| 114 |
+
|
| 115 |
+
# Create query templates for demo
|
| 116 |
+
templates = [
|
| 117 |
+
{
|
| 118 |
+
"id": "template-1",
|
| 119 |
+
"question": "How many customers do we have?",
|
| 120 |
+
"query": "SELECT COUNT(*) as customer_count FROM customers"
|
| 121 |
+
},
|
| 122 |
+
{
|
| 123 |
+
"id": "template-2",
|
| 124 |
+
"question": "Show me recent orders",
|
| 125 |
+
"query": "SELECT o.id, o.order_date, c.name FROM orders o JOIN customers c ON o.customer_id = c.id ORDER BY o.order_date DESC LIMIT 10"
|
| 126 |
+
},
|
| 127 |
+
{
|
| 128 |
+
"id": "template-3",
|
| 129 |
+
"question": "What's the total revenue?",
|
| 130 |
+
"query": "SELECT SUM(total_amount) as total_revenue FROM orders"
|
| 131 |
+
}
|
| 132 |
+
]
|
| 133 |
+
|
| 134 |
+
for template in templates:
|
| 135 |
+
template_result = call_mcp("write_graph", {
|
| 136 |
+
"action": "create_node",
|
| 137 |
+
"label": "QueryTemplate",
|
| 138 |
+
"properties": {
|
| 139 |
+
"id": template["id"],
|
| 140 |
+
"question": template["question"],
|
| 141 |
+
"query": template["query"],
|
| 142 |
+
"created_at": time.strftime("%Y-%m-%dT%H:%M:%SZ")
|
| 143 |
+
}
|
| 144 |
+
})
|
| 145 |
+
|
| 146 |
+
print("β
Created query templates")
|
| 147 |
+
|
| 148 |
+
# Verify the setup
|
| 149 |
+
verification = call_mcp("query_graph", {
|
| 150 |
"query": """
|
| 151 |
+
MATCH (w:Workflow {id: 'demo-workflow-1'})-[:HAS_INSTRUCTION]->(i:Instruction)
|
| 152 |
+
RETURN w.name, count(i) as instruction_count
|
| 153 |
""",
|
| 154 |
+
"parameters": {}
|
| 155 |
})
|
| 156 |
+
|
| 157 |
+
if verification.get('data'):
|
| 158 |
+
workflow_name = verification['data'][0]['w.name']
|
| 159 |
+
instruction_count = verification['data'][0]['instruction_count']
|
| 160 |
+
print(f"β
Verification: '{workflow_name}' with {instruction_count} instructions")
|
| 161 |
+
|
| 162 |
+
print("π Demo data seeded successfully!")
|
| 163 |
+
print("\nπ Next steps:")
|
| 164 |
+
print("1. Open http://localhost:3000 in your browser")
|
| 165 |
+
print("2. Ask a question like: 'Show me all customers who have placed orders'")
|
| 166 |
+
print("3. Watch the agent process the workflow")
|
| 167 |
+
print("4. During the 5-minute pause, you can edit instructions in Neo4j Browser")
|
| 168 |
+
print("5. Neo4j Browser: http://localhost:7474 (username: neo4j, password: password)")
|
| 169 |
+
|
| 170 |
+
return True
|
| 171 |
|
| 172 |
+
def check_services():
|
| 173 |
+
"""Check if required services are available"""
|
| 174 |
+
try:
|
| 175 |
+
# Check MCP health
|
| 176 |
+
health_response = requests.get(f"{MCP_URL.replace('/mcp', '/health')}", timeout=5)
|
| 177 |
+
if health_response.status_code != 200:
|
| 178 |
+
print("β MCP service not available")
|
| 179 |
+
return False
|
| 180 |
+
|
| 181 |
+
# Check MCP API
|
| 182 |
+
test_response = requests.post(
|
| 183 |
+
MCP_URL,
|
| 184 |
+
headers={"X-API-Key": API_KEY, "Content-Type": "application/json"},
|
| 185 |
+
json={"tool": "get_schema"},
|
| 186 |
+
timeout=5
|
| 187 |
+
)
|
| 188 |
+
if test_response.status_code != 200:
|
| 189 |
+
print("β MCP API not responding")
|
| 190 |
+
return False
|
| 191 |
+
|
| 192 |
+
print("β
Services are available")
|
| 193 |
+
return True
|
| 194 |
+
|
| 195 |
+
except Exception as e:
|
| 196 |
+
print(f"β Service check failed: {e}")
|
| 197 |
+
return False
|
| 198 |
|
| 199 |
+
if __name__ == "__main__":
|
| 200 |
+
print("π Starting seed process...")
|
| 201 |
+
|
| 202 |
+
if not check_services():
|
| 203 |
+
print("β Cannot proceed - services not available")
|
| 204 |
+
exit(1)
|
| 205 |
+
|
| 206 |
+
if create_demo_workflow():
|
| 207 |
+
print("β
Seed completed successfully")
|
| 208 |
+
exit(0)
|
| 209 |
+
else:
|
| 210 |
+
print("β Seed failed")
|
| 211 |
+
exit(1)
|