Skip to content

Python SDK

The QilbeeDB Python SDK provides a complete interface for interacting with QilbeeDB, including graph operations, Cypher queries, agent memory management, and comprehensive security features.

PyPI version Python 3.8+

Installation

# Install from PyPI
pip install qilbeedb

# Or install from source
cd sdks/python
pip install -e .

Quick Start

from qilbeedb import QilbeeDB

# Connect and authenticate
db = QilbeeDB("http://localhost:7474")
db.login("admin", "SecureAdmin@123!")

# Create a graph and add nodes
graph = db.graph("my_graph")
alice = graph.create_node(["Person"], {"name": "Alice", "age": 30})
bob = graph.create_node(["Person"], {"name": "Bob", "age": 35})

# Create a relationship
graph.create_relationship(alice.id, "KNOWS", bob.id, {"since": 2020})

# Query with Cypher
results = graph.query("MATCH (p:Person) RETURN p.name, p.age")
for row in results:
    print(f"{row['p.name']}: {row['p.age']}")

Authentication

QilbeeDB supports multiple authentication methods for different use cases.

from qilbeedb import QilbeeDB

# Connect and login with username/password
db = QilbeeDB("http://localhost:7474")
db.login("admin", "SecureAdmin@123!")

# Check authentication status
if db.is_authenticated():
    print("Successfully authenticated")

# Logout when done
db.logout()

API keys are recommended for automated applications, CI/CD pipelines, and service-to-service communication.

# Option 1: Initialize with API key directly
db = QilbeeDB({
    "uri": "http://localhost:7474",
    "api_key": "qilbee_live_your_api_key_here"
})

# Option 2: Switch to API key after JWT login
db = QilbeeDB("http://localhost:7474")
db.login("admin", "SecureAdmin@123!")
db.set_api_key("qilbee_live_your_api_key_here")

Connection Options

# Full configuration options
db = QilbeeDB({
    "uri": "http://localhost:7474",
    "api_key": "qilbee_live_your_api_key_here",  # or use login()
    "timeout": 30,          # Request timeout in seconds
    "verify_ssl": True,     # Verify SSL certificates
    "persist_tokens": True  # Persist JWT tokens
})

Context Manager

# Automatic cleanup with context manager
with QilbeeDB("http://localhost:7474") as db:
    db.login("admin", "SecureAdmin@123!")
    graph = db.graph("my_graph")
    # Operations...
# Connection automatically closed

Working with Graphs

Creating and Managing Graphs

# Get or create a graph
graph = db.graph("my_graph")

# List all graphs
graphs = db.list_graphs()
print(f"Available graphs: {graphs}")

# Create a new graph explicitly
new_graph = db.create_graph("analytics_graph")

# Delete a graph
db.delete_graph("old_graph")

Working with Nodes

Creating Nodes

# Create node with single label
user = graph.create_node(['User'], {
    'name': 'Alice',
    'email': 'alice@example.com'
})

# Create node with multiple labels
person = graph.create_node(
    ['Person', 'User', 'Admin'],
    {
        'name': 'Bob',
        'age': 35,
        'city': 'San Francisco'
    }
)

Reading Nodes

# Get node by ID
node = graph.get_node(user.id)

# Find nodes by label
users = graph.find_nodes('User')

# Find nodes with limit
recent_users = graph.find_nodes('User', limit=10)

Updating Nodes

# Update node properties
user.set('age', 31)
user.set('updated_at', '2024-01-15')
graph.update_node(user)

Deleting Nodes

# Delete node (must have no relationships)
graph.delete_node(user.id)

# Detach delete (removes relationships too)
graph.detach_delete_node(user.id)

Working with Relationships

Creating Relationships

# Create relationship between nodes
friendship = graph.create_relationship(
    alice,           # source node or ID
    'KNOWS',         # relationship type
    bob,             # target node or ID
    {                # properties (optional)
        'since': '2020-01-15',
        'strength': 0.9
    }
)

Reading Relationships

# Get all relationships for a node
relationships = graph.get_relationships(alice)

# Get outgoing relationships only
outgoing = graph.get_relationships(alice, direction='outgoing')

# Get incoming relationships only
incoming = graph.get_relationships(bob, direction='incoming')

Cypher Queries

Basic Queries

# Simple query
results = graph.query("MATCH (n:Person) RETURN n.name, n.age")

