Define a state schema
from polos import WorkflowState
class ShoppingCartState(WorkflowState):
items: list[dict] = []
total: float = 0.0
import { z } from 'zod';
const ShoppingCartStateSchema = z.object({
items: z.array(z.record(z.unknown())).default([]),
total: z.number().default(0),
});
type ShoppingCartState = z.infer<typeof ShoppingCartStateSchema>;
Create a stateful workflow
from polos import workflow, WorkflowContext
@workflow(id="shopping_cart", state_schema=ShoppingCartState)
async def shopping_cart(ctx: WorkflowContext, payload: CartPayload):
if payload.action == "add" and payload.item:
ctx.state.items.append(payload.item.model_dump())
ctx.state.total += payload.item.price * payload.item.quantity
elif payload.action == "remove" and payload.item_id:
for i, item in enumerate(ctx.state.items):
if item.get("id") == payload.item_id:
ctx.state.total -= item["price"] * item["quantity"]
ctx.state.items.pop(i)
break
elif payload.action == "clear":
ctx.state.items = []
ctx.state.total = 0.0
return {"items": ctx.state.items, "total": ctx.state.total}
import { defineWorkflow } from '@polos/sdk';
const shoppingCartWorkflow = defineWorkflow<CartPayload, ShoppingCartState, CartResult>(
{ id: 'shopping_cart', stateSchema: ShoppingCartStateSchema },
async (ctx, payload) => {
if (payload.action === 'add' && payload.item) {
ctx.state.items.push({
id: payload.item.id,
name: payload.item.name,
price: payload.item.price,
quantity: payload.item.quantity,
});
ctx.state.total += payload.item.price * payload.item.quantity;
} else if (payload.action === 'remove' && payload.itemId) {
const idx = ctx.state.items.findIndex((item) => item['id'] === payload.itemId);
if (idx >= 0) {
const item = ctx.state.items[idx]!;
ctx.state.total -= (Number(item['price']) || 0) * (Number(item['quantity']) || 1);
ctx.state.items.splice(idx, 1);
}
} else if (payload.action === 'clear') {
ctx.state.items = [];
ctx.state.total = 0;
}
return { items: ctx.state.items, total: ctx.state.total };
},
);
Initialize with state
# Start workflow with initial state
handle = await polos.invoke(
"shopping_cart",
payload={"action": "add", "item": {...}},
initial_state={"items": [], "total": 0.0},
)
// Start workflow with initial state
const handle = await polos.invoke(
'shopping_cart',
{ action: 'add', item: { /* ... */ } },
{ initialState: { items: [], total: 0 } },
);
Run it
git clone https://github.com/polos-dev/polos.git
cd polos/python-examples/10-state-persistence
cp .env.example .env # Add your POLOS_PROJECT_ID and API key
uv sync
python main.py
git clone https://github.com/polos-dev/polos.git
cd polos/typescript-examples/10-state-persistence
cp .env.example .env # Add your POLOS_PROJECT_ID and API key
npm install
npx tsx main.ts