First release. Election-day incident triage with a live AI Hub agent inside an IRIS Interoperability production. Tested end to end on 7 November 2026: power-outage report accepted, agent verdict critical, alert fired, incident recorded (session 66, 7 messages, all Completed, no errors).
An InterSystems IRIS interoperability workflow that triages election-day incidents with an AI Hub agent. An election worker or coordinator submits an incident report; the production normalizes it, the AI agent classifies its severity, recommends an action and drafts the alert text; critical incidents trigger an alert, and every incident is persisted for a simple dashboard.
Built for the InterSystems programming contest "AI Agents in Interoperability Workflows" (development and submission window: 26 October – 8 November 2026). Based on the official ai-hub-dev-template — the template's Sample classes are kept untouched; the app lives in the ElectionTriage package.
Status: tested end to end (7 November 2026). The production runs the full flow live: a power-outage report is accepted, the AI agent classifies it
critical, the alert fires and the incident is recorded — session 66, 7 messages, all Completed, no errors. See the demo video.
ElectionTriage.IncidentService receives an incident report as JSON and injects it into the production.ElectionTriage.IncidentProcess (ObjectScript Ens.BusinessProcess, no BPL) trims the free text, defaults the timestamp and falls back to the catch-all category when the incoming category is unknown.ElectionTriage.TriageOperation calls ElectionTriage.TriageAgent (ObjectScript SDK, %AI.Agent), which returns severity (critical / high / medium / low), one recommended action and a short alert text.critical incidents to ElectionTriage.AlertOperation (writes the alert to the console log and marks the report ALERTED).ElectionTriage.RecordOperation stores each triaged report in ElectionTriage.IncidentRecord, which the dashboard lists with the Recent() query (most recent first).HTTP POST (JSON) +-----------------------------+
incident report --> IncidentService --> IncidentProcess (ObjectScript)
| normalize
v
TriageOperation
| %AI.Agent (Config Store creds)
v
+---------------+---------------+
| severity = critical? |
+-------+---------------+-------+
| yes | no
v |
AlertOperation |
| |
+-----------+-----------+
v
RecordOperation
|
v
IncidentRecord (dashboard)
The agent uses exactly these 10 LA County categories (validated and renamed to California English terms on 7 November 2026). Typical severity is a guide only — the agent decides per incident.
| Category | Examples | Typical severity |
|---|---|---|
| Voting equipment | BMD not powering on / frozen; ballot printer fault | High–Critical |
| ePollbook / check-in | Check-in tablet down; queue not processing | High |
| Accessibility | Accessible voting equipment unavailable | High |
| Supplies | Missing provisional ballots / envelopes / signage | Medium–High |
| Staffing | Election worker no-show; vote center without quorum | Medium–High |
| Power / connectivity | Power outage; vote center internet down | Critical |
| Safety / intimidation | Voter being intimidated; electioneering inside the limit | Critical |
| Ballot box / drop box | Damaged or full drop box; ballot box fault | High |
| Mail-in voting | Discrepancy in a batch of received ballots | Medium |
| Operational question | Procedure, hours, voter redirection questions | Low |
Requires the AI Hub Community Docker image, build 154 (iris-community-2026.3.0AI.154.0-docker.tar.gz, x64 for Windows). Download it from the Early Access Program portal (requires a login) — this is the one step that needs the developer's account.
# 1. Load the image
docker load -i /path/to/iris-community-2026.3.0AI.154.0-docker.tar.gz
# 2. Make sure the Dockerfile IMAGE matches the loaded image name
# (default in this repo: docker.iscinternal.com/docker-intersystems/intersystems/iris-community:2026.3.0AI.154.0)
# 3. Create an EMPTY .env file (scaffold stage: no LLM calls run without
# the Config Store entry below, so no key belongs here)
touch .env
# 4. Build and start
docker-compose up -d --build
Management Portal: http://localhost:52773/csp/sys/UtilHome.csp (SuperUser / SYS). IRIS Terminal: docker-compose exec -it iris iris session iris.
Then start the production ElectionTriage.IncidentProduction from the Management Portal (Interoperability > Productions) or the terminal.
LLM credentials are resolved from the IRIS Config Store, never from code or from .env. ElectionTriage.TriageConfig reads the entry AI.LLM.triage (Area AI, Type LLM, Name triage) with GetDetails(..., validate=1, resolveSecrets=1) and builds the OpenAI provider from the resolved api_key. Setup, in the IRIS terminal (docker compose exec iris iris session iris), as SuperUser — type the API key only in the terminal, never in chat or in a file:
set $namespace="%SYS"
do ##class(%ConfigStore.DescriptorManager).RebuildRegistry() // registers the AI.LLM descriptor
write ##class(Security.Resources).Create("AIUseResource")
write ##class(Security.Resources).Create("AIEditResource")
set $namespace="IRISAPP"
write ##class(%Wallet.Collection).Create("AISecrets", {"UseResource":"AIUseResource","EditResource":"AIEditResource"})
set key="sk-..." // your OpenAI API key, typed in the terminal only
write ##class(%Wallet.KeyValue).Create("AISecrets.OpenAI", {"Usage":"CUSTOM","Secret":{"api_key":(key)}})
kill key
Set llmConfig = {"model_provider": "openai", "model": "gpt-4o-mini", "api_key": "secret://AISecrets.OpenAI#api_key"}
Set sc = ##class(%ConfigStore.Configuration).Create("AI", "LLM", "", "triage", llmConfig)
Do:$$$ISERR(sc) $SYSTEM.Status.DisplayError(sc)
Verify with Set sc = ##class(%ConfigStore.Configuration).GetDetails("AI.LLM.triage", .details, 1, 1) followed by ZWRITE details — the api_key must show the real key, not the secret://... reference. Until the entry exists, the agent's %OnInit() fails loudly with setup instructions.
curl -X POST http://localhost:9980/ \
-H "Content-Type: application/json" \
-d '{
"VoteCenter": "Long Beach City Hall",
"Category": "Power / connectivity",
"Description": "Power outage at the vote center, voting machines are down.",
"ReporterName": "Maria Silva",
"ReporterContact": "[email protected]"
}'
Expected response: {"status": "accepted", "category": "Power / connectivity"}. Then check the production trace, the agent's severity/action/alert text, the console-log alert (critical incidents) and the ElectionTriage.IncidentRecord table for the persisted row.
Watch the demo video (1:31) — narrated walkthrough: the problem, the architecture, a live power-outage report (accepted, category "Power / connectivity"), the production trace (7 messages, all Completed, agent verdict critical, alert fired, incident recorded), and the visual trace of the full flow.
skills/ — AI Hub agent skills from the template (config store, LangChain, MCP server, ObjectScript SDK, policies, RAG, subagents, toolsets).src/Sample/ — template example classes (tools, toolsets, agents, MCP servers). Untouched.src/ElectionTriage/ — the app:
IncidentReport.cls — interoperability message + taxonomy validation.IncidentService.cls — REST Business Service.IncidentProcess.cls — ObjectScript BusinessProcess: normalize → triage → route → persist.TriageAgent.cls — %AI.Agent subclass (system prompt + taxonomy).TriageConfig.cls — Config Store credential placeholder (no keys).TriageOperation.cls — Business Operation wrapping the agent.AlertOperation.cls — critical-alert dispatch (console log + status ALERTED).RecordOperation.cls — persistence for the dashboard.IncidentRecord.cls — persistent record + Recent() query.IncidentProduction.cls — production definition.Dockerfile, docker-compose.yml, module.xml — template wiring, with ElectionTriage.PKG added to module.xml.MIT License — the template's LICENSE is kept as-is, and the ElectionTriage package is released under the same MIT license.