for row in results:
    print(f"Name: {row['n.name']}, Age: {row['n.age']}")

Parameterized Queries

# Query with parameters (recommended for security)
results = graph.query("""
    MATCH (p:Person)
    WHERE p.age > $min_age AND p.city = $city
    RETURN p.name, p.age
    ORDER BY p.age DESC
    LIMIT $limit
""", {
    "min_age": 25,
    "city": "San Francisco",
    "limit": 10
})

Complex Queries

# Relationship traversal
results = graph.query("""
    MATCH (user:User {name: $username})-[:KNOWS]->(friend)-[:KNOWS]->(fof)
    WHERE fof.name <> $username
    RETURN DISTINCT fof.name, fof.email
    LIMIT 20
""", {"username": "Alice"})

Query Builder

For programmatic query construction, use the fluent Query Builder API:

from qilbeedb.query import Query

# Build query fluently
results = (
    Query(graph)
    .match('(p:Person)-[:KNOWS]->(f:Person)')
    .where('p.city = $city', {'city': 'San Francisco'})
    .return_clause('f.name', 'f.age')
    .order_by('f.age', desc=True)
    .limit(10)
    .execute()
)

for row in results:
    print(row)

User Management (Admin Only)

Administrators can create, update, and manage user accounts.

Creating Users

# Create a new user
user = db.create_user(
    username="developer1",
    password="SecureP@ss123!",
    email="dev1@example.com",
    roles=["Developer", "Read"]
)
print(f"Created user: {user['id']}")

Available Roles

Role Description
Admin Full administrative access
Developer Development and testing access
DataScientist Analytics and query access
Agent AI agent operations
Read Read-only access

Listing and Managing Users

# List all users
users = db.list_users()
for user in users:
    print(f"{user['username']}: {user['roles']}")

# Get a specific user
user = db.get_user("user-uuid-here")

# Update user roles
db.update_user_roles("user-uuid-here", ["Developer", "DataScientist"])

# Update user password
db.update_user("user-uuid-here", password="NewSecureP@ss!")

# Delete a user
db.delete_user("user-uuid-here")

API Key Management

Create and manage API keys for application authentication.

Creating API Keys

# Create a new API key
result = db.create_api_key("my-application-key")
api_key = result["key"]  # Store this securely!
key_id = result["id"]
print(f"Created API key: {api_key[:20]}...")

Security Note

The API key is only shown once when created. Store it securely as it cannot be retrieved later.

Managing API Keys

# List all API keys (key values are masked)
keys = db.list_api_keys()
for key in keys:
    print(f"ID: {key['id']}, Name: {key['name']}, Created: {key['created_at']}")

# Delete an API key
db.delete_api_key("key-uuid-here")

Using API Keys

# Use the API key in your application
app_db = QilbeeDB({
    "uri": "http://localhost:7474",
    "api_key": "qilbee_live_your_api_key_here"
})

# All operations use the API key automatically
graph = app_db.graph("my_graph")

Rate Limit Policy Management (Admin Only)

Administrators can create custom rate limiting policies for different endpoints.

Creating Rate Limit Policies

# Create a custom rate limit policy
policy = db.create_rate_limit_policy(
    name="API Strict Limit",
    endpoint_type="GeneralApi",  # or {"Custom": "/api/special"}
    max_requests=100,
    window_secs=3600,  # 100 requests per hour
    enabled=True
)
print(f"Created policy: {policy['id']}")

Endpoint Types

Type Description
Login Authentication endpoints
ApiKeyCreation API key creation endpoints
GeneralApi General API endpoints
UserManagement User management endpoints
{"Custom": "/path"} Custom endpoint pattern

Managing Policies

# List all rate limit policies
policies = db.list_rate_limit_policies()
for policy in policies:
    print(f"{policy['name']}: {policy['max_requests']} req/{policy['window_secs']}s")

# Get a specific policy
policy = db.get_rate_limit_policy("policy-uuid-here")

# Update a policy
db.update_rate_limit_policy(
    policy_id="policy-uuid-here",
    max_requests=200,
    enabled=False
)

# Delete a policy
db.delete_rate_limit_policy("policy-uuid-here")

Account Lockout Management (Admin Only)

Monitor and manage locked accounts due to failed login attempts.

Viewing Locked Accounts

