Skip to content

[WIP] Add human in the loop (HITL) BBE examples - #6414

Open
lochana-chathura wants to merge 2 commits into
ballerina-platform:masterfrom
lochana-chathura:hitl_bbe
Open

[WIP] Add human in the loop (HITL) BBE examples#6414
lochana-chathura wants to merge 2 commits into
ballerina-platform:masterfrom
lochana-chathura:hitl_bbe

Conversation

@lochana-chathura

@lochana-chathura lochana-chathura commented Aug 7, 2026

Copy link
Copy Markdown
Member

Purpose

$subject.

Fixes ballerina-platform/ballerina-library#9007

Summary

  • Added two Ballerina by Example samples for ai:Agent human-in-the-loop workflows.
  • Added approval handling for transfers, including conditional approval for transfers above 500.
  • Added interactive approval, rejection, session resumption, account validation, and balance checks.
  • Added documentation and metadata for both examples.
  • Registered both examples under the AI agents category.
  • Updated the ai library dependency to version 1.13.0.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 12245b0f-8fa5-4ac3-a53d-2078e0f8a5cf

📥 Commits

Reviewing files that changed from the base of the PR and between d3a2206 and 4ba00c3.

📒 Files selected for processing (1)
  • gradle.properties

📝 Walkthrough

Walkthrough

Added two Ballerina banking agent examples. One uses explicit human approval for transfers. The other requires approval only for transfers above 500. Both include interactive session resumption, documentation, metadata, catalog entries, and the AI library version update.

Changes

AI agent approval examples

Layer / File(s) Summary
Human-in-the-loop banking flow
examples/ai-agent-human-in-the-loop/ai_agent_human_in_the_loop.bal
Adds account storage, balance and transfer tools, approval handling, and resumable agent sessions.
Conditional transfer approval
examples/ai-agent-conditional-approval/ai_agent_conditional_approval.bal
Adds a transfer approval predicate for amounts above 500, account validation, locked balance updates, and session resumption.
Example documentation and catalog
examples/ai-agent-human-in-the-loop/*, examples/ai-agent-conditional-approval/*, examples/index.json, gradle.properties
Adds documentation, searchable metadata, catalog entries, and updates stdlibAiVersion to 1.13.0.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant main
  participant bankingAgent
  participant AccountStore
  User->>main: Submit banking request
  main->>bankingAgent: Run request
  bankingAgent-->>main: ApprovalRequiredError
  main->>User: Collect approval decision
  main->>bankingAgent: Resume session
  bankingAgent->>AccountStore: Validate and update balances
Loading

Possibly related issues

  • ballerina-platform/ballerina-library#9007 — Adds the requested ai:Agent human-in-the-loop BBE examples, including conditional approval.

Suggested reviewers: keizer619, gimantha, maryamzi

Poem

A rabbit checks each guarded flow,
Pausing where approvals must go.
Above five hundred, decisions land,
Then balances shift by careful hand.
Two agent examples now run bright.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description only includes an unresolved purpose placeholder and issue link; all required template sections are missing. Complete the required sections, including goals, approach, testing, security checks, samples, release note, documentation, and test environment.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: adding human-in-the-loop Ballerina by Example examples.
Linked Issues check ✅ Passed The PR adds HITL BBE examples and updates the AI dependency to version 1.13.0, satisfying issue #9007.
Out of Scope Changes check ✅ Passed The examples, metadata, index entry, and AI dependency update are directly related to the linked HITL BBE objective.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@examples/ai-agent-conditional-approval/ai_agent_conditional_approval.bal`:
- Around line 40-53: Update transfer to reject non-positive amounts and
identical fromAccount/toAccount values before checking balances or modifying
accounts. Preserve the existing not-found and insufficient-funds validation, and
return descriptive errors for both new invalid-input cases.

In `@examples/ai-agent-human-in-the-loop/ai_agent_human_in_the_loop.bal`:
- Around line 31-44: Update transfer to reject amounts that are not greater than
0d and transfers where fromAccount and toAccount refer to the same account,
before modifying accounts. Preserve the existing account lookup and
insufficient-funds checks, and only execute the debit and credit assignments
after both validations pass.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c17774f1-3b45-4b26-9234-1f4aa98c8b61

📥 Commits

Reviewing files that changed from the base of the PR and between 2b0432a and d3a2206.

⛔ Files ignored due to path filters (2)
  • examples/ai-agent-conditional-approval/ai_agent_conditional_approval.out is excluded by !**/*.out
  • examples/ai-agent-human-in-the-loop/ai_agent_human_in_the_loop.out is excluded by !**/*.out
📒 Files selected for processing (7)
  • examples/ai-agent-conditional-approval/ai_agent_conditional_approval.bal
  • examples/ai-agent-conditional-approval/ai_agent_conditional_approval.md
  • examples/ai-agent-conditional-approval/ai_agent_conditional_approval.metatags
  • examples/ai-agent-human-in-the-loop/ai_agent_human_in_the_loop.bal
  • examples/ai-agent-human-in-the-loop/ai_agent_human_in_the_loop.md
  • examples/ai-agent-human-in-the-loop/ai_agent_human_in_the_loop.metatags
  • examples/index.json

Comment on lines +40 to +53
isolated function transfer(string fromAccount, string toAccount, decimal amount)
returns string|error {
lock {
Account? sender = accounts[fromAccount];
Account? recipient = accounts[toAccount];
if sender is () || recipient is () {
return error("One or both accounts were not found.");
}
if sender.balance < amount {
return error(string `Insufficient funds in account '${fromAccount}'.`);
}
// Debit the sender and credit the recipient.
accounts[fromAccount] = {id: sender.id, owner: sender.owner, balance: sender.balance - amount};
accounts[toAccount] = {id: recipient.id, owner: recipient.owner, balance: recipient.balance + amount};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🔴 Critical | ⚡ Quick win

Validate transfer invariants before balance updates.

Reject amount <= 0d. A negative amount reverses the transfer direction.

Reject identical fromAccount and toAccount. The second assignment then overwrites the debit and increases the account balance by amount.

Proposed fix
 isolated function transfer(string fromAccount, string toAccount, decimal amount)
         returns string|error {
+    if amount <= 0d {
+        return error("Transfer amount must be greater than zero.");
+    }
+    if fromAccount == toAccount {
+        return error("Source and destination accounts must be different.");
+    }
     lock {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
isolated function transfer(string fromAccount, string toAccount, decimal amount)
returns string|error {
lock {
Account? sender = accounts[fromAccount];
Account? recipient = accounts[toAccount];
if sender is () || recipient is () {
return error("One or both accounts were not found.");
}
if sender.balance < amount {
return error(string `Insufficient funds in account '${fromAccount}'.`);
}
// Debit the sender and credit the recipient.
accounts[fromAccount] = {id: sender.id, owner: sender.owner, balance: sender.balance - amount};
accounts[toAccount] = {id: recipient.id, owner: recipient.owner, balance: recipient.balance + amount};
isolated function transfer(string fromAccount, string toAccount, decimal amount)
returns string|error {
if amount <= 0d {
return error("Transfer amount must be greater than zero.");
}
if fromAccount == toAccount {
return error("Source and destination accounts must be different.");
}
lock {
Account? sender = accounts[fromAccount];
Account? recipient = accounts[toAccount];
if sender is () || recipient is () {
return error("One or both accounts were not found.");
}
if sender.balance < amount {
return error(string `Insufficient funds in account '${fromAccount}'.`);
}
// Debit the sender and credit the recipient.
accounts[fromAccount] = {id: sender.id, owner: sender.owner, balance: sender.balance - amount};
accounts[toAccount] = {id: recipient.id, owner: recipient.owner, balance: recipient.balance + amount};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/ai-agent-conditional-approval/ai_agent_conditional_approval.bal`
around lines 40 - 53, Update transfer to reject non-positive amounts and
identical fromAccount/toAccount values before checking balances or modifying
accounts. Preserve the existing not-found and insufficient-funds validation, and
return descriptive errors for both new invalid-input cases.

Comment on lines +31 to +44
isolated function transfer(string fromAccount, string toAccount, decimal amount)
returns string|error {
lock {
Account? sender = accounts[fromAccount];
Account? recipient = accounts[toAccount];
if sender is () || recipient is () {
return error("One or both accounts were not found.");
}
if sender.balance < amount {
return error(string `Insufficient funds in account '${fromAccount}'.`);
}
// Debit the sender and credit the recipient.
accounts[fromAccount] = {id: sender.id, owner: sender.owner, balance: sender.balance - amount};
accounts[toAccount] = {id: recipient.id, owner: recipient.owner, balance: recipient.balance + amount};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reject non-positive amounts and same-account transfers.

amount has no lower-bound validation. A negative amount credits the sender and debits the recipient.

If fromAccount == toAccount, Line 44 overwrites the debit from Line 43 with balance + amount. This creates funds in the account.

Validate amount > 0d and require distinct account IDs before updating accounts.

Proposed fix
 isolated function transfer(string fromAccount, string toAccount, decimal amount)
         returns string|error {
+    if amount <= 0d {
+        return error("Transfer amount must be greater than zero.");
+    }
+    if fromAccount == toAccount {
+        return error("Source and destination accounts must be different.");
+    }
     lock {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
isolated function transfer(string fromAccount, string toAccount, decimal amount)
returns string|error {
lock {
Account? sender = accounts[fromAccount];
Account? recipient = accounts[toAccount];
if sender is () || recipient is () {
return error("One or both accounts were not found.");
}
if sender.balance < amount {
return error(string `Insufficient funds in account '${fromAccount}'.`);
}
// Debit the sender and credit the recipient.
accounts[fromAccount] = {id: sender.id, owner: sender.owner, balance: sender.balance - amount};
accounts[toAccount] = {id: recipient.id, owner: recipient.owner, balance: recipient.balance + amount};
isolated function transfer(string fromAccount, string toAccount, decimal amount)
returns string|error {
if amount <= 0d {
return error("Transfer amount must be greater than zero.");
}
if fromAccount == toAccount {
return error("Source and destination accounts must be different.");
}
lock {
Account? sender = accounts[fromAccount];
Account? recipient = accounts[toAccount];
if sender is () || recipient is () {
return error("One or both accounts were not found.");
}
if sender.balance < amount {
return error(string `Insufficient funds in account '${fromAccount}'.`);
}
// Debit the sender and credit the recipient.
accounts[fromAccount] = {id: sender.id, owner: sender.owner, balance: sender.balance - amount};
accounts[toAccount] = {id: recipient.id, owner: recipient.owner, balance: recipient.balance + amount};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/ai-agent-human-in-the-loop/ai_agent_human_in_the_loop.bal` around
lines 31 - 44, Update transfer to reject amounts that are not greater than 0d
and transfers where fromAccount and toAccount refer to the same account, before
modifying accounts. Preserve the existing account lookup and insufficient-funds
checks, and only execute the debit and credit assignments after both validations
pass.

@sonarqubecloud

sonarqubecloud Bot commented Aug 7, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add BBE examples for new ai:Agent HITL(human in the loop) feature

1 participant