Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions python-agent/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Python cache files
__pycache__/
*.py[cod]
*$py.class

# Test databases
*.db

# Virtual environments
venv/
env/
.env

# IDE files
.vscode/
.idea/
*.swp
*.swo

# Logs
*.log

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt
188 changes: 188 additions & 0 deletions python-agent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# Sentrius Python Agent

This Python agent provides the same APIs and operations as the Java agent, enabling integration with the Sentrius platform for authentication, registration, heartbeat monitoring, and provenance event submission.

## Features

- **Keycloak Integration**: Full authentication support using Keycloak JWT tokens
- **Agent Registration**: Automatic registration with the Sentrius API server
- **Heartbeat Monitoring**: Continuous heartbeat mechanism to maintain connection
- **Provenance Events**: Submit detailed provenance events for audit trails
- **RSA Encryption**: Secure communication using ephemeral RSA keys
- **Configurable**: Support for both YAML configuration files and environment variables
- **Extensible**: Base agent framework for creating custom agents

## Architecture

The Python agent mirrors the Java agent architecture with these key components:

### Services
- **KeycloakService**: Handles authentication and token management
- **AgentClientService**: Manages API communication with Sentrius server
- **EphemeralKeyGen**: RSA key generation and cryptographic operations
- **SentriusAgent**: Main agent framework coordinating all services

### Agent Framework
- **BaseAgent**: Abstract base class for all agents

## Configuration

### YAML Configuration
```yaml
keycloak:
server_url: "http://localhost:8080"
realm: "sentrius"
client_id: "python-agent"
client_secret: "your-client-secret"

agent:
name_prefix: "python-agent"
agent_type: "python"
callback_url: "http://localhost:8081"
api_url: "http://localhost:8080"
heartbeat_interval: 30

llm:
enabled: false
provider: "openai"
model: "gpt-3.5-turbo"
api_key: null
endpoint: null
```

### Environment Variables
```bash
KEYCLOAK_SERVER_URL=http://localhost:8080
KEYCLOAK_REALM=sentrius
KEYCLOAK_CLIENT_ID=python-agent
KEYCLOAK_CLIENT_SECRET=your-client-secret
AGENT_NAME_PREFIX=python-agent
AGENT_API_URL=http://localhost:8080
AGENT_CALLBACK_URL=http://localhost:8081
AGENT_HEARTBEAT_INTERVAL=30
```

## Usage

### Agent Framework
The Python agent provides a framework for creating custom agents that integrate with the Sentrius platform. All agents interact through APIs using JWT authentication, working with DTOs from the API and the LLM proxy.

### Creating Custom Agents
```python
from agents.base import BaseAgent

class MyCustomAgent(BaseAgent):
def __init__(self, config_path=None):
super().__init__("My Custom Agent", config_path=config_path)

def execute_task(self):
# Your custom agent logic here
# Note: All data access is through Sentrius APIs, not direct database connections
self.submit_provenance(
event_type="CUSTOM_TASK",
details={"task": "custom_operation"}
)

def run(self):
# Start the agent lifecycle
self.start()
self.execute_task()
self.stop()
```

### Running Custom Agents
```bash
# With configuration file
python -c "from my_agent import MyCustomAgent; agent = MyCustomAgent('config.yaml'); agent.run()"

# With environment variables
python -c "from my_agent import MyCustomAgent; agent = MyCustomAgent(); agent.run()"
```

## API Operations

The Python agent supports all the same API operations as the Java agent:

### Agent Registration
- **Endpoint**: `POST /api/v1/agent/register`
- **Purpose**: Register the agent with the Sentrius API server
- **Authentication**: Keycloak JWT token required

### Heartbeat
- **Endpoint**: `POST /api/v1/agent/heartbeat`
- **Purpose**: Send periodic status updates to maintain connection
- **Frequency**: Configurable (default: 30 seconds)

### Provenance Submission
- **Endpoint**: `POST /api/v1/agent/provenance/submit`
- **Purpose**: Submit detailed provenance events for audit trails
- **Data**: Event type, timestamp, agent ID, and custom details

## Dependencies

- `requests`: HTTP client for API communication
- `PyJWT`: JWT token handling
- `cryptography`: RSA key generation and encryption
- `pyyaml`: YAML configuration parsing