# Get all locked accounts
locked = db.get_locked_accounts()
print(f"Total locked accounts: {locked['count']}")
for user, status in locked['locked_users']:
    print(f"  {user}: {status['lockout_remaining_seconds']}s remaining")

Checking Lockout Status

# Get lockout status for a specific user
status = db.get_lockout_status("suspicious_user")
print(f"User: {status['username']}")
print(f"  Locked: {status['status']['locked']}")
print(f"  Failed attempts: {status['status']['failed_attempts']}")
print(f"  Remaining attempts: {status['status']['remaining_attempts']}")
print(f"  Lockout count: {status['status']['lockout_count']}")

Locking and Unlocking Accounts

# Manually lock an account
result = db.lock_account("suspicious_user", reason="Suspicious activity detected")
print(f"Lock result: {result['success']}")

# Unlock an account
result = db.unlock_account("suspicious_user")
print(f"Unlock result: {result['success']}")

Lockout Behavior

Setting Default
Max failed attempts 5
Initial lockout duration 15 minutes
Progressive lockout Doubles each time (up to 24 hours)
Auto-unlock Yes, after lockout expires

Token Revocation

Revoke JWT tokens to immediately invalidate them before expiration.

Revoking Current Token

# Login and get a token
login_response = db.login("admin", "SecureAdmin@123!")
access_token = login_response.get("access_token")

# Revoke the current token (secure logout)
result = db.revoke_token(access_token)
print(f"Token revoked with jti: {result['jti']}")

Revoking All User Tokens (Admin Only)

# Revoke all tokens for a potentially compromised user
result = db.revoke_all_tokens(
    user_id="user-uuid-here",
    reason="security_incident"
)
print(f"All tokens revoked for user: {result['user_id']}")

Security Incident Response

def handle_security_incident(admin_db, compromised_user_ids):
    """Revoke all tokens for potentially compromised accounts."""
    for user_id in compromised_user_ids:
        admin_db.revoke_all_tokens(user_id, reason="security_incident")
        admin_db.lock_account(user_id, reason="security_investigation")
        print(f"Secured account: {user_id}")

Audit Logging (Admin Only)

Query and monitor security events for compliance and debugging.

Querying Audit Logs

# Query all audit logs
result = db.get_audit_logs(limit=100)
print(f"Total events: {result['count']}")
for event in result['events']:
    print(f"{event['event_time']}: {event['event_type']} - {event['result']}")

Filtering Audit Logs

# Filter by event type
login_events = db.get_audit_logs(event_type="login", limit=50)

# Filter by username
user_events = db.get_audit_logs(username="admin", limit=50)

# Filter by result
failed_events = db.get_audit_logs(result="unauthorized", limit=50)

# Filter by IP address
ip_events = db.get_audit_logs(ip_address="192.168.1.100", limit=50)

# Filter by time range
recent_events = db.get_audit_logs(
    start_time="2025-01-01T00:00:00Z",
    end_time="2025-12-31T23:59:59Z",
    limit=100
)

Convenience Methods

# Get recent failed login attempts
failed_logins = db.get_failed_logins(limit=20)
for event in failed_logins:
    print(f"Failed login from {event['ip_address']} at {event['event_time']}")

# Get all events for a specific user
user_activity = db.get_user_audit_events("alice", limit=50)

# Get security-relevant events (unauthorized/forbidden)
security_events = db.get_security_events(limit=50)

Audit Event Types

Category Event Types
Authentication login, logout, login_failed, token_refresh, token_refresh_failed
User Management user_created, user_updated, user_deleted, password_changed
Role Management role_assigned, role_removed
API Keys api_key_created, api_key_revoked, api_key_used, api_key_validation_failed
Token Revocation token_revoked, all_tokens_revoked
Authorization permission_denied, access_granted
Rate Limiting rate_limit_exceeded
Account Lockout account_lockout_triggered, account_locked, account_unlocked

Agent Memory

Storing Episodes

from qilbeedb.memory import Episode

# Get agent memory manager
memory = db.agent_memory('customer_service_bot')

# Store conversation episode
episode = Episode.conversation(
    agent_id='customer_service_bot',
    user_input='How do I reset my password?',
    agent_response='You can reset your password by clicking...'
)
episode_id = memory.store_episode(episode)

# Store observation
observation = Episode.observation(
    agent_id='customer_service_bot',
    observation='User seems frustrated with login process'
)
memory.store_episode(observation)

