Feedple Python SDK
The official Python SDK for the Feedple AI platform. Connect your database to Feedple with a single class — the SDK handles authentication, schema sync, and query execution automatically.
Table of Contents
- How It Works
- Requirements
- Installation
- Quick Start
- Configuration
- Identity & Access Control
- Schema Sync
- IR Query Execution
- Connection Management
- Utilities
- API Reference
- License
How It Works
Your App Feedple SDK Feedple API
│ │ │
│ FeedpleSDK(api_key, db, …) │ │
│─────────────────────────────>│ │
│ │── connect() ─────────────────>│
│ │<─ auth.ack (session_id) ──────│
│ │ │
│ │── schema.started ────────────>│
│ │── schema.data (chunks) ──────>│
│ │── schema.completed ──────────>│
│ │ │
│ │<─ ir.request (IR payload) ────│
│ │── ir.ack ────────────────────>│
│ │ [executes SQL against DB] │
│ │── ir.result ─────────────────>│
│ │ │
- Connect & Authenticate — Opens a persistent WebSocket connection and sends your API key. The server responds with a
session_idused to resume after disconnects. - Sync Schema — Inspects your database (tables, columns, PKs, FKs, indexes) and sends the schema to Feedple in chunks. Re-syncs on a configurable interval; skips if nothing changed.
- Execute Queries — Receives incoming IR query requests from Feedple, enforces RBAC, executes them safely against your database, and returns the results.
Requirements
- Python ≥ 3.8
- A database supported by SQLAlchemy (PostgreSQL, MySQL, SQLite, and others)
Installation
pip install feedple-sdk
Install with a specific database driver:
# PostgreSQL
pip install feedple-sdk psycopg2-binary
# MySQL
pip install feedple-sdk pymysql
# SQLite (built into Python — no extra driver needed)
pip install feedple-sdk
Quick Start
from sqlalchemy import create_engine
from feedple_sdk import FeedpleSDK, Identity
# 1. Create your database engine (SQLAlchemy)
db = create_engine("postgresql+psycopg2://user:pass@localhost/mydb")
# 2. Define which tables Feedple can access
identity = Identity(
name="production",
all_tables=True, # expose every table, or…
# allowed_tables=["users", "orders", "products"], # …restrict to specific tables
)
# 3. Initialise the SDK — it starts immediately in the background
sdk = FeedpleSDK(
api_key="sk_live_...",
db=db,
identity=identity,
)
# Your application keeps running normally.
# The SDK manages the WebSocket connection on a background thread.
Note:
FeedpleSDK.__init__starts a background daemon thread and returns immediately. Your application does not block.
Configuration
All parameters are keyword-only.
sdk = FeedpleSDK(
# Required
api_key="sk_live_...", # Your Feedple API key
db=engine, # SQLAlchemy Engine
identity=identity, # Identity (see below)
# Schema sync
auto_sync=True, # Sync schema on startup and periodically (default: True)
sync_interval=60, # Seconds between sync cycles (default: 60)
# Connection
reconnect_enabled=True, # Reconnect on disconnect (default: True)
max_retries=None, # Max reconnect attempts; None = unlimited (default: None)
probe_before_connect=False, # HTTP probe before WS handshake for clearer errors (default: False)
)
Parameter Reference
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key |
str |
required | Your Feedple API key. Raises ValueError if empty. |
db |
Engine |
required | SQLAlchemy database engine. |
identity |
Identity |
required | Controls which tables are accessible. |
auto_sync |
bool |
True |
Periodically re-inspect and send the schema. |
sync_interval |
int |
60 |
Seconds between schema re-sync cycles. |
reconnect_enabled |
bool |
True |
Automatically reconnect on connection loss. |
max_retries |
int | None |
None |
Cap on reconnect attempts. None means unlimited. |
probe_before_connect |
bool |
False |
Perform an HTTP GET before the WS handshake to surface clearer server error messages (e.g. 403 bodies). |
Identity & Access Control
Identity controls which database tables Feedple can see and query.
from feedple_sdk import Identity
# Grant access to all tables
admin_identity = Identity(
name="admin",
all_tables=True,
)
# Restrict to specific tables only
restricted_identity = Identity(
name="analytics-service",
allowed_tables=["users", "orders", "products", "events"],
all_tables=False, # default
)
Identity Fields
| Field | Type | Default | Description |
|---|---|---|---|
name |
str | None |
— | Human-readable label for this identity. |
allowed_tables |
list[str] |
[] |
Tables this identity may access. Ignored when all_tables=True. |
all_tables |
bool |
False |
When True, all current and future tables are accessible. |
Security: The SDK enforces RBAC on every IR query request. If the IR references a table not in
allowed_tables, aPermissionErroris raised and anir.erroris returned to the server — the query never reaches the database.
Schema Sync
The SDK automatically syncs your schema on startup and then every sync_interval seconds. You can also trigger a sync manually:
import asyncio
# Manually trigger a schema sync (async — must be called from an async context)
asyncio.run(sdk.sync_schema())
What gets synced
For each table the identity can access, the SDK sends:
- Columns — name, type string, nullable flag, default value
- Primary key — constrained column names
- Foreign keys — local columns, referenced table, referenced columns
- Indexes — name, column names, unique flag
- Unique constraints — name, column names
Sensitive column filtering
The following column names are never sent to Feedple, regardless of the identity setting:
password, token, secret, hash, salt, ssn, credit_card
You can call filter_sensitive_columns manually:
from feedple_sdk.core.schema_services import filter_sensitive_columns
safe_schema = filter_sensitive_columns(raw_schema)
IR Query Execution
The SDK receives IR (Intermediate Representation) query objects from the Feedple server and executes them against your database. You do not call this yourself — it is invoked automatically via the WebSocket.
IR Schema
ir = {
"operation": "query", # always "query"
"table": "orders", # primary FROM table
"fields": [ # columns to SELECT
{"column": "orders.id", "expression": None, "alias": None},
{"column": "orders.amount", "expression": "sum", "alias": "total"},
{"column": "orders.user_id","expression": "count(distinct)", "alias": "unique_users"},
],
"joins": [ # JOIN clauses
{
"table": "users",
"on_left": "orders.user_id",
"on_right": "users.id",
"join_type": "INNER", # "INNER" or "LEFT"
}
],
"filters": [ # WHERE conditions (ANDed together)
{"column": "orders.status", "operator": "eq", "value": "active"},
{"column": "orders.amount", "operator": "gte", "value": 100},
],
"group_by": ["orders.status"],
"having": [{"column": "orders.id", "operator": "gt", "value": 5}],
"order_by": ["orders.created_at DESC"],
"limit": 100,
"offset": 0,
}
Supported filter operators
| Operator | Aliases | SQL |
|---|---|---|
eq |
= |
col = ? |
neq |
!= |
col != ? |
gt |
> |
col > ? |
gte |
>= |
col >= ? |
lt |
< |
col < ? |
lte |
<= |
col <= ? |
in |
in_ |
col IN (?, ?, …) |
not_in |
not in |
col NOT IN (?, ?, …) |
is_null |
— | col IS NULL |
is_not_null |
— | col IS NOT NULL |
like |
— | col LIKE ? |
ilike |
— | col ILIKE ? |
Supported aggregate expressions
count, count(distinct), sum, avg, min, max
Connection Management
Reconnect behaviour
The SDK reconnects automatically with exponential back-off:
| Attempt | Delay |
|---|---|
| 1 | 5 s |
| 2 | 10 s |
| 3 | 20 s |
| 4+ | 40 s → capped at 60 s |
Authentication failures (auth.error) are not retried — the SDK stops immediately and logs the error.
Session resume
The session_id received in auth.ack is stored and re-sent on every reconnect attempt. The server resumes the session if it is still within TTL, or issues a new session ID if it has expired.
Stopping the SDK
sdk.stop()
Signals the background thread to stop, closes the WebSocket, and halts the event loop. Idempotent — safe to call multiple times.
Utilities
SQLCompiler
Validate and RBAC-check raw SQL strings before executing them yourself:
compiler = sdk._build_compiler()
# Raises PermissionError if the SQL references a denied table
safe_sql = compiler.compile("SELECT id, name FROM users WHERE active = 1")
Schema utilities
from feedple_sdk.core.schema_services import (
get_schema,
generate_schema_hash,
should_sync_schema,
filter_sensitive_columns,
)
schema = get_schema(db=engine, identity=identity)
hash_ = generate_schema_hash(schema)
changed = should_sync_schema(old_schema, new_schema)
API Reference
FeedpleSDK
class FeedpleSDK:
def __init__(
self,
*,
api_key: str,
db: Engine,
identity: Identity,
auto_sync: bool = True,
sync_interval: int = 60,
reconnect_enabled: bool = True,
max_retries: Optional[int] = None,
probe_before_connect: bool = False,
) -> None: ...
async def sync_schema(self) -> None: ...
def stop(self) -> None: ...
Identity
@dataclass
class Identity:
name: Optional[str]
allowed_tables: List[str] = field(default_factory=list)
all_tables: bool = False
PolicyEngine
class PolicyEngine:
def __init__(self, identity: Identity): ...
def can_access_table(self, table: str) -> bool: ...
def validate_ir_access(self, ir: dict) -> None: ...
SQLCompiler
class SQLCompiler:
def __init__(self, policy: PolicyEngine, dialect: str = "postgres"): ...
def parse(self, sql: str) -> exp.Expression: ...
def extract_tables(self, ast: exp.Expression) -> List[str]: ...
def validate_access(self, tables: List[str]) -> None: ...
def compile(self, sql: str) -> str: ...
Environment URLs
By default the production release SDK targets the official Feedple AI production cluster (https://feedple-ai-614817435356.us-central1.run.app).
To switch to a local development environment during SDK development, set DEV_ENV = True in src/feedple_sdk/core/request.py:
DEV_ENV = True # uses http://localhost:8000/api/v1 and ws://localhost:8000/api/v1/tenants/ws
License
feedple-sdk is distributed under the terms of the MIT license.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file feedple_sdk-1.0.3.tar.gz.
File metadata
- Download URL: feedple_sdk-1.0.3.tar.gz
- Upload date:
- Size: 37.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
22dbb8302eec27495fffdcd3de0e53c8bcb7513e937d80f0cf8341cac972149a
|
|
| MD5 |
2006fdfaac10d75ec87c4627e8cf3a37
|
|
| BLAKE2b-256 |
5a4dec9c4037f98b4b43f61662c2aa4aaa8f15347dc66236fb8269554503f7d2
|
File details
Details for the file feedple_sdk-1.0.3-py3-none-any.whl.
File metadata
- Download URL: feedple_sdk-1.0.3-py3-none-any.whl
- Upload date:
- Size: 34.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
533dd918277b24861112d06026eec4d9ac07d09e2ecc530d0438097e00b9cffb
|
|
| MD5 |
86bbefc6b0fb54a04ade6f111579cb28
|
|
| BLAKE2b-256 |
b193f446bd30c9b12991b6dc10112fbaef1ef9dde2ea4ee2725cda530efb24c9
|