# Can an AI assistant build a Fishbowl Jasper report?

> Jasper reports are Fishbowl's original printed reports. With ILC MCP, an AI assistant drafts one from scratch or from an existing report, tests the query, compiles it on the JasperReports version Fishbowl runs, and installs it where you choose. A browser editor lets a person adjust the layout alongside it.

In March 2008 I wrote my first iReport. I was doing contract IT for a biotech company in Irvine, California, a company I'd first worked for in high school during an overnight system cut-over. A Fishbowl consultant was set up in the server closet, and we got talking. He asked if I knew databases. I'd used ERP systems at other jobs, cut my teeth on the Microsoft Great Plains 9 database, and could put together useful SQL. Fishbowl was the first entire system I could understand from end to end. Back then it ran on Firebird, before the move to MySQL.

The Java I'd learned in AP Computer Science in high school was enough to pick up iReport quickly. I'm fairly sure that first report tracked raw materials by expiration date. I wish I'd kept the file. It's probably on one of the seven or so laptops I've gone through since.

Reports took time: the query, the approach, and the iReport software itself. To free up memory, the editor would sometimes reload a report from disk, and anything you hadn't saved was gone. Lose an hour or two of work that way and you start pressing Ctrl+S after every change. I still have the habit, and I'm fairly sure the current iReport still has the bug. I've written well over a thousand Jasper reports since then.