# Store action
action = Episode.action(
    agent_id='customer_service_bot',
    action='Sent password reset email',
    result='Email sent successfully'
)
memory.store_episode(action)

Retrieving Episodes

# Get recent episodes
recent = memory.get_recent_episodes(10)
for episode in recent:
    print(f"Type: {episode.episode_type}")
    print(f"Content: {episode.content}")
    print(f"Time: {episode.event_time}")

Memory Management

# Get memory statistics
stats = memory.get_statistics()
print(f"Total episodes: {stats.total_episodes}")
print(f"Average relevance: {stats.avg_relevance}")

# Consolidate memory
consolidated = memory.consolidate()
print(f"Consolidated {consolidated} episodes")

# Forget low-relevance episodes
forgotten = memory.forget(min_relevance=0.2)
print(f"Forgot {forgotten} episodes")

# Clear all episodes
memory.clear()

Memory Configuration

memory = db.agent_memory(
    "agent-001",
    max_episodes=10000,
    min_relevance=0.1,
    auto_consolidate=True,
    auto_forget=True,
    consolidation_threshold=5000,
    episodic_retention_days=30
)

Error Handling

from qilbeedb.exceptions import (
    QilbeeDBError,
    ConnectionError,
    QueryError,
    AuthenticationError,
    PermissionDeniedError,
    NodeNotFoundError
)

try:
    db = QilbeeDB("http://localhost:7474")
    db.login("admin", "password")
    graph = db.graph("my_graph")

    # Your operations here
    node = graph.get_node(123)

except AuthenticationError as e:
    print(f"Authentication failed: {e}")
except PermissionDeniedError as e:
    print(f"Permission denied: {e}")
except ConnectionError as e:
    print(f"Failed to connect: {e}")
except QueryError as e:
    print(f"Query failed: {e}")
except NodeNotFoundError as e:
    print(f"Node not found: {e}")
except QilbeeDBError as e:
    print(f"Database error: {e}")

API Reference

QilbeeDB Class

Main database client.

Connection Methods:

Method Description
health() Get database health status
close() Close the database connection

Graph Methods:

Method Description
graph(name) Get or create graph
list_graphs() List all graphs
create_graph(name) Create new graph
delete_graph(name) Delete graph

Authentication Methods:

Method Description
login(username, password) Login with JWT
logout() Logout and clear auth
is_authenticated() Check auth status
set_api_key(api_key) Switch to API key auth
refresh_token() Refresh JWT access token

User Management Methods (Admin):

Method Description
create_user(username, password, email, roles) Create user
list_users() List all users
get_user(user_id) Get user by ID
update_user(user_id, password, roles) Update user
update_user_roles(user_id, roles) Update user roles
delete_user(user_id) Delete user

API Key Methods:

Method Description
create_api_key(name) Create API key
list_api_keys() List API keys
delete_api_key(key_id) Delete API key

Rate Limit Methods (Admin):

Method Description
create_rate_limit_policy(...) Create policy
list_rate_limit_policies() List policies
get_rate_limit_policy(id) Get policy
update_rate_limit_policy(...) Update policy
delete_rate_limit_policy(id) Delete policy

Account Lockout Methods (Admin):

Method Description
get_locked_accounts() Get all locked accounts
get_lockout_status(username) Get lockout status
lock_account(username, reason) Lock account
unlock_account(username) Unlock account

Token Revocation Methods:

Method Description
revoke_token(token) Revoke specific token
revoke_all_tokens(user_id, reason) Revoke all user tokens (Admin)

Audit Log Methods (Admin):

Method Description
get_audit_logs(**filters) Query audit logs
get_failed_logins(limit) Get failed logins
get_user_audit_events(username, limit) Get user events
get_security_events(limit) Get security events

Agent Memory Methods:

Method Description
agent_memory(agent_id, config) Create agent memory

Graph Class

Graph operations.

Method Description
create_node(labels, properties) Create node
get_node(node_id) Get node by ID
update_node(node) Update node
delete_node(node_id) Delete node
detach_delete_node(node_id) Delete node with relationships
find_nodes(label, limit) Find nodes by label
create_relationship(...) Create relationship
get_relationships(node, direction) Get relationships
query(cypher, parameters) Execute Cypher query

Node Class

Attribute Description
id Node ID
labels Node labels list
properties Node properties dict
Method Description
get(key, default) Get property
set(key, value) Set property
__getitem__(key) Access property: node["name"]
__setitem__(key, value) Set property: node["age"] = 31

