Skip to main content

Official AI Prompt

Use this prompt to generate a complete saga with Claude, ChatGPT, Cursor, or any other AI.


The Prompt

Copy and paste, replacing [YOUR CONTEXT] with your business flow description:

You will help me implement Sagaweaw in my Spring Boot project.

Sagaweaw is a Java/Kotlin library for distributed transaction orchestration
with automatic compensation. Developers define steps using a fluent builder.
The engine handles persistence, exponential retry, reverse-order compensation,
and a REST observability API (/api/sagas, /api/dead-letters) protected by token.

## Rules — follow these exactly:

- Steps with .compensate() are automatically COMPENSABLE (reversible)
- Steps without .compensate() are automatically PIVOT (point of no return)
- Steps with infinite retry and no compensate() are automatically RETRIABLE
- Never use @Transactional on the Saga class — the engine manages transactions
- The context (SagaContext) carries state between steps
- Use mutable fields (var in Kotlin, non-final in Java) for step outputs in the context

## Two ways to develop and test the saga:

### Case 1 — Saga with no real database dependencies
Add @AutoStart and implement SagaSampler<Context> to provide sample data.
The saga fires automatically on startup when sagaweaw.auto-start.enabled=true.
Sample data does not need to reference real database IDs.

### Case 2 — Saga that needs real database data
Use the built-in trigger endpoint (POST /api/sagas/trigger/{sagaName})
with a real JSON payload containing existing IDs from the database.

## My project context:

[YOUR CONTEXT]

## Based on my context, generate:

1. Which business flow should be a Saga and why
2. The ordered list of steps with their compensations
3. Which step is the PIVOT (point of no return) and why
4. The complete Saga class in [Java / Kotlin — specify which]
5. Whether Case 1 or Case 2 applies for local testing, and why
6. If Case 1 applies: the sampleContext() implementation
7. How to fire the saga from the existing service in production (sagaManager.start())

Example

Input

[YOUR CONTEXT]

I have an e-commerce with:
- InventoryService: reserve(productId, qty) / release(productId, qty)
- PaymentService: charge(customerId, amount) / refund(chargeId)
- ShippingService: schedule(orderId, address) — cannot be cancelled automatically
- NotificationService: sendConfirmation(orderId, email) — must always succeed

I want a saga to process orders. Using Kotlin.

Expected Output

The AI will generate:

Flow analysis:

  • reserve-stock → compensate: release-stock
  • charge-payment → compensate: refund-payment
  • schedule-shippingPIVOT (once scheduled, cannot be automatically cancelled)
  • send-confirmationRETRIABLE (must always succeed, infinite retry)

Case 1 applies — this saga doesn't depend on real DB IDs, so @AutoStart + sampleContext() works.

Complete Kotlin class:

@Saga("order-processing")
@AutoStart
@Component
class OrderProcessingSaga(
private val inventoryService: InventoryService,
private val paymentService: PaymentService,
private val shippingService: ShippingService,
private val notificationService: NotificationService,
) : SagaDefinition<OrderProcessingSaga.Context>,
SagaSampler<OrderProcessingSaga.Context> {

data class Context(
val orderId: UUID,
val customerId: UUID,
val productId: UUID,
val quantity: Int,
val amount: BigDecimal,
val email: String,
val address: String,
var chargeId: String? = null,
) : KSagaContext() {
override fun key() = orderId.toString()
}

override fun sampleContext() = Context(
orderId = UUID.fromString("00000000-0000-0000-0000-000000000001"),
customerId = UUID.fromString("00000000-0000-0000-0000-000000000002"),
productId = UUID.fromString("00000000-0000-0000-0000-000000000003"),
quantity = 2,
amount = BigDecimal("299.90"),
email = "sample@example.com",
address = "Rua das Flores, 123",
)

override fun define(saga: SagaBuilder<Context>): SagaFlow<Context> = saga
.step("reserve-stock") {
invoke { ctx -> inventoryService.reserve(ctx.productId, ctx.quantity) }
compensate { ctx -> inventoryService.release(ctx.productId, ctx.quantity) }
}
.step("charge-payment") {
invoke { ctx ->
ctx.chargeId = paymentService.charge(ctx.customerId, ctx.amount)
}
compensate { ctx ->
ctx.chargeId?.let { paymentService.refund(it) }
}
}
.step("schedule-shipping") { // PIVOT — no compensate
invoke { ctx -> shippingService.schedule(ctx.orderId, ctx.address) }
}
.step("send-confirmation") { // RETRIABLE — infinite retry
invoke { ctx -> notificationService.sendConfirmation(ctx.orderId, ctx.email) }
retry(infiniteRetry(5.seconds))
}
.build()
}

Production wiring:

@Service
class OrderService(private val sagaManager: SagaManager) {
fun placeOrder(request: OrderRequest) {
sagaManager.start<OrderProcessingSaga>(
OrderProcessingSaga.Context(
orderId = UUID.randomUUID(),
customerId = request.customerId,
productId = request.productId,
quantity = request.quantity,
amount = request.totalAmount,
email = request.email,
address = request.address,
)
)
}
}

Tips for Better Results

Do

  • Name your existing services and what each one does
  • Mention external integrations (Stripe, BACEN, Twilio, AWS SQS)
  • Say which operations are irreversible (the PIVOT candidates)
  • Mention idempotency requirements
  • Specify Java or Kotlin

Avoid

  • Vague descriptions like "I have a payments system"
  • Asking for sagas for operations that happen in a single database transaction
  • Forgetting to mention external service dependencies

IDE Integration

Cursor

  1. Open chat (Cmd+K / Ctrl+K)
  2. Paste the prompt with your context
  3. Review and apply the generated code

GitHub Copilot

  1. Create a saga-prompt.md with the prompt text
  2. Open Copilot Chat and reference the file
  3. Ask it to generate based on your services

Additional Resources