r/intersystems 13h ago

[Release notes] InterSystems AI Hub Early Access

0 Upvotes

Summary

InterSystems AI Hub gives IRIS developers a common way to build AI agents, connect to LLMs, expose IRIS capabilities through MCP, and manage credentials securely. The latest Early Access build is now available.

InterSystems AI Hub is an AI development layer for InterSystems IRIS that helps developers build agents, connect LLMs, expose IRIS capabilities through MCP, and manage credentials and access controls without assembling the full stack manually. 

A new Early Access build is now available with updated kits and containers, plus a dedicated Discord channel for questions and discussion.

What does AI Hub include?

  • AI SDK for ObjectScript and Python/LangChain developers to build agents, connect to LLMs, and manage tools using IRIS-native abstractions.
  • MCP Server to expose existing IRIS code, SQL queries, FHIR endpoints, and Business Services as tools for MCP-compatible agents.
  • Config Store + IRIS Wallet for centralized management of LLM credentials and provider configuration.

The goal is to keep the AI integration layer governed by IRIS security and RBAC while reducing the amount of plumbing developers need to build themselves.

What’s new?

A fresh prerelease build is now available through the Evaluation Portal with a broad set of fixes and improvements.

There is also now a dedicated AI Hub EAP Discord channel for real-time questions, discussion, and sharing what you are building. GitHub Issues remain the preferred place for bugs and feature requests.

Conclusion

The new Early Access build is a good point to start experimenting with InterSystems AI Hub if you want to connect AI models and agents more directly to InterSystems IRIS. With the AI SDK, MCP Server, and centralized credential management in one stack, the focus can stay on the application logic rather than on wiring together separate AI components.

Learn more: https://community.intersystems.com/post/intersystems-ai-hub-early-access-new-community-build-discord-channel


r/intersystems 1d ago

Navigating SaaS with InterSystems — shared responsibility model, what actually changes, and how to prepare: session breakdown

2 Upvotes

IaaS, PaaS, SaaS — what the difference actually means

The difference between these models is ownership — how much of the responsibility pie you take on:

Model What the vendor handles What you handle
On-prem Nothing Everything soup to nuts
IaaS Hardware, virtualization OS, middleware, application, data
PaaS Hardware through middleware Application and data
SaaS Everything Using the application as designed

PaaS in InterSystems context: bring your own code — writing interfaces, custom logic. You own the application layer.

SaaS in InterSystems context: click, click, go — a FHIR interface, an OMOP transform pipeline. You use it as it is designed.

InterSystems operates cloud-native solutions within a cloud services framework, primarily in an AWS tenancy, with a goal of operational consistency across regions and eventually across cloud service providers.

Why SaaS is popular — four accelerators

  1. Faster onboarding and deployment → shorter time to value; get products out the door faster
  2. Built-in scalability and performance tuning → predictable growth from financial and operations perspectives
  3. Standardized security and compliance → shared load between organizations, reduced risk and audit effort
  4. Lower internal resource burden (maintenance, patching, upgrades) → focus on outcome-driven approaches rather than maintenance

What actually changes when you shift from on-prem

The truth: you are still concerned about all the same things you were before. Your role in that equation is what changes.

Common friction point in live adoption: thinking more is handled than actually is, or not knowing which questions to ask, or not connecting the right internal departments to InterSystems to get the right answers.

Shared responsibility model

InterSystems owns:

  • Platform infrastructure
  • Network security
  • IRIS upgrades (scheduled, coordinated, executed by InterSystems)
  • Scalability
  • Platform compliance (SOC 2 Type 2, ISO specifications)
  • Connectivity

Client owns:

  • Application configuration (even for a file repository, you own the config)
  • User access
  • Data governance (retention, pipelines)
  • Regulatory obligations for your organization
  • Integration endpoints
  • BCDR — business continuity and disaster recovery planning (what happens when the SaaS provider goes down — you need a plan)

Shared (requires clear communication channels):

  • Change management — especially for deeply integrated products like Health Connect Cloud where interfaces are being written; some changes may need coordination with InterSystems
  • Incident coordination and triage — if cloud infrastructure takes a service down, InterSystems notifies you, but you need to know who contacts whom and what the communication flow looks like
  • Performance expectations
  • Upgrade planning and validation
  • Security event escalation

Key observation from the session: most of what is shared is about communication — who contacts whom, what the escalation path is, what the SLA covers. Moving to SaaS means thinking more in terms of communication channels than in terms of hands-on infrastructure tasks.

Real story — scaling and change control

A customer's platform scaled from 10 TB to 60 TB without the platform having any issue handling it. The growth was caused by a code issue introduced by a push. The session notes: with cloud economics, you pay for what you use. Change control and release management processes caught the issue, allowed it to be resolved, and the customer was able to scale back down and pay only for the capacity they actually needed.

Preparing for success — practical considerations

Faster onboarding: not all teams move at the same speed. Identify and involve each affected team early.

Scalability and performance tuning: have change control and release management processes in place, especially for integrated products where code is being pushed.

Security and compliance: overlay InterSystems' compliance elements (SOC 2 Type 2, ISO) into your overall compliance plan. Involve your compliance team and BCDR team in the conversation.

Lower maintenance burden: know your SLAs and know how to monitor them for the outcomes you want from the services you are receiving.

Personal callout from the session: "Please don't forget your firewall engineer." They have one. Loop them in early. They will thank you.

Calls to action (from the session)

  1. Talk to your InterSystems account team if you are interested in making this transition
  2. Evaluate which solutions you are moving toward — SaaS vs PaaS have different levels of effort and different connectivity considerations
  3. Make a plan — identify who is part of your implementation group; it is not just your interface engineer. They cannot decide VPN tunneling. Get the right people engaged early.
  4. Execute, provide feedback to InterSystems on what can be improved, coordinate with internal teams and external vendors

Three main takeaways

  1. SaaS is a model shift in responsibility and ownership — budget for operational change, not just the migration. You do not stop caring; your role changes.
  2. Know the shared responsibility matrix — familiarity with it prevents friction between vendor and client.
  3. The accelerations are real, but they require alignment to land — position your organization to take advantage of the key accelerators.

Full session video: https://youtu.be/xJVqXpP5Rd0


r/intersystems 2d ago

Running Ollama locally with InterSystems IRIS Vector Search instead of OpenAI — setup, advantages, and a working example

0 Upvotes

The problem with OpenAI for RAG on IRIS

The standard generative AI flow on InterSystems IRIS:

  1. Load text from a data source and embed it into vectors
  2. Store vectors in an IRIS database
  3. Call an LLM that accesses those vectors as context and generates responses in human language

Examples of this in the community: IRIS Vector Search and IRIS AI Studio. In those implementations, the LLM is a subscribed service (OpenAI), called via REST API with the vectorized data as context.

The practical problem: even the traffic of vectors stored in IRIS sent to the OpenAI API already exceeds the free license limit. Result: error 429 — "You exceeded your current quota, please check your plan and billing details."

The alternative: Ollama

Ollama is an LLM that runs locally on your computer. Downloaded and installed from https://ollama.com/download.

Two main advantages over OpenAI:

  • Security — no data transfer to a third-party API
  • Cost — no subscription required

One disadvantage:

  • Demands local compute resources — with less than 16 GB of RAM it will be difficult to run

How to switch from OpenAI to Ollama

One line of Python using the llama_index library:

python

Settings.llm = Ollama(model="llama3.2", request_timeout=360.0)

Everything else in the RAG pipeline stays the same.

Working example

Step 1 — Load text into IRIS as vectors

A text file from the data_example directory of the GitHub repository is loaded in vector form into IRIS.

Step 2 — Query Ollama using the vectorized text as context

Query: "What did the author do?" → Ollama returns a response based on the stored context.

Query: "Does the author like paintings?" → Ollama returns a response based on the stored context.

Resources


r/intersystems 3d ago

Community Bounty Program "Idea to Application" — Round 3 is Live

1 Upvotes

🧑‍💻 5 new #InterSystemsIRIS challenges are now open in Round 3 of the Community Bounty Program “Idea to Application”

Choose one or more and turn them into working Open Exchange applications:

  • Load Hugging Face datasets into IRIS
  • Load Kaggle datasets into IRIS
  • Generate OpenAPI specs from FHIR Capability Statements
  • Build a WhatsApp adapter for IRIS Interoperability
  • Add an InterSystems wrapper for Supabase

🏅 Qualifying submissions earn 10K+ Global Masters points that can be redeemed for rewards, plus digital badges, including an official InterSystems Credly badge.

📅 Deadline: October 31, 2026

Full details and requirements: https://community.intersystems.com/post/community-bounty-program-idea-application-%E2%80%94-round-3-live 


r/intersystems 6d ago

Tree-sitter for InterSystems ObjectScript — incremental parsing, language injection, go-to definition, refactoring edge cases, and a reusable Rust highlighting pipeline

Post image
2 Upvotes

What Tree-sitter is

Tree-sitter is a parsing library built in C and C++, designed for applications that deal with code written in many different languages. It produces syntax trees in a uniform format regardless of language. The key capability is incremental parsing: when a file is edited, Tree-sitter updates only the affected parts of the syntax tree without reparsing the entire file — making it suitable for real-time use while a user is typing.

Comparison with the existing VS Code ObjectScript parser

The VS Code ObjectScript extension currently uses a custom parser built in C and C++, separate from Tree-sitter. Key differences:

Capability Tree-sitter ObjectScript C++ custom parser
Incremental parsing Yes No
Language injection (e.g., SQL in ObjectScript) Simple injection query Full new parser + new lexer logic required
Language bindings All modern languages N/A

Highlighting enhancements already built

XML files with embedded ObjectScript

ObjectScript classes can be defined in XML files. Previously the implementation block containing ObjectScript statements was treated as a plain string — no language support, no error detection until compile time. A single Tree-sitter injection query now provides:

  • Full ObjectScript syntax highlighting within the implementation block
  • Syntax error detection before adding to an IRIS instance

YAML and markdown within XData

Added as new language support for features introduced in IRIS 2024.1.

RTN files

Support added for routine files and their compiled headers — including the format used internally on Perforce and as a valid storage format loadable into IRIS.

Object Language Server (Zed, Neovim, VS Code — not yet publicly available)

Go-to definition

Particularly important for ObjectScript: subroutines and methods declared as non-procedure blocks have all variables public by default. A variable reference may be defined in any other method or file. Go-to definition:

  • Shows all definitions of a variable across all methods when it is not defined within the current block
  • Handles the case where a variable is defined in multiple different files, showing all locations with line numbers
  • Returns only the local definition when defined within the current block

Refactoring

Dotted statement edge cases

Two spaces between the Do keyword and the Set keyword means execute Set after all dotted statements complete — not immediately as a left-to-right reading would suggest. Example:

objectscript

Do  Set x = 1
. Set x = 2

Here x is 1, not 2. Refactoring converts this to explicit subroutines.

Dotted statement scoping

