Skip to main content
Version: 5.1

Build a Claim Handling Durable Agent

Time15 minutes
What you'll buildA durable AI agent that handles expense claims.

The durable AI agent receives expense claims, validates them, and pays them out — but only after a Finance reviewer approves the payment from the Integration Control Plane. If the process crashes while waiting, it resumes exactly where it left off.

Prerequisites​

A working WSO2 Integrator environment.

Local setup

Install and launch WSO2 Integrator on your machine.

WSO2 Cloud Account

For AI assisted development and WSO2 Cloud deployments.

Also required:

WSO2 Integrator Copilot

Signed in to WSO2 Integrator Copilot (provides the default AI model — no API key needed)

Docker

Docker installed, including Docker Compose. It runs the Temporal server that keeps the workflow's durable record.

Step 1: Create the integration​

  1. Open WSO2 Integrator.
  2. Select Create in the Create a Project card.
  3. Set Project Name to agent.
  4. Set Integration Name to ClaimHandler.
  5. Click Create.

Step 2: Add a durable agentic workflow​

Creating the agent is also where you describe it: the model it thinks with, its role, and the instructions it plans from.

  1. In the design view, click Add Artifact Manually.

  2. Under AI Integration, select Durable Agentic Workflow. The Create New Durable Agentic Workflow form opens.

    Create Durable AgentCreate Durable Agent
  3. Set Name to claimAgent.

  4. Leave Model on Default WSO2 Model Provider, the model your Copilot sign-in provides.

  5. Set Role to Expense claim assistant.

  6. Set Instructions to:

    Process expense claims end to end. Validate each claim with validateClaim first and
    reject invalid claims with a clear reason. When a claim is valid, pay it with payClaim
    using the claimed amount. Finish with a one-line summary of the outcome.
  7. Input Data Type is the structured payload each run starts with. Create the claim record here: click the field, select + Create New Type, and on the Create from scratch tab keep Kind as Record, set Name to ExpenseClaim, then click + next to Fields and add:

    FieldType
    claimIdstring
    amountdecimal
  8. Click Save.

  9. Click Create Agent.

Creating the claimAgent durable agentic workflow, filling in the model, role, instructions, and an ExpenseClaim input typeCreating the claimAgent durable agentic workflow, filling in the model, role, instructions, and an ExpenseClaim input type

Step 3: Attach the agent activities​

Activities are the units of work the agent can call. Each one runs durably — completed work is never lost or repeated, even across restarts.

Attach the claim validator​

  1. Click + on the activity anchor at the bottom right of the agent node. The Activities panel opens.
  2. Under Current Integration, click + Create Activity. The Workflow Activity form opens.
  3. Set Activity Name to validateClaim.
  4. Under Parameters, click + Add Parameter. Set Type to the ExpenseClaim record created in Step 2 and Name to expenseClaim, then click Add.
  5. Set Return Type to boolean and click Save.
  6. Click the validateClaim form under Current Integration. Leave Retry Policy on No Retry and click Save.
Creating the validateClaim activity and registering it on the claimAgent nodeCreating the validateClaim activity and registering it on the claimAgent node

validateClaim joins the agent node as a capability and appears under Workflow Activities in the left sidebar.

Define the claim validator body​

Creating the activity gives it a signature but an empty body. The activity is a function, so its flow returns the validation result. Make it return true only for positive claim amounts:

  1. In the left sidebar, expand Workflow Activities and select validateClaim.
  2. Click + on the flow diagram to open the node panel, then under Control, select Return.
  3. Click the Expression field to open the value helper, then select Inputs > expenseClaim > amount.
  4. With the cursor after the inserted value, type > 0d to require a positive amount.
  5. Click Save, then select claimAgent in the left sidebar to return to the agent diagram.
Defining the validateClaim activity body with a Return stepDefining the validateClaim activity body with a Return step

Add the payment activity​

Paying out is the risky step, so gate it behind a person. The activity is created the same way as the validator, and the register form is where the gate goes on:

  1. Click + on the activity anchor at the bottom right of the agent node, then under Current Integration, click the + icon to create the activity.

  2. Set Activity Name to payClaim.

  3. Under Parameters, click + Add Parameter. Set Type to ExpenseClaim and Name to expenseClaim, then click Add.

  4. Leave Return Type empty and click Save.

  5. Click the payClaim form under Current Integration to open its register form, and set Approval Policy to Human Approval. Now, before the agent runs the activity, a review activity is created and the agent suspends durably until a reviewer proceeds or rejects.

  6. Set Reviewer Roles to Finance, the roles permitted to decide that approval.

  7. Click Save.

Creating the payClaim activity and registering it with Human Approval and the Finance reviewer roleCreating the payClaim activity and registering it with Human Approval and the Finance reviewer role

payClaim joins the agent node beside validateClaim, drawn with a badge marking it as gated. The agent can now propose a payment, but it cannot release one on its own.

Step 4: Start the agent from a service​

