Taruvi SDK Guide for APP Mode Functions
Complete reference for using the Taruvi SDK within APP mode serverless functions.
Function Signature
APP mode functions must use this exact signature:
def main(params, user_data, sdk_client):
"""
APP mode function entry point.
Args:
params: User parameters + params['__function__'] metadata
user_data: Dict with id, username, email, full_name
sdk_client: Pre-authenticated Taruvi SDK client
Returns:
Any JSON-serializable data
"""
pass
Parameters Explained
params - Dictionary containing:
- User-provided parameters from function invocation
params['__function__']- Function metadata (name, slug, execution_mode, etc.)
user_data - Dictionary containing authenticated user info:
{
"id": 123,
"username": "alice",
"email": "alice@example.com",
"full_name": "Alice Smith"
}
sdk_client - Pre-authenticated Taruvi SDK client
- Already authenticated with current user context
- Ready to use - no need to call auth methods
- Provides access to all platform features
Database Module
CRUD operations on DataTables.
Methods
sdk_client.database.query(table_name) # Returns QueryBuilder (chainable)
sdk_client.database.get(table_name, record_id) # Get single record
sdk_client.database.create(table_name, data) # Create record
sdk_client.database.update(table_name, record_id, data) # Update record
sdk_client.database.delete(table_name, record_id) # Delete record
QueryBuilder Chaining
.filter(field, operator, value) # Operators: eq, ne, gt, gte, lt, lte, in, contains
.sort(field, direction) # direction: "asc" or "desc"
.page_size(limit) # Limit results
.execute() # Returns list[dict]
Examples
Simple Query:
def main(params, user_data, sdk_client):
users = sdk_client.database.query("users").execute()
return {"users": users}
Query with Filters:
def main(params, user_data, sdk_client):
active_users = sdk_client.database.query("users")\
.filter("status", "eq", "active")\
.filter("age", "gte", 18)\
.sort("created_at", "desc")\
.page_size(10)\
.execute()
return {"users": active_users, "total": len(active_users)}
Get Single Record:
def main(params, user_data, sdk_client):
user_id = params.get("user_id")
user = sdk_client.database.get("users", user_id)
return {"user": user}
Create Record:
def main(params, user_data, sdk_client):
new_user = sdk_client.database.create("users", {
"username": params.get("username"),
"email": params.get("email"),
"status": "active"
})
return {"created": True, "user": new_user}
Update Record:
def main(params, user_data, sdk_client):
user_id = params.get("user_id")
updated_user = sdk_client.database.update("users", user_id, {
"status": "inactive"
})
return {"updated": True, "user": updated_user}
Delete Record:
def main(params, user_data, sdk_client):
user_id = params.get("user_id")
sdk_client.database.delete("users", user_id)
return {"deleted": True, "user_id": user_id}
Functions Module
Execute other serverless functions and retrieve results.
Methods
sdk_client.functions.execute(function_slug, params, is_async=False, timeout=None)
sdk_client.functions.get_result(task_id)
sdk_client.functions.list(limit=None, offset=None)
sdk_client.functions.get(function_slug)
sdk_client.functions.list_invocations(function_slug, status=None, limit=None, offset=None)
Examples
Execute Sync Function:
def main(params, user_data, sdk_client):
result = sdk_client.functions.execute(
"send-email",
params={
"to": "user@example.com",
"subject": "Welcome"
}
)
return {"email_sent": True, "result": result}
Execute Async Function:
def main(params, user_data, sdk_client):
result = sdk_client.functions.execute(
"process-large-dataset",
params={"dataset_id": 123},
is_async=True
)
task_id = result['invocation']['celery_task_id']
return {"task_started": True, "task_id": task_id}
Get Async Result:
def main(params, user_data, sdk_client):
task_id = params.get("task_id")
result = sdk_client.functions.get_result(task_id)
return {
"status": result['data']['status'],
"result": result['data'].get('result')
}
List Functions:
def main(params, user_data, sdk_client):
functions = sdk_client.functions.list(limit=10)
return {"functions": functions['data']}
Secrets Module
Access secrets securely without hardcoding credentials.
Methods
sdk_client.secrets.get_secret(key, app=None, tags=None)
sdk_client.secrets.get_secrets(keys, app=None)
sdk_client.secrets.list_secrets(search=None, app=None, tags=None, secret_type=None, page=1, page_size=20)
sdk_client.secrets.update(key, value)
Examples
Get Single Secret:
def main(params, user_data, sdk_client):
api_key = sdk_client.secrets.get_secret("SENDGRID_API_KEY")
# Use the secret
send_email_with_api_key(api_key["value"])
return {"sent": True}
Get Multiple Secrets:
def main(params, user_data, sdk_client):
secrets = sdk_client.secrets.get_secrets([
"SENDGRID_API_KEY",
"STRIPE_SECRET_KEY",
"AWS_ACCESS_KEY"
])
sendgrid_key = secrets["SENDGRID_API_KEY"]["value"]
stripe_key = secrets["STRIPE_SECRET_KEY"]["value"]
return {"keys_loaded": True}
List Secrets:
def main(params, user_data, sdk_client):
secrets = sdk_client.secrets.list_secrets(
search="API",
tags=["production"]
)
return {"secrets": secrets['data']}
⚠️ Critical Rules
- Never hardcode secrets in function code
- Always use get_secret() to retrieve credentials
- Handle missing secrets gracefully with try/except
- Never log secret values - only log keys
Analytics Module
Execute saved analytics queries with parameters.
Methods
sdk_client.analytics.execute(query_slug, params=None)
Returns
{
"data": [...], # Query results
"total": 100, # Row count
"execution_key": "..." # Execution tracking key
}
Examples
Simple Query Execution:
def main(params, user_data, sdk_client):
result = sdk_client.analytics.execute("monthly-revenue")
return {"revenue": result["data"]}
Query with Parameters:
def main(params, user_data, sdk_client):
result = sdk_client.analytics.execute(
"user-signups",
params={
"start_date": "2024-01-01",
"end_date": "2024-12-31",
"group_by": "month"
}
)
return {
"signups": result["data"],
"total": result["total"]
}
Query with Dynamic Filters:
def main(params, user_data, sdk_client):
region = params.get("region", "US")
category = params.get("category", "all")
result = sdk_client.analytics.execute(
"sales-by-region",
params={
"region": region,
"product_category": category
}
)
return result["data"]
Notes
- Queries must be created first (use MCP analytics tools or API)
- Supports Jinja2 templating in query definitions
- Uses secrets for database credentials
- Results are cached based on execution_key
Storage Module
Upload, download, and manage files in storage buckets.
Methods
sdk_client.storage.list_buckets()
sdk_client.storage.create_bucket(name, description=None)
sdk_client.storage.get_bucket(name)
sdk_client.storage.update_bucket(name, data)
sdk_client.storage.delete_bucket(name)
# Bucket operations (chainable)
sdk_client.storage.from_(bucket_name).upload(files, paths)
sdk_client.storage.from_(bucket_name).download(path)
sdk_client.storage.from_(bucket_name).list()
sdk_client.storage.from_(bucket_name).delete(paths)
Examples
Upload File:
def main(params, user_data, sdk_client):
with open("report.pdf", "rb") as f:
result = sdk_client.storage.from_("documents").upload(
files=[("report.pdf", f)],
paths=["uploads/report.pdf"]
)
return {"uploaded": True, "path": result[0]["path"]}
Download File:
def main(params, user_data, sdk_client):
file_path = params.get("file_path")
file_data = sdk_client.storage.from_("documents").download(file_path)
# Process file_data
return {"downloaded": True, "size": len(file_data)}
List Files:
def main(params, user_data, sdk_client):
files = sdk_client.storage.from_("documents").list()
return {"files": files, "total": len(files)}
Delete Files:
def main(params, user_data, sdk_client):
paths = params.get("paths", [])
sdk_client.storage.from_("documents").delete(paths)
return {"deleted": True, "count": len(paths)}
Create Bucket:
def main(params, user_data, sdk_client):
bucket = sdk_client.storage.create_bucket(
name="user-uploads",
description="User uploaded documents"
)
return {"created": True, "bucket": bucket}
Users Module
Manage users and retrieve user information.
Methods
sdk_client.users.list_users(search=None, is_active=None, is_staff=None, roles=None, page=1, page_size=20)
sdk_client.users.get_user(username)
sdk_client.users.create_user(username, email, password, ...)
sdk_client.users.update_user(username, data)
sdk_client.users.delete_user(username)
Examples
Get User:
def main(params, user_data, sdk_client):
username = params.get("username")
user = sdk_client.users.get_user(username)
return {"user": user}
List Users:
def main(params, user_data, sdk_client):
users = sdk_client.users.list_users(
search="alice",
is_active=True,
page=1,
page_size=10
)
return {"users": users['data'], "total": users['total']}
Create User:
def main(params, user_data, sdk_client):
new_user = sdk_client.users.create_user(
username=params.get("username"),
email=params.get("email"),
password=params.get("password"),
first_name=params.get("first_name"),
last_name=params.get("last_name")
)
return {"created": True, "user": new_user}
Update User:
def main(params, user_data, sdk_client):
username = params.get("username")
updated_user = sdk_client.users.update_user(username, {
"first_name": params.get("first_name"),
"is_active": True
})
return {"updated": True, "user": updated_user}
Policy Module
Check authorization permissions and filter allowed resources.
Methods
sdk_client.policy.check_resources(resources, principal, aux_data=None)
sdk_client.policy.filter_allowed(principal, resources, actions)
Examples
Check Permissions:
def main(params, user_data, sdk_client):
result = sdk_client.policy.check_resources(
resources=[{
"resource": {
"kind": "datatable",
"id": "users"
},
"actions": ["read", "write"]
}],
principal={
"id": user_data["id"],
"roles": ["user"],
"attr": {"department": "engineering"}
}
)
can_read = result["results"][0]["actions"]["read"] == "EFFECT_ALLOW"
can_write = result["results"][0]["actions"]["write"] == "EFFECT_ALLOW"
return {"can_read": can_read, "can_write": can_write}
Filter Allowed Resources:
def main(params, user_data, sdk_client):
all_tables = [
{"kind": "datatable", "id": "users"},
{"kind": "datatable", "id": "orders"},
{"kind": "datatable", "id": "admin_logs"}
]
allowed = sdk_client.policy.filter_allowed(
principal={"id": user_data["id"], "roles": ["user"]},
resources=all_tables,
actions=["read", "write"]
)
return {"allowed_tables": allowed}
Auth Module
ℹ️ Usually not needed in APP mode functions
The sdk_client is already authenticated with the current user context.
Methods
sdk_client.auth.signInWithPassword(username, password)
sdk_client.auth.signInWithToken(token, token_type) # token_type: 'jwt', 'api_key', 'session_token'
sdk_client.auth.refreshToken(refresh_token)
sdk_client.auth.signOut()
sdk_client.auth.is_authenticated # Property
Typical Usage (Recommended)
In most cases, you don't need auth methods because sdk_client is already authenticated:
def main(params, user_data, sdk_client):
# ✅ sdk_client is already authenticated as the calling user
# ✅ Just use it directly
users = sdk_client.database.query("users").execute()
return users
Advanced Usage (If Needed)
If you need to authenticate as a different user or service account:
def main(params, user_data, sdk_client):
# Get service account API key from secrets
service_key = sdk_client.secrets.get_secret("SERVICE_ACCOUNT_KEY")
# Authenticate as service account
service_client = sdk_client.auth.signInWithToken(
token=service_key["value"],
token_type='api_key'
)
# Use service_client for privileged operations
admin_data = service_client.database.query("admin_logs").execute()
return {"admin_data": admin_data}
External SDK Usage
Auth methods are primarily for external SDK usage (scripts, CLIs, standalone apps):
# External Python script (NOT an APP mode function)
from taruvi import Client
client = Client(api_url='https://api.taruvi.cloud', app_slug='my-app')
# Authenticate
auth_client = client.auth.signInWithPassword(
username='user@example.com',
password='password'
)
# Use authenticated client
users = auth_client.database.query("users").execute()
Complete Examples
Email Notification Function
def main(params, user_data, sdk_client):
# Get parameters
recipient_id = params.get("user_id")
message = params.get("message")
# Fetch recipient from database
recipient = sdk_client.database.get("users", recipient_id)
# Get SendGrid API key from secrets
sendgrid = sdk_client.secrets.get_secret("SENDGRID_API_KEY")
# Call email function
result = sdk_client.functions.execute(
"send-email",
params={
"to": recipient["email"],
"subject": "Notification",
"body": message,
"api_key": sendgrid["value"]
}
)
return {
"sent": True,
"recipient": recipient["email"],
"message_id": result.get("message_id")
}
Data Processing Pipeline
def main(params, user_data, sdk_client):
# Get input data
dataset_id = params.get("dataset_id")
# Fetch dataset
dataset = sdk_client.database.get("datasets", dataset_id)
# Check permissions
can_process = sdk_client.policy.check_resources(
resources=[{
"resource": {"kind": "dataset", "id": dataset_id},
"actions": ["process"]
}],
principal={"id": user_data["id"], "roles": ["analyst"]}
)
if can_process["results"][0]["actions"]["process"] != "EFFECT_ALLOW":
return {"error": "Permission denied"}
# Execute processing function asynchronously
result = sdk_client.functions.execute(
"process-dataset",
params={"dataset_id": dataset_id},
is_async=True
)
# Upload results to storage
task_id = result['invocation']['celery_task_id']
return {
"processing": True,
"task_id": task_id,
"dataset": dataset["name"]
}
Report Generation Function
def main(params, user_data, sdk_client):
# Get date range from params
start_date = params.get("start_date")
end_date = params.get("end_date")
# Execute analytics query
revenue_data = sdk_client.analytics.execute(
"monthly-revenue",
params={
"start_date": start_date,
"end_date": end_date,
"group_by": "month"
}
)
# Get user signups
signup_data = sdk_client.analytics.execute(
"user-signups",
params={
"start_date": start_date,
"end_date": end_date
}
)
# Generate report content
report_content = f"""
Revenue Report
Period: {start_date} to {end_date}
Total Revenue: ${sum(r['revenue'] for r in revenue_data['data'])}
New Signups: {signup_data['total']}
"""
# Upload report to storage
with open("/tmp/report.txt", "w") as f:
f.write(report_content)
with open("/tmp/report.txt", "rb") as f:
sdk_client.storage.from_("reports").upload(
files=[("report.txt", f)],
paths=[f"reports/{start_date}_to_{end_date}.txt"]
)
return {
"report_generated": True,
"total_revenue": sum(r['revenue'] for r in revenue_data['data']),
"new_signups": signup_data['total']
}
Critical Rules
❌ Don't Do This
- Don't create new Client() - Use provided
sdk_client - Don't call auth methods -
sdk_clientis already authenticated - Don't hardcode secrets - Always use
secrets.get_secret() - Don't skip error handling - User input can be anything
- Don't assume records exist - Always check before operations
✅ Do This
- Validate all params - Check for required fields
- Handle exceptions gracefully - Use try/except blocks
- Return meaningful data - Include success flags and error messages
- Use secrets for credentials - Never hardcode API keys
- Check permissions - Use policy module when needed
- Log important events - For debugging and audit trails
Error Handling Pattern
def main(params, user_data, sdk_client):
try:
# Validate params
user_id = params.get("user_id")
if not user_id:
return {"success": False, "error": "user_id is required"}
# Fetch user
user = sdk_client.database.get("users", user_id)
# Get secret
api_key = sdk_client.secrets.get_secret("API_KEY")
# Perform operation
result = perform_operation(user, api_key["value"])
return {"success": True, "result": result}
except Exception as e:
return {
"success": False,
"error": str(e),
"error_type": type(e).__name__
}
Related Documentation
- Full SDK Docs: SDK Overview
- API Reference: REST API Documentation
- Authentication: Auth Guide
- Data Service: Data Service API
- Storage: Storage API
- Functions: Functions API