This skill should be used when the user asks about "workflow patterns", "saga pattern", "state machine workflow", "Continue-As-New", "deterministic workflow", "long-running workflow", "workflow design", or needs guidance on structuring Temporal workflows for specific business scenarios.
From timelordnpx claudepluginhub therealbill/mynet --plugin timelordThis skill uses the workspace's default tool permissions.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
Guidance for designing and implementing Temporal workflow patterns in Go and Python.
All Temporal workflows must be deterministic. The same inputs must always produce the same sequence of commands.
Determinism Rules:
time.Now() - use workflow.Now(ctx)rand - use workflow.SideEffect() for random valuesworkflow.SideEffect()workflow.Go() for concurrencyAllowed Operations:
workflow.ExecuteActivity()workflow.ExecuteChildWorkflow()workflow.Sleep() and workflow.NewTimer()workflow.GetSignalChannel()workflow.SetQueryHandler()workflow.ExecuteLocalActivity()workflow.NewNexusClient() and client.ExecuteOperation()Implement distributed transactions with compensating actions for rollback.
When to Use:
Go Implementation:
func OrderSagaWorkflow(ctx workflow.Context, order Order) error {
var compensations []func(context.Context) error
// Step 1: Reserve inventory
err := workflow.ExecuteActivity(ctx, ReserveInventory, order).Get(ctx, nil)
if err != nil {
return err
}
compensations = append(compensations, func(ctx context.Context) error {
return ReleaseInventory(ctx, order)
})
// Step 2: Charge payment
err = workflow.ExecuteActivity(ctx, ChargePayment, order).Get(ctx, nil)
if err != nil {
return compensate(ctx, compensations)
}
compensations = append(compensations, func(ctx context.Context) error {
return RefundPayment(ctx, order)
})
// Step 3: Ship order
err = workflow.ExecuteActivity(ctx, ShipOrder, order).Get(ctx, nil)
if err != nil {
return compensate(ctx, compensations)
}
return nil
}
func compensate(ctx workflow.Context, compensations []func(context.Context) error) error {
// Execute compensations in reverse order
for i := len(compensations) - 1; i >= 0; i-- {
ao := workflow.ActivityOptions{StartToCloseTimeout: time.Minute}
actCtx := workflow.WithActivityOptions(ctx, ao)
workflow.ExecuteActivity(actCtx, compensations[i]).Get(ctx, nil)
}
return errors.New("saga rolled back")
}
Explicit state transitions controlled by signals.
When to Use:
Go Implementation:
type OrderState string
const (
StatePending OrderState = "pending"
StateApproved OrderState = "approved"
StateShipped OrderState = "shipped"
StateCancelled OrderState = "cancelled"
)
func OrderStateMachineWorkflow(ctx workflow.Context, orderID string) error {
state := StatePending
workflow.SetQueryHandler(ctx, "getState", func() (OrderState, error) {
return state, nil
})
approvalCh := workflow.GetSignalChannel(ctx, "approve")
shipCh := workflow.GetSignalChannel(ctx, "ship")
cancelCh := workflow.GetSignalChannel(ctx, "cancel")
for state != StateShipped && state != StateCancelled {
selector := workflow.NewSelector(ctx)
selector.AddReceive(approvalCh, func(c workflow.ReceiveChannel, more bool) {
if state == StatePending {
state = StateApproved
}
})
selector.AddReceive(shipCh, func(c workflow.ReceiveChannel, more bool) {
if state == StateApproved {
state = StateShipped
}
})
selector.AddReceive(cancelCh, func(c workflow.ReceiveChannel, more bool) {
if state != StateShipped {
state = StateCancelled
}
})
selector.Select(ctx)
}
return nil
}
Workflow representing a business entity with long lifecycle.
When to Use:
Key Consideration: Use Continue-As-New to prevent history growth.
func CustomerEntityWorkflow(ctx workflow.Context, customer Customer) error {
// Set up query handlers
workflow.SetQueryHandler(ctx, "getCustomer", func() (Customer, error) {
return customer, nil
})
eventCh := workflow.GetSignalChannel(ctx, "event")
eventCount := 0
maxEvents := 1000 // Trigger Continue-As-New
for {
selector := workflow.NewSelector(ctx)
selector.AddReceive(eventCh, func(c workflow.ReceiveChannel, more bool) {
var event CustomerEvent
c.Receive(ctx, &event)
customer = processEvent(customer, event)
eventCount++
})
selector.Select(ctx)
// Continue-As-New to manage history size
if eventCount >= maxEvents {
return workflow.NewContinueAsNewError(ctx, CustomerEntityWorkflow, customer)
}
}
}
Reset workflow history while preserving state.
When to Use:
History Size Guidelines:
| Scenario | Recommended Threshold |
|---|---|
| Simple workflows | 10,000 events |
| Complex workflows | 5,000 events |
| High-frequency signals | 1,000 events |
func BatchProcessorWorkflow(ctx workflow.Context, cursor string) error {
for i := 0; i < 100; i++ {
var result BatchResult
err := workflow.ExecuteActivity(ctx, ProcessBatch, cursor).Get(ctx, &result)
if err != nil {
return err
}
cursor = result.NextCursor
if result.Done {
return nil
}
}
// Continue with new history, preserving cursor
return workflow.NewContinueAsNewError(ctx, BatchProcessorWorkflow, cursor)
}
Decompose complex workflows into smaller, manageable units.
When to Use:
func ParentWorkflow(ctx workflow.Context, orders []Order) error {
var futures []workflow.ChildWorkflowFuture
// Launch child workflows in parallel
for _, order := range orders {
cwo := workflow.ChildWorkflowOptions{
WorkflowID: "order-" + order.ID,
}
childCtx := workflow.WithChildOptions(ctx, cwo)
future := workflow.ExecuteChildWorkflow(childCtx, ProcessOrderWorkflow, order)
futures = append(futures, future)
}
// Wait for all children
for _, future := range futures {
if err := future.Get(ctx, nil); err != nil {
// Handle individual order failure
workflow.GetLogger(ctx).Error("Order failed", "error", err)
}
}
return nil
}
Recurring workflow executions on a schedule.
Configuration:
func main() {
c, _ := client.Dial(client.Options{})
options := client.StartWorkflowOptions{
ID: "daily-report",
TaskQueue: "reports",
CronSchedule: "0 9 * * *", // 9 AM daily
}
c.ExecuteWorkflow(context.Background(), options, DailyReportWorkflow)
}
Cron Workflow Best Practice:
func DailyReportWorkflow(ctx workflow.Context) error {
// Each cron run gets workflow.Now() as start time
reportDate := workflow.Now(ctx)
// Process report for this execution
err := workflow.ExecuteActivity(ctx, GenerateReport, reportDate).Get(ctx, nil)
// Cron workflows should complete, not loop
return err
}
Invoke workflows in other namespaces through typed service contracts with durable execution guarantees.
When to Use:
When NOT to Use:
Go Implementation (Caller):
func OrderWorkflow(ctx workflow.Context, order Order) (*OrderResult, error) {
nexusClient := workflow.NewNexusClient("payments-endpoint", "payment-service")
future := nexusClient.ExecuteOperation(ctx, "charge", ChargeInput{
OrderID: order.ID,
Amount: order.Total,
}, workflow.NexusOperationOptions{
ScheduleToCloseTimeout: 5 * time.Minute,
})
var chargeResult ChargeOutput
if err := future.Get(ctx, &chargeResult); err != nil {
return nil, fmt.Errorf("payment failed: %w", err)
}
return &OrderResult{PaymentID: chargeResult.TransactionID}, nil
}
Never do these in workflow code:
// WRONG: Non-deterministic time
deadline := time.Now().Add(time.Hour)
// CORRECT: Use workflow time
deadline := workflow.Now(ctx).Add(time.Hour)
// WRONG: Direct random
id := uuid.New().String()
// CORRECT: SideEffect for randomness
var id string
workflow.SideEffect(ctx, func(ctx workflow.Context) interface{} {
return uuid.New().String()
}).Get(&id)
// WRONG: Goroutines
go processItem(item)
// CORRECT: Workflow goroutines
workflow.Go(ctx, func(ctx workflow.Context) {
processItem(ctx, item)
})
| Requirement | Pattern |
|---|---|
| Multi-service transaction with rollback | Saga |
| Discrete states with signal-driven transitions | State Machine |
| Long-lived business entity | Entity + Continue-As-New |
| Processing large datasets | Batch + Continue-As-New |
| Recurring scheduled tasks | Cron |
| Complex workflow decomposition | Child Workflows |
| Cross-namespace durable communication | Nexus Operations |
For detailed examples and advanced patterns, consult:
references/saga-examples.md - Complete saga implementationsreferences/state-machine-examples.md - State machine variationsWorking code examples in examples/:
order-saga.go - E-commerce saga workflowapproval-state-machine.go - Document approval workflow