Track, validate, and visualize business flows in production applications.
Business-Use is a lightweight framework for ensuring your critical business workflows execute correctly in production. Define expected flows, track events as they happen, and automatically validate that your business logic works as intended.
business-use.mp4
Traditional monitoring tells you what happened. Business-Use tells you if it happened correctly.
from business_use import initialize, ensure
# Define your business flow expectations
ensure(
id="payment_processed",
flow="checkout",
run_id=order_id,
data={"amount": 99.99, "status": "completed"}
)
ensure(
id="inventory_updated",
flow="checkout",
run_id=order_id,
data={"product_id": "abc", "quantity": -1},
validator=lambda data, ctx: data["quantity"] < 0, # Validate inventory decreased
description="Inventory should decrease after order"
)Business-Use automatically validates:
- ✅ Events happened in the correct order
- ✅ Dependencies between steps were satisfied
- ✅ Time constraints were met
- ✅ Business rules were validated
- ✅ No steps were skipped
- 🔍 Flow Validation: Ensure events happen in the correct order with proper dependencies
- ⚡ Zero Overhead: Asynchronous batching means no blocking I/O in your application
- 🛡️ Never Fails: SDK errors are caught internally - your application never crashes
- 🎯 End-to-End Testing: Trigger flows and validate execution with the
ensurecommand - 📊 Visualization: Interactive UI to explore flow graphs and debug failures
- 🔧 Type-Safe: Full TypeScript support with automatic type inference
- 🚀 Production Ready: Used in production, handles high-throughput workloads
- ⏱️ Time-Aware Polling: Smart timeout handling with live progress updates
# Using uvx (recommended - no installation needed)
uvx business-use-core init # Interactive setup (first time only)
uvx business-use-core server dev # Start development server
# Or install globally
pip install business-use-core
business-use init
business-use server devThe backend runs at http://localhost:13370
Python:
pip install business-useJavaScript/TypeScript:
pnpm add @desplega.ai/business-use
# or: npm install @desplega.ai/business-usePython:
from business_use import initialize, ensure
# Initialize once at app startup
initialize(api_key="your-api-key")
# Track business events
ensure(
id="user_signup",
flow="onboarding",
run_id="user_12345",
data={"email": "user@example.com", "plan": "premium"}
)
ensure(
id="email_sent",
flow="onboarding",
run_id="user_12345",
data={"type": "welcome_email"},
dep_ids=["user_signup"],
validator=lambda data, ctx: any(d["data"]["plan"] == "premium" for d in ctx["deps"])
)JavaScript:
import { initialize, ensure } from '@desplega.ai/business-use';
// Initialize once at app startup
initialize({ apiKey: 'your-api-key' });
// Track business events
ensure({
id: 'user_signup',
flow: 'onboarding',
runId: 'user_12345',
data: { email: 'user@example.com', plan: 'premium' }
});
ensure({
id: 'email_sent',
flow: 'onboarding',
runId: 'user_12345',
data: { type: 'welcome_email' },
depIds: ['user_signup'],
validator: (data, ctx) => ctx.deps.some(d => d.data.plan === 'premium')
});Evaluate a completed flow run:
# Evaluate a specific run
business-use flow eval user_12345 onboarding --verbose
# With graph visualization
business-use flow eval user_12345 onboarding --show-graph --verbose
# HTTP API
curl -X POST http://localhost:13370/v1/run-eval \
-H "X-Api-Key: your-api-key" \
-d '{"run_id": "user_12345", "flow": "onboarding"}'Trigger and validate flows end-to-end:
# Run a single flow from trigger to completion
business-use flow ensure checkout
# Run with live progress updates
business-use flow ensure checkout --live
# Run all flows with triggers in parallel
business-use flow ensure --parallel 3
# Custom timeouts and JSON output
business-use flow ensure checkout --max-timeout 60000 --json-outputcd ui && pnpm install && pnpm dev
# Open http://localhost:5173Or you can use the automatic deployed version at business-use.com.
See the examples/ directory for complete examples:
- Python: Simple order processing flow
- JavaScript: User onboarding flow
Business-Use consists of four components:
┌─────────────┐ ┌─────────────┐
│ Python │────▶│ │
│ SDK │ │ Backend │
└─────────────┘ │ (FastAPI) │◀────┐
│ │ │
┌─────────────┐ │ SQLite DB │ │
│ JavaScript │────▶│ │ │
│ SDK │ └─────────────┘ │
└─────────────┘ │ │
│ │
┌──────▼─────┐ │
│ React UI │──────┘
│ (Optional) │
└────────────┘
- SDKs (Python/JS): Batch events asynchronously, never block your app
- Backend: Stores events, validates flows, provides evaluation API
- UI: Visualize flow graphs, explore run history, debug failures
Business-Use supports trigger nodes for automated end-to-end testing. Define trigger nodes in YAML to execute HTTP requests or commands that start your flows:
# .business-use/checkout.yaml
flow: checkout
nodes:
- id: checkout_trigger
type: trigger
handler: http_request
handler_input:
params:
url: https://api.example.com/checkout
method: POST
body:
product_id: "test-123"
run_id_extractor:
engine: python
script: "output['order_id']"
- id: payment_processed
type: act
dep_ids: [checkout_trigger]
- id: inventory_updated
type: assert
dep_ids: [payment_processed]
validator:
engine: python
script: "data['quantity'] < 0"Then run end-to-end tests:
# Test a single flow
business-use flow ensure checkout --live
# Test all flows in parallel
business-use flow ensure --parallel 5 --liveThe ensure command will:
- Execute the trigger (HTTP request or command)
- Extract the run_id from the response
- Poll the flow evaluation until it passes, fails, or times out
- Show live progress updates with remaining time
Validate that orders follow the correct flow:
cart_created → payment_initiated → payment_processed → inventory_updated → order_confirmed
Ensure onboarding steps happen in order:
signup → email_verified → profile_completed → welcome_email_sent
Track payment flows with validation:
payment_initiated → fraud_check_passed → payment_processed → receipt_sent
Validate ETL workflows:
data_extracted → data_transformed → data_validated → data_loaded
- SDK Architecture: Deep dive into SDK design and batching
- Core Architecture: Backend architecture and domain model
- CLI Reference: Complete CLI command documentation
- CLAUDE.md: Development guide for contributors
.
├── core/ # FastAPI backend + CLI
├── sdk-py/ # Python SDK
├── sdk-js/ # JavaScript/TypeScript SDK
├── ui/ # React visualization UI
└── examples/ # Example implementations
The FastAPI backend handles event ingestion, storage, and flow validation.
What it does:
- Receives events from SDKs via
/v1/events-batchendpoint - Validates event sequences against flow definitions
- Executes trigger nodes for end-to-end testing
- Manages secrets and configuration
- Provides CLI for flow management and evaluation
Key Features:
- Trigger Execution: Execute HTTP requests or bash commands to start flows
- Secrets Management: Secure storage of API keys with
${secret.KEY}syntax - YAML Flows: Declarative flow definitions in
.business-use/directory - E2E Testing:
flow ensurecommand for automated testing - Hexagonal Architecture: Clean separation of domain logic from infrastructure
Installation:
# Development (local)
cd core
uv sync
uv run business-use init # Interactive setup
uv run business-use server dev # Start with auto-reload
# Production (PyPI)
uvx business-use-core init # No installation needed
uvx business-use-core server devMain Commands:
# Server
business-use server dev # Development server with auto-reload
business-use server prod # Production server (4 workers)
# Flow Management
business-use flow ensure [flow] # Execute trigger + validate (E2E testing)
business-use flow eval <run_id> <flow> # Evaluate completed run
business-use flow graph [flow] # Show flow structure
business-use flow runs # List recent runs
# Node Management
business-use nodes sync # Sync YAML flows to database
business-use nodes validate # Validate YAML files
# Workspace
business-use workspace init # Create .business-use/ directory
# Database
business-use db migrate # Run migrationsConfiguration:
config.yaml- API key, database path, log levelsecrets.yaml- Sensitive values (gitignored).business-use/*.yaml- Flow definitions
Architecture:
domain/- Pure business logic (zero dependencies)execution/- Expression evaluation (Python/CEL/JS)adapters/- Storage implementations (SQLite)eval/- Orchestration layerapi/- FastAPI HTTP endpointsloaders/- YAML flow loaderstriggers/- Trigger executionsecrets_manager/- Secrets management
Example Flow with Trigger:
# .business-use/checkout.yaml
flow: checkout
nodes:
- id: create_order
type: trigger
handler: http_request
handler_input:
params:
url: "${API_BASE_URL}/orders"
method: POST
headers:
Authorization: "Bearer ${secret.API_KEY}"
body: '{"product": "test-123"}'
run_id_extractor:
engine: python
script: "output['order_id']"
- id: payment_processed
type: act
dep_ids: [create_order]
conditions:
- timeout_ms: 30000Development:
cd core
uv sync
uv run ruff format src/ # Format
uv run ruff check src/ --fix # Lint
uv run mypy src/ # Type checkLightweight Python SDK for tracking business events with async batching.
What it does:
- Track events from Python applications
- Batch events asynchronously in background thread
- Never fails or blocks your application code
- Thread-safe for concurrent use
Installation:
pip install business-use
# or
uv add business-useAPI Reference:
initialize(api_key, url, batch_size, batch_interval, max_queue_size)
Initialize the SDK before using ensure(). Must be called once at app startup.
Parameters:
api_key(str, optional): API key (default:BUSINESS_USE_API_KEYenv var)url(str, optional): Backend URL (default:BUSINESS_USE_URLorhttp://localhost:13370)batch_size(int): Events per batch (default: 100)batch_interval(int): Flush interval in seconds (default: 5)max_queue_size(int): Max queue size (default:batch_size * 10)
ensure(id, flow, run_id, data, filter, dep_ids, validator, description, conditions, additional_meta)
Track a business event. Type is auto-determined by validator presence.
Parameters:
id(str, required): Unique node/event identifierflow(str, required): Flow identifierrun_id(str | callable, required): Run identifier or lambdadata(dict, required): Event data payloadfilter(callable, optional): Filter function(data, ctx) -> boolevaluated on backenddep_ids(list[str] | callable, optional): Dependency node IDsvalidator(callable, optional): Validation function(data, ctx) -> boolexecuted on backend. If provided, creates "assert" node; if absent, creates "act" node.description(str, optional): Human-readable descriptionconditions(list[NodeCondition], optional): Timeout constraintsadditional_meta(dict, optional): Additional metadata
Validator Context:
Both filter and validator receive ctx parameter with:
ctx["deps"]- List of upstream dependency events:[{"flow": str, "id": str, "data": dict}, ...]
shutdown(timeout)
Gracefully shutdown and flush remaining events (optional, auto-shuts down on exit).
Example:
from business_use import initialize, ensure, NodeCondition
# Initialize
initialize(api_key="your-api-key")
# Track action (no validator)
ensure(
id="payment_processed",
flow="checkout",
run_id="order_123",
data={"amount": 100, "currency": "USD"},
dep_ids=["cart_created"]
)
# Track assertion (with validator)
def validate_total(data, ctx):
"""Validator has access to upstream events via ctx["deps"]"""
items = [d for d in ctx["deps"] if d["id"] == "item_added"]
total = sum(item["data"]["price"] for item in items)
return data["total"] == total
ensure(
id="order_total_valid",
flow="checkout",
run_id="order_123",
data={"total": 150},
dep_ids=["item_added"],
validator=validate_total, # Creates "assert" node
conditions=[NodeCondition(timeout_ms=5000)]
)
# Using filter with upstream context
def check_approved(data, ctx):
"""Filter based on upstream event data"""
return all(d["data"].get("status") == "approved" for d in ctx["deps"])
ensure(
id="order_completed",
flow="checkout",
run_id=lambda: get_current_run_id(),
data={"order_id": "ord_123"},
filter=check_approved, # Evaluated on backend
dep_ids=["payment_processed", "inventory_reserved"]
)Key Features:
- Non-blocking: Events batched and sent in background
- Never fails: All errors caught internally, never propagated to user code
- Thread-safe: Safe for concurrent use
- Context-aware: Validators/filters access upstream deps via
ctx["deps"]
Development:
cd sdk-py
uv sync
uv run pytest # Run tests
uv run python example.py # Run example
uv run ruff format src/ tests/ # Format
uv run ruff check src/ --fix # LintEnvironment Variables:
export BUSINESS_USE_API_KEY="your-api-key"
export BUSINESS_USE_URL="http://localhost:13370"Lightweight JavaScript/TypeScript SDK with full type safety and async batching.
What it does:
- Track events from JavaScript/TypeScript applications
- Batch events asynchronously in background
- Never fails or blocks your application
- Full TypeScript support with type inference
Installation:
pnpm add @desplega.ai/business-use
# or
npm install @desplega.ai/business-useAPI Reference:
initialize(options)
Initialize the SDK before using ensure().
Options:
apiKey(string, optional): API key (default:BUSINESS_USE_API_KEYenv var)url(string, optional): Backend URL (default:BUSINESS_USE_URLorhttp://localhost:13370)batchSize(number): Events per batch (default: 100)batchInterval(number): Flush interval in ms (default: 5000)maxQueueSize(number): Max queue size (default:batchSize * 10)
ensure(options)
Track a business event. Type is auto-determined by validator presence.
Options:
id(string, required): Unique node/event identifierflow(string, required): Flow identifierrunId(string | function, required): Run identifier or functiondata(object, required): Event data payloadfilter(function, optional): Filter function(data, ctx) => booleanevaluated on backenddepIds(string[] | function, optional): Dependency node IDsvalidator(function, optional): Validation function(data, ctx) => booleanexecuted on backend. If provided, creates "assert" node; if absent, creates "act" node.description(string, optional): Human-readable descriptionconditions(NodeCondition[], optional): Timeout constraintsadditional_meta(object, optional): Additional metadata
Validator Context:
Both filter and validator receive ctx parameter with:
ctx.deps- Array of upstream dependency events:[{flow: string, id: string, data: object}, ...]
shutdown(timeout)
Gracefully shutdown and flush remaining events (returns Promise).
Example:
import { initialize, ensure } from '@desplega.ai/business-use';
// Initialize
initialize({ apiKey: 'your-api-key' });
// Track action (no validator)
ensure({
id: 'payment_processed',
flow: 'checkout',
runId: 'order_123',
data: { amount: 100, currency: 'USD' },
depIds: ['cart_created']
});
// Track assertion (with validator)
ensure({
id: 'order_total_valid',
flow: 'checkout',
runId: 'order_123',
data: { total: 150 },
depIds: ['item_added'],
validator: (data, ctx) => {
// Validator has access to upstream events via ctx.deps
const items = ctx.deps.filter(d => d.id === 'item_added');
const total = items.reduce((sum, item) => sum + item.data.price, 0);
return data.total === total;
}, // Creates "assert" node
conditions: [{ timeout_ms: 5000 }]
});
// Using filter with upstream context
ensure({
id: 'order_completed',
flow: 'checkout',
runId: () => getCurrentRunId(),
data: { orderId: 'ord_123' },
filter: (data, ctx) => {
// Filter based on upstream event data
return ctx.deps.every(d => d.data.status === 'approved');
}, // Evaluated on backend
depIds: ['payment_processed', 'inventory_reserved']
});TypeScript Support:
// Full type inference
ensure({
id: 'payment',
flow: 'checkout',
runId: 'order_123',
data: { amount: 100, currency: 'USD' },
validator: (data, ctx) => {
// data and ctx are automatically typed
return data.amount > 0 && ctx.deps.length > 0;
}
});
// Explicit typing for better type safety
interface OrderData {
orderId: string;
total: number;
}
ensure<OrderData>({
id: 'order_validation',
flow: 'checkout',
runId: 'order_456',
data: { orderId: '12345', total: 200 },
validator: (data, ctx) => {
// Full autocomplete for data.orderId, data.total
return data.total > 0;
}
});Key Features:
- Zero failures: SDK errors never crash your code
- Non-blocking: Async batching prevents blocking I/O
- Type-safe: Full TypeScript with type inference
- Context-aware: Validators/filters access upstream deps via
ctx.deps
Development:
cd sdk-js
pnpm install
pnpm build # Build SDK
pnpm test # Run tests
pnpm example # Run example
pnpm typecheck # Type check
pnpm format # Format
pnpm lint:fix # LintEnvironment Variables:
export BUSINESS_USE_API_KEY="your-api-key"
export BUSINESS_USE_URL="http://localhost:13370"Interactive React application for visualizing flow graphs and exploring run history.
What it does:
- Visualize flow graphs with interactive node positioning
- Explore run history and event data
- Debug flow failures with detailed evaluation results
- Real-time updates via TanStack Query
Tech Stack:
- React 18 - UI framework
- xyflow - Flow graph visualization
- TanStack Query - Data fetching and caching
- Tailwind CSS - Styling
- TypeScript - Type safety
- Vite - Build tool
Quick Start:
cd ui
pnpm install
pnpm dev # Start dev server at http://localhost:5173Features:
- Interactive Flow Graphs: Drag nodes, zoom, pan
- Run History: Browse all flow executions
- Event Inspection: View event data and metadata
- Evaluation Results: See passed/failed nodes with details
- Real-time Updates: Auto-refresh on new data
Development:
cd ui
pnpm install
pnpm dev # Development server
pnpm build # Production build
pnpm preview # Preview build
pnpm lint # Lint
pnpm lint:fix # Lint with auto-fix
pnpm format # Format with Prettier
pnpm format:check # Check formattingProject Structure:
ui/
├── src/
│ ├── components/ # React components
│ ├── lib/ # API client, queries, types
│ └── App.tsx # Main app
├── public/ # Static assets
└── package.json
cd core
uv sync
uv run business-use server dev # Development with auto-reloadcd sdk-py
uv sync
uv run pytestcd sdk-js
pnpm install
pnpm testcd ui
pnpm install
pnpm devSee RELEASE.md for detailed release instructions.
Want to see Business-Use in action? Check out our integration examples:
- RealWorld App: Article publication and user interaction flows
- More examples coming soon!
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes with tests
- Run formatting and linting
- Commit your changes
- Push to the branch
- Open a Pull Request
MIT License - see LICENSE for details.
- GitHub Issues: https://github.com/desplega-ai/business-use/issues
- Documentation: https://github.com/desplega-ai/business-use#readme
Because production monitoring should focus on business outcomes, not just technical metrics. Track what matters: your users' journeys through your application.
Made with ❤️ by Desplega AI