An agent does nothing until something starts it. Give the integration an HTTP resource that hands each incoming claim to claimAgent and answers with the ID of the run it started.

  1. Click ClaimHandler in the breadcrumb to open the integration overview, click + Add Artifact, then under Integration as API, click HTTP Service.
  2. On the Create HTTP Service form, keep Service Contract on Design From Scratch, leave Service Base Path as /, and click Create.
  3. The service opens with no resources. Click + Add Resource.
  4. Set HTTP Method to POST and Resource Path to claim.
  5. Click + Define Payload, open the Browse Existing Types tab, select ExpenseClaim under the current integration, and click Save.
  6. Click Save to create the resource. Its own diagram opens.
  7. Click +, then under Workflow, click Run Durable Agent.
  8. Set Durable Agentic Workflow to claimAgent.
  9. Set Query to Process Claim. This is the user turn appended to the agent's system prompt, so the model plans this run from it.
  10. Set Input to the request payload, which carries the claim itself, and leave Instance ID Variable Name as instanceId. Click Save.
  11. Click + below the node, click Return under Control, set Expression to instanceId, and click Save.

The resource now starts an agent run for every claim it receives and answers with that run's instance ID.

Adding an HTTP service with a POST claim resource that starts the claimAgent run and returns its instance IDAdding an HTTP service with a POST claim resource that starts the claimAgent run and returns its instance ID
Hold on to the instance ID

run starts the agent and returns immediately with its instance ID. It does not wait for the claim to finish, which is the point: the run may sit on the payClaim approval for days. Return the ID to the caller, because it is what addresses this run later.

Step 5: Start the local ICP server​

The gated payClaim suspends the run until a Finance reviewer decides on it, and the Integration Control Plane console is where that decision is made. Start a local ICP server before running the integration, so the approval has somewhere to land.

  1. Click ClaimHandler in the breadcrumb to open the integration overview.
  2. In the right panel, under Integration Control Plane, check Enable ICP monitoring.
  3. Expand Publish to local ICP and click Start ICP Server.

The terminal opens on an ICP Server task and logs the startup. The server is ready once it reports the console address:

Starting ICP Server with configuration: /Users/<you>/.wso2-integrator/components/icp/2.1.0/conf/deployment.toml
... message="WSO2 Integrator: ICP Console started at https://localhost:9446"
... message="Workflow management service started at 0.0.0.0:9446"

The status bar at the bottom right switches from ICP: Stopped to ICP: Running.

Enabling ICP monitoring, expanding Publish to local ICP, and starting the local ICP server from the Deployment Options panelEnabling ICP monitoring, expanding Publish to local ICP, and starting the local ICP server from the Deployment Options panel
Start ICP before the integration

Enable ICP monitoring writes the runtime bridge configuration that points this integration at the local ICP server. Start ICP first so the integration registers with it as it boots; otherwise the run has no inbox to publish the payClaim approval to.

Step 6: Start the Temporal server​

A durable workflow keeps its record in a workflow engine. The runtime's mode defaults to LOCAL, which expects a Temporal server on localhost:7233, so start one before running the integration. Temporal's sample Compose file brings up a server and its dependencies in Docker:

git clone https://github.com/temporalio/samples-server.git
cd samples-server/compose
docker compose up

Leave the containers running for the rest of this guide.

LOCAL is one of four deployment modes. A production integration usually points at a self-hosted or managed server instead, which is a matter of configuration rather than a change to the workflow.

Step 7: Run it​

  1. Select Run in the integration header to start the integration.

    If the integration does not yet hold access details for the default provider, the first run asks: "This integration uses the WSO2 default AI provider, but it isn't configured yet. Configure it now?" Click Configure Now. It writes the provider's access details to Config.toml using your Copilot sign-in, and the run continues. Later runs refresh them on their own.

  2. Watch the terminal. After Compiling source and Running executable, the runtime bridge connects to the ICP server started in Step 5:

    ... module=wso2/icp.runtime.bridge message="ICP agent initialized with server URL: https://localhost:9445"
    ... module=wso2/icp.runtime.bridge message="ICP agent started successfully with job ID: {\"id\":59000}"
    ... module=wso2/icp.runtime.bridge message="Full heartbeat acknowledged by ICP server"

    The heartbeat is the integration registering itself, which is what puts the payClaim approval in front of a reviewer later.

Step 8: Submit a new claim​

Once the service is up, a notification asks "1 service found in the integration. Test with Try It Client?". Click Test. A TryIt.hurl file opens beside the designer, holding a request generated from the claim resource. Send the claim from there.

The generated request already carries the method, URL, and content type, along with the schema the resource expects:

Running the integration, with the Try It file opening automatically once the service is upRunning the integration, with the Try It file opening automatically once the service is up

Fill in a real claim: replace the {?} placeholder for claimId and the 0 for amount, then click the run button in the request cell's left gutter to send it.

{
"claimId": "2002",
"amount": 1500
}

The response appears under the cell as 201 Created, with the new run's instance ID as the body:

Status: 201 Created
01a0b2bd-4405-7694-8b4d-4e3bfb1eeea0
Filling in the claim payload and sending it from the Try It file, returning 201 Created with the instance IDFilling in the claim payload and sending it from the Try It file, returning 201 Created with the instance ID

