Core Concepts
Essential concepts for Business-as-Code development
Understanding these core concepts is essential for mastering Business-as-Code.
The Five Pillars
Every business built with Business-as-Code is composed of five fundamental elements:
1. Entities: What Exists
Entities are the things in your business domain. They use semantic types from Schema.org, O*NET, and other vocabularies.
// Core entity types
$.Person // People (customers, employees, users)
$.Organization // Companies, businesses
$.Product // Physical or digital products
$.Service // Services offered
$.Order // Purchase orders
$.Event // Events and happenings
$.Place // Physical locations
$.CreativeWork // Content, documents
// Create entities
const customer = await $.Person.create({
$type: 'Person',
givenName: 'Alice',
familyName: 'Johnson',
email: '[email protected]',
})
const business = await $.Organization.create({
$type: 'Organization',
name: 'Acme Corp',
legalName: 'Acme Corporation LLC',
})Key principles:
- Entities are semantic (they mean something)
- Use standard vocabularies first
- Extend when necessary
- Every entity has a unique
$id - Entities carry their
$type
2. Relationships: How Things Connect
Relationships express how entities relate to each other using semantic predicates.
// Relationship patterns
$.Customer.places.Order
$.Order.contains.Product
$.Organization.employs.Person
$.Person.worksFor.Organization
$.Product.manufacturedBy.Organization
// Create relationships
await db.relate(customer, $.places, order)
await db.relate(order, $.contains, product)
await db.relate(employee, $.worksFor, company)
// Query relationships
const orders = await db.related(customer, $.places, $.Order)
const products = await db.related(order, $.contains, $.Product)
const employer = await db.related(employee, $.worksFor, $.Organization)Relationship characteristics:
- Bidirectional (every relationship has an inverse)
- Semantic (AI understands meaning)
- Queryable (navigate the graph)
- Type-safe (TypeScript enforced)
3. Events: What Happens
Events represent state changes and triggers for business logic. They use past-tense verbs.
// Common event patterns
$.Order.created
$.Payment.processed
$.Shipment.delivered
$.Customer.registered
$.Subscription.cancelled
$.Product.outOfStock
$.Invoice.sent
// Listen for events
on($.Order.created, async (order) => {
console.log('New order:', order.orderNumber)
// Handle the event
})
// Emit events
await send($.Order.created, {
$type: 'Order',
orderNumber: 'ORD-001',
customer: customer.$id,
totalPrice: 99.99,
})Event characteristics:
- Asynchronous by default
- Can trigger multiple handlers
- Can cascade (event triggers event)
- Carry semantic data
- Enable decoupled systems
4. Workflows: How to Respond
Workflows are sequences of operations triggered by events.
// Order fulfillment workflow
on($.Order.created, async (order) => {
// Step 1: Validate inventory
const available = await db.checkInventory(order.orderedItem)
if (!available) {
await send($.Order.cancel, {
order,
reason: 'out-of-stock',
})
return
}
// Step 2: Process payment
const payment = await send($.Payment.process, {
order,
amount: order.totalPrice,
})
// Step 3: Update inventory
if (payment.status === 'succeeded') {
for (const item of order.orderedItem) {
await db.decrement($.Product, item.orderItem, {
inventory: item.orderQuantity,
})
}
// Step 4: Send confirmation
await send($.Email.send, {
to: order.customer.email,
template: 'order-confirmation',
data: { order, payment },
})
// Step 5: Trigger fulfillment
await send($.Order.fulfill, { order })
}
})
// Fulfillment creates shipment
on($.Order.fulfilled, async (order) => {
const shipment = await $.Shipment.create({
$type: 'ParcelDelivery',
order: order.$id,
trackingNumber: generateTrackingNumber(),
expectedDelivery: addDays(new Date(), 3),
})
await send($.Shipment.created, shipment)
})
// Shipment notifications
on($.Shipment.created, async (shipment) => {
await send($.Email.send, {
to: shipment.order.customer.email,
template: 'shipment-notification',
data: { shipment },
})
})Workflow patterns:
- Event-driven (triggered by events)
- Composable (workflows can call workflows)
- Error-handling (try/catch, compensating actions)
- Parallel execution (Promise.all)
- Sequential chains (event cascades)
5. Decisions: What to Choose
Decisions are logic points where the business chooses between options, often powered by AI.
// Manual decision logic
on($.Order.created, async (order) => {
// Decide shipping method based on value
let shippingMethod
if (order.totalPrice > 100) {
shippingMethod = 'express'
} else if (order.customer.membershipLevel === 'premium') {
shippingMethod = 'priority'
} else {
shippingMethod = 'standard'
}
await send($.Shipment.create, {
order,
method: shippingMethod,
})
})
// AI-powered decisions
on($.Product.needsRestock, async (product) => {
// AI decides reorder quantity
const decision = await ai.decide('inventory-reorder', {
product,
salesHistory: await db.analyze($.Order, {
product,
timeRange: '90d',
}),
seasonality: await db.analyze('seasonal-trends', {
product,
category: product.category,
}),
supplier: await db.related(product, $.suppliedBy, $.Organization),
})
if (decision.shouldReorder) {
await send($.PurchaseOrder.create, {
product,
quantity: decision.recommendedQuantity,
supplier: decision.preferredSupplier,
urgency: decision.urgency,
})
}
})
// A/B testing decisions
on($.Customer.visits, async (customer) => {
// Decide which variant to show
const variant = await ai.decide('ab-test', {
test: 'homepage-v2',
customer,
segmentation: customer.segment,
})
await send($.UI.render, {
customer,
variant: variant.selected,
tracking: variant.trackingId,
})
})Decision characteristics:
- Rule-based or AI-powered
- Context-aware
- Auditable (track decisions made)
- Optimizable (improve over time)
- Explainable (why this decision?)
The Semantic Graph
All entities and relationships form a knowledge graph:
Graph Queries
Navigate the graph semantically:
// Direct relationships
const orders = await db.related(customer, $.places, $.Order)
// Multi-hop queries
const manufacturers = await db.query({
start: customer,
path: $.places.Order.contains.Product.manufacturer.Organization,
})
// Traverse with filters
const recentOrders = await db.related(customer, $.places, $.Order, {
where: {
orderDate: { $gte: subDays(new Date(), 30) },
},
})
// Aggregate queries
const totalSpent = await db.aggregate(customer, {
relationship: $.places,
type: $.Order,
operation: 'sum',
field: 'totalPrice',
})Data Flow
Understanding how data flows through a Business-as-Code application:
Event Cascades
Events can trigger other events, creating workflows:
// Initial event
await send($.Order.created, order)
// Triggers workflow
on($.Order.created, async (order) => {
const payment = await send($.Payment.process, { order })
// Emits $.Payment.processed
})
// Which triggers next workflow
on($.Payment.processed, async (payment) => {
await send($.Order.fulfill, { order: payment.order })
// Emits $.Order.fulfilled
})
// Which triggers fulfillment
on($.Order.fulfilled, async (order) => {
await send($.Shipment.create, { order })
// Emits $.Shipment.created
})
// And so on...
on($.Shipment.created, async (shipment) => {
await send($.Email.send, {
/* notification */
})
})State Management
Business-as-Code uses event sourcing principles:
// State is derived from events
const order = {
$id: 'order-001',
status: 'created', // Initial state
events: [],
}
// Events change state
on($.Order.created, async (order) => {
await db.update($.Order, order.$id, {
status: 'processing',
events: [...order.events, { type: 'created', timestamp: new Date() }],
})
})
on($.Payment.processed, async (payment) => {
await db.update($.Order, payment.order.$id, {
status: 'paid',
events: [...order.events, { type: 'paid', timestamp: new Date() }],
})
})
// Query current state
const order = await db.get($.Order, orderId)
console.log(order.status) // Current state
// Replay events to reconstruct state
const history = order.events.map((e) => ({
type: e.type,
timestamp: e.timestamp,
}))Error Handling
Graceful error handling in workflows:
on($.Order.created, async (order) => {
try {
// Attempt payment
const payment = await send($.Payment.process, {
order,
amount: order.totalPrice,
})
if (payment.status === 'succeeded') {
await send($.Order.fulfill, { order })
} else {
throw new Error('Payment failed')
}
} catch (error) {
// Compensating action
await send($.Order.cancel, {
order,
reason: 'payment-error',
error: error.message,
})
// Notify customer
await send($.Email.send, {
to: order.customer.email,
template: 'order-failed',
data: { order, error },
})
// Log for analysis
await db.create($.ErrorLog, {
type: 'payment-failure',
order: order.$id,
error: error.message,
timestamp: new Date(),
})
}
})Testing Concepts
Test business logic semantically:
import { test, expect } from 'vitest'
import $, { db, on, send } from 'sdk.do'
test('order fulfillment workflow', async () => {
// Setup
const customer = await $.Person.create({
name: 'Test Customer',
email: '[email protected]',
})
const product = await $.Product.create({
name: 'Test Product',
inventory: 10,
})
// Create order
const order = await $.Order.create({
customer,
orderedItem: [
{
orderItem: product,
orderQuantity: 2,
},
],
totalPrice: 99.99,
})
// Emit event
await send($.Order.created, order)
// Wait for workflow
await waitFor(async () => {
const updatedProduct = await db.get($.Product, product.$id)
expect(updatedProduct.inventory).toBe(8)
})
// Check order status
const updatedOrder = await db.get($.Order, order.$id)
expect(updatedOrder.status).toBe('fulfilled')
})Best Practices
1. Entity Design
// Good: Rich semantic entities
const customer = await $.Person.create({
$type: 'Person',
givenName: 'Alice',
familyName: 'Johnson',
email: '[email protected]',
telephone: '+1-555-0100',
address: {
$type: 'PostalAddress',
streetAddress: '123 Main St',
addressLocality: 'Austin',
addressRegion: 'TX',
postalCode: '78701',
},
membershipLevel: 'premium',
joinDate: new Date(),
})
// Avoid: Minimal data
const user = { name: 'Alice', email: '[email protected]' }2. Event Naming
// Good: Past tense, specific
$.Order.created
$.Payment.processed
$.Shipment.delivered
$.Customer.registered
// Avoid: Present tense or vague
$.Order.create
$.Payment.process
$.Shipment.deliver
$.Customer.signup3. Workflow Organization
// Good: Single responsibility
on($.Order.created, handleOrderCreation)
on($.Payment.processed, handlePaymentProcessed)
on($.Order.fulfilled, handleOrderFulfilled)
// Avoid: God workflows
on($.Order.created, async (order) => {
// 500 lines of code handling everything
})4. Decision Documentation
// Good: Document decision logic
on($.Product.needsRestock, async (product) => {
const decision = await ai.decide('inventory-reorder', {
product,
// Document what data AI uses
salesHistory: await db.analyze($.Order, { product, timeRange: '90d' }),
seasonality: await db.analyze('seasonal-trends', { product }),
leadTime: product.supplier.leadTime,
targetStockLevel: product.reorderPoint * 2,
})
// Document why this threshold
if (decision.confidence > 0.8) {
await send($.PurchaseOrder.create, {
product,
quantity: decision.recommendedQuantity,
reasoning: decision.explanation,
})
}
})Summary
The five core concepts work together:
- Entities - Define what exists (customers, products, orders)
- Relationships - Connect entities semantically
- Events - Signal state changes
- Workflows - Respond to events
- Decisions - Choose actions (manual or AI)
Together, they form an autonomous business that:
- Understands itself (semantic entities)
- Connects naturally (semantic relationships)
- Reacts automatically (event-driven)
- Operates intelligently (AI decisions)
- Scales seamlessly (distributed workflows)
Next: Autonomous Operations →