Relationship Class

Attribute Description
id Relationship ID
type Relationship type
start_node Start node ID
end_node End node ID
properties Relationship properties dict

Real-World Examples

Social Network

# Create social network
db = QilbeeDB("http://localhost:7474")
db.login("admin", "SecureAdmin@123!")
graph = db.graph("social_network")

# Create users
alice = graph.create_node(['User', 'Person'], {
    'username': 'alice',
    'name': 'Alice Johnson',
    'age': 28,
    'city': 'San Francisco'
})

bob = graph.create_node(['User', 'Person'], {
    'username': 'bob',
    'name': 'Bob Smith',
    'age': 32,
    'city': 'New York'
})

# Create friendship
graph.create_relationship(
    alice, 'FRIEND', bob,
    {'since': '2023-02-25', 'strength': 0.8}
)

# Find friends
results = graph.query("""
    MATCH (user:User {username: $username})-[:FRIEND]->(friend)
    RETURN friend.name, friend.city
""", {"username": "alice"})

Knowledge Graph

# Create knowledge graph
graph = db.graph("knowledge_base")

# Create concepts
python = graph.create_node(['Concept', 'ProgrammingLanguage'], {
    'name': 'Python',
    'paradigm': 'multi-paradigm',
    'year': 1991
})

web_dev = graph.create_node(['Concept', 'Domain'], {
    'name': 'Web Development',
    'category': 'software'
})

# Create semantic relationship
graph.create_relationship(python, 'USED_FOR', web_dev, {'popularity': 0.9})

# Query concepts
results = graph.query("""
    MATCH (lang:ProgrammingLanguage)-[:USED_FOR]->(domain:Domain)
    WHERE domain.name = $domain_name
    RETURN lang.name, lang.paradigm
""", {"domain_name": "Web Development"})

Recommendation System

# Create recommendation graph
graph = db.graph("recommendations")

# Create user and products
user = graph.create_node(['Customer'], {'user_id': 'U001', 'name': 'Jane Doe'})
laptop = graph.create_node(['Product'], {
    'product_id': 'P001',
    'name': 'Laptop Pro',
    'category': 'Electronics'
})

# Track purchase
graph.create_relationship(user, 'PURCHASED', laptop, {'date': '2024-01-15', 'rating': 5})

# Find recommendations
recommendations = graph.query("""
    MATCH (u:Customer {user_id: $user_id})-[:PURCHASED]->(p:Product)
          <-[:PURCHASED]-(similar:Customer)-[:PURCHASED]->(rec:Product)
    WHERE NOT (u)-[:PURCHASED]->(rec)
    RETURN rec.name, COUNT(similar) as score
    ORDER BY score DESC
    LIMIT 5
""", {"user_id": "U001"})

Best Practices

Use Parameterized Queries

Always use parameters instead of string interpolation:

# Good: Parameterized query
results = graph.query(
    "MATCH (p:Person) WHERE p.name = $name RETURN p",
    {"name": user_input}
)

# Bad: String interpolation (vulnerable to injection)
results = graph.query(
    f"MATCH (p:Person) WHERE p.name = '{user_input}' RETURN p"
)

Use Context Managers

Always use context managers for automatic cleanup:

# Good: Context manager
with QilbeeDB("http://localhost:7474") as db:
    db.login("admin", "SecureAdmin@123!")
    graph = db.graph("my_graph")
    # Operations...

# Bad: Manual management
db = QilbeeDB("http://localhost:7474")
graph = db.graph("my_graph")
# Operations...
db.close()  # Easy to forget!

Use API Keys for Applications

# For automated applications, use API keys
db = QilbeeDB({
    "uri": "http://localhost:7474",
    "api_key": os.environ.get("QILBEEDB_API_KEY")
})

Handle Errors Appropriately

from qilbeedb.exceptions import AuthenticationError, ConnectionError

try:
    db = QilbeeDB("http://localhost:7474")
    db.login("admin", "password")
except AuthenticationError:
    # Handle authentication failure
    print("Invalid credentials")
except ConnectionError:
    # Handle connection issues
    print("Cannot connect to database")

Development

Running Tests

pip install -e .[dev]
pytest tests/

Code Formatting

black qilbeedb/
flake8 qilbeedb/
mypy qilbeedb/

Next Steps