Note: The Python agent accesses data through Sentrius APIs using DTOs and the LLM proxy, not through direct database connections.

## Installation

```bash
pip install -r requirements.txt
```

## Testing

Run the test suite:
```bash
python tests/test_services.py
```

## Security

- Uses ephemeral RSA key pairs for secure communication
- Validates JWT tokens using Keycloak public keys
- Supports encrypted data exchange with the API server
- Maintains secure token management throughout agent lifecycle

## Integration with Java Ecosystem

This Python agent is designed to work seamlessly with the existing Java-based Sentrius infrastructure:

- Compatible with the same API endpoints
- Uses identical authentication mechanisms
- Submits provenance events in the same format
- Supports the same agent lifecycle management
- Can be launched using the same agent launcher service

## Example Provenance Events

The agent automatically submits various provenance events:

```json
{
"event_type": "AGENT_REGISTRATION",
"timestamp": "2024-01-01T12:00:00.000Z",
"agent_id": "python-agent-abc123",
"details": {
"agent_id": "python-agent-abc123",
"callback_url": "http://localhost:8081",
"agent_type": "python"
}
}
```

```json
{
"event_type": "SQL_QUERY_SUCCESS",
"timestamp": "2024-01-01T12:01:00.000Z",
"agent_id": "python-agent-abc123",
"details": {
"question_number": 1,
"question": "What are the top 5 customers by revenue?",
"response_length": 245
}
}
```
82 changes: 77 additions & 5 deletions python-agent/agents/base.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,84 @@
from abc import ABC, abstractmethod
from typing import Dict, Any, Optional
import logging

from services.sentrius_agent import SentriusAgent
from services.config import SentriusAgentConfig

logger = logging.getLogger(__name__)


class BaseAgent(ABC):
"""Abstract base class for all agents."""
def __init__(self, name: str, config: dict):
"""Abstract base class for all agents with Sentrius API integration."""

def __init__(self, name: str, config_path: Optional[str] = None, config: Optional[SentriusAgentConfig] = None):
self.name = name
self.config = config

# Load configuration
if config:
self.config = config
elif config_path:
self.config = SentriusAgentConfig.from_yaml(config_path)
else:
self.config = SentriusAgentConfig.from_env()

# Initialize Sentrius agent
self.sentrius_agent = SentriusAgent(self.config)

logger.info(f"Initialized {self.__class__.__name__}: {self.name}")

@abstractmethod
def run(self):
"""Method to execute the agent's task."""
def execute_task(self):
"""Method to execute the agent's specific task."""
pass

def run(self):
"""Main run method that handles agent lifecycle."""
try:
with self.sentrius_agent:
logger.info(f"Starting {self.name} agent")

# Submit start event
self.sentrius_agent.submit_provenance_event(
event_type="AGENT_START",
details={
"agent_name": self.name,
"agent_class": self.__class__.__name__
}
)

# Execute the specific task
self.execute_task()

# Submit completion event
self.sentrius_agent.submit_provenance_event(
event_type="AGENT_COMPLETE",
details={
"agent_name": self.name,
"status": "completed"
}
)

logger.info(f"{self.name} agent completed successfully")

except Exception as e:
logger.error(f"{self.name} agent failed: {e}")

# Submit error event
try:
self.sentrius_agent.submit_provenance_event(
event_type="AGENT_ERROR",
details={
"agent_name": self.name,
"error": str(e),
"error_type": type(e).__name__
}
)
except:
pass # Don't fail if we can't submit error event

raise

def submit_provenance(self, event_type: str, details: Dict[str, Any]):
"""Submit a provenance event."""
self.sentrius_agent.submit_provenance_event(event_type, details)
Empty file.
33 changes: 0 additions & 33 deletions python-agent/agents/sql_agent/sql_agent.py

This file was deleted.

20 changes: 20 additions & 0 deletions python-agent/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Sentrius Python Agent Configuration
keycloak:
server_url: "http://localhost:8080"
realm: "sentrius"
client_id: "python-agent"
client_secret: "your-client-secret"

agent:
name_prefix: "python-agent"
agent_type: "python"
callback_url: "http://localhost:8081"
api_url: "http://localhost:8080"
heartbeat_interval: 30

llm:
enabled: false
provider: "openai"
model: "gpt-3.5-turbo"
api_key: null
endpoint: null
Loading