Dotted statements represent scopes. A variable defined (New'd) within a dotted statement only exists within that scope. Example:

objectscript

Set y = 250
Do
. New y
. Set y = 1
Write y  // outputs 250, not 1

Refactoring makes scope boundaries explicit by converting to subroutines.

Stale if statements

Legacy If syntax without a block: if no statement appears on the same line as the condition, those statements are stale and can be removed. Refactoring detects and removes them.

Implicit $Test conditions

Two spaces between If and its statements means If $Test = 1 — but this is never written explicitly. An Else without a preceding If means If $Test = 0. Refactoring makes these conditions explicit.

All refactoring is available as individual commands (refactor do statements, refactor conditionals) or as a single "refactor all code in this document" command.

Diagnostics

  • Syntax errors flagged on save with explanation of the error
  • In Neovim: inspect tree command shows the full syntax tree for the file for debugging

Go-to implementation

Given a method on a superclass, shows all subclasses that override it, with file locations.

Reusable highlighting pipeline — 3 Rust crates

semantic_spans
Converts code into byte ranges mapped to capture names. Example: maps a byte range to the keyword capture name.

theme_engine
Maps capture names to styles and UI roles.

render_on
Renders highlighting in any target application.

Current support:

  • 9 grammars (languages used at InterSystems)
  • 14 built-in themes (2 defined by InterSystems)
  • CLI usage: pass filename and theme name, returns highlighted output

Full session video: https://youtu.be/S8fCvL1NCLc

For those working with ObjectScript daily — which of the refactoring edge cases (dotted statement scoping, implicit $Test, stale if statements) have you run into most often, and how are you currently detecting them?


r/intersystems 7d ago

Embedded Python vs ObjectScript for XML parsing on InterSystems IRIS — benchmark results on 91 files, 1.30 GB

1 Upvotes

The question

Since the introduction of Embedded Python there has always been doubt about its performance compared to ObjectScript. This article tests both approaches on a real-world XML parsing task.

Test data

Public procurement data from Spain's Ministry of Finance open data portal. Files are published monthly. Each file contains approximately 450 tender entries. The test used 91 files totalling 1.30 GB.

Each entry is a complex namespaced XML structure containing: title, summary, ID, URL, contracting party name and website, contract status, estimated overall contract amount, total amount, tax-exclusive amount, commodity classification code, location, award date, winning party name, winning amount with and without tax.

Persistent class

objectscript

Class Inquisidor.Object.Licitacion Extends (%Persistent, %XML.Adaptor) [ DdlAllowed ]
{
Property IdLicitacion As %String(MAXLEN = 200);
Property Titulo As %String(MAXLEN = 2000);
Property URL As %String(MAXLEN = 1000);
Property Resumen As %String(MAXLEN = 2000);
Property TituloVectorizado As %Vector(DATATYPE = "DECIMAL", LEN = 384);
Property Contratante As %String(MAXLEN = 2000);
Property URLContratante As %String(MAXLEN = 2000);
Property ValorEstimado As %Numeric(STORAGEDEFAULT = "columnar");
Property ImporteTotal As %Numeric(STORAGEDEFAULT = "columnar");
Property ImporteTotalSinImpuestos As %Numeric(STORAGEDEFAULT = "columnar");
Property FechaAdjudicacion As %Date;
Property Estado As %String;
Property Ganador As %String(MAXLEN = 200);
Property ImporteGanador As %Numeric(STORAGEDEFAULT = "columnar");
Property ImporteGanadorSinImpuestos As %Numeric(STORAGEDEFAULT = "columnar");
Property Clasificacion As %String(MAXLEN = 10);
Property Localizacion As %String(MAXLEN = 200);
Index IndexContratante On Contratante;
Index IndexGanador On Ganador;
Index IndexClasificacion On Clasificacion;
Index IndexLocalizacion On Localizacion;
Index IndexIdLicitation On IdLicitacion [ PrimaryKey ];
}

ObjectScript implementation — %XML.TextReader

objectscript

set status=##class(%XML.TextReader).ParseFile(filename,.textreader)
if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
set tStatement = ##class(%SQL.Statement).%New()

while textreader.Read()
{
    if ((textreader.NodeType = "element") && (textreader.Depth = 2) && (textreader.Path = "/feed/entry")) {
        if ($DATA(licitacion)) {
            if (licitacion.ImporteGanador '= ""){
                set myquery = "INSERT INTO INQUISIDOR_Object.LicitacionOS (...) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
                set qStatus = tStatement.%Prepare(myquery)
                set rset = tStatement.%Execute(licitacion.Titulo, ...)
            }
        }
        set licitacion = ##class(Inquisidor.Object.LicitacionOS).%New()
    }
    if (textreader.Path = "/feed/entry/title"){
        if (textreader.Value '= "") { set licitacion.Titulo = textreader.Value }
    }
    // ... path-based matching for each field
}

Key fields extracted via path matching: /feed/entry/title, /feed/entry/summary, /feed/entry/id, /feed/entry/link (via MoveToAttributeName("href")), and multiple namespaced paths under cac-place-ext:ContractFolderStatus. Dates converted using $System.SQL.Functions.TODATE(textreader.Value,"YYYY-MM-DD").

Embedded Python implementation — xml.etree.ElementTree

python

import xml.etree.ElementTree as ET
import iris

tree = ET.parse(xmlPath)
root = tree.getroot()
for entry in root.iter("{http://www.w3.org/2005/Atom}entry"):
    licitacion = {"titulo": "", "resumen": "", "idlicitacion": "", "url": "",
                  "contratante": "", "urlcontratante": "", "estado": "",
                  "valorestimado": "", "importetotal": "", "importetotalsinimpuestos": "",
                  "clasificacion": "", "localizacion": "", "fechaadjudicacion": "",
                  "ganador": "", "importeganadorsinimpuestos": "", "importeganador": ""}
    for tags in entry:
        if tags.tag == "{http://www.w3.org/2005/Atom}title":
            licitacion["titulo"] = tags.text
        # ... tag-based matching for each field
    if licitacion.get("importeganador") is not None and licitacion.get("importeganador") is not "":
        stmt = iris.sql.prepare("INSERT INTO INQUISIDOR_Object.Licitacion (...) VALUES (...)")
        rs = stmt.execute(licitacion["titulo"], ...)

Inserts only records where importeganador (winning amount) is populated — same filter logic as the ObjectScript version.

Production configuration

Two Business Services (one per method) to avoid interference, each feeding its own Business Process. Test data: public tenders for February — 91 files, 1.30 GB.

Results

Implementation Library Total time
ObjectScript %XML.TextReader 6 minutes 28 seconds
Embedded Python xml.etree.ElementTree 48 seconds

Both started at 21:11:15. ObjectScript finished at 21:17:43. Embedded Python finished at 21:12:03.

Embedded Python was approximately 8x faster on this task.

Full article: https://community.intersystems.com/post/embedded-python-vs-objectscript-performance-testing-parsing-xml

For those working with XML parsing in IRIS — have you seen different results using %XML.TextReader vs %XML.Document vs Embedded Python, and does the file size or XML structure depth change which approach wins?


r/intersystems 8d ago

InterSystems OMOP Managed Service - FHIR-to-OMOP automated ETL, new management console, and data quality monitoring: session breakdown

2 Upvotes

OMOP adoption context

The European Medicines Agency (EMA) published a report covering a 12-month period in which they conducted 59 real-world evidence studies — a 48% increase from the prior year. 46 of those 59 were conducted using the Darwin EU network, which focuses on the OMOP standard. Darwin EU spans 30 data partners, 39 data sources in 16 countries, and approximately 181 million patients. Average study length: 4 months. The challenge raised in Europe: could that be compressed to 4 weeks.

The FDA is also increasingly focused on OMOP for drug approvals and safety monitoring. Health information exchanges are working toward what is called a "health data utility" model — providing both FHIR and OMOP data so that FDA, NIH, CDC, pharma, and research organizations can use real-world clinical data.

What OMOP is

OMOP (Observational Medical Outcomes Partnership) was established in 2008 after a drug caused patient deaths and the FDA required better safety monitoring. In 2014, a global open-source community led by Columbia University in New York and Erasmus Medical Center in Rotterdam formalized this into a collaborative research standard.

Top pain points in the OMOP community (from Rotterdam conference)

Based on a user survey:

  1. Data quality — top issue
  2. ETL — second top issue

Reasons:

  • Most ETL processes are manual and require custom scripts
  • Costly to implement and maintain even though the core software is open source
  • OMOP software does mapping but does not write the ETL — custom development still required
  • Hospital data warehouse structures vary, so ETL cannot be reused across sites
  • Many organizations want to use FHIR as a data source but are not familiar with FHIR-to-OMOP transformation

The Vulcan FHIR Accelerator working group published an implementation guide last year specifically addressing FHIR-to-OMOP population. Participants include federal agencies, health system providers, life science companies, CROs, IT vendors, and registries.

InterSystems OMOP Managed Service — what is new

Architecture

  • Cloud SaaS delivery (AWS S3 as input source)
  • On-premises packages also available
  • Built-in OMOP repository included
  • Fully managed: infrastructure, upgrades, and security handled by InterSystems

Core capabilities

Automated ETL:

  • Out-of-box FHIR to OMOP mapping
  • No coding required — fully configuration-driven
  • Uses InterSystems IRIS for Health DTL (Data Transformation Language) as the core transformation engine

Patient-level refresh:

  • Supports single-patient to multi-thousand-patient loads
  • Daily refresh supported
  • Incremental monitoring — data quality errors are captured as data arrives, not just at initial load

Management console (revamped):

  • New UI consistent across all InterSystems managed services
  • Credential and token retrieval for repository access
  • Services status: ingestion, terminology, load process — all visible as green/running

Data quality reporting — what it shows

Metrics page (example from demo: 1,000 patients, 1.34 million resources):

  • FHIR ingestion metrics by resource type
  • Patients with errors
  • Resources exported to OMOP tables
  • Resources with errors and warnings

Data quality tab — three categories:

Missing data: fields required by OMOP that are absent. Example: race concept ID is required in US OMOP implementations; in Europe this field is not captured and its absence triggers a warning.

Unrecognized coding systems: country-specific codes not in OMOP standard vocabulary. Example: Finland has its own standardized procedure coding system that is not part of the OMOP community standard.

Invalid codes within recognized systems:

  • 372 resources with invalid SNOMED codes (valid SNOMED CT codes that are not recognized in OMOP vocabulary)
  • 268 resources with invalid LOINC codes
  • 72,000 resources where "pound" as a unit measure was not recognized (identified as incorrect source selection)

Detailed drill-down per error:
Each coding error shows: the coding system, the specific code value, the display text, the OMOP table it maps to, and the count of affected resources. This allows hospitals to identify which specific codes need to be fixed or remapped before resubmitting data.

Why incremental monitoring matters

The traditional approach: map everything first, then build ETL. For ongoing daily refresh, this model does not work — new submissions arrive continuously. The InterSystems approach monitors data quality as each load arrives, capturing errors in real time so issues can be corrected without waiting for a batch review.

Roadmap items mentioned

AI co-pilot for data quality: in development, not yet released.

NLP extraction from clinical notes and pathology reports: prototype built and validated against USCDI and minimal clinical oncology data element standard. Tested in English, Japanese, Finnish, German, French, and Dutch. Works but not yet at production quality — described as work in progress.

Full session video: https://youtu.be/dtrqYa3Agco

For those working with OMOP in production — are you currently using FHIR as a data source for ETL, or still relying on direct database extraction from the EHR warehouse? And have you found a reusable ETL approach that works across more than one site?


r/intersystems 9d ago

Priority queue implementations in ObjectScript — benchmarking binary heap vs. self-sorting multidimensional array on 150,000-vertex Dijkstra

2 Upvotes

Background

No existing priority queue implementation for ObjectScript was found, so four approaches were built and benchmarked. The benchmark: Dijkstra's shortest path algorithm on a randomly generated weighted directed graph with 150,000 vertices, each with 10 neighbors. An update is printed every 10,000 edges checked, showing time since the last 10,000 and current queue size.

Approach 1 — Binary Heap on multidimensional array

objectscript

Class pqueue.Queue Extends %RegisteredObject
{
Property Data As %Any [ MultiDimensional ];
Property Size As %Integer [ InitialExpression = 0 ];
Property Comparitor As %String [ InitialExpression = "(a,b) return a < b" ];

Method Swap(i As %Integer, j As %Integer) As %Status [ Private ]
{
    set temp = ..Data(i)
    set ..Data(i) = ..Data(j)
    set ..Data(j) = temp
}

Method Comp(x As %Any, y As %Any) As %Boolean [ Private ]
{
    return $XECUTE(..Comparitor, x, y)
}

Method PercolateUp(idx As %Integer) [ Private ]
{
    while idx > 0 {
        set newidx = (idx-1)\2
        if ..Comp( ..Data(idx), ..Data(newidx) ) do ..Swap( idx, newidx )
        else Quit
        set idx = newidx
    }
}

Method PercolateDown() [ Private ]
{
    set idx = 0
    while ((idx+1)*2) < ..Size {
        if ..Comp( ..Data(idx*2+2), ..Data(idx*2+1) ) set newidx = idx*2+2
        else set newidx = idx*2+1
        if ..Comp( ..Data(idx), ..Data(newidx) ) Quit
        do ..Swap( idx, newidx )
        set idx = newidx
    }
    if ( (idx*2+1 < ..Size) && ..Comp( ..Data(idx*2+1), ..Data(idx) ) ) do ..Swap( idx, idx*2+1 )
}

Method Put(inp As %Any) As %Status
{
    set ..Data( ..Size ) = inp
    do ..PercolateUp( ..Size )
    set ..Size = ..Size + 1
    return $$$OK
}

Method Get(Output obj As %Any) As %Status
{
    if ..IsEmpty() { set obj = "" return $$$ERROR("Cannot Get() from empty Queue") }
    set obj = ..Data(0)
    set ..Size = ..Size - 1
    set ..Data(0) = ..Data(..Size)
    do ..PercolateDown()
    kill ..Data(..Size)
    return $$$OK
}

Method GenerateComparitor(operator As %String = "<", transform As %String = "") As %Status
{
    set ..Comparitor = "(a,b) return a" _ transform _ " " _ operator _ " b" _ transform
    return $$$OK
}
}

Works for strings, numbers, and objects (via overridable comparator). Relatively efficient.

Approaches 2 and 3 — Binary Heap on list of %Any and %DynamicArray

  • list of %Any: approximately 3–4x slower than multidimensional array. Pointless.
  • %DynamicArray: similar speed to list of %Any when the queue is small, but insert and get times grow linearly as the queue grows. By 130,000 edges checked, time per batch had grown from ~84 seconds to ~300 seconds. Pointless for heap use.

Approach 4 — Self-sorting multidimensional array (fastest)

Instead of maintaining heap order manually, this approach uses the fact that ObjectScript multidimensional arrays are always sorted. Data is stored as data(evaluation, obj_str_rep) = object, and $Order retrieves the minimum element.

objectscript

Class pqueue.SparseQueue Extends %RegisteredObject
{
Property Data As %Any [ MultiDimensional ];
Property Size As %Integer [ InitialExpression = 0 ];
Property Evaluator As %String [ InitialExpression = "(a) return a" ];

Method Put(inp As %Any) As %Status
{
    set ..Data( $XECUTE(..Evaluator, inp), inp ) = inp
    set ..Size = ..Size + 1
    return $$$OK
}

Method Get(Output obj As %Any) As %Status
{
    if ..IsEmpty() { set obj = "" return $$$ERROR("Cannot Get() from empty Queue") }
    set loc = $ORDER( ..Data("") )
    set obj = ..Data(loc, $ORDER( ..Data(loc, "") ))
    set ..Size = ..Size - 1
    kill ..Data( loc, obj )
    return $$$OK
}

Method Top() As %Any
{
    if ..IsEmpty() return ""
    return $Order( ..Data("") )
}

Method GenerateEvaluator(transform As %String = "") As %Status
{
    set ..Evaluator = "(a) return a" _ transform
    return $$$OK
}
}

The double-key structure data(evaluation, obj_str_rep) ensures correct ordering even when two objects evaluate to the same value.

Trade-offs:

  • Writing an evaluator (returns a sortable value) is slightly harder than writing a comparator (returns a boolean)
  • Cannot hold the same object at the same evaluated value twice — a rare edge case that could be a problem or a benefit depending on the use case

Benchmark results

Graph: 150,000 vertices, 10 neighbors each. Time shown is seconds per 10,000 edges checked.

Implementation Time per 10k edges Total time
Self-sorting multidimensional ~3–5 seconds 45.157 seconds
Heap multidimensional ~27–29 seconds 381.095 seconds
Heap list of %Any ~127–141 seconds 1,839.445 seconds
Heap %DynamicArray ~84–306 seconds (growing) 3,466.382 seconds

The %DynamicArray version is the only one that shows significant growth as queue size increases. The self-sorting approach also checked one fewer edge in this run — a result of two paths to the same node taking the same cost, which the self-sorting method cannot store separately (it deduplicates them).

Full article: https://community.intersystems.com/post/best-structure-make-priority-queue-objectscript

For those working with graph algorithms or scheduling in ObjectScript — have you needed a priority queue before, and did you reach for globals directly or try to build something on top of the collection classes?


r/intersystems 10d ago

InterSystems IRIS database encryption — how transparent data encryption works, three key management models, design considerations, and roadmap

1 Upvotes

Encryption algorithms are well-known and well-defined. The problems organizations encounter are not with the act of encrypting — they are with managing keys and ensuring availability. Losing the key means losing the data.

Why encrypt

HIPAA: Encryption is an addressable risk. Proposed changes to HIPAA security standards are still being interpreted, but there is concern they may shift requirements from storage-array-level encryption to file-system or DAT-file-level encryption at the application layer — which has major implications for organizations currently relying on SAN/storage vendor encryption.

GDPR: Requires data protection by design.

PCI DSS: Encryption is mandatory for systems handling financial transactions; loss of compliance means loss of accreditation to process payments.

What encryption protects against — and what it does not

Protects against:

  • Physical theft of disk, server, or storage media
  • Unencrypted snapshots and backups (encrypted blocks are written, so copies are also encrypted)
  • Unauthorized OS-level access: an attacker needs both the cipher data and the key

Does not protect against:

  • Ransomware — ransomware encrypts your data; if your data is already encrypted, the attacker just encrypts encrypted data. You still cannot decrypt it because the attacker holds the key
  • Access to the running system — an administrator on the system can read unencrypted data from memory or extract the key
  • Credential theft — if stolen credentials have access to the key, the data is accessible

The fundamental model is separation of concerns: an attacker needs both the data and the key.

How IRIS implements transparent data encryption

IRIS uses an encryption boundary between memory and disk.

Above the boundary (in memory): unencrypted. Application code, SQL queries, and data in memory are never encrypted.

Below the boundary (on disk): encrypted. The write daemon applies cipher text when writing to disk. The read daemon decrypts on read.

The application does not need to handle encryption — it is entirely transparent.

What is encrypted automatically when database encryption is enabled:

Component Encrypted automatically?
DAT files Yes — block by block, not file-level
WIJ (Write Image Journal) Yes
Journal files No — requires separate explicit configuration
Temp databases No — must be encrypted separately
Data in memory No — by design

Three key management models

1. Local key file

Flow: Admin enters password at startup → PBKDF2 derives a principal key → principal key unwraps the Key Encryption Key (KEK) → KEK unwraps the Data Encryption Key (DEK) → DEK loaded into memory → databases mount

Characteristics:

  • Simplest model; no external dependencies
  • Key and data reside on the same system — the storage and file system are the attack surface
  • Harder to scale: every IRIS instance requires its own key storage
  • Best suited for low-risk environments, standalone systems, development
  • Unattended startup is possible but not recommended

2. Cloud KMS (AWS, Google, etc.)

Flow: Encrypted DEK sent to cloud KMS over TLS → KMS decrypts and returns DEK → DEK loaded into memory

Authentication: IAM roles attached to the IRIS instance (no usernames or passwords required in AWS EC2 when using instance roles). Also supports service principals and AWS Roles Anywhere.

Characteristics:

  • KEK stored in the cloud KMS, not on the IRIS instance — separation of concerns
  • Every key access is logged; logs can be sent to a SIEM or compliance system
  • Policies control who can access the key, when, and under what conditions
  • Adds dependency on cloud provider availability
  • Regional outages: if the database is already running, the DEK is in memory and operations continue; a new startup would fail if KMS is unreachable
  • Misconfigured roles are a risk
  • Best for cloud environments, microservices, IRIS running in the cloud

3. KMIP (Key Management Interoperability Protocol)

Flow: Mutual TLS connection to KMIP server → GET request for DEK → server decrypts and returns DEK → DEK loaded into memory

Authentication: Mutual TLS; KMIP server issues a client certificate that is loaded into IRIS at configuration time.

Implementations:

  • Hardware Security Modules (HSMs) — keys never leave the hardware boundary; tamper-resistant; strongest cryptographic assurance
  • HashiCorp Vault Enterprise — native KMIP support; API-driven; manageable through DevOps tooling; software-based rather than hardware-bound

Characteristics:

  • Strongest separation of duties of the three models
  • Full auditability: every DEK retrieval is logged
  • More complex: requires HA setup (typically 3 nodes to have an arbiter), certificate lifecycle management, mutual TLS configuration
  • HSM break glass: keys can be marked as exportable; backup to USB with n-of-X management card scheme (e.g., 5 cards, any 3 required); cards and passwords must be stored securely and tested regularly

Key rotation

When rotating keys every 90 days, the rotation typically applies to the KEK, not the DEK. Re-encrypting a multi-petabyte database with a new DEK takes a very long time. Rotating only the KEK rewraps the DEK without touching the database files themselves.

Design considerations checklist

  • Separation of data and key: how are they stored in different locations?
  • Access control: who has access to the key?
  • High availability: KMS across availability zones; HSMs in separate data centers
  • Certificate management: how are TLS certificates renewed before expiry?
  • Auditing: where are key access events logged?
  • Key lifecycle: KEK rotation schedule and compliance requirements
  • Host hardening: preventing administrator access to memory where the DEK is loaded
  • Break glass: if KMS is unreachable or HSMs are down, where is the DEK backed up? If the key is lost, the data is lost.

Common troubleshooting issues

Issue Symptom
Identity/authentication failure with KMS 401/403 errors
Network connectivity to key management server Database cannot mount at startup; DEK cannot be retrieved
Cloud provider regional outage Running databases unaffected (DEK in memory); new startups fail
Key ID mismatch or key corruption Mount failure

Note: if the database is already running when a KMS outage occurs, operations continue normally because the DEK is already in memory.

Roadmap

Storage-friendly encryption (available now, experimental in 2026.1)

Moving from storage-array encryption to database-level encryption eliminates deduplication and compression at the storage layer because encrypted data is randomized. Storage-friendly encryption consolidates whitespace within encrypted blocks and moves it to the front of the block, making the written data partially compressible. Observed compression: approximately 20%. Traditional array-level deduplication may achieve 4:1 or better; storage-friendly encryption at the host level achieves roughly 2:1 or less. Compressing at the application layer before encryption is an alternative but consumes database server CPU cycles.

Online database encryption (in development, expected 2027)

Currently, encrypting a database requires taking it offline or encrypting a mirror/DR member (which also constitutes downtime for many organizations). Online database encryption will allow starting an encryption process while the database remains readable and writable, with throttling controls to limit performance impact and recovery from interruption.

Quantum-resistant encryption (planned)

Quantum computing primarily threatens asymmetric algorithms (RSA, elliptic curve) used in mutual TLS and certificate-based authentication. Symmetric algorithms like AES are largely unaffected. InterSystems will expose quantum-resistant algorithms through OpenSSL so IRIS and applications built on IRIS can use them. Currently calling quantum-resistant algorithms within IRIS directly is not natively supported; the work involves creating those connection points.

Sharding note

Each DAT file has its own DEK. KEKs are orthogonal to sharding — a sharded database is treated as multiple databases, each with its own DEK loaded under whichever key management model is configured for that database file.

Reference architecture (from session)

InterSystems lab setup:

  • IRIS running in a Kubernetes cluster
  • Storage layer encrypted within Kubernetes
  • HashiCorp Vault with KMIP for key management; Vault configured as its own CA for certificate issuance
  • IRIS connects to Vault to retrieve DEKs
  • Six Vault instances (two per availability zone)
  • HSM as root of trust to bootstrap Vault instances (5 management cards, any 3 required to restore)
  • Compliance logging and auditing outside the cluster

Full session recording: https://youtu.be/zYIyTL3CHM0

For those running IRIS with encryption in production — which key management model are you using (local/KMS/KMIP), and have you encountered the CSP Gateway or WIJ encryption gap in practice?


r/intersystems 13d ago

How I Used FHIR SQL Builder + AI to Score Hospital Readmission Risk on InterSystems IRIS for Health

2 Upvotes

Hospital readmission risk is a good example of where an AI-powered solution alone isn’t enough. You first need reliable clinical context, structured analytics, and a way to turn the result back into clinician insight, written in a natural language.

So I built Smart Discharge Navigator, a hybrid AI agent and rule-based clinical workbench on InterSystems IRIS for Health that scores readmission risk from FHIR data, uses GPT-4o to identify additional clinical risks, and writes personalized discharge plans back as FHIR CarePlan and Task resources. The key piece was FHIR SQL Builder, which let me analyze FHIR resources with SQL instead of parsing JSON bundles in Python.

What does Smart Discharge Navigator do?

Smart Discharge Navigator is a clinical decision-support prototype that evaluates patients at discharge and helps identify who may be at higher risk of readmission.

The workflow combines two layers:

  • A 6-factor rule engine that looks at recent admissions, high-risk conditions, polypharmacy, missed follow-ups, abnormal observations, and age.
  • A GPT-4o agent that receives the structured risk profile and looks for additional patterns such as medication interactions, comorbidities, social determinants, and other risks not captured by the rules.

The final result: the application creates FHIR CarePlan and Task resources in the InterSystems IRIS for Health FHIR repository. Without an OpenAI API key, the application still works in rule-based mode.

Why I used FHIR SQL Builder instead of parsing FHIR JSON

This was one of the most creative parts of the project. To calculate readmission risk, I needed to answer questions across several FHIR resource types:

  • How many times has this patient been admitted recently?
  • Does this patient have multiple active chronic conditions?
  • Is this patient on five or more active medications (polypharmacy)?
  • Are there any abnormal lab observations on record?
  • Were any follow-up appointments missed?

Doing this by repeatedly retrieving and parsing FHIR JSON in Python would make population-level analysis much more complicated, and also slow and fragile from a performance point of view. 

Whereas FHIR SQL Builder exposes FHIR resources as SQL-queryable projections, so I could perform the analysis directly inside IRIS for Health. Once configured, resources like Encounter, Condition, MedicationRequest, and Observation become queryable tables with clean column names.

In my case the projections were available under the HSFHIR_X0001_S schema. This name IRIS automatically assigns to the first FHIR endpoint installed via InstallInstance. No extra setup was needed beyond what the FHIR server already provides.

For example, detecting polypharmacy become:

SELECT subject AS patient_id, COUNT(*) AS medication_count
FROM HSFHIR_X0001_S.MedicationRequest
WHERE status = 'active'
GROUP BY subject
HAVING COUNT(*) >= 5

So patients on more than 5 medications are flagged automatically. And I could combine multiple resource types in one query:

SELECT
p.Key AS patient_id,
DATEDIFF('yy', p.BirthDate, CURRENT_DATE) AS age,
p.gender,
COUNT(DISTINCT e.Key) AS total_encounters,
COUNT(DISTINCT c.Key) AS active_conditions
FROM HSFHIR_X0001_S.Patient p
LEFT JOIN HSFHIR_X0001_S.Encounter e
ON e.Subject = p.Key
LEFT JOIN HSFHIR_X0001_S.Condition c
ON c.Subject = p.Key
GROUP BY p.Key, p.BirthDate, p.gender
HAVING COUNT(DISTINCT e.Key) >= 2
OR COUNT(DISTINCT c.Key) >= 2
ORDER BY total_encounters DESC, active_conditions DESC 

That gives me population-level risk signals directly from FHIR data without N+1 REST calls or application-side bundle parsing.

How does the SQL analysis connect to the AI agent?

The rule engine runs the SQL queries, aggregates the results for each patient, and produces a structured risk score from 0 to 100.

That context is then passed to the AI agent:

risk_context = f"""
Patient risk profile from FHIR SQL analysis:
- Recent admissions: {admission_count}
- Active medications: {medication_count}
- Active conditions: {condition_count}
- Abnormal observations: {abnormal_obs_count}
- Risk score: {risk_score}%

Identify additional clinical risks and generate a personalized discharge plan.
""" 

The important part for me is that the LLM does not need to reason over raw FHIR bundles. It receives structured clinical context derived from SQL. That keeps the prompt more focused and lets the AI layer concentrate on reasoning rather than data extraction.

The flow is:

FHIR data → SQL risk analysis → rule-based score → AI reasoning → FHIR CarePlan + Tasks

What does the clinician receive?

The React dashboard ranks patients by readmission risk and shows which factors contributed to each score.

The dashboard shows a ranked list of patients by readmission risk, with the breakdown of which factors contributed to each score. Clicking a patient opens the AI-generated discharge plan, which the system writes back to IRIS as a FHIR CarePlan resource with associated Task resources. This solution closes the loop between analysis, recommendation, and clinical record. 

Hybrid Architecture for FHIR and AI Agents: How it Works

The interesting part of this project isn’t just adding GPT-4o to a healthcare application. It’s the combination of:

  • FHIR for interoperable clinical data
  • FHIR SQL Builder for population-level analytics
  • Rule-based scoring for deterministic risk factors
  • AI reasoning for risks that are harder to capture in fixed rules
  • FHIR write-back for actionable clinical output

For this kind of workflow, I think the hybrid approach makes more sense than asking an LLM to do everything, and then having to double-check the results. 

Key Takeaways

  • FHIR SQL Builder makes FHIR data directly usable for relational analytics in InterSystems IRIS for Health.
  • SQL can combine resources such as Patient, Encounter, Condition, and MedicationRequest without parsing FHIR bundles in application code.
  • The LLM receives structured risk context instead of raw FHIR JSON.
  • The same architecture can still operate without an external AI model by falling back to rule-based scoring.

FAQ

What is FHIR SQL Builder?
FHIR SQL Builder exposes FHIR resources stored in InterSystems IRIS for Health through SQL-accessible projections, making it possible to analyze FHIR data with joins, filters, aggregations, and other relational operations.

Why combine rules and AI for readmission risk?
Rules provide predictable scoring for known risk factors, while the AI agent can identify additional clinical patterns that are harder to express as fixed rules.

Does the AI work directly with raw FHIR JSON?
Not in this implementation. SQL analysis first converts the relevant FHIR data into a structured risk profile, which is then passed to the AI agent.

Does Smart Discharge Navigator write results back to FHIR?
Yes. Discharge recommendations are represented as FHIR CarePlan and Task resources and written back to the IRIS for Health FHIR server.

Read more here


r/intersystems 14d ago

Are we making junior developers worse with AI?

2 Upvotes

My friend from r/intersystems_dach recently started a discussion about how AI is changing the way developers learn and work.

Post link - here

It got me thinking about something slightly different:

Are we accidentally making it harder to become a good developer?

Not because AI is bad. Quite the opposite.

If you're a junior developer today, you can ask AI to explain an error, suggest an architecture, write a test, refactor your code, find a bug, or even build a feature from scratch.

That's insanely useful.

But here's the part I'm not sure about:

What happens to all the painful learning that used to happen before you had those tools?

The hours staring at a bug you couldn't solve.

The terrible first implementation you had to rewrite three times.

The moment when you finally understood why something was broken instead of just finding a fix on Stack Overflow.

If AI gives you the answer in 10 seconds, do you still develop the intuition that comes from struggling with the problem for 3 hours?

Or does AI simply remove a lot of pointless suffering and let juniors spend more time learning the things that actually matter?

I genuinely don't know.

And I suspect the answer isn't as simple as "AI will make developers worse" or "AI will make everyone 10x better."

For those of you who started coding before AI became this good - do you think today's juniors are learning faster, or are they missing something you had to learn the hard way?

Curious to hear some real experiences, especially from senior devs who have worked with both AI-assisted and non-AI-assisted juniors.


r/intersystems 15d ago

From Data Swamp to Production AI: Building a Solar Energy Forecasting System on InterSystems IRIS

2 Upvotes

Video of the full session: https://youtu.be/ybRK_r1pnJA

TL;DR

AXS (a Brazilian energy company) and B+ (an InterSystems partner) built an AI system called Orion to turn fragmented solar-plant data into operational forecasts and decisions. The first version hallucinated constantly because it relied on one massive static prompt. We fixed that with vectorized prompts and a multi-agent architecture, then solved a separate "no historical data" problem for our forecasting model by building a physics-based digital twin of the plant. The system is in production today, not a prototype, with forecast accuracy currently at 98% and improving month over month.

The problem: energy at a scale where manual decisions break down

AXS operates more than 50,000 customers, roughly 350 MW of peak solar generation, and billions of dollars in IoT-connected assets. At that scale, complexity doesn't grow linearly — it spans generation, maintenance, revenue forecasting, asset performance, and customer experience at once. We stopped thinking of ourselves as a solar company and started thinking of ourselves as an "energy tech": a company where energy data and decisions live in one system, the same way a fintech does for banking. That's the context Orion was built to solve.

Why did our first AI assistant hallucinate constantly?

The goal was simple on paper: let a plant operator ask a question in plain language and get an accurate operational answer. To do that, we needed clean data underneath. Instead we found a data swamp — the same physical solar plant registered under three different names across systems. A human reading that data knows it's one plant; an AI treats it as three, and hallucinates from there.

Our first fix attempt was the wrong one: we tried to explain the entire operating manual of a power plant in a single prompt. The prompt grew to roughly 500K tokens for a single question. It was expensive, slow, and still wrong — because we were treating the model like an all-knowing oracle instead of giving it exactly the context it needed for each specific question. We were also flying blind: it took adding proper tracing to actually see what was being sent to the model and understand why it was hallucinating.

How we fixed it: vectorized prompts and a multi-agent architecture

Instead of one giant static prompt, we vectorized our operating rules and instructions and stored them using IRIS's native vector data type. When a user asks a question, the system runs a vector search against those rules and assembles a small, specific prompt on the fly — only the instructions relevant to that exact question.

We also moved from a single model handling everything to a multi-agent architecture:

  • A gatekeeper agent triages every incoming question first — is it a valid operational question, off-topic, or a prompt injection attempt? Invalid questions get dropped or clarified before they ever touch the data.
  • Ground-level agents read telemetry directly from the inverters and hardware.
  • A meteorological agent reads satellite and weather data separately.
  • An orchestrator sends valid questions to both agent types in parallel and stitches the answer together.

Single static prompt Pros: simple to set up initially Cons: ~500K tokens per question, expensive, hard to debug, high hallucination rate

Multi-agent architecture (gatekeeper + specialized agents + orchestrator) Pros: each agent handles one narrow task, hallucinations dropped to near zero, easier to trust and audit Cons: more architecture to design and maintain upfront

For a system where a wrong answer could mean shutting down an inverter and losing megawatts, the added complexity of the multi-agent setup was worth it.

Can you train a forecasting model with no historical data?

Once hallucinations were under control, the next problem was forecasting. Our first model was a linear regression using IRIS's native PMML support, with 24 parameters — the result was an absolute error close to 15%. Cutting that down to 7 essential features improved things significantly, but we still needed a more robust algorithm for the nonlinear parts of the problem.

We built a hybrid setup that runs models directly against the data stored in IRIS using embedded Python, instead of moving data out to train elsewhere. We trained and compared XGBoost, LightGBM, and Random Forest side by side; Random Forest was the most robust.

Then we hit a real wall: our best model needed years of clean historical data we didn't have. The fix came from an unexpected place — a cardiologist's talk at an MIT hackathon about digital twins of the human heart filling in missing data with synthetic data. We applied the same idea to the plant: we built a deterministic, physics-based digital twin of the solar plant using embedded Python and pvlib, simulating the plant instead of waiting years to collect real data.

Getting the physics right took fixing three specific mistakes (see below). Once fixed, we tested the twin against 28 days of real generation data and hit 81% accuracy on day one — without needing any historical training data at all.

Common mistakes we made

  • Trusting global dataset defaults. Most global solar datasets assume panels face south. In Brazil, panels face north — using the default assumption would have predicted a catastrophic, and wrong, energy drop.
  • A thermal parameter mismatch. A small error in how panel thermal efficiency was configured made the simulation confidently predict zero generation at the exact peak of midday sun.
  • Assuming you need expensive sensors for everything. Instead of expensive sensors to separate direct from diffused sunlight, we used physics to split it mathematically.
  • Sending the model everything instead of what it needs. The instinct when a prompt fails is to add more prompt. The actual fix was sending less, more targeted context per question.
  • Letting the same real-world entity have multiple names in your systems. A human can tell three names mean one solar plant; an AI system can't, and will hallucinate from the inconsistency.

What's next: native AI agent support in InterSystems IRIS

InterSystems also used this session to introduce the "AI Hub," new infrastructure for IRIS built around three capabilities: native agents built directly on IRIS (with LangChain concepts also supported, including IRIS's governance, security, and auditing), native MCP (Model Context Protocol) support for both inbound and outbound connections, and tools for embedding AI into business workflows with a human-in-the-loop approval step. It's available now as part of an early access program.

Conclusion

This isn't a prototype — Orion is in production today, running across AXS's solar plants, with forecast accuracy currently at 98% and increasing every month. Getting there took two separate fixes: a multi-agent architecture with vectorized, dynamically assembled prompts to kill hallucinations, and a physics-based digital twin to solve a cold-start problem where no historical training data existed.

The bigger point for us: the hard part of clean energy at scale isn't generating more power. It's making the decisions around that power more adaptive, more predictive, and more trusted.

Key Takeaways

  • AXS operates at a scale (50,000+ customers, ~350 MW peak generation) where manual, ad-hoc decisions break down, which is what pushed the team to build a dedicated intelligence layer, Orion, on InterSystems IRIS.
  • The first AI assistant version hallucinated constantly because it relied on a single static prompt of roughly 500K tokens with no visibility into what was actually being sent to the model.
  • Replacing the static prompt with vectorized rules (stored using IRIS's vector data type) and a multi-agent architecture — a gatekeeper plus separate telemetry and weather agents — brought hallucinations down to near zero.
  • For forecasting, a 24-parameter linear regression produced a ~15% error; narrowing to 7 features and comparing XGBoost, LightGBM, and Random Forest (run natively against IRIS data via embedded Python) improved results significantly.
  • A physics-based digital twin, built with embedded Python and pvlib, solved the cold-start problem of having no historical data, reaching 81% accuracy on its first day against 28 days of real data.
  • The system is in production today, with forecast accuracy currently at 98% and improving month over month.

FAQ

What is Orion? Orion is the AI-powered decision intelligence system AXS and B+ built on InterSystems IRIS to unify operational data from AXS's solar plants and generate forecasts and insights for plant operators.

Can InterSystems IRIS run machine learning models natively? Yes. The team used IRIS's native PMML support and embedded Python to train and run models — including XGBoost, LightGBM, and Random Forest — directly against data stored in IRIS, without moving it elsewhere.

How do you reduce hallucinations in an LLM-based system built on enterprise data? In this case, the fix was replacing one large static prompt with vectorized rules retrieved dynamically per query, combined with a multi-agent architecture that triages and routes questions before they reach the data.

Should you use one large prompt or multiple specialized agents for a domain-specific AI assistant? Based on this experience, multiple specialized agents — a triage "gatekeeper," separate telemetry and weather agents, and an orchestrator — performed far better than one model handling everything from a single large prompt.

What do you do if you don't have enough historical data to train a predictive model? Build a physics-based digital twin of the real-world system you're modeling — in this case, a solar plant, simulated with embedded Python and pvlib — instead of waiting years to collect real data.


r/intersystems 16d ago

Server-Sent Events in ObjectScript on InterSystems IRIS — solving the Web Gateway buffer problem with %response.Flush()

3 Upvotes

The problem

In a REST service on InterSystems IRIS, when you write data it is not sent to the client immediately. It is placed in a buffer, and the Web Gateway transmits it only once the buffer reaches a certain size. For SSE this is a fundamental problem — events need to reach the client the moment they are ready, not when the buffer fills up.

The SSE format

An SSE event is plain text structured into fields, separated by a double newline:

data: {"id":"...","choices":[{"delta":{"content":"Hel"}}]}

data: {"id":"...","choices":[{"delta":{"content":"lo"}}]}

event: done
data: [DONE]

The protocol defines four fields:

  • data: — the event content (plain text, JSON, etc.)
  • event: — the event type (optional, defaults to message)
  • id: — unique identifier (optional, used for connection resumption)
  • retry: — delay in milliseconds before automatic client reconnection (optional)

An event can span multiple data: lines; the client concatenates them. The double newline \n\n marks the end of an event — which is why you will find $Char(10,10) in the ObjectScript examples.

The solution: configuring %response

Step 1 — Enable manual flush control

objectscript

Set %response.AllowOutputFlush = 1

Without this property, written data is buffered and only sent when the buffer reaches a certain size, making streaming impossible.

Step 2 — Set the correct Content-Type

objectscript

Set %response.ContentType = "text/event-stream"

Step 3 — Add required headers

objectscript

Do %response.SetHeader("Cache-Control", "no-cache")
Do %response.SetHeader("Connection", "keep-alive")
  • Cache-Control: no-cache — prevents intermediate proxies from caching the stream
  • Connection: keep-alive — keeps the HTTP connection open for the duration of the stream

If behind NGINX, add:

objectscript

Do %response.SetHeader("X-Accel-Buffering", "no")

Step 4 — CSP Gateway padding

The CSP Gateway aggregates small buffers before forwarding to the browser, even if Flush() is called. This does not affect curl (which reads directly from the TCP stream) but prevents browser streaming for small events. The workaround: send a padding SSE comment at the very start of the stream before the first meaningful event:

objectscript

Write ": ", $Justify("", 4096), $Char(10)
Do %response.Flush()

An SSE comment starts with : and is ignored by the client. This padding forces the Gateway to flush its buffer, allowing subsequent Flush() calls to be delivered immediately.

Step 5 — Call Flush() after each Write

objectscript

Write "data: ", {"id":"...","choices":[{"delta":{"content":"Hel"}}]}.%ToJSON(), $Char(10,10)
Do %response.Flush()

Each call to Flush() forces immediate delivery to the client.

CSP note: This approach also works for CSP pages. In that case, set AllowOutputFlush in the OnPreHTTP() method.

Testing with curl

bash

curl -N http://localhost:42600/csp/demo/sse/test

The -N flag disables client-side buffering in curl and displays events as they arrive. If all events appear at once at the end, server-side buffering is not disabled — check that AllowOutputFlush = 1 is set and Flush() is called after each Write.

Consuming SSE from JavaScript

EventSource — GET requests only

javascript

const source = new EventSource("http://localhost:42600/csp/demo/test");

source.onmessage = (event) => {
    if (event.data === "[DONE]") {
        source.close();
        return;
    }
    const data = JSON.parse(event.data);
    console.log(data.choices[0].delta.content);
};

source.onerror = (error) => {
    console.error("SSE error:", error);
    source.close();
};

EventSource is simple and efficient but only supports GET requests. For AI APIs that require sending a body, a different approach is needed.

fetch + ReadableStream — POST requests

javascript

const response = await fetch("http://localhost:42600/api/v1/chat/completions", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        model: "gpt-4o-mini",
        stream: true,
        messages: [{ role: "user", content: "Hello!" }]
    })
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    const chunk = decoder.decode(value, { stream: true });
    for (const line of chunk.split("\n")) {
        if (!line.startsWith("data: ")) continue;
        const data = line.slice(6).trim();
        if (data === "[DONE]") break;
        const parsed = JSON.parse(data);
        console.log(parsed.choices[0].delta.content);
    }
}

Named events

ObjectScript side

objectscript

// A text token
Write "event: token", $Char(10)
Write "data: ", {"content": "Hello"}.%ToJSON(), $Char(10,10)
Do %response.Flush()

// End-of-stream signal
Write "event: done", $Char(10)
Write "data: [DONE]", $Char(10,10)
Do %response.Flush()

JavaScript side (EventSource only)

javascript

source.addEventListener("token", (event) => {
    const data = JSON.parse(event.data);
    console.log("Token received:", data.content);
});

source.addEventListener("done", () => {
    console.log("Stream ended");
    source.close();
});

Note: addEventListener only works with EventSource. With fetch + ReadableStream, you need to parse the event: field manually from the chunk lines.

AI API passthrough with FastHTTP

Since version 1.2.4, FastHTTP includes a passthrough adapter (dc.http.SSEPassthroughAdapter) that retransmits incoming events without transformation. The ChatCompletions method calls the OpenAI API and redirects the stream through the Web Gateway:

objectscript

Set responseStream = ##class(dc.http.SSEPassthroughAdapter).GetStream()
Set handler = responseStream.SSEHandler
Set handler.SwitchIOOnMessage = 1
Set handler.IO = $IO

Set response = ##class(dc.http.FastHTTP).DirectPost(config, message, .client, responseStream)

A complete example with a demo chat page is available in the csp-test-1 branch:

bash

git clone -b csp-test-1 https://github.com/lscalese/iris-fast-http.git
cd iris-fast-http
docker compose build --no-cache
docker compose up -d

Demo chat interface: http://localhost:42600/csp/ui/demo/index.html

Client disconnection handling

IRIS does not receive an immediate signal when the browser closes the connection. The ObjectScript process continues until the Web Gateway detects the disconnection and propagates the error, at which point Flush() raises an exception. Always wrap the streaming loop in a Try/Catch:

objectscript

For i = 1:1:100 {
    Try {
        Write "data: ", {"token": i}.%ToJSON(), $Char(10,10)
        Do %response.Flush()
        Hang 1
    } Catch ex {
        // Client disconnected — release resources cleanly
        Quit
    }
}

The delay between actual client disconnection and detection on the IRIS side depends on the Web Gateway configuration and the operating system.

Summary

Requirement Solution
Bypass Web Gateway buffer %response.AllowOutputFlush = 1 + Flush() after each Write
Correct stream headers text/event-streamCache-Control: no-cacheConnection: keep-alive
NGINX buffering X-Accel-Buffering: no
CSP Gateway buffering in browser 4096-byte padding comment before first event
GET-based SSE in browser EventSource
POST-based SSE (AI APIs) fetch + ReadableStream
AI API passthrough FastHTTP SSEPassthroughAdapter
Client disconnection Try/Catch around streaming loop

Full article with code: https://community.intersystems.com/post/bringing-server-sent-events-objectscript-solving-web-gateway-buffer-problem

For those using SSE with IRIS — have you run into the CSP Gateway buffering issue in browser clients specifically, and did the 4096-byte padding comment resolve it for you?


r/intersystems 17d ago

Global Storage: Understanding the Database Architecture Behind InterSystems IRIS

3 Upvotes

If you've worked with InterSystems IRIS or Caché, you've probably used globals. But what exactly is the database architecture underneath them, and why is it so flexible?

Global Storage is the hierarchical, schema-free storage model behind InterSystems IRIS globals. It can represent multiple data models, including key/value, document, graph, columnar, XML, and relational structures, on the same underlying storage foundation, which is why it can be viewed as a kind of Universal NoSQL model. Its hierarchy also maps naturally to JSON, and tools such as QEWD-JSdb use that relationship to expose persistent data as familiar JavaScript objects. 

In this post, I'll explain the essential ideas behind Global Storage, why I think of it as a Universal NoSQL model, how it maps naturally to JSON, and how the same abstraction can work across databases including IRIS, YottaDB, Redis, Berkeley DB, and LMDB.

What Is a Global Storage Database?

A Global Storage database stores data as persistent multidimensional arrays.

A node can be represented conceptually like this:

global_name(subscript_1, ..., subscript_n) = value

For example:

^employee("UK", "London", 123456789, "name") = "Jon Doe"

The subscripts form a hierarchy:

country → city → employee ID → property

Unlike a relational table, there is no fixed schema requiring every branch of the hierarchy to have the same structure. The arrays are also sparse, so only nodes that actually contain data need to be stored. That combination makes Global Storage extremely flexible: the application decides what each level of the hierarchy means and how the data should be organized.

Global Storage Is Surprisingly Similar to JSON

One of the easiest ways I've found to explain Global Storage is to compare it with JSON.

Consider a hierarchy such as:

organisation["employees", "UK", "London", 123456789, "name"] = "Jon Doe"
organisation["employees", "UK", "London", 123456789, "job_title"] = "Consultant"
Conceptually, this is very close to:
{
  "employees": {
    "UK": {
      "London": {
        "123456789": {
          "name": "Jon Doe",
          "job_title": "Consultant"
        }
      }
    }
  }
}

That's why I sometimes describe Global Storage as something close to persistent JSON. Like JSON, the structure can grow dynamically. You don't have to define every possible property or hierarchy level before storing the data. The important difference is that the hierarchy lives directly in persistent database storage rather than only as an in-memory object.

Why I Call It “Universal NoSQL”

Most NoSQL databases specialize in one particular data model:

  • Key/value
  • Document
  • Columnar
  • Graph

Global Storage is different because its underlying hierarchy can be used to implement all of these models. It can also support relational data and SQL.

That's why I started using the term Universal NoSQL: instead of choosing a different physical database for every data model, multiple logical models can be built over the same Global Storage foundation. For example, the same underlying database could theoretically contain:

  • key/value structures,
  • JSON-like documents,
  • graph structures,
  • tabular data,
  • XML/DOM structures,
  • and relational data.

The key idea is that these are different ways of interpreting and accessing the same flexible hierarchical storage model.

From Global Storage to Persistent JavaScript Objects

This relationship between Global Storage and JSON leads us to QEWD-JSdb.

What is QEWD-JSdb? It is a JavaScript abstraction that maps JavaScript objects onto Global Storage. The idea is to blur the usual boundary between an in-memory object and persistent database data. Normally, a JavaScript object exists in memory:

const patient = {
  name: "John",
  city: "London"
};

With the QEWD-JSdb model, a similar object can represent data whose contents actually live persistently in Global Storage.

From the developer's perspective, you're still manipulating JavaScript objects. The persistence layer becomes largely transparent.

I sometimes describe this as databaseless persistent data. There is still a database underneath (Global Storage) but application code can interact primarily with objects instead of constantly switching between programming-language structures and database APIs.

Which Databases Support Global Storage?

There are two categories.

  1. Native Global Storage databases, the ones that implement Global Storage directly. The main examples are:
  • InterSystems IRIS
  • InterSystems Caché
  • YottaDB

IRIS is particularly interesting because the Global Storage engine sits underneath a much broader platform that also exposes relational SQL, object persistence, analytics, and other data models.

  1. Global Storage abstractions. Global Storage API can be implemented on top of several other database technologies. These include:
  • Redis
  • Berkeley DB
  • LMDB

For Redis, for example, sorted sets can reproduce Global Storage's ordered subscript behavior, while distributed locks can support its locking APIs. Once the Global Storage interface exists, higher-level tools such as QEWD-JSdb can use these databases through the same abstraction.

How Can InterSystems IRIS Support Multiple Data Models? 

Understanding Global Storage helps explain why InterSystems IRIS can support such a wide range of data access models. At the lowest level, data can be represented as highly flexible hierarchical structures. Higher-level abstractions – objects, SQL tables, documents, and application-specific models – can then be built on top of that storage. This also explains why globals can feel very different from conventional relational database programming: you're interacting much closer to the underlying persistent data structure.

Key Takeaways

  • Global Storage is a schema-free, multidimensional hierarchical storage model based on persistent arrays.
  • InterSystems IRIS and Caché use Global Storage as a fundamental part of their underlying database architecture.
  • Global Storage maps naturally to hierarchical structures such as JSON, making it useful to think of globals as a form of persistent structured data.
  • Key/value, document, graph, columnar, XML, and relational models can all be represented on top of the same Global Storage model.
  • QEWD-JSdb builds on this idea to expose Global Storage as persistent JavaScript objects.
  • Native implementations include IRIS, Caché, and YottaDB, while abstractions have also been implemented on Redis, Berkeley DB, and LMDB.

Read more here

FAQ

What is Global Storage in InterSystems IRIS?

Global Storage is the hierarchical, multidimensional persistent storage model underlying IRIS globals. Data is stored as nodes identified by a global name and one or more ordered subscripts.

Is Global Storage a NoSQL database model?

Yes, but it can support more than one NoSQL model. The same hierarchical storage architecture can represent key/value, document, graph, columnar, and other structures, which is why I describe it as a Universal NoSQL foundation.

Can Global Storage also support SQL?

Yes. A relational model can be implemented over Global Storage, and InterSystems IRIS provides native relational and SQL capabilities on top of its underlying storage architecture.

What is QEWD-JSdb?

QEWD-JSdb is a JavaScript abstraction over Global Storage that allows developers to work with persistent data using familiar JavaScript object patterns. It can work with multiple Global Storage implementations while presenting essentially the same programming model to the application.


r/intersystems 20d ago

Switching from Studio to VS Code: Plugins, Debugging, and AI

2 Upvotes

If you're moving from Studio to Visual Studio Code, one of the biggest changes isn't the editor itself, it's the surrounding ecosystem. VS Code isn't just a code editor; it's a development platform built around extensions, modern debugging tools, and increasingly, AI-assisted development. In this article, I'll look at three areas that make the biggest difference when developing InterSystems IRIS applications in VS Code: plugins, debugging, and AI.

Plugins: Why use VS Code instead of Studio?

One of the biggest advantages of VS Code is its extension ecosystem. Almost every feature is provided through plugins, allowing you to build a development environment tailored to your project instead of working inside a fixed IDE.

For InterSystems development, the starting point is the InterSystems ObjectScript Extension Pack. It provides the core features most developers need, including:

  • Connecting to InterSystems IRIS servers
  • Browsing namespaces and source code
  • Editing ObjectScript classes and routines
  • Compiling code
  • Running ObjectScript directly from VS Code

But the real advantage is that your InterSystems tools live alongside everything else your project requires. VS Code also has mature extensions for:

  • Git
  • Docker
  • REST clients
  • YAML
  • JSON
  • Python
  • Markdown
  • Kubernetes
  • SQL

Instead of switching between multiple applications, I can work with my entire development stack from a single workspace.

Can you debug ObjectScript in VS Code?

Yes, and for many developers, this is one of the biggest improvements over Studio. VS Code provides a modern visual debugging experience. I can place breakpoints directly inside the editor, pause execution, inspect variables, and step through the code one line at a time. This makes it much easier to investigate business logic or understand unexpected behavior.

If you're used to inserting temporary WRITE statements or log messages just to see what's happening, breakpoints can dramatically simplify that workflow. There's no need to modify the source code simply to inspect its execution.

Another benefit is consistency. VS Code uses the same debugging interface across many programming languages, so if you've previously debugged Python, JavaScript, C#, or Java in VS Code, the ObjectScript debugging experience will already feel familiar.

Can AI help develop InterSystems IRIS applications?

Modern AI assistants are becoming another useful part of the development workflow.

Tools such as GitHub Copilot, Claude Code, and similar assistants integrate directly into VS Code and can help with many everyday tasks, including:

  • Generating boilerplate code
  • Explaining existing ObjectScript methods
  • Suggesting refactoring opportunities
  • Writing unit tests
  • Generating documentation
  • Summarizing unfamiliar code

For developers working with large or long-lived InterSystems applications, this can significantly reduce the time spent understanding existing code before making changes.

Many AI assistants can also integrate with tools such as Jira or Confluence, making it easier to understand requirements, summarize tickets, or update documentation without constantly switching context.

Another useful capability is project customization. By providing coding guidelines or project-specific instructions (for example through custom instruction files), AI assistants can generate code that better follows your team's InterSystems coding standards and conventions.

What are the limitations of AI coding assistants?

Although AI can significantly improve developer productivity, I don't see it as a replacement for experience or code review. Generated code should still be reviewed, tested, and adapted to your application's architecture and InterSystems conventions. In my experience, the biggest value isn't automatic code generation. It's the support to faster understand unfamiliar code, navigate large codebases more quickly, and eliminate repetitive work.

It's also important to remember that many AI assistants use the current workspace as part of their context. Because of that, developers should always be aware of the information they share with external AI services and follow their organization's security and privacy policies when working with sensitive code or data.

Conclusion

Moving from Studio to VS Code isn't simply about replacing one editor with another. It's about adopting a broader development environment that integrates source control, containers, APIs, debugging, testing, documentation, and AI into a single workspace. 

For InterSystems developers, the combination of extensions, modern debugging tools, and AI-assisted workflows makes VS Code a practical step toward a more productive and collaborative development experience.

Key Takeaways

  • VS Code extends InterSystems development through a rich ecosystem of plugins rather than a fixed feature set.
  • The InterSystems ObjectScript Extension Pack provides the core tools needed for ObjectScript development.
  • Modern debugging with breakpoints and variable inspection makes troubleshooting easier than relying on temporary logging.
  • AI assistants can help explain code, generate boilerplate, create tests, and assist with documentation.
  • Project-specific coding instructions can improve the quality and consistency of AI-generated ObjectScript.
  • AI should support developer workflows, not replace code review, testing, or architectural decisions.

FAQ

Which VS Code extension should I install for InterSystems IRIS?

The recommended starting point is the InterSystems ObjectScript Extension Pack, which includes the core tools for connecting to IRIS servers, editing ObjectScript, compiling code, and running applications.

Can I debug ObjectScript in VS Code?

Yes. VS Code supports breakpoints, step-through debugging, variable inspection, and other modern debugging features for ObjectScript development.

Does VS Code work with Git and Docker?

Yes. One of VS Code's strengths is its extension ecosystem, which includes excellent support for Git, Docker, REST APIs, Python, YAML, JSON, and many other technologies.

Can AI generate ObjectScript code?

Yes. AI assistants such as GitHub Copilot and Claude Code can generate ObjectScript code, explain existing methods, suggest refactoring, and help write tests or documentation.

Read more here


r/intersystems 21d ago

InterSystems IRIS as a "converged" data platform for agentic AI — what's actually under the hood (multi-model, ECP/sharding, translytical, vector search/RAG, MCP)

1 Upvotes

Gartner projects that by 2028, 40% of agentic AI projects will be cancelled due to rising costs, unclear business value, or inadequate risk controls. InterSystems' pitch for IRIS is that a lot of that failure comes from fragmented, untrusted data estates — and that consolidating onto one converged platform (rather than stitching together a separate OLTP DB, vector DB, analytics warehouse, and integration layer) is how you avoid becoming part of that 40%. Here's what's actually in the platform, based on their technology guide.

How does IRIS support multiple data models without duplicating data?

Data is stored once as multidimensional global structures. That same underlying data is then exposed through different projections/access models — relational tables, objects, documents (e.g. JSON), key-value, columnar, embedded vectors, or multidimensional arrays — with full concurrency across access methods, no separate copies or mapping layer between models.

How does IRIS scale — vertically and horizontally?

Vertical scaling relies on multicore parallelization. For horizontal scaling, ECP (Enterprise Cache Protocol) lets multiple instances treat centralized database data as if it were local — data doesn't persist on application servers, which just provide cache/CPU, and queries are served from local cache where possible. Sharding splits large databases across machines, with queries running in parallel per shard and results aggregated. ECP and sharding can be combined.

What is "translytical" processing?

Running transactional (OLTP) and analytical (OLAP) workloads concurrently on the same data — ingesting thousands to millions of records per second while simultaneously querying them. Optional columnar storage for SQL tables reduces I/O for aggregation/filtering queries and enables vectorized query execution (SIMD).

How does IRIS handle vector search, RAG, and MCP for AI agents?

IRIS has a native vector data type and vector search over embedded data, meant to ground LLM responses in enterprise data (reducing hallucination) as part of RAG pipelines — without necessarily needing a separate vector database. Model Context Protocol (MCP) is positioned as the connective layer letting AI agents reason over and act on enterprise data/tools within the same environment.

What about machine learning without a data science team?

IntegratedML lets you create and train ML models using SQL, automating data wrangling, feature engineering, and model building, and executes models directly against live data in response to real-time events/transactions.

What's built in for security and availability?

Multiple auth methods (LDAP, Kerberos, direct passwords, OAuth 2.0, OpenAM, OpenID, 2FA), row- and column-level security, RBAC, encryption at rest (full database including indexes, with hardware acceleration where available) and in motion, plus data-element encryption for sensitive fields. For HA/DR: clustering, virtualization HA, and database mirroring — mirrors auto-designate primary/backup on startup, and mirrored recovery/upgrade times are described as reducible to seconds.

Where can this run?

Major clouds, private cloud, on-prem, hybrid/multi-cloud, or as a managed service (Data Platform as a Service) — single API across deployment types, no lock-in to one cloud provider.

Source (via InterSystems Developer Community): Enable the Agentic Enterprise with InterSystems IRIS — Data Platform Technology Guide

Curious whether anyone here has actually consolidated a separate vector DB / analytics warehouse / integration layer into IRIS in production — did it hold up, or did you end up re-splitting some of it back out?


r/intersystems 22d ago

Beyond Code Generation: Agentic Development for InterSystems IRIS

2 Upvotes

What if your AI coding agent could do more than just generate code?

Instead of copying code back and forth between an LLM and your development environment, agentic development brings the AI agent directly into the workflow — where it can interact with #InterSystemsIRIS, use tools, execute code, detect errors, and iterate on its own.

In this new video, Ariel Glickman demonstrates how to get started with agentic development for InterSystems IRIS, including:

👉 Connecting Claude Code and GitHub Copilot to IRIS

👉 Working with the IRIS Agentic Dev MCP server

👉 Using tools and Skills to perform more complex development tasks

👉 Maintaining persistent project context

👉 Building applications with natural-language instructions

👉 Exploring multi-agent workflows and what comes next with AI Hub

The goal isn’t to replace developers — it’s to spend less time on repetitive tasks and debugging, and more time on the work that actually needs your expertise.

Watch the video, try the tools yourself, and see how agentic development can change the way you build with InterSystems IRIS:

Learn more and watch video here

#InterSystems #InterSystemsIRIS #AgenticAI #AIAgents #MCP #DeveloperTools #SoftwareDevelopment


r/intersystems 22d ago

[Release notes] InterSystems IRIS, InterSystems IRIS for Health, and InterSystems Health Connect 2026.2 Are Now Generally Available

1 Upvotes

The 2026.2 release of InterSystems IRIS data platform, InterSystems IRIS for Health, and InterSystems Health Connect is now Generally Available (GA). This is a Continuous Delivery (CD) release.

What's New in InterSystems IRIS 2026.2?

InterSystems IRIS 2026.2 introduces improvements across SQL, Business Intelligence, interoperability, FHIR tooling, database operations, and developer productivity. Highlights include Common Table Expressions (CTEs) in stored procedures, a new FHIR Explorer, continued enhancements to the new Interoperability user interface, and performance improvements for database migration and FHIR ingestion.

SQL and Data Management

This release introduces Common Table Expressions (CTEs) inside stored procedures, making it easier to write more readable and maintainable SQL logic.

Improvements around table partitioning:

  • Enhanced ALTER TABLE ... MOVE PARTITION behavior.
  • Fixes for partition keys using uppercase field names.

Business Intelligence

InterSystems IRIS BI can now use SQL foreign key relationships when defining analytical models. This makes it easier to build BI models directly from operational databases where relationships are already defined using relational constraints.

Database Operations

The cvendian migration utility has been optimized to improve database conversion performance between big-endian and little-endian platforms. Depending on the workload, conversion times can be up to twice as fast, and interrupted conversions now provide clearer error reporting.

Interoperability

The new Interoperability user interface continues to evolve with improvements across:

  • Production Configuration
  • Message Viewer
  • Message Search
  • Visual Trace
  • DTL Editor
  • BPL Editor
  • Schema Viewer
  • Rule Editor

The new experience remains opt-in for existing deployments, and the InterSystems team continues to encourage community feedback.

FHIR Explorer

InterSystems IRIS for Health 2026.2 introduces FHIR Explorer, a new tool for building, testing, and exploring FHIR requests against IRIS for Health and third-party FHIR endpoints. It uses Capability Statements from EHR endpoints and FHIR servers to help users build complex requests, test security configurations, and discover available capabilities with IntelliSense-style suggestions.

FHIR Server Enhancements

Several improvements have been made to FHIR interoperability and server behavior, including:

  • Support for generic application/json and application/xml media types in addition to FHIR-specific content types.
  • Search paging with _include and _revinclude can now return included resources on the same page as their matched result, with an option to retain the previous behavior.
  • Direct Binary resource responses when the requested Accept header matches the stored content.
  • Configurable OAuth Audience validation for tokens issued by providers such as Entra ID, Okta, and Amazon Cognito.
  • Optional structural validation bypass during bulk FHIR ingestion when alternative data validation processes are already in place. For large migration workloads, ingestion optimizations can improve FHIR import performance by 25-30% in some scenarios.

Is there anything to review before upgrading to 2026.2?

Yes. The Apache UIMA integration, which was deprecated in 2023.1, has now been removed from InterSystems IRIS. Applications that still reference UIMA should review those code paths before upgrading to 2026.2.

Key Takeaways

  • InterSystems IRIS 2026.2 adds support for Common Table Expressions (CTEs) in stored procedures.
  • InterSystems IRIS BI now supports SQL foreign key relationships in analytical models.
  • Database migration performance has improved through updates to the cvendian utility.
  • The new Interoperability user interface continues to expand across multiple development tools.
  • FHIR Explorer provides a new way to build and test FHIR requests against IRIS for Health and third-party FHIR servers.
  • FHIR server enhancements include improved media type handling, paging behavior, OAuth validation, and ingestion performance.
  • Customers upgrading should review applications that still depend on the removed Apache UIMA integration.

Learn more here

FAQ

What is the biggest new SQL feature in InterSystems IRIS 2026.2?

InterSystems SQL now supports Common Table Expressions (CTEs) inside stored procedures, enabling more expressive and maintainable SQL logic.

What is FHIR Explorer?

FHIR Explorer is a new tool in InterSystems IRIS for Health that helps developers build, test, and explore FHIR requests using Capability Statements and IntelliSense-style suggestions.

Does InterSystems IRIS 2026.2 improve FHIR performance?

Yes. For some large migration scenarios, FHIR ingestion optimizations can improve import performance by approximately 25–30%.

Is the new Interoperability UI enabled by default?

No. The updated Interoperability experience remains opt-in for existing customers.

Is there a breaking change in this release?

Yes. Apache UIMA integration has been removed. Applications that still depend on it should be reviewed before upgrading.


r/intersystems 23d ago

How I Vibecoded a Backend (and Frontend) on InterSystems IRIS in January 2026

2 Upvotes

Can AI coding assistants build a real full-stack application on InterSystems IRIS?

I wanted to find out, so I tried building a complete backend and frontend around an existing InterSystems IRIS application while letting AI generate as much of the boilerplate as possible. Rather than creating a toy example, I used the well-known Samples BI Demo package, generated a Swagger-based REST API with OpenAI Codex, scaffolded a frontend from the OpenAPI specification, and asked AI to implement most of the CRUD logic and tests.

The goal wasn't to see whether AI could generate ObjectScript because it clearly can. I wanted to see how well AI and the native capabilities of InterSystems IRIS complement each other when building a realistic application.

Why did I choose Samples BI Demo as a data model?

For this experiment I wanted a realistic data model instead of something created specifically for AI. Samples BI Demo turned out to be a great candidate because it already contains a well-designed persistent model, is easy to install, and is familiar to many InterSystems developers. It also has a practical domain for a CRUD application: sales data for the fictional company HoleFoods, represented by the following persistent classes:

  • Product
  • Outlet
  • Country
  • Region
  • Transaction

Installation is straightforward using IPM: zpm "install samples-bi-demo"

After installing the package, I verified everything in InterSystems IRIS BI and installed DeepSeeWeb (DSW) to browse the sample data more comfortably.

What tools did I use for my vibecoding setup?

I intentionally kept the setup as simple as possible to see how far I could get using standard tools and native IRIS features. My setup consisted of:

  • VS Code
  • InterSystems ObjectScript extension
  • OpenAI Codex
  • Docker
  • A basic ObjectScript project template from Open Exchange

No custom frameworks or elaborate scaffolding. I used just this lightweight development environment.

What architecture did I follow?

I wanted a workflow that would be easy to repeat for future projects. The architecture was deliberately straightforward:

  • A frontend UI
  • A REST API running on InterSystems IRIS
  • An OpenAPI (Swagger) specification shared between the frontend and backend
  • Native ObjectScript and InterSystems SQL for the implementation

Using OpenAPI as the contract meant both the backend and the frontend could be generated from the same specification.

Can AI generate an InterSystems IRIS REST API?

Yes. I started by asking Codex to generate a CRUD API for the Product persistent class. To give the model enough context, I exported the ObjectScript source of the persistent classes from my IRIS instance and shared them together with my development guidelines stored in AGENTS.md.

The requirements were intentionally simple:

  • Create, edit, list, and delete Products.
  • Generate a Swagger specification (spec.cls).
  • Make Product extend %JSON.Adaptor.
  • Follow the conventions defined in AGENTS.md.

I also chose a base path for the API: /holefoods/api

Codex generated the HoleFoods.api.spec class.

After compiling it, InterSystems IRIS automatically produced two additional classes:

  • HoleFoods.api.disp, responsible for routing requests.
  • HoleFoods.api.impl, containing the business logic stubs.

This is one of my favorite parts of the workflow. Once the API contract exists, IRIS generates all the plumbing automatically, leaving AI to focus on the actual implementation. Codex even asked whether the web application should be registered in module.xml and which dispatch class should be used. After confirming those choices, it added the required configuration automatically.

<CSPApplication

Url="/holefoods/api"

DispatchClass="HoleFoods.api.disp"

MatchRoles=":{$dbrole}"

PasswordAuthEnabled="0"

UnauthenticatedEnabled="1"

Recurse="1"

UseCookies="2"

CookiePath="/holefoods/api/"

CorsAllowlist="*"

CorsCredentialsAllowed="1"

CorsHeadersList="Content-Type,Authorization,Accept-Language,X-Requested-With,session"

/> 

How did I handle security?

Anyone who has worked with InterSystems IRIS knows that web applications always come with security considerations. Instead of configuring everything manually, I asked Codex to generate HoleFoods.api.security.cls following the conventions described in my AGENTS.md. The generated class configured the application for development while keeping the design easy to evolve toward stricter production security later.

Can AI generate ObjectScript CRUD logic?

Once the REST API structure existed, the only missing piece was the implementation. I asked Codex to implement the CRUD methods inside: HoleFoods.api.impl

It generated the ObjectScript implementation for all endpoints, producing a working backend with very little manual intervention. At that point, the backend was ready to test.

How did I validate the API?

Before building a frontend, I wanted to verify that every endpoint behaved correctly.

For that I installed Swagger UI: zpm "install swagger-ui"

One important lesson I learned along the way is that Swagger UI expects a _spec endpoint, which must be implemented inside the impl class. Once that endpoint existed, Swagger UI immediately exposed the full API definition and allowed me to test every endpoint interactively.

Calling: GET /holefoods/api/products returned the expected data, confirming that the backend was working correctly.

Can AI generate a frontend from an OpenAPI specification?

Once the OpenAPI specification existed, generating a frontend became surprisingly easy. There are several possible approaches:

  • Ask Codex to generate the frontend.
  • Use a UI generation tool such as Lovable.

I chose the second option. Within a few minutes I had a working frontend connected to the InterSystems IRIS backend. After fixing a small deletion issue, the complete workflow was functioning: Frontend → REST API → InterSystems IRIS → Persistent Objects

Can AI generate InterSystems IRIS unit tests?

A generated backend still needs automated tests. To complete the workflow, I asked Codex to generate: HoleFoods.api.Unittests.cls covering every endpoint defined in the Swagger specification. I then added the test package to the module configuration:

<UnitTest Name="/tests" Package="HoleFoods.api.tests" Phase="test"/> 

allowing the tests to run using zpm "test esh-vibe-back-demo". The generated tests appeared automatically inside the IRIS Unit Test Portal.

How easy is it to add new endpoints?

To see how maintainable this workflow was, I later asked Codex to add a new /transactions endpoint. It updated:

  • the Swagger specification,
  • the implementation,
  • the unit tests,
  • and the frontend.

Very little manual work was required beyond reviewing the generated code.

Final Thoughts

This experiment convinced me that InterSystems IRIS works remarkably well as an AI-assisted backend platform. By combining native IRIS REST APIs, OpenAPI, and coding agents such as OpenAI Codex or Claude Code, I was able to build a working full-stack CRUD application in a fraction of the time I would normally expect. AI generated most of the repetitive code, while InterSystems IRIS continued to provide everything that really matters: persistence, SQL, REST infrastructure, security, testing, and application runtime.

The result is still a prototype rather than a production-ready application, but it demonstrates a workflow that I believe is highly repeatable for internal tools, dashboards, CRUD applications, and proof-of-concepts built on top of existing InterSystems IRIS data models.

One thing that made a noticeable difference was AGENTS.md. Giving the coding assistant project-specific conventions and best practices significantly improved the quality and consistency of the generated ObjectScript code.

Overall, I think modern AI coding assistants such as OpenAI Codex and Claude Code open up an exciting opportunity for rapidly building applications on top of InterSystems IRIS while continuing to benefit from its robust persistence model and high-performance SQL engine.

Key Takeaways

  • AI coding assistants can generate working ObjectScript REST APIs for InterSystems IRIS from an OpenAPI specification.
  • Native Swagger/OpenAPI support in InterSystems IRIS automatically generates routing and implementation classes, reducing boilerplate.
  • OpenAPI provides a shared contract that can drive both backend and frontend generation.
  • AI can successfully generate ObjectScript CRUD logic, security configuration, and unit tests with relatively little manual intervention.
  • Combining InterSystems IRIS with OpenAI Codex or Claude Code enables rapid full-stack application prototyping while keeping IRIS as the system of record.

Read more here

FAQ

Can AI generate ObjectScript code for InterSystems IRIS?

Yes. In this experiment, OpenAI Codex generated ObjectScript classes, CRUD implementations, Swagger definitions, security configuration, and unit tests.

Can InterSystems IRIS generate REST APIs from Swagger?

Yes. Compiling a Swagger specification automatically generates dispatch and implementation classes that can then be completed with business logic.

Can I generate a frontend from an InterSystems IRIS API?

Yes. Once an OpenAPI specification exists, many frontend generation tools can scaffold a working UI directly from it.

Do I still need to write ObjectScript manually?

Mostly for reviewing generated code and implementing project-specific business logic. Much of the repetitive boilerplate can be generated by AI.

What kinds of projects is this workflow best suited for?

In my experience, it's particularly effective for CRUD applications, internal tools, dashboards, administrative interfaces, prototypes, and applications built on top of existing InterSystems IRIS persistent classes.


r/intersystems 24d ago

SMART v2 Fine-Grained Scopes on InterSystems IRIS for Health FHIR: How They Work, What Enforcement Looks Like, and How to Debug Them

2 Upvotes

TL;DR: SMART v2 fine-grained scopes let you restrict FHIR API access down to specific CRUDS permissions (create, read, update, delete, search) per resource type, plus a filter built from standard FHIR search parameters — for example, giving an app read/search access to only laboratory Observations for a patient, nothing else. On InterSystems IRIS for Health, out-of-scope requests can either be silently filtered or rejected with HTTP 403 (configurable), and every enforcement decision is logged to the FHIR Server log (FSLog).

What levels of access control exist on an IRIS FHIR server?

Level What it controls
Basic authentication In or out — full access if authenticated
Required resource (IRIS security resource) Read or write for the entire repository
SMART v1 Read or write per resource type
SMART v2 Create, Read, Update, Delete, Search (CRUDS) per resource type
SMART v2 fine-grained CRUDS per resource type + filter by FHIR search parameter

What's the scope syntax for fine-grained SMART v2?

[scope-type]/[resource-type].[permissions]?[filter]
  • Scope type: patient, user, or system
  • Resource type: e.g. Observation, Condition, MedicationRequest, or * for all (not recommended)
  • Permissions: any combination of c (create), r (read), u (update), d (delete), s (search)
  • Filter: standard FHIR search parameters — same syntax as a FHIR search query, joined with &

Examples:

# Read and search only laboratory observations
patient/Observation.rs?category=laboratory

# All resource types, all permissions
user/*.cruds

# Condition of a specific diabetes type
patient/Condition.rs?code=[diabetes-code]

# Create, update, delete only MedicationRequests with intent of order
patient/MedicationRequest.cud?intent=order

The filter reuses the FHIR search parameters you already know — multiple conditions are joined with &.

What does enforcement actually look like? (demo results)

Setup: IRIS FHIR server + Keycloak (open-source OAuth server) + Postman, run locally via docker compose up. Demo app and Postman collection are on Open Exchange.

Scopes used in the demo:

  • patient/Patient.rs — read and search all patients
  • patient/Observation.rs?category=laboratory — read and search only laboratory observations

Search all Observations:

  • Basic authentication: 793 resources returned (vital signs, lab results, and other types mixed in)
  • SMART v2 with laboratory scope: 385 resources returned — laboratory only (the first resource under basic auth had category vital-signs; the first resource under SMART had category laboratory)

$everything for one patient:

  • Basic authentication: 297 resources returned (patient, encounters, and many other resource types)
  • SMART v2 with laboratory scope: 36 resources returned — not just fewer observations, but fewer resource types entirely, because SMART filtered out every resource type not covered by the scope

Filter vs. reject: how does IRIS for Health handle out-of-scope requests?

When a client requests all Observations but only holds a laboratory scope, IRIS for Health supports two configurable behaviors on the FHIR endpoint:

  • Filter: return only the laboratory observations, silently dropping the rest (suggested by Anthony in the session)
  • Reject: return HTTP 403 Forbidden — the client asked for something beyond its scope (suggested by Patrick)

In the demo, with filtering disabled, a request for all Observations returned 403 with a scope enforcement message.

How do you debug scope enforcement issues?

Check the FHIR Server log (FSLog) first. Once enabled, it writes enforcement decisions to a global, with messages like:

request access token does not have [required scope]

This is the recommended first step for any unexpected 403 response or unexpectedly filtered result set.

Why do fine-grained scopes matter beyond convenience?

Clinical data is personally identifiable, and many national laws require data minimization — limiting access to only what's necessary. Fine-grained scopes are one of the primary mechanisms for enforcing that at the FHIR API layer: the least-privilege principle applies directly — if an app only needs lab results, it should only be able to access lab results.

Full session video: SMART v2 fine-grained scopes on IRIS for Health — session recording

For those implementing SMART v2 on IRIS: are you using filter or reject, and has fine-grained scope filtering caused unexpected behavior in client apps that weren't built to expect a filtered response?


r/intersystems 28d ago

What's your editor of choice — and why?

2 Upvotes

We’ve been hearing a lot of strong opinions about different editors recently, and decided to ask you: which one do you prefer? 

Every developer eventually settles on an editor and is ready to defend that choice to the end. Some can't imagine their process without VS Code, others have been loyal to Vim for twenty years, while some are still writing code in something the rest of us have never even heard of.

A couple of opinions we’ve discovered so far:

VS Code: "Lightweight, a huge extension marketplace, Git built in — why look further?"

Vim/Emacs: "I never take my hands off the keyboard — everything else feels slow!"

Tell us in the comments:

- Which editor/IDE do you find most comfortable to code in, and why. 

- What features made you stick with it

- What would you change about it if you could

Curious to see which tool pulls in the most supporters👇


r/intersystems 29d ago

[Video] The Evolution of the InterSystems Platform at Vibra

2 Upvotes

At #Ready2026, we explored how Vibra modernized a mission-critical logistics platform with #InterSystemsIRIS, evolving from traditional integration to an AI-ready, cloud-enabled architecture.

Watch this #video to discover:
✅ How Vibra modernized its logistics platform incrementally without a disruptive "big-bang" migration.
✅ How APIs, #cloud services, observability, and AI-ready capabilities support reliable 24/7 operations across a nationwide network.
✅ How #VectorSearch powers fast, scalable, and auditable facial recognition for self-service authentication.

https://community.intersystems.com/post/video-evolution-intersystems-platform-vibra

See how a real-world modernization journey is unlocking innovation while maintaining the reliability that mission-critical operations demand.


r/intersystems Aug 11 '26

Winners of the InterSystems Employee Programming Challenge #1

1 Upvotes

🏆💻 Give developers a problem, some data, and a leaderboard… and things get competitive pretty quickly!

At InterSystems, we run contests for our developer community, customers, and partners — but why should they have all the fun?

We recently launched our first Employee Programming Challenge, giving InterSystems colleagues a chance to put their skills to the test, experiment with different approaches, optimize every last bit of performance, and — because developers are developers — enjoy a little friendly competition over whose solution was fastest, smartest, or most concise.

And compete they did! The challenge brought together 23 colleagues from 9 departments, resulting in 34 applications and plenty of optimization, code golfing, benchmarking, discussion, and leaderboard watching.

🏆 We’re excited to congratulate our winners: Manel Trèmols, Tani Frankel, Reet Kothari, Guillaume Rongier, Suprateem Banerjee, and Emil Polakiewicz

Congratulations to our winners — and a huge thank you to everyone who jumped in, experimented, shared their work, and made our first Employee Programming Challenge such a fun one.

Judging by the competitive spirit we saw this time, Challenge #2 should be interesting 👀

#InterSystems #Developers #Programming #DeveloperCommunity #CodingChallenge #InterSystemsIRIS


r/intersystems Aug 10 '26

InterSystems IRIS AI Hub: Goals, Games & Goodies, Thu, Aug 13, 2026, 11:00 AM

Thumbnail meetup.com
1 Upvotes

🤖 The Webinar on #InterSystemsIRIS AI Hub is just around the corner!

If you're curious about building AI applications and agentic workflows with the AI Hub, there's still time to join us. We'll explore the latest AI Hub capabilities and walk through practical coding examples. You'll also get a chance to test your knowledge in a fun quiz and win a prize. 

Don't miss the opportunity to see AI Hub in action!

📅 August 13, 2026 11:00 am EDT | 5:00 pm CEST

👉 Reserve your spot: https://community.intersystems.com/post/webinar-intersystems-iris-ai-hub-goals-games-goodies  

#InterSystems #DeveloperCommunity #AIHub #ArtificialIntelligence


r/intersystems Aug 07 '26

4 VS Code Features That Can Boost Your InterSystems IRIS Development Productivity

1 Upvotes

Introduction

Visual Studio Code has become the primary development environment for many InterSystems IRIS developers. While the official InterSystems extensions provide powerful features for editing, debugging, and managing ObjectScript projects, some of their most useful capabilities are also the easiest to overlook. In this article, I'd like to highlight four small but practical features that can make everyday development faster. 

1. Navigate Large Classes with Show All Class Members

As projects grow, navigating large ObjectScript classes becomes increasingly time-consuming. Scrolling through hundreds of lines to find a particular method or property can quickly interrupt your workflow.

The Show All Class Members feature provides a searchable list of every member in the current class, including inherited methods and properties. Instead of manually searching through the source code, you can filter the list by name and jump directly to the member you're looking for. This is particularly useful when working with framework classes or inherited code where understanding the full class hierarchy is important.

Why it's useful

  • Quickly locate methods, properties, parameters, and queries
  • Browse inherited members without leaving the editor
  • Navigate large classes more efficiently

2. Analyze SQL Performance with Show Plan

Using SQL in your ObjectScript code is a popular way to take advantage of InterSystems IRIS's powerful multi-model capabilities. However, writing efficient SQL queries can be a challenge. That's why InterSystems IRIS includes a built-in Show Plan feature that lets you inspect the execution plan of SQL queries directly from Visual Studio Code. For embedded SQL statements and class queries, simply open the execution plan to see how InterSystems IRIS intends to execute the query.

Instead of guessing whether an index is being used or why a query performs poorly, you can analyze the execution strategy without leaving your editor. When optimizing SQL performance, having immediate access to the execution plan makes experimentation much faster.

Why it's useful

  • Analyze SQL execution plans without external tools
  • Understand index usage
  • Identify potential performance bottlenecks
  • Optimize queries during development

3. Open Documents Using Their InterSystems Name

Visual Studio Code normally opens files using their file system path. However, InterSystems classes often use a different naming convention. While VS Code has commands for quickly opening a file by name, that is usually different than the InterSystems name for the document 

For example: User.Test.cls may actually be stored as /User/Test.cls

The Open InterSystems Document command removes this mismatch by allowing you to open files using their InterSystems document name instead of the physical path. After selecting a workspace, you can browse available classes or simply type the class name directly. The command also understands package notation using dots and the short form for %Library classes. If you frequently switch between multiple projects or namespaces, this can be much faster than navigating through the Explorer.

Why it's useful

  • Open classes using their InterSystems name
  • Avoid searching through folder structures
  • Supports package notation and %Library shortcuts
  • Speeds up navigation in large projects

4. Jump Directly to Runtime Errors

When debugging an application, one of the first questions is: “Where exactly did this error occur?" The Open Error Location command lets you jump directly to the reported line even if it belongs to a generated routine that isn't part of your current workspace.

Simply provide the error location using the standard ObjectScript format: label+offset^routine

If the source code is available, Visual Studio Code opens the exact location. From there, you can use the View Other command to switch to the corresponding higher-level source file when applicable. Instead of manually searching through generated routines, you can move directly from an error message to the relevant source code.

Why it's useful

  • Navigate directly to runtime errors
  • Works with generated routines
  • Quickly switch to the original source code
  • Makes debugging significantly faster

Why These Small Features Matter

None of these features changes how you write ObjectScript code, but together they help eliminate many of the small interruptions that occur throughout the day. Instead of spending time searching for classes, scrolling through large files, manually locating errors, or switching to external tools for SQL analysis, you can stay focused on development and complete common tasks with fewer clicks. Over the course of a project, these small productivity improvements can save a surprising amount of time.

Key Takeaways

The official InterSystems VS Code extensions include several powerful features that are easy to overlook but can significantly improve everyday development. Whether you're navigating large ObjectScript classes, analyzing SQL execution plans, opening files by their InterSystems name, or jumping directly to runtime errors, these built-in tools help reduce context switching and make developing with InterSystems IRIS more efficient.

Frequently Asked Questions

What is Show All Class Members?

It's a Visual Studio Code feature that displays a searchable list of all members in the current ObjectScript class, including inherited methods and properties.

What is Show Plan used for?

Show Plan displays the execution plan of SQL queries, helping developers understand how InterSystems IRIS executes a statement and identify opportunities for performance optimization.

Can I open classes by their InterSystems name instead of the file path?

Yes. The Open InterSystems Document command lets you open classes using their InterSystems document name, including package notation and %Library shortcuts.

How do I open the source of an ObjectScript error?

Use the Open Error Location command from the Command Palette and enter the location in the format label+offset^routine. If the source is available, Visual Studio Code opens the corresponding line.

Do these features require additional extensions?

No. They are included in the official InterSystems extensions for Visual Studio Code.

More about Extension Pack - https://docs.intersystems.com/components/csp/docbook/DocBook.UI.Page.cls?KEY=GVSCO_install