In this post, we'll build an agentic Logic App that decides whether
to approve, escalate, or deny a refund. The Agent applies policy,
pauses for human approval when needed, and emails the customer
with the final decision.
Why this pattern?
Most refund flows are a mix of clear rules (auto-approve low amounts
for valid reasons) and edge cases (needs a human). Logic Apps now
support an Agent action (Azure OpenAI) that can reason, call tools,
and control the flow --- perfect for policy + people.
What we're building (at a glance)
HTTP POST (refund request JSON)
└─ Agent "RefundAgent" (Azure OpenAI gpt-4.1-mini)
├─ Tool: Send_Mail_For_Action (Outlook/Webhook) -> pause & wait for approver
├─ Tool: Send_Final_Status_Email (Outlook) -> notify customer
└─ Tool: EndWorkflow (Terminate) -> clean run completion
└─ Response 200 (optional output)
🧩 Decision Policy
Auto-approve if:
- Amount ≤ 200
- Reason contains damaged, defective, or never arrived
Escalate if:
- Amount > 200
- Reason is unclear or outside policy
Deny if:
- Reason violates policy (e.g., buyer’s remorse outside window)
The incoming request (HTTP trigger)
The Logic App expects a JSON payload like:
{
"requestId": "REQ-2025-0918-001",
"customerEmail": "alex@example.com",
"orderId": "ORD-992311",
"reason": "Item arrived damaged. Screen was cracked.",
"amount": 149.99
}
Here's a sample payloads ready for testing.
How the Agent thinks
- System message (policy + format): tells the agent to produce a deterministic JSON decision and guide the flow.
- User message: injects the raw trigger body (
@{triggerBody()}
) so the Agent sees requestId, email, reason, amount.
The Agent then chooses tools: - Call Send_Email_For_Action only when
a human decision is required. - Otherwise, jump to
Send_Final_Status_Email with a clear, customer-friendly message. -
End with EndWorkflow once the goal is reached.
Human-in-the-Loop (how the pause works)
Your Send_Email_For_Action tool uses: - Outlook "Mail with Options": sends an actionable email (e.g., Approve / Deny). - The workflow waits until the
approver clicks an option;tool resumes with the approver's choice.
The JSON (your workflow)
Trigger (HTTP POST)
- Type: Request (kind: Http)
- Schema: requestId, customerEmail, orderId, reason, amount
Agent action: RefundAgent
- Model: Azure OpenAI gpt-4.1-mini
- System: policy + human-loop instructions
- User: includes the trigger body
- Channels: Allow both input and output channels
🔄 Human-in-the-Loop Requires Real-Time Channels
To make the human approval loop (HITL) work correctly, you need to enable the following option in the Channels tab of your Agent action:
✅ Allow both input and output channels
- This keeps the workflow active while the Agent is waiting on a human decision.
- The approver’s response (Approve / Deny) is posted back to the callback URL, and because both channels are open, the Agent can resume in real time without restarting the workflow.
- Without this option enabled, the workflow would end after the first response, and you couldn’t support HITL interactions.
Tool 1: Send_Email_For_Action
- Purpose: Pause for human approval when the Agent isn't confident
- Pieces:
- Send_email_for_Approval_Or_Denial: Outlook Mail with Options
subscription with:
- To: approver (your demo address)
- Subject:
@{agentParameters('Subject')} #Your input is required#
- Body:
@agentParameters('Body')
- Options:
@agentParameters('User Options')
(e.g., "Approve, Deny")
- Send_email_for_Approval_Or_Denial: Outlook Mail with Options
subscription with:
Tool 2: Send_Final_Status_Email
- Purpose: Notify the customer of the final decision
- Inputs:
- Subject:
@agentParameters('Subject')
- Body :
<p class="editor-paragraph">@{agentParameters('Body')}</p>
- To : the customer (your JSON uses a fixed list; parameterize to
customerEmail
for production)
- Subject:
Tool 3: EndWorkflow
- Purpose: cleanly terminate with Succeeded once done
📊 Run History
One of the most useful ways to validate and debug your Logic App is by looking at the Run History. Each execution shows:
- Workflow steps on the left: trigger, RefundAgent, and tools (e.g., Send Email for Action, Send Final Status Email).
- Agent log on the right: detailed reasoning steps, the request payload, and the deterministic JSON decision generated by the Agent.
- Status indicators ✅ or ❌ that help you quickly spot whether a step succeeded or failed.
In the RefundAgent example:
📸 Screenshot: Run History — left side shows the Logic App workflow steps, right side shows the Agent log with reasoning and decision.
- For a high-value refund ($275.50), the Agent matched a valid reason (“defective”) but since the amount exceeded $200, it escalated to a human approver. The run shows the “Send Email for Approval or Denial” step being called.
- For a lower-value refund ($145.00), the Agent saw that the reason (“item damaged”) was valid and the amount was below the threshold, so it auto-approved the refund and sent the final status email directly to the customer.
This gives full transparency into how the decision was made and which path the workflow followed — critical for auditability in HITL (Human-in-the-Loop) scenarios.
Wrap-up
You now have a deterministic, auditable refund flow that mixes
policy automation with human judgement --- all inside Logic
Top comments (0)