Timothy Eastridge commited on
Commit
28e46ad
Β·
1 Parent(s): 5d556b0
.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 Knowledge Graph
2
 
3
- A graph-driven agentic system that uses Neo4j as the knowledge graph backend, with MCP server for graph operations, an intelligent agent for workflow execution, and a web interface for interaction.
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  ## Architecture
6
 
7
- - **Neo4j**: Knowledge graph database storing workflows, instructions, and metadata
8
- - **MCP Server**: Single gateway for all Neo4j operations with API key authentication
9
- - **Agent**: Executes workflows by reading instructions from Neo4j and performing actions
10
- - **Frontend**: Next.js web interface for user interaction and monitoring
11
- - **PostgreSQL**: Data source for schema discovery and query execution
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
  ## Quick Start
14
 
15
- 1. **Clone and setup**:
 
 
 
 
 
16
  ```bash
17
  git clone <repository-url>
18
- cd 20250922_agentic_kg
19
  cp .env.example .env
20
  ```
21
 
22
- 2. **Edit environment variables**:
23
- - Update `.env` with your API keys and configuration
24
- - Set `LLM_API_KEY` for OpenAI/Claude access
25
- - Set `MCP_API_KEYS` for MCP server authentication
 
26
 
27
- 3. **Start services**:
 
 
 
 
 
28
  ```bash
29
  make up
30
  ```
31
 
32
- 4. **Check health**:
33
  ```bash
34
- make neo4j-health
35
- make logs
36
  ```
37
 
38
- ## Available Commands
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
- - `make up` - Start all services
41
- - `make down` - Stop all services
42
- - `make logs` - Show service logs
43
- - `make seed` - Seed database with initial data
44
- - `make clean` - Stop and remove volumes
45
- - `make restart` - Restart all services
46
- - `make neo4j-health` - Check Neo4j health
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
- ## Services
 
 
 
 
 
 
 
 
 
49
 
50
- - **Neo4j**: http://localhost:7474 (Browser), bolt://localhost:7687 (Bolt)
51
- - **MCP Server**: http://localhost:3001
52
- - **Frontend**: http://localhost:3000
53
- - **PostgreSQL**: localhost:5432
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
  ## Development
56
 
57
- The system is designed as a monorepo with the following structure:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
 
 
 
 
59
  ```
60
- β”œβ”€β”€ neo4j/ # Neo4j Docker configuration
61
- β”œβ”€β”€ mcp/ # MCP server implementation
62
- β”œβ”€β”€ agent/ # Agent implementation
63
- β”œβ”€β”€ frontend/ # Next.js frontend
64
- β”œβ”€β”€ postgres/ # PostgreSQL configuration
65
- β”œβ”€β”€ ops/ # Operations scripts
66
- └── docker-compose.yml
 
67
  ```
68
 
69
- ## Features
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
- - Graph-driven workflow execution
72
- - Human-in-the-loop pauses for review
73
- - Natural language to SQL translation
74
- - Real-time workflow monitoring
75
- - Graph visualization
76
- - Audit logging
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
 
78
- ## Status
 
 
 
 
 
79
 
80
- 🚧 **In Development** - Core infrastructure setup complete, implementing MCP server and agent components.
 
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 main.py .
9
 
10
- CMD ["python", "main.py"]
 
 
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" # Browser
8
- - "7687:7687" # Bolt
9
  environment:
10
- - NEO4J_AUTH=neo4j/password
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
- - postgres_data:/var/lib/postgresql/data
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
- - MCP_PORT=8000
44
- - MCP_API_KEYS=dev-key-123,external-key-456
45
- - NEO4J_BOLT_URL=bolt://neo4j:7687
46
- - NEO4J_AUTH=neo4j/password
47
- - POSTGRES_CONNECTION=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/testdb
48
  depends_on:
49
- - neo4j
50
- - postgres
 
 
 
 
 
 
 
 
 
 
 
 
 
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:-30}
 
59
  - LLM_API_KEY=${LLM_API_KEY}
60
- - LLM_MODEL=${LLM_MODEL:-gpt-4}
 
61
  depends_on:
62
- - mcp
63
- - neo4j
 
 
 
 
 
 
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
- volumes:
75
- neo4j_data:
76
- postgres_data:
 
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": ["dom", "dom.iterable", "esnext"],
 
 
 
 
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": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "types/**/*.d.ts"],
23
- "exclude": ["node_modules"]
 
 
 
 
 
 
 
 
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
- MCP_URL = "http://mcp:8000/mcp"
5
- API_KEY = "dev-key-123"
 
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
- # Create demo workflow
16
- workflow = call_mcp("write_graph", {
17
- "action": "create_node",
18
- "label": "Workflow",
19
- "properties": {
20
- "id": "demo-workflow-1",
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": "Instruction",
61
- "properties": inst
 
 
 
 
 
 
62
  })
63
- print(f"Created instruction: {inst['id']}")
64
 
65
- # Link to workflow
66
- call_mcp("query_graph", {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  "query": """
68
- MATCH (w:Workflow {id: $wid}), (i:Instruction {id: $iid})
69
- CREATE (w)-[:HAS_INSTRUCTION]->(i)
70
  """,
71
- "parameters": {"wid": "demo-workflow-1", "iid": inst['id']}
72
  })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
- # Create instruction chain
75
- call_mcp("query_graph", {
76
- "query": """
77
- MATCH (i1:Instruction {id: 'inst-1'}), (i2:Instruction {id: 'inst-2'})
78
- CREATE (i1)-[:NEXT_INSTRUCTION]->(i2)
79
- """
80
- })
81
-
82
- call_mcp("query_graph", {
83
- "query": """
84
- MATCH (i2:Instruction {id: 'inst-2'}), (i3:Instruction {id: 'inst-3'})
85
- CREATE (i2)-[:NEXT_INSTRUCTION]->(i3)
86
- """
87
- })
88
-
89
- # Create indexes
90
- call_mcp("query_graph", {"query": "CREATE INDEX workflow_id IF NOT EXISTS FOR (w:Workflow) ON (w.id)"})
91
- call_mcp("query_graph", {"query": "CREATE INDEX instruction_id IF NOT EXISTS FOR (i:Instruction) ON (i.id)"})
92
- call_mcp("query_graph", {"query": "CREATE INDEX instruction_status_seq IF NOT EXISTS FOR (i:Instruction) ON (i.status, i.sequence)"})
 
 
 
 
 
 
 
93
 
94
- print("βœ… Seeding complete!")
 
 
 
 
 
 
 
 
 
 
 
 
 
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)