Skip to content

MARKET: E-commerce — Returns Fraud Detection & Processing ​

examples/42-market-ecommerce.halo policies |* parallel |! people

Automate return requests — detect fraud patterns, verify purchase history, process legitimate returns, escalate suspicious ones to loss prevention

Open in the playground →

halo
// ============================================================
// MARKET: E-commerce — Returns Fraud Detection & Processing
// PURPOSE: Automate return requests — detect fraud patterns,
//          verify purchase history, process legitimate returns,
//          escalate suspicious ones to loss prevention
// ============================================================

// --- Policies ---
policy PII           : Redact(CreditCard) & Redact(SSN)
policy FraudPolicy   : Block(RefundAbuse) & Block(WardrobeReturn)
policy CostGuard     : MaxSpend(0.50)

// --- Tools ---
tool OrdersAPI     : REST("api.shopify.com/admin/orders", apiKey: Env.SHOPIFY_KEY)
tool PaymentGW     : POST("api.stripe.com/v1/refunds", apiKey: Env.STRIPE_KEY)
tool CXSlack       : POST("hooks.slack.com/services/cx-team")

// --- Store ---
tool ReturnHistory  : VectorStore(Env.PINECONE_KEY, namespace: "return-patterns")
tool FraudSignals   : VectorStore(Env.PINECONE_KEY, namespace: "fraud-indicators")

// --- Struct ---
schema ReturnDecision {
  approved       : Boolean
  refund_amount  : Number
  fraud_score    : Number
  action         : String
}

// --- Agents ---
agent ReturnBot [openai/gpt-4o-mini, temp: 0.0]
  equips OrdersAPI, PaymentGW
  requires PII, CostGuard

agent FraudDetector [anthropic/claude-sonnet-4, temp: 0.0]
  equips ReturnHistory, FraudSignals
  requires PII, FraudPolicy, CostGuard

// --- The Pipeline ---
@timeout(2m)
@retry(2, 5s)
pipeline ProcessReturn(request: ReturnRequest) -> ReturnDecision:
  request
    // Step 1: Fan-out — verify order and check fraud signals in parallel
    |* {
         ReturnBot.verify_order(
           tool: OrdersAPI,
           order_id: context.data.request.order_id,
           customer_id: context.data.request.customer_id
         ),
         FraudDetector.score_risk(
           customer_id: context.data.request.customer_id,
           return_reason: context.data.request.reason,
           item_value: context.data.request.item_price,
           days_since_purchase: context.data.request.days_owned
         )
       }

    // Step 2: Gate — if fraud score is high, escalate immediately
    |? (context.data.score_risk.fraud_score > 70)
    |> CXSlack.post(
         message: "🚩 FRAUD ALERT — manual review required",
         order: context.data.verify_order,
         fraud: context.data.score_risk,
         channel: "loss-prevention"
       )
    |! yield(CXSlack, context.data.score_risk, [context.data.verify_order], 4h)
    ~> listen(CXSlack.Reaction)

    // Step 3: Gate — auto-approve if fraud score is low and within policy
    |? (context.data.score_risk.fraud_score < 30)

    // Step 4: Process the refund
    |> ReturnBot.issue_refund(
         tool: PaymentGW,
         order_id: context.data.request.order_id,
         amount: context.data.request.item_price,
         method: "original_payment"
       )

    // Step 5: Log the return for future pattern detection
    |> ReturnHistory.log(
         customer: context.data.request.customer_id,
         amount: context.data.request.item_price,
         reason: context.data.request.reason,
         fraud_score: context.data.score_risk.fraud_score
       )

curl -fsSL https://halolang.com/install.sh | sh