The agent validates the claim, decides to pay it, and pauses: the gated payClaim created an approval review for the Finance role. The workflow now waits durably; you can even restart the integration and nothing is lost.

Step 9: See the claim waiting in ICP​

The run is now sitting on the payClaim approval, and the ICP console is where that wait is visible.

The claimAgent execution timeline, with Thinking and validateClaim completed and review-payClaim still runningThe claimAgent execution timeline, with Thinking and validateClaim completed and review-payClaim still running
  1. In WSO2 Integrator, under Publish to local ICP, click View in ICP. The console opens in the browser, already signed in as the super admin, on the All Projects page.

  2. That page already lists default-project, and it holds an integration named claimhandler. Neither was created by hand: the integration registered both with ICP when it started, and because it carries a durable workflow it is registered as a workflow integration.

  3. Open default-project, then claimhandler. The Dev environment reports 1/1 Active and lists Workflow Definitions with claimAgent selected.

  4. Click View Workflows. The Workflow Executions page lists one instance for claimAgent, whose Workflow ID is the instance ID the claim request returned, with status Running and the time it started.

  5. Click the instance to open Execution Details:

    • Workflow Input shows the claim the run started from, the Query it was given, and the agent name.
    • The timeline below is the run so far: the agent thought, completed validateClaim, thought again.
    • At the end of the timeline, you will see that the agent opened review-payClaim, which is still running. That open review is the gate holding the payment.
Opening the ICP console on the auto-registered claimhandler integration and drilling into the running claimAgent execution waiting on review-payClaimOpening the ICP console on the auto-registered claimhandler integration and drilling into the running claimAgent execution waiting on review-payClaim

Step 10: Give your user the Finance role​

The review is on the timeline, but it is not yet addressed to you. payClaim was registered with Finance as its reviewer role, and the console signs you in as admin, who does not carry that role yet. Roles reach users through groups, so create a Finance role that can see and decide human tasks, and a group that grants it.

  1. Click Default Organization at the top of the console to leave the integration, then in the left navigation, under MANAGEMENT, click Access-control. Inside an integration, Access-control shows only that integration's roles and groups. The Users tab lists a single user, admin (System Administrator).
  2. Open the Roles tab and click + Create Role. Set Role Name to Finance, expand Workflow-Management, and select workflow_mgt:view_human_tasks, workflow_mgt:manage_human_tasks, and workflow_mgt:view_workflows. Click Create.
  3. Open the Groups tab, click + Create Group, set Name to Finance Reviewers, and click Create.
  4. Click Finance Reviewers. On the USERS tab, click + Add Users, select System Administrator (admin), and click Add.
  5. On the ROLES tab, click + Add Roles. Select Finance in the Roles dropdown, leave Applicable Environments on All Environments, and click Add.
Creating the Finance role with the workflow permissions, creating the Finance Reviewers group, and adding admin and the Finance role to itCreating the Finance role with the workflow permissions, creating the Finance Reviewers group, and adding admin and the Finance role to it

The console confirms Role(s) added to group successfully. admin now holds Finance through Finance Reviewers, so the approval reaches it. In a real deployment, add the accounts of the people who approve payments to this group; admin stands in for them here.

Step 11: Approve the payment​

  1. Use the breadcrumb at the top of the console to return to default-project, then claimhandler.

  2. In the left navigation, under MANAGE, click Human Tasks. The page gathers the human tasks and review activities for claimhandler, and it shows only the ones applicable to you. Without the Finance role added in Step 10, this list stays empty.

  3. With Status on Pending, one task is listed: Approval required: payClaim, badged Approval gate, on claimAgent, carrying the workflow ID of your run.

  4. Click the task. The panel lays out the decision:

    • Activity names the activity and its workflow, links the parent workflow, and gives the Trigger as Approval gate — review before the activity runs.
    • Activity Arguments is read-only and holds the claim ID and amount the agent proposes to pay.
    • Decisions offers Proceed (run with the original arguments), Proceed with Changes (edit the arguments first), and Reject (fail the activity instead).
  5. Click Proceed. Confirm Proceed repeats the arguments and warns that the activity runs with them and that this cannot be undone. Click Proceed to release the payment.

The console reports Activity proceeded, and on the next refresh the list reads No pending tasks.

Opening the payClaim approval under Human Tasks and releasing the payment with ProceedOpening the payClaim approval under Human Tasks and releasing the payment with Proceed

Open the run again from Workflows. payClaim has now completed. The agent takes one closing turn, and the execution reads Completed, with a Closed time and a Workflow Result holding the agent's own summary of the claim. The model words it differently on each run, for example:

The claim with ID 2002 has been processed and paid successfully.
The completed claimAgent execution, with its workflow result and an all-green timeline ending in payClaimThe completed claimAgent execution, with its workflow result and an all-green timeline ending in payClaim

The timeline is green end to end, and it shows where the time went: the thinking turns and validateClaim took seconds, payClaim ran in milliseconds once released, and review-payClaim accounts for almost the entire run. For most of the run, nobody was working on the claim. It was waiting for a person, and it lost nothing by waiting.

Next steps​