Initial Release
A Smart Loan Broker demo built end-to-end with the BMAD Method during the
“Agentic Engineering Live on Stage” session at the InterSystems READY 2026
conference on Tuesday, April 28, 2026.
The demo shows an Angular 21 single-page application submitting loan applications
through a REST API to an InterSystems IRIS Interoperability Production. The
Production decomposes each request into a visible BPL workflow that persists
the application, calls a (simulated) Credit Bureau, applies decision rules, and
returns one of three outcomes — Approved, Rejected, or Manual Review —
to the user.
The companion talk slides are in this repository at the project root:
The entire backlog was generated from a single product brief using the BMAD Method.
Read these in order to follow how requirements flowed into stories:
Implementation stories (each with acceptance criteria, dev notes, completion notes,
and code-review findings):
A presenter cheat sheet covers the runtime flow and
the IRIS Management Portal trace navigation.
The BMAD Method (Brian Madison Agentic Development) is a workflow framework for
running an agentic software-engineering pipeline — Product Brief → PRD → Architecture
→ Epics → Stories → Dev → Code Review → QA — with each phase optionally driven by
specialized AI agents.
BMAD installs into a target project as a self-contained _bmad/ directory plus
configuration. The bundled installer is invoked from the BMAD repo:
# Clone the BMAD method git clone https://github.com/bmad-code-org/BMAD-METHOD.git cd BMAD-METHODRun the installer against your project root
node tools/installer/install.js --target /path/to/your/project
After install, your project gets:
_bmad/ — workflow engine, agent definitions, slash-command templates_bmad-output/ — where planning and implementation artifacts are written.claude/agents/ (and equivalents for .cline/, .roo/) — IDE-specific agentThis repo was bootstrapped against BMAD v6.0.0-Beta.8 with the BMM module
(Brian Madison Method) for the planning and implementation workflows, and the
TestArch module for QA.
For the slash commands used in this project, see .claude/commands/ (or run
/bmad-help inside Claude Code).
http://localhost:8880 (the default for localhost-healthshare)_SYSTEM / _SYSTEM (default — change for non-demo use)All commands assume the project root
/path/to/loandemo. The IRIS commands can
be issued either from the IRIS Terminal in the HSCUSTOM namespace, or via
the Atelier API / VS Code ObjectScript extension / iris-dev-mcp tooling.
git clone https://github.com/jbrandtmse/loandemo.git
cd loandemo
The src/LoanDemo/ directory mirrors the IRIS class hierarchy. Use any of these
options to load and compile:
Option A — VS Code with InterSystems ObjectScript extension
loandemo.code-workspace settings and theobjectscript.conn block in .vscode/settings.json (point it at your IRISsrc/LoanDemo folder → Import and Compile with flagsbckry.Option B — IRIS Terminal
// In the HSCUSTOM namespace:
Set tSC = $System.OBJ.ImportDir("/path/to/loandemo/src/LoanDemo", "*.cls", "bckry", , 1)
Write $System.Status.GetErrorText(tSC)
Option C — REST (Atelier API) or the iris-dev-mcp tools
# With iris-dev-mcp configured against HSCUSTOM:
mcp__iris-dev-mcp__iris_doc_load \
path="/path/to/loandemo/src/**/*.cls" \
compile=true \
flags="bckry" \
namespace="HSCUSTOM"
You should now see the following classes in HSCUSTOM:
LoanDemo.Data.LoanApplicationLoanDemo.Message.{LoanRequest,LoanResponse,CreditCheckRequest,CreditCheckResponse,LoanUpdateRequest}LoanDemo.Service.LoanServiceLoanDemo.Process.LoanBrokerLoanDemo.Operation.{CreditBureau,LoanPersistence}LoanDemo.Rule.DecisionLogicLoanDemo.REST.DispatcherLoanDemo.ProductionLoanDemo.InstallerLoanDemo.Test.DecisionLogicTestThe installer is idempotent and self-contained — it switches into %SYS
internally, creates (or updates) /loandemo/api, and configures the dispatch
class plus authentication settings the demo expects.
// In any namespace:
Set tSC = ##class(LoanDemo.Installer).Setup()
Write $System.Status.GetErrorText(tSC)
Or via MCP:
mcp__iris-dev-mcp__iris_execute_classmethod \
className="LoanDemo.Installer" \
methodName="Setup"
Verify with:
Write ##class(LoanDemo.Installer).Status()
You should get a JSON line like:
{
"name": "/loandemo/api",
"installed": 1,
"dispatchClass": "LoanDemo.REST.Dispatcher",
"namespace": "HSCUSTOM",
"autheEnabled": 96,
"matchRoles": ":%All",
"enabled": 1
}
autheEnabled: 96 means password + unauthenticated access (suitable for the
live demo; tighten before any non-demo deployment). matchRoles: ":%All" grants
the application all roles for the duration of a request.
To remove later:
Do ##class(LoanDemo.Installer).Uninstall()
Do ##class(Ens.Director).StartProduction("LoanDemo.Production")
// Verify: Write ##class(Ens.Director).GetProductionStatus() // 1 = Running
You should see four items running:
| Item | Class | Role |
|---|---|---|
LoanService |
LoanDemo.Service.LoanService |
Receives the LoanRequest from the dispatcher |
LoanBroker |
LoanDemo.Process.LoanBroker |
BPL orchestration |
CreditBureau |
LoanDemo.Operation.CreditBureau |
Simulated credit-score lookup |
LoanPersistence |
LoanDemo.Operation.LoanPersistence |
Saves and updates the application row |
If you recompile any BPL or Operation class, fully stop and start the Production
—UpdateProductiondoes not pick up new method bodies. Use:Do ##class(Ens.Director).StopProduction(10, 1) Do ##class(Ens.Director).StartProduction("LoanDemo.Production")
curl -u _SYSTEM:_SYSTEM \
-X POST \
-H "Content-Type: application/json" \
-d '{"applicantName":"Sam","requestedAmount":15000,"taxId":"123-45-6789"}' \
http://localhost:8880/loandemo/api/loan/apply
Expected: HTTP 200 with a body shaped like
{"status":"success","applicationId":42,"decision":"Approved","creditScore":761}
Credit scores are deterministic per Tax ID via $ZCRC, so the same input always
produces the same decision — handy for live demos.
cd frontend
npm install
npm start
The dev server runs at http://localhost:4200/ (the IRIS dispatcher’s CORS
config explicitly whitelists this origin). Submit a loan application, watch the
spinner, and see the decision panel render with the result.
Open the Management Portal at
http://localhost:8880/csp/sys/UtilHome.csp (login _SYSTEM/_SYSTEM),
switch to HSCUSTOM, then go to Interoperability → View → Messages and
filter by Source = LoanBroker. Click the most recent session to see the
8-message flow:
LoanService → LoanBroker (LoanRequest)
LoanBroker → LoanPersistence (initial save)
LoanBroker → CreditBureau (credit check)
LoanBroker → LoanPersistence (update with score + decision)
LoanBroker → LoanService (LoanResponse)
Each message header and body is browsable. See
https://github.com/jbrandtmse/loandemo/blob/main/docs/demo-walkthrough.md for the full presenter
cheat sheet.
// All tests (5 methods, all should pass):
Do ##class(%UnitTest.Manager).RunTest("LoanDemo.Test.DecisionLogicTest")
Or via MCP:
mcp__iris-dev-mcp__iris_execute_tests \
target="LoanDemo.Test.DecisionLogicTest" \
level="class"
Tests cover the three decision branches plus the four boundary edges
(701/700, 500/499) so the documented thresholds are locked into a regression test.
The DecisionLogic.GetDecision(score) rule is intentionally simple and isolated
so it can be unit-tested without the Production framework:
| Score | Decision |
|---|---|
> 700 |
Approved |
500 ≤ score ≤ 700 |
Manual Review |
< 500 |
Rejected |
Note the strict inequalities at the edges: score = 700 is Manual Review,
not Approved; score = 500 is Manual Review, not Rejected.
POST /loandemo/api/loan/apply Content-Type: application/jsonRequest: { "applicantName": "string", // ≥ 2 chars "requestedAmount": <number>, // > 0 "taxId": "string" // pattern ^[0-9-]{4,15}$ }
Success response (HTTP 200): { "status": "success", "applicationId": <int>, "decision": "Approved" | "Rejected" | "Manual Review" | "Pending", "creditScore": <int 300–850> }
Error response (HTTP 400): { "status": "error", "message": "<reason>" }
CORS is enabled on the dispatcher (HandleCorsRequest = 1) and the response
echoes Access-Control-Allow-Origin: http://localhost:4200 for the Angular dev
server.
loandemo/
├── README.md # this file
├── https://github.com/jbrandtmse/loandemo/blob/main/LICENSE # MIT
├── Agentic Engineering Live on Stage # READY 2026 talk slides
│ using the BMAD method.pptx
├── CLAUDE.md # agent guidance for Claude Code
├── _bmad/ # BMAD workflow engine + agents
├── _bmad-output/
│ ├── planning-artifacts/ # brief, PRD, architecture, epics
│ └── implementation-artifacts/ # per-story files, sprint status
├── docs/
│ └── demo-walkthrough.md # presenter cheat sheet
├── src/LoanDemo/ # ObjectScript backend
│ ├── Data/
│ ├── Message/
│ ├── Service/
│ ├── Process/
│ ├── Operation/
│ ├── Rule/
│ ├── REST/
│ ├── Test/
│ ├── Installer.cls
│ └── Production.cls
└── https://github.com/jbrandtmse/loandemo/blob/main/frontend/ # Angular 21 SPA
└── src/app/
├── components/loan-form/
├── services/loan.service.ts
└── models/
Released under the MIT License.