Python SDK for generating WhatsApp Flows and Message Templates using LLMs
Project description
Roovy SDK
A Python SDK for generating WhatsApp Flows and Message Templates using LLMs. Generate valid, schema-compliant JSON from natural language descriptions.
Features
- 🚀 Simple API - Generate WhatsApp Flows and Message Templates with a single function call
- ✅ Schema Validation - Built-in Pydantic models ensure valid output
- 🔄 Auto-Retry - Automatic retries with error feedback for better results
- 📡 Streaming Support - Stream responses for real-time feedback
- 🔌 Provider Agnostic - Works with OpenAI, Groq, Ollama, or any OpenAI-compatible API
- 📝 Type Safe - Full type hints and Pydantic models
- 📋 Dual Output - Template generation returns both creation and send payloads
Installation
pip install roovy-sdk
Quick Start
Generate a WhatsApp Flow
from roovy_sdk import RoovyClient
client = RoovyClient(
api_key="your-api-key",
base_url="https://api.openai.com/v1", # or any OpenAI-compatible endpoint
model="gpt-4o",
)
# Generate a WhatsApp Flow from natural language
flow = client.generate(
"Create a customer feedback form with name, email, rating (1-5 stars), and comments"
)
# Access the validated flow
print(flow.model_dump_json(indent=2, by_alias=True))
Generate a Message Template
# Generate both creation + send payloads
result = client.generate_template(
"Send John a shipping notification for order ORD-456"
)
# Template creation JSON (register with Meta for approval)
print(result.creation.model_dump_json(indent=2))
# Send message JSON (ready to send to user)
print(result.send.model_dump_json(indent=2))
Smart placeholder extraction: The SDK automatically extracts values from your prompt into the send payload. If no meaningful values are found, it uses descriptive placeholders like <CUSTOMER_NAME>.
Configuration
Using Environment Variables
import os
from roovy_sdk import RoovyClient
os.environ["ROOVY_API_KEY"] = "your-api-key"
os.environ["ROOVY_BASE_URL"] = "https://api.openai.com/v1"
os.environ["ROOVY_MODEL"] = "gpt-4o"
client = RoovyClient()
Provider Examples
OpenAI:
client = RoovyClient(
api_key="sk-...",
base_url="https://api.openai.com/v1",
model="gpt-4o",
)
Groq:
client = RoovyClient(
api_key="gsk_...",
base_url="https://api.groq.com/openai/v1",
model="llama-3.3-70b-versatile",
)
Ollama (local):
client = RoovyClient(
api_key="ollama", # any non-empty string
base_url="http://localhost:11434/v1",
model="llama3.2",
)
Advanced Usage
Streaming Generation
def on_chunk(chunk: str):
print(chunk, end="", flush=True)
# Stream a flow
flow = client.generate_stream(
"Create a booking form for a concert",
on_chunk=on_chunk,
)
# Stream a template
result = client.generate_template_stream(
"Create a promotional offer template with image",
on_chunk=on_chunk,
)
Custom Retry Settings
flow = client.generate(
"Create a survey form",
max_retries=5,
temperature=0.3,
)
Custom System Prompt
flow = client.generate(
"Create a registration form",
system_prompt="You are a WhatsApp Flows expert...",
)
Direct Schema Access
from roovy_sdk.schema import (
WhatsAppFlow,
Screen,
TextInput,
Footer,
validate_flow,
)
# Build flows programmatically
screen = Screen(
id="WELCOME",
title="Welcome",
layout=SingleColumnLayout(
type="SingleColumnLayout",
children=[
TextHeading(type="TextHeading", text="Hello!"),
]
)
)
# Validate any JSON against the schema
result = validate_flow({"version": "7.2", "screens": [...]})
if result["success"]:
flow = result["data"]
Template Validation
from roovy_sdk import validate_template_result
result = validate_template_result({
"creation": {"name": "my_template", "category": "UTILITY", "components": [...]},
"send": {"messaging_product": "whatsapp", "to": "...", "type": "template", "template": {...}}
})
if result["success"]:
template = result["data"] # TemplateResult object
Schema Reference
Flow Components
The SDK includes complete Pydantic models for all WhatsApp Flow components:
Text: TextHeading, TextSubheading, TextBody, TextCaption
Input: TextInput, TextArea, Dropdown, RadioButtonsGroup, ChipsSelector, CheckboxGroup, OptIn
Date/Media: CalendarPicker, DatePicker, PhotoPicker, DocumentPicker, Image
Navigation: Footer, Button, EmbeddedLink
Conditional: If, Switch
Container: Form, SingleColumnLayout
Template Components
Result: TemplateResult (contains .creation and .send)
Creation: TemplateCreation, HeaderComponent, BodyComponent, FooterComponent, ButtonsComponent
Buttons: QuickReplyButton, UrlButton, PhoneNumberButton
Send: TemplateSend, SendComponent, TextParameter, ImageParameter, VideoParameter, DocumentParameter
Supported Template Types
| Type | Category | Description |
|---|---|---|
| Text only | UTILITY / MARKETING | Body with {{N}} placeholders |
| Header Text | UTILITY | Static text header + body |
| Image Header | MARKETING | Image header + body |
| Document Header | UTILITY | Document attachment + body |
| Video Header | MARKETING | Video header + body |
| Quick Reply Buttons | UTILITY | Up to 3 quick reply buttons |
| URL Button | MARKETING | Up to 2 URL buttons |
| Call Button | UTILITY | 1 phone number button |
| Authentication (OTP) | AUTHENTICATION | OTP verification message |
API Reference
RoovyClient
RoovyClient(
api_key: str | None = None, # API key (or ROOVY_API_KEY env var)
base_url: str | None = None, # Base URL (or ROOVY_BASE_URL env var)
model: str | None = None, # Model name (or ROOVY_MODEL env var)
)
client.generate()
client.generate(
prompt: str, # Natural language description
*,
max_retries: int = 3, # Number of retry attempts
temperature: float = 0.2, # LLM temperature
system_prompt: str | None = None, # Custom system prompt
) -> WhatsAppFlow
client.generate_stream()
client.generate_stream(
prompt: str, # Natural language description
on_chunk: Callable[[str], None] | None = None, # Chunk callback
*,
temperature: float = 0.2, # LLM temperature
system_prompt: str | None = None, # Custom system prompt
) -> WhatsAppFlow
client.generate_template()
client.generate_template(
prompt: str, # Natural language description
*,
max_retries: int = 3, # Number of retry attempts
temperature: float = 0.2, # LLM temperature
system_prompt: str | None = None, # Custom system prompt
) -> TemplateResult # Has .creation and .send properties
client.generate_template_stream()
client.generate_template_stream(
prompt: str, # Natural language description
on_chunk: Callable[[str], None] | None = None, # Chunk callback
*,
temperature: float = 0.2, # LLM temperature
system_prompt: str | None = None, # Custom system prompt
) -> TemplateResult
validate_flow()
from roovy_sdk import validate_flow
result = validate_flow(flow_dict)
# Returns: {"success": True, "data": WhatsAppFlow} or {"success": False, "error": ValidationError}
validate_template_result()
from roovy_sdk import validate_template_result
result = validate_template_result(template_dict)
# Returns: {"success": True, "data": TemplateResult} or {"success": False, "error": ValidationError}
Changelog
v0.3.2 (2026-03-03)
🔧 FLOW Button Support
- Fixed:
generate_template()now correctly handles FLOW button templates — send payload includessub_type: "flow",index, andactionparameter withflow_token - New:
FlowButtoncreation model —{type: FLOW, text, flow_id, flow_action, navigate_screen} - New:
FlowAction+FlowActionParametermodels for FLOW button send components - Updated:
SendComponent.sub_typenow accepts"flow"in addition to"quick_reply"and"url" - Updated:
SendComponent.indexis nowstr(wasint) — Meta API requires string indexes ("0","1") - Updated:
ButtonsComponentvalidation enforces max 1 FLOW button
v0.3.1 (2026-03-03)
📖 Documentation & PyPI Update
- Updated: README with full template generation documentation, API reference, and usage examples
- Added: Changelog to PyPI project page
v0.3.0 (2026-03-03)
🎉 Message Template Generation
- New:
client.generate_template()— Generate WhatsApp Message Templates from natural language - New:
client.generate_template_stream()— Streaming version of template generation - New:
TemplateResult— Returns both template creation JSON (for Meta approval) and send message JSON - New: Smart placeholder extraction — auto-extracts values from prompts into send payload parameters
- New:
template_schema.py— Complete Pydantic models for all template types (Text, Image, Document, Video headers; Quick Reply, URL, Call buttons; OTP/Authentication) - New: Built-in validation for button limits (max 3 Quick Reply, max 2 URL, max 1 Call)
- New:
validate_template_result()andvalidate_template_creation()helpers
v0.2.3 (2026-03-03)
🔧 Terminal Screen Fix
- Fixed: Terminal screen in generated flows now shows a thank-you/confirmation message instead of a data review screen
- Fixed: System prompt updated with explicit Rule #9 — terminal screens must NOT display user data back as TextBody lines
- Fixed: Working example in system prompt corrected to use
"🎉 Booking Confirmed!"pattern - Added:
"success": trueto terminal screen in examples
v0.2.2 (2026-03-02)
📦 Initial Public Release
- WhatsApp Flow generation from natural language via
client.generate() - Streaming support via
client.generate_stream() - Complete Pydantic schema for all WhatsApp Flow components (v6.3–v7.2)
- Auto-retry with validation error feedback
- Provider agnostic — works with OpenAI, Groq, Ollama, or any OpenAI-compatible API
- Bundled WhatsApp Flows documentation for enhanced LLM context
validate_flow()helper for validating arbitrary JSON
License
MIT License - see LICENSE for details.
Project details
Release history Release notifications | RSS feed
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 roovy_sdk-0.3.3.tar.gz.
File metadata
- Download URL: roovy_sdk-0.3.3.tar.gz
- Upload date:
- Size: 25.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
821aa35a8dcaec6de1142f717f10a0a7aaf06a169f407766699d02d615e85039
|
|
| MD5 |
39f8efa694ce706f863a3d4eebdcb3bf
|
|
| BLAKE2b-256 |
720ffc85845733a500f88b2d5be57ae146d6c95465207c6e3e1f449735b20fb3
|
File details
Details for the file roovy_sdk-0.3.3-py3-none-any.whl.
File metadata
- Download URL: roovy_sdk-0.3.3-py3-none-any.whl
- Upload date:
- Size: 28.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
57ce75095a4bf09cf8bbe4b2b16d35ea84cfc04c636e758d6f2b97caa2fc7467
|
|
| MD5 |
1badb2ce72c9df7fe7639b82806552c5
|
|
| BLAKE2b-256 |
abace7012c4a81bf9c29f7d3359ce2ddab73159f02fd0c835009ebdc4b254301
|