Jasper reports are still how Fishbowl prints most of its documents, and they're the kind I've written the most of. Earlier this month I wrote that [I probably won't write a report ever again](/blog/custom-reports-with-ilc-mcp). With ILC MCP, an AI assistant can now build Jasper reports too.

## How it works

<figure>
<svg class="hiw" viewBox="0 0 720 432" role="img" aria-label="Five steps: the AI starts from scratch or from one existing report file, tests the query on your data, compiles the report on the version Fishbowl runs, asks which folder and menu it goes in, and installs it as version 1, visible to admins until granted." style="display:block;width:100%;height:auto;border-radius:16px;font-family:'Hanken Grotesk',system-ui,sans-serif"><style>@keyframes hiw-r0{0%,7%{opacity:.28}10%,92%{opacity:1}100%{opacity:.28}}@keyframes hiw-c0{0%,12%{opacity:0;transform:scale(.85)}15%,92%{opacity:1;transform:scale(1)}100%{opacity:0}}.hiw .r0{animation:hiw-r0 14s infinite}.hiw .c0{animation:hiw-c0 14s infinite;transform-box:fill-box;transform-origin:center}@keyframes hiw-r1{0%,21%{opacity:.28}24%,92%{opacity:1}100%{opacity:.28}}@keyframes hiw-c1{0%,26%{opacity:0;transform:scale(.85)}29%,92%{opacity:1;transform:scale(1)}100%{opacity:0}}.hiw .r1{animation:hiw-r1 14s infinite}.hiw .c1{animation:hiw-c1 14s infinite;transform-box:fill-box;transform-origin:center}@keyframes hiw-r2{0%,36%{opacity:.28}39%,92%{opacity:1}100%{opacity:.28}}@keyframes hiw-c2{0%,41%{opacity:0;transform:scale(.85)}44%,92%{opacity:1;transform:scale(1)}100%{opacity:0}}.hiw .r2{animation:hiw-r2 14s infinite}.hiw .c2{animation:hiw-c2 14s infinite;transform-box:fill-box;transform-origin:center}@keyframes hiw-r3{0%,50%{opacity:.28}53%,92%{opacity:1}100%{opacity:.28}}@keyframes hiw-c3{0%,55%{opacity:0;transform:scale(.85)}58%,92%{opacity:1;transform:scale(1)}100%{opacity:0}}.hiw .r3{animation:hiw-r3 14s infinite}.hiw .c3{animation:hiw-c3 14s infinite;transform-box:fill-box;transform-origin:center}@keyframes hiw-r4{0%,64%{opacity:.28}67%,92%{opacity:1}100%{opacity:.28}}@keyframes hiw-c4{0%,69%{opacity:0;transform:scale(.85)}72%,92%{opacity:1;transform:scale(1)}100%{opacity:0}}.hiw .r4{animation:hiw-r4 14s infinite}.hiw .c4{animation:hiw-c4 14s infinite;transform-box:fill-box;transform-origin:center}@media (prefers-reduced-motion:reduce){.hiw g{animation:none!important;opacity:1!important;transform:none!important}}</style><rect width="720" height="432" rx="16" fill="#1C2045"/><g class="r0"><rect x="24" y="24" width="672" height="64" rx="12" fill="#fff"/><circle cx="60" cy="56" r="17" fill="#FAB435"/><text x="60" y="63" text-anchor="middle" font-size="19" font-weight="800" fill="#1C2045">1</text><text x="92" y="63" font-size="20" font-weight="700" fill="#1C2045">Starts new or from a report</text></g><g class="c0"><rect x="502" y="40" width="170" height="32" rx="16" fill="#EEF0F7"/><text x="587.0" y="61" text-anchor="middle" font-size="14.5" font-weight="800" fill="#1C2045">Blank, or one report file</text></g><g class="r1"><rect x="24" y="104" width="672" height="64" rx="12" fill="#fff"/><circle cx="60" cy="136" r="17" fill="#FAB435"/><text x="60" y="143" text-anchor="middle" font-size="19" font-weight="800" fill="#1C2045">2</text><text x="92" y="143" font-size="20" font-weight="700" fill="#1C2045">Tests the query on your data</text></g><g class="c1"><rect x="562" y="120" width="110" height="32" rx="16" fill="#DDF1E5"/><text x="617.0" y="141" text-anchor="middle" font-size="14.5" font-weight="800" fill="#17603A">✓ 42 rows</text></g><g class="r2"><rect x="24" y="184" width="672" height="64" rx="12" fill="#fff"/><circle cx="60" cy="216" r="17" fill="#FAB435"/><text x="60" y="223" text-anchor="middle" font-size="19" font-weight="800" fill="#1C2045">3</text><text x="92" y="223" font-size="20" font-weight="700" fill="#1C2045">Compiles on Fishbowl's version</text></g><g class="c2"><rect x="552" y="200" width="120" height="32" rx="16" fill="#DDF1E5"/><text x="612.0" y="221" text-anchor="middle" font-size="14.5" font-weight="800" fill="#17603A">✓ No errors</text></g><g class="r3"><rect x="24" y="264" width="672" height="64" rx="12" fill="#fff"/><circle cx="60" cy="296" r="17" fill="#FAB435"/><text x="60" y="303" text-anchor="middle" font-size="19" font-weight="800" fill="#1C2045">4</text><text x="92" y="303" font-size="20" font-weight="700" fill="#1C2045">Asks where it goes</text></g><g class="c3"><rect x="442" y="280" width="230" height="32" rx="16" fill="#EEF0F7"/><text x="557.0" y="301" text-anchor="middle" font-size="14.5" font-weight="800" fill="#1C2045">Custom folder · Inventory menu</text></g><g class="r4"><rect x="24" y="344" width="672" height="64" rx="12" fill="#fff"/><circle cx="60" cy="376" r="17" fill="#FAB435"/><text x="60" y="383" text-anchor="middle" font-size="19" font-weight="800" fill="#1C2045">5</text><text x="92" y="383" font-size="20" font-weight="700" fill="#1C2045">Installs it</text></g><g class="c4"><rect x="442" y="360" width="230" height="32" rx="16" fill="#EEF0F7"/><text x="557.0" y="381" text-anchor="middle" font-size="14.5" font-weight="800" fill="#1C2045">v1 · admins only until granted</text></g></svg>
<figcaption>The AI builds a Jasper report in five steps, and it only installs the report after a clean compile.</figcaption>
</figure>

1. **It starts from scratch or from a report you have.** The AI can build a new report from nothing, or start from a single existing report file and change it from there.
2. **It tests the query** against your Fishbowl data before it goes into the report.
3. **It compiles the report** with the same JasperReports version Fishbowl runs. The AI can only call the report ready after a clean compile. Compiling checks the report file and doesn't read your data.
4. **It asks where the report goes.** You choose the folder and which modules show it in their print menus.
5. **It installs the report.** A new report is visible to Fishbowl admins until an admin grants it to groups.

Every save is a version, so you can roll back to an earlier one. The AI can only remove reports it installed.

## Changing a report

<figure>
<svg class="chg" viewBox="0 0 720 432" role="img" aria-label="A person asks the AI to add each part's lead time to the Inventory Reorder List and sort by it. A Lead time column appears, the rows re-sort from longest lead time to shortest, and the change is saved as version 2 with an option to roll back to version 1." style="display:block;width:100%;height:auto;border-radius:16px;font-family:'Hanken Grotesk',system-ui,sans-serif"><style>
.chg .bub{animation:chg-b 12s infinite}
.chg .col{animation:chg-col 12s infinite}
.chg .ver{animation:chg-v 12s infinite}
.chg .m0{transform:translateY(36px);animation:chg-m0 12s infinite}
.chg .m1{transform:translateY(72px);animation:chg-m1 12s infinite}
.chg .m3{transform:translateY(-108px);animation:chg-m3 12s infinite}
@keyframes chg-b{0%,3%{opacity:0}8%,92%{opacity:1}100%{opacity:0}}
@keyframes chg-col{0%,18%{opacity:0}24%,92%{opacity:1}100%{opacity:0}}
@keyframes chg-v{0%,56%{opacity:0}61%,92%{opacity:1}100%{opacity:0}}
@keyframes chg-m0{0%,38%{transform:translateY(0)}47%,92%{transform:translateY(36px)}100%{transform:translateY(0)}}
@keyframes chg-m1{0%,38%{transform:translateY(0)}47%,92%{transform:translateY(72px)}100%{transform:translateY(0)}}
@keyframes chg-m3{0%,38%{transform:translateY(0)}47%,92%{transform:translateY(-108px)}100%{transform:translateY(0)}}
@media (prefers-reduced-motion:reduce){.chg .bub,.chg .col,.chg .ver,.chg .m0,.chg .m1,.chg .m3{animation:none!important}}
</style>
<rect width="720" height="432" rx="16" fill="#1C2045"/>
<g class="bub"><rect x="282" y="20" width="414" height="44" rx="14" fill="#fff"/><text x="489" y="48" text-anchor="middle" font-size="16" font-weight="700" fill="#1C2045">Add each part's lead time, and sort by it.</text></g>
<rect x="24" y="80" width="672" height="262" rx="14" fill="#fff"/>
<text x="46" y="114" font-size="19" font-weight="800" fill="#1C2045">Inventory Reorder List</text>
<rect x="596" y="96" width="80" height="26" rx="13" fill="#EEF0F7"/><text x="636" y="114" text-anchor="middle" font-size="12.5" font-weight="800" fill="#6B6F86">Custom</text>
<g class="col"><rect x="500" y="134" width="180" height="196" rx="8" fill="#FFF3D6"/></g>
<g font-size="12.5" font-weight="800" fill="#6B6F86" letter-spacing=".05em"><text x="46" y="156">PART</text><text x="300" y="156">ON HAND</text><text x="400" y="156">REORDER AT</text></g>
<g class="col"><text x="516" y="156" font-size="12.5" font-weight="800" fill="#8A5A00" letter-spacing=".05em">LEAD TIME</text></g>
<g stroke="#E6E7EF"><line x1="40" y1="168" x2="680" y2="168"/><line x1="40" y1="204" x2="680" y2="204"/><line x1="40" y1="240" x2="680" y2="240"/><line x1="40" y1="276" x2="680" y2="276"/><line x1="40" y1="312" x2="680" y2="312"/></g>
<g font-size="16" font-weight="600" fill="#1C2045">
<g class="m0"><text x="46" y="192">Steel bracket</text><text x="300" y="192">4</text><text x="400" y="192">10</text><text class="col" x="516" y="192">21 days</text></g>
<g class="m1"><text x="46" y="228">Hex bolt M8</text><text x="300" y="228">120</text><text x="400" y="228">200</text><text class="col" x="516" y="228">5 days</text></g>
<g class="m2"><text x="46" y="264">Gasket kit</text><text x="300" y="264">2</text><text x="400" y="264">6</text><text class="col" x="516" y="264">14 days</text></g>
<g class="m3"><text x="46" y="300">Shelf panel</text><text x="300" y="300">8</text><text x="400" y="300">12</text><text class="col" x="516" y="300">30 days</text></g>
</g>
<text x="24" y="389" font-size="13" font-weight="800" fill="#B8BCD6" letter-spacing=".08em">VERSIONS</text>
<rect x="120" y="368" width="44" height="30" rx="8" fill="#2E3466"/><text x="142" y="389" text-anchor="middle" font-size="15" font-weight="800" fill="#fff">v1</text>
<g class="ver"><text x="180" y="390" font-size="18" font-weight="800" fill="#B8BCD6">→</text>
<rect x="212" y="368" width="44" height="30" rx="8" fill="#FAB435"/><text x="234" y="389" text-anchor="middle" font-size="15" font-weight="800" fill="#1C2045">v2</text>
<text x="272" y="389" font-size="15" font-weight="700" fill="#fff">Lead time added, sorted by it</text>
<text x="696" y="389" text-anchor="end" font-size="15" font-weight="800" fill="#7FD3A6">↺ Roll back to v1</text></g>
</svg>
<figcaption>A change to a custom report is saved as a new version, and the earlier version stays available.</figcaption>
</figure>

Ask for a change to one of your custom reports and the AI edits it in place as a new version. Fishbowl's own reports are never changed. If you want one modified, for example the standard packing slip with a lot number column, the AI copies it as "Packing Slip (Custom)" and works on the copy.

## The browser editor

<figure>
<svg class="bed" viewBox="0 0 720 432" role="img" aria-label="A simplified browser report editor. A person selects the To Order field and widens it, and the width in the properties panel changes. Then the editor shows that the AI assistant changed the report, with a choice to load its version or keep yours. The person loads it, a vendor group band appears in the layout, and the report compiles." style="display:block;width:100%;height:auto;border-radius:16px;font-family:'Hanken Grotesk',system-ui,sans-serif"><style>
.bed .sel{transform-box:fill-box;transform-origin:left center;transform:scaleX(1.3);animation:bed-sel 14s infinite}
.bed .w58{opacity:0;animation:bed-w58 14s infinite}
.bed .w75{animation:bed-w75 14s infinite}
.bed .saved{animation:bed-saved 14s infinite}
.bed .chg{opacity:0;animation:bed-chg 14s infinite}
.bed .bar{opacity:0;animation:bed-bar 14s infinite}
.bed .ld{animation:bed-ld 14s infinite}
.bed .vend{animation:bed-vend 14s infinite}
.bed .down{animation:bed-down 14s infinite}
.bed .cons{animation:bed-vend 14s infinite}
.bed .cur{opacity:0;animation:bed-cur 14s infinite}
@keyframes bed-sel{0%,8%{opacity:0;transform:scaleX(1)}11%,14%{opacity:1;transform:scaleX(1)}23%,92%{opacity:1;transform:scaleX(1.3)}100%{opacity:0;transform:scaleX(1)}}
@keyframes bed-w58{0%,8%{opacity:0}11%,21%{opacity:1}23%,100%{opacity:0}}
@keyframes bed-w75{0%,21%{opacity:0}23%,92%{opacity:1}100%{opacity:0}}
@keyframes bed-saved{0%,33%{opacity:1}35%,58%{opacity:0}61%,100%{opacity:1}}
@keyframes bed-chg{0%,33%{opacity:0}35%,58%{opacity:1}61%,100%{opacity:0}}
@keyframes bed-bar{0%,35%{opacity:0}38%,57%{opacity:1}60%,100%{opacity:0}}
@keyframes bed-ld{0%,54%{fill:#FAB435}55%,57%{fill:#E09A12}58%,100%{fill:#FAB435}}
@keyframes bed-vend{0%,58%{opacity:0}62%,92%{opacity:1}100%{opacity:0}}
@keyframes bed-down{0%,58%{transform:translateY(-28px)}62%,92%{transform:translateY(0)}100%{transform:translateY(-28px)}}
@keyframes bed-cur{0%{opacity:0;transform:translate(470px,330px)}4%{opacity:1;transform:translate(470px,330px)}10%{transform:translate(515px,186px)}14%{transform:translate(515px,186px)}23%{transform:translate(533px,186px)}30%{transform:translate(533px,186px)}47%{transform:translate(262px,324px)}56%{opacity:1;transform:translate(262px,324px)}62%,100%{opacity:0;transform:translate(262px,324px)}}
@media (prefers-reduced-motion:reduce){.bed *{animation:none!important}.bed .cur{opacity:0}}
</style>
<rect width="720" height="432" rx="16" fill="#1C2045"/>
<rect x="16" y="16" width="688" height="400" rx="12" fill="#fff"/>
<rect x="16" y="16" width="688" height="40" rx="12" fill="#F4F5FA"/><rect x="16" y="44" width="688" height="12" fill="#F4F5FA"/><line x1="16" y1="56" x2="704" y2="56" stroke="#E6E7EF"/>
<text x="32" y="41" font-size="14" font-weight="800" fill="#1C2045">Report editor</text>
<g class="saved"><rect x="146" y="25" width="64" height="22" rx="11" fill="#DDF1E5"/><text x="178" y="40" text-anchor="middle" font-size="11.5" font-weight="800" fill="#17603A">● Saved</text></g>
<g class="chg"><rect x="146" y="25" width="196" height="22" rx="11" fill="#FDEBD3"/><text x="244" y="40" text-anchor="middle" font-size="11.5" font-weight="800" fill="#9A5B00">● Changed by the AI assistant</text></g>
<rect x="486" y="25" width="70" height="22" rx="6" fill="#fff" stroke="#D5D8E4"/><text x="521" y="40" text-anchor="middle" font-size="11.5" font-weight="700" fill="#1C2045">Compile</text>
<rect x="564" y="25" width="128" height="22" rx="6" fill="#1C2045"/><text x="628" y="40" text-anchor="middle" font-size="11.5" font-weight="700" fill="#fff">Compile + Publish</text>
<line x1="150" y1="56" x2="150" y2="416" stroke="#E6E7EF"/><line x1="560" y1="56" x2="560" y2="416" stroke="#E6E7EF"/>
<g font-size="12" font-weight="700" fill="#1C2045"><text x="28" y="80" font-size="10.5" font-weight="800" fill="#6B6F86" letter-spacing=".06em">SECTIONS</text>
<text x="28" y="106">Title</text><text x="28" y="132">Column Header</text><rect x="22" y="144" width="122" height="24" rx="6" fill="#EEF0F7"/><text x="28" y="161">Detail</text><text x="28" y="188">Page Footer</text>
<text x="28" y="222" font-size="10.5" font-weight="800" fill="#6B6F86" letter-spacing=".06em">DEFINITIONS</text><text x="28" y="248" fill="#6B6F86">Query (SQL)</text><text x="28" y="272" fill="#6B6F86">Fields</text></g>
<g font-size="11.5" font-weight="700" fill="#6B6F86"><text x="572" y="80" font-size="10.5" font-weight="800" letter-spacing=".06em">PROPERTIES</text>
<text x="572" y="106">expression</text><rect x="572" y="112" width="120" height="22" rx="5" fill="#fff" stroke="#D5D8E4"/><text x="580" y="127" fill="#1C2045">qtyToOrder</text>
<text x="572" y="156">x</text><rect x="626" y="143" width="66" height="22" rx="5" fill="#fff" stroke="#D5D8E4"/><text x="634" y="158" fill="#1C2045">470</text>
<text x="572" y="186">width</text><rect x="626" y="173" width="66" height="22" rx="5" fill="#fff" stroke="#D5D8E4"/><text class="w58" x="634" y="188" fill="#1C2045">58</text><text class="w75" x="634" y="188" fill="#1C2045">75</text>
<text x="572" y="216">height</text><rect x="626" y="203" width="66" height="22" rx="5" fill="#fff" stroke="#D5D8E4"/><text x="634" y="218" fill="#1C2045">14</text></g>
<rect x="160" y="68" width="390" height="340" fill="#F7F7F9"/><rect x="166" y="74" width="378" height="300" fill="#fff" stroke="#E6E7EF"/>
<g fill="none" stroke="#C9CCDA" stroke-dasharray="4 3"><rect x="172" y="80" width="366" height="52"/><rect x="172" y="136" width="366" height="28"/></g>
<text x="180" y="108" font-size="19" font-weight="800" fill="#1C2045">Inventory Reorder List</text><text x="180" y="125" font-size="11" font-weight="600" fill="#6B6F86">Items at or below reorder point</text>
<g font-size="11.5" font-weight="800" fill="#1C2045"><text x="180" y="155">Product</text><text x="306" y="155">On Hand</text><text x="382" y="155">Reorder</text><text x="470" y="155">To Order</text></g>
<g class="vend"><rect x="172" y="168" width="366" height="24" fill="#FFF3D6" stroke="#E7B54A" stroke-dasharray="4 3"/><text x="180" y="184" font-size="11.5" font-weight="800" fill="#8A5A00">Vendor: vendorName</text></g>
<g class="down"><rect x="172" y="196" width="366" height="28" fill="none" stroke="#C9CCDA" stroke-dasharray="4 3"/>
<g font-size="10.5" font-weight="700" fill="#1C2045"><rect x="178" y="202" width="96" height="16" rx="3" fill="#EEF0F7"/><text x="183" y="214">productNum</text><rect x="304" y="202" width="70" height="16" rx="3" fill="#EEF0F7"/><text x="308" y="214">qtyOnHand</text><rect x="380" y="202" width="80" height="16" rx="3" fill="#EEF0F7"/><text x="384" y="214">reorderPoint</text><rect x="468" y="202" width="58" height="16" rx="3" fill="#EEF0F7"/><text x="472" y="214">qtyToOrder</text></g>
<rect class="sel" x="467" y="201" width="58" height="18" rx="3" fill="none" stroke="#FAB435" stroke-width="2" stroke-dasharray="4 2"/>
<rect x="172" y="228" width="366" height="24" fill="none" stroke="#C9CCDA" stroke-dasharray="4 3"/><text x="530" y="244" text-anchor="end" font-size="10.5" font-weight="600" fill="#6B6F86">Page 1</text></g>
<g class="bar"><rect x="176" y="282" width="358" height="66" rx="10" fill="#fff" stroke="#E7B54A" stroke-width="1.5"/><text x="190" y="304" font-size="12.5" font-weight="800" fill="#1C2045">The AI assistant changed this report.</text>
<rect class="ld" x="190" y="314" width="118" height="24" rx="6" fill="#FAB435"/><text x="249" y="330" text-anchor="middle" font-size="11.5" font-weight="800" fill="#1C2045">Load its version</text>
<rect x="316" y="314" width="84" height="24" rx="6" fill="#fff" stroke="#D5D8E4"/><text x="358" y="330" text-anchor="middle" font-size="11.5" font-weight="700" fill="#1C2045">Keep mine</text></g>
<g class="cons"><text x="168" y="396" font-size="11" font-weight="700" fill="#17603A" font-family="ui-monospace,Consolas,monospace">✓ compiled · updated with the assistant's changes</text></g>
<path class="cur" d="M0 0 L0 17 L5 12.5 L8.5 20 L11 19 L7.6 11.6 L14 11.6 Z" fill="#1C2045" stroke="#fff" stroke-width="1.2"/>
</svg>
<figcaption>A person widens a field by hand, then loads the AI assistant's change without losing their own.</figcaption>
</figure>

Some changes are quicker by hand, like moving a field, changing a font or widening a column. ILC's browser report editor shows the report's layout, and a person can move and resize fields, edit text and expressions, and work with each section of the report.

The editor uses the same JasperReports version as Fishbowl, so it won't offer anything Fishbowl can't open. Newer desktop editors save files Fishbowl rejects, which is a common problem for anyone editing Fishbowl reports today.

A person and the AI can work on the same report. If the AI changes it while you're editing, the editor tells you, and you choose whether to load the AI's version or keep yours. For people allowed to install reports, Compile + Publish updates an installed report in Fishbowl in one step, as a new version you can roll back.

## Limits today

- A report is a single file. Subreports aren't supported for now, to keep reports simple.
- Logos and QR codes are coming. 1D barcodes work today.
- There's no preview with data before install. You install the report and run it in Fishbowl to check it.
- Reports that need more, like several subreports or a layout per customer, are work for our team, and we quote them like any other report project.

Building Jasper reports is part of the Custom reports add-on for ILC MCP, for teams that need it.

## Where to start

Pick a report your team exports to Excel and reformats by hand every week. That's usually the first one worth having the AI build. If there's a report you've been waiting on, [tell us what it should show](/contact).

**Related:**
- [Can an AI assistant build a Fishbowl report and install it?](/blog/ai-builds-fishbowl-reports)
- [Why I probably won't write a report ever again](/blog/custom-reports-with-ilc-mcp)
- [Fishbowl custom reports](/fishbowl-custom-reports)

---

*From Israel Lopez Consulting (ILC). Custom Fishbowl Inventory integrations and software, and Fishbowl experts since 2015. Written by Israel Lopez, published October 19, 2026. Questions about this topic, or want to reach the people who wrote it? Visit https://israellopezconsulting.com/contact*
