Source: https://docs.cumuluslabs.io/order-resolution
Content version: 0addd1d0

# Build an order-support and refund flow

Build an agent that handles refund requests, invoice questions, replacements and specialist escalation. For a damaged-order refund, it verifies access, finds the order, checks policy, asks for confirmation and reports the business service’s response.

The screenshots use Studio with synthetic data. You implement the example endpoints and set the verification and refund rules. Select an image to view it at full size.

## Follow the complete decision map {#map}

![The full order-resolution flow including verification, request classification, multiple resolution paths and fallback](https://docs.cumuluslabs.io/docs-assets/support-resolution-map.png)

The main flow calls two components: account verification and refund review. It then routes the request to an invoice explanation, replacement case, refund review or specialist. Give each failed check and transfer a defined fallback.

| Path | Business rule | Expected outcome |
| --- | --- | --- |
| Access verified | The business verification endpoint authorizes access | Continue to account lookup |
| Access not verified | Never disclose protected account facts | End with a safe next step |
| Invoice question | Explain returned account facts with approved policy | Confirm the question was answered or escalate |
| Replacement request | Record the item and requested remedy | Create a review/replacement case; do not claim shipment |
| Refund eligible | Eligibility comes from the business policy endpoint | Ask for explicit confirmation before requesting the write |
| Refund ineligible or uncertain | Avoid unsupported promises and repeated writes | Create a manual-review case |
| Specialist unavailable | A failed connection is not a completed handoff | Record an agreed callback or alternate route |

## Verify access before reading account facts {#verification}

![The verification component inspector explaining what to collect before the business check](https://docs.cumuluslabs.io/docs-assets/support-verification-component.png)

The verification component collects the information your business procedure requires, then calls `verify_account_access`. Its response provides the authorization decision. A branch in the parent flow checks that result before calling `lookup_account`.

Use a response variable mapping such as `identity_verified → $.authorized` for the business endpoint's boolean decision. Treat missing or invalid data as a failure; do not ask a model to invent authorization. Your endpoint owns the actual access check and must not trust a caller's assertion alone.

Test verified access, a wrong answer, refusal, an unknown account and a verification-service outage separately. The end state for an unverified caller must remain useful without exposing account details.

## Classify and route the request {#routing}

![An extraction node capturing request type and order reference](https://docs.cumuluslabs.io/docs-assets/support-request-extraction.png)

Use extraction for conversational facts such as request type and order reference. Set an enum for the supported request types instead of leaving every downstream branch to match free-form wording.

![The request-routing branch with refund, replacement, invoice and fallback destinations](https://docs.cumuluslabs.io/docs-assets/support-resolution-routing.png)

Route on the extracted value, with an explicit fallback for unsupported or unclear requests. Keep verified business facts separate from model-extracted conversation fields. An extracted “refund” intent does not establish eligibility or permission to issue one.

## Pin the knowledge this version can use {#knowledge}

![Selected ready policy documents and an unselected document still indexing](https://docs.cumuluslabs.io/docs-assets/support-knowledge.png)

Upload your return policy and replacement handbook, wait for readiness and select the documents on the draft. Publishing fixes the selected document versions for that publication. The third source is still indexing, so it is not selected.

Use knowledge for explanations and policy context. Use the business eligibility endpoint for the authoritative decision on a specific order. For contradictory or missing sources, define escalation rather than asking the agent to fill the gap.

See [knowledge configuration and generations](/docs/knowledge) for model selection, upload, indexing and re-embedding. A document being present in the workspace is different from it being pinned to the running agent.

## Bind the business actions {#actions}

![The support agent's named account, eligibility, refund and ticket actions](https://docs.cumuluslabs.io/docs-assets/support-action-list.png)

The example uses five actions: verify account access, read the account, check eligibility, request a refund and create a ticket. Each is an HTTPS service you own.

![The refund action editor showing endpoint, method, timeout, authentication, channels and input schema](https://docs.cumuluslabs.io/docs-assets/support-action-contract.png)

Define the action's request and response schema, credential reference, timeout and idempotency behavior. For `create_refund`, the business endpoint must ensure that repeating the same effect key does not create a second refund. Cumulus records the attempt; the downstream transaction contract makes repeating the request safe.

Example business responses might include `{ "authorized": true }`, `{ "eligible": true }` and `{ "state": "confirmed", "refund_id": "REF-DEMO-81" }`. These are conventions you implement and map into variables, not built-in Cumulus refund APIs. Require the fields the next decision depends on.

## Review eligibility and get confirmation {#refund}

![The refund component branch checking the eligibility response before requesting consent](https://docs.cumuluslabs.io/docs-assets/support-refund-eligibility.png)

Keep the eligibility decision, caller confirmation and write separate. The caller should hear the approved remedy before being asked to authorize it. Route an ineligible result to review.

![The refund function node with wait-for-result behavior and its next transition](https://docs.cumuluslabs.io/docs-assets/support-refund-action.png)

Wait for the result when the next statement depends on it. A status message such as “I am checking that now” describes work in progress; it does not claim that the refund succeeded.

If the response confirms completion, state the returned identifier and agreed next step. If the outcome is uncertain, reconcile it with the business service before another write. The [uncertain-action example](/docs/investigate-runs#uncertain) shows the record an operator reviews.

## Handle escalation as a real outcome {#escalation}

![A transfer node with a destination and the unavailable-specialist fallback](https://docs.cumuluslabs.io/docs-assets/support-transfer-fallback.png)

Create the review case before a handoff when your process requires it. Configure the transfer destination and failure path. If the specialist cannot be reached, explain that clearly and record the alternate next step.

Test busy destinations, failed transfers, an uncertain transfer result and caller refusal. A configured destination proves setup; a real authorized carrier call establishes routing and media behavior.

## Notify your application and inspect the result {#delivery}

![Lifecycle webhooks configured for run completion, analysis and recording updates](https://docs.cumuluslabs.io/docs-assets/support-webhooks.png)

Use signed lifecycle webhooks to tell your application that a run ended or an output became available. Verify signatures and deduplicate deliveries by event identity. Before closing a case, read the run, action receipts and downstream transaction.

For an API-started phone run, use your published agent and authorized target. This request demonstrates per-run context:

<!-- operation:runs.create -->
```json
{
  "channel": "phone",
  "agent_id": "order-resolution",
  "to": "+14155550123",
  "from": "+14155550100",
  "dynamic_variables": { "business_name": "Acme", "account_reference": "DEMO-42" },
  "metadata": { "account_reference": "DEMO-42", "order_id": "ORDER-DEMO-81" }
}
```

Send it to [Start a run](/docs/reference/runs.create) with your environment's API key and a retained `Idempotency-Key`. An admitted run is not proof that the refund was issued. Follow the run to completion and read its external-action evidence.

## Acceptance cases before release {#acceptance}

| Case | Checkable expectation |
| --- | --- |
| Caller refuses verification | No protected account disclosure or lookup that bypasses authorization |
| Eligibility endpoint returns false | No refund request |
| Caller declines the remedy | No refund write |
| Refund endpoint times out after a possible commit | Reconciliation/manual review; no blind second write |
| Policy document is unavailable | Defined fallback; no invented policy |
| Specialist is busy | The configured fallback is visible in the run |

Use [regression testing](/docs/regression-testing) for repeatable conversational checks and mocks. Complete real business-endpoint and carrier acceptance separately. Then [release the tested publication](/docs/release-an-agent).

After release, use the run ID to find the executed publication, selected path and refund receipt. Keep the downstream refund or review-case ID with the same business record.
