Customer Review Analyzer with Natural Function
This tutorial walks through building an HTTP service that uses a Natural Function to analyze a customer review and return structured feedback. It is the end-to-end scenario for the Natural Functions feature.
By the end you will have a POST /api/v1/analyze endpoint that takes a single customer review and returns a typed ReviewResponse containing the overall sentiment, a concise summary, per-topic sentiment, a churn-risk flag, and a suggested follow-up action. All of it is produced by an LLM, using a Natural Function as the body.
Natural functions are an experimental feature. Enable experimental features in WSO2 Integrator before using them: open Settings, expand Extensions, select the Ballerina extension, and tick Experimental: Enable Experimental Feature.
Before you start, open the Command Palette (Cmd+Shift+P / Ctrl+Shift+P) and run Ballerina: Configure default WSO2 model provider. Sign in with your WSO2 account when prompted. This is a one-time per-project setup; WSO2 Integrator writes the configuration values into the project automatically.
The first run may also prompt you for the wso2aiKey configuration value. The Configure Application dialog handles that for you.
What you'll build
- Create the natural function. Define a typed signature, a return type with a record, an English prompt body, and a model-provider connection.
- Create the HTTP service that exposes the function over
POST /api/v1/analyze. - Wire the resource flow to call the natural function and return the typed response.
- Run and test the service end-to-end.
1. Create the natural function
Step 1.1: Open the create form
From the project sidebar, hover the Natural Functions node and click the + that appears on the right.
(You can also reach the same form from the integration Overview page: click + Add Artifact and pick Natural Function under Other Artifacts.)
Step 1.2: Name and parameter
The Create New Natural Function form opens. Set:
| Field | Value |
|---|---|
| Name | analyzeCustomerReviews |
Click + Add Parameter and fill in:
| Field | Value |
|---|---|
| Type | string |
| Name | customerReview |
| Description | Review of the customer |
Click Save. The parameter appears as a pill in the Parameters list.
Step 1.3: Build the return type
The function will return a ReviewResponse record. The fastest way to define one is to import a JSON sample.
Click the Return Type field. From the dropdown, click Create New Type.
In the Create New Type dialog, switch to the Import tab. Set:
| Field | Value |
|---|---|
| Format | JSON |
| Name | ReviewResponse |
Paste the following JSON sample into the textarea:
{
"sentiment": "mixed",
"summary": "Customer loves the sound quality but is frustrated by a faulty charging case and slow support response.",
"topics": [
{ "name": "sound quality", "sentiment": "positive" },
{ "name": "charging case", "sentiment": "negative" },
{ "name": "customer support", "sentiment": "negative" }
],
"churn_risk": true,
"suggested_action": "Reach out with a replacement case and apologize for the support delay."
}
Click Import. WSO2 Integrator infers and registers three types under the Types node in the sidebar:
ReviewResponse: the top-level record with fieldssentiment,summary,topics,churn_risk,suggested_action.Topics: the array type used for thetopicsfield (an alias forTopicsItem[]).TopicsItem: the per-element record with fieldsnameandsentiment.
ReviewResponse is selected automatically as the function's return type.
Why these field names matter: the runtime turns the record (and its nested types) into a JSON schema and sends it to the LLM. Field names, types, and any descriptions you add become part of the contract the model is constrained to. See Typed Return Inference for the details.
Step 1.4: Create the function
Click Create. WSO2 Integrator generates the Ballerina source and opens the function in the Flow Designer. The sidebar updates with three additions:
- Connections:
_analyzeCustomerReviewsModel(the model-provider connection WSO2 Integrator created for this function). - Types:
ReviewResponse,Topics,TopicsItem. - Natural Functions:
analyzeCustomerReviews.
The flow shows a single Prompt node between Start and the end of the function:
Step 1.5: Bind the model provider
Hover the cog icon on the right of the Prompt node. The tooltip reads Configure Model Provider. Click it.
The Configure Model Provider Connection panel slides in. Pick the auto-created _analyzeCustomerReviewsModel connection and click Save.
If you'd rather use OpenAI, Anthropic, Azure OpenAI, or any other provider, click + Create New Model Provider and pick from the catalogue:
Step 1.6: Write the prompt
Click the pencil icon at the top-right of the Prompt node. The inline editor opens; click Expand Editor for the full Markdown editor with formatting tools.
Type the following prompt. Use Bold for the role line, and the Insert menu (or just type) to interpolate the parameter:
You are a customer review analyzer. For the review below, identify the overall sentiment, extract the key topics being discussed with their individual sentiment, and suggest a follow-up action if needed.
Review:
${customerReview}
Close the expanded view and click Save. The natural function is complete; the Prompt node shows the saved body inline, and behind the scenes WSO2 Integrator generated the Ballerina source.
- Visual Designer
- Ballerina Code
function analyzeCustomerReviews(string customerReview) returns ReviewResponse|error {
ReviewResponse|error result = natural {
You are a **customer review analyzer**. For the review below, identify
the overall sentiment, extract the key topics being discussed with their
individual sentiment, and suggest a follow-up action if needed.
Review: ${customerReview}
};
return result;
}
2. Create the HTTP service
The function is callable; now we expose it as an API.
Step 2.1: Add the service artifact
Click the back arrow to return to the integration Overview, then + Add Artifact. Under Integration as API, pick HTTP Service.
In the Create HTTP Service form, set:
| Field | Value |
|---|---|
| Service Contract | Design From Scratch |
| Service Base Path | /api/v1 |
Click Create. The HTTP Service editor opens with no resources yet.
Step 2.2: Add the POST resource
Click + Add Resource.
In the Select HTTP Method to Add picker, choose POST, then configure the resource:
| Field | Value |
|---|---|
| HTTP Method | POST |
| Resource Path | analyze |
| Payload (Type / Name) | string / review |
| Responses | 201 returns ReviewResponse; 500 returns error |
Click Save. The resource flow opens with Start, an empty placeholder, and an Error Handler.
3. Call the natural function from the resource
Step 3.1: Open the Add Node panel
Click the empty placeholder between Start and Error Handler. The Add Node panel slides in. Expand the AI category and click Call Natural Function.
Step 3.2: Pick the function
The Natural Functions picker lists every natural function in the project. Pick analyzeCustomerReviews.
Step 3.3: Bind the argument
The configuration form opens. Each parameter on the function becomes a row; here you only have CustomerReview.
Bind CustomerReview to the inbound payload variable review. Leave Result (the variable name that will hold the typed return value, used by the next node) as reviewResponse, and Variable Type as the locked ReviewResponse (it always matches the function's declared return type).
Click Save. The natural-function node lands in the flow.
Step 3.4: Add the return
Click the empty placeholder between the natural function call and Error Handler. In the Add Node panel, under Control, pick Return.
In the Return panel, set the Expression / Return value to reviewResponse.
The completed flow:
4. Run and test
Step 4.1: Run the service
From the Overview page click Run. WSO2 Integrator applies the --experimental flag and starts the service.
Step 4.2: Send a test request
From the resource editor, click Try It in the top-right toolbar. Send a POST /api/v1/analyze with this body:
{
"review": "Loved the sound quality, but the charging case died after a week and support never replied."
}
Step 4.3: Read the structured response
The natural function returns a fully structured response matching ReviewResponse.
The LLM analyzed the review, identified the overall sentiment, extracted per-topic sentiment, flagged the customer as a churn risk, and suggested a concrete follow-up action. The response comes back as a typed ReviewResponse record, with no JSON parsing or schema validation in your code.
Ballerina HTTP services return
201 Createdfor POST requests by default; that is expected behaviour, not an error.
What's next
- Natural Functions reference — the single-page reference covering the form, the Prompt node, typed return inference, and calling from a flow.
- Email Generator with Direct LLM — a similar tutorial built around direct LLM calls.


























