PHARMA FACTORY - HYBRID
Hybrid Track: Add OpenX Without Replacing Anything
You already have an industrial backbone. This path adds OpenX beside it, without disruption.
Layer OpenX alongside DeltaV, HighByte, SCADA or MES. You are not ripping and replacing; you are adding a workspace where your data is organized and read through saved queries.
What you will have
- Saved queries over your existing data
- API endpoints for LIMS, dashboards or AI tools
- Any AI over MCP, reading the same queries
All without touching your control systems.
The approach
| Layer | What stays | What is added |
|---|---|---|
| Control | SCADA, DeltaV, PLCs | Nothing - OpenX does not touch it |
| Data | Historians, databases | A connection that receives a copy of the data |
| Query | Ad-hoc SQL, manual reports | Saved warm queries |
| AI | Scattered tools | Any MCP client reading the saved queries |
Phase 1: Connect your data
Step 1.1: Add a connection
On the canvas
- Open your workspace.
- Drag a Connection node from the Node Bank onto the canvas.
- In its inspector's Settings tab, set the Connection ID (tick Is IoT Edge Device if an IoT Edge gateway sends for it). There is no connection string to enter: the connection sets up its own device identity.
- Save, then Deploy. Deploy registers the connection as a device on Fathym's shared IoT hub, or your own once your workspace has its IoT fabric.
- Open the inspector's Connection Info tab. It shows the credentials your historian or gateway uses to send data (device, MQTT, AMQP and HTTP details).
Or ask Azi
AZI
Tell me: "Create a connection for our pharma historian." I propose it; accept it, then Deploy builds it.
Step 1.2: How your sources reach OpenX
Your historian or SCADA system forwards data to the connection's device:
| Source | How it reaches OpenX |
|---|---|
| OSIsoft PI | Through an edge gateway, over MQTT |
| Aveva Historian | Through an edge gateway (OPC UA to MQTT) |
| Rockwell FactoryTalk | Over MQTT |
| Your own sensors | Straight to the device over MQTT, AMQP or HTTP |
TIP
No connection yet? Add a Simulator node to follow along. The surfaces and queries are the same.
Phase 2: Create a monitoring surface
Step 2.1: Create the surface
On the canvas
- Drag a Surface node from the Node Bank onto the canvas.
- In its inspector's Settings, name it
Cleanroom-Monitoring. - Draw a line from your connection to the surface.
- Save. A surface is live as soon as it is saved.
Or ask Azi
AZI
"Create a surface called Cleanroom-Monitoring, fed by our pharma historian connection." Accept it, and it is live.
Step 2.2: Check the data is flowing
Open the Live Stream panel. You should see your temperature, pressure and batch messages arriving.
Phase 3: Build compliance queries with Azi
Where your data is
Your workspace's device data lands in one table, Data (Devices in workspaces whose IoT fabric was set up
earlier). Each message's payload is JSON in its RawData column, so a query unpacks it with
todynamic(RawData). The field names below (zone, temperature, pressure, batchId, eventType) are
examples; use the ones your systems send. Ask Azi to sample with Data | take 5 first. The queries below are examples to adapt, not tested against your data.
In the main Azi panel, Azi proposes each warm query together with the surface it sits on, and it waits for a person to read and accept it (unless you have turned on Greenfield). Inside the Warm Query Manager, she drafts the query instead and you save it with the canvas Save icon.
Step 3.1: Temperature compliance
"Create a warm query that checks whether cleanroom temperature stayed between 18 and 22°C in the last 24 hours."
Data
| where EnqueuedTime > ago(24h)
| extend Payload = todynamic(RawData)
| where tostring(Payload.zone) == "Cleanroom"
| summarize MinTemp = min(todouble(Payload.temperature)),
MaxTemp = max(todouble(Payload.temperature)),
AvgTemp = avg(todouble(Payload.temperature))
| extend Compliant = MinTemp >= 18 and MaxTemp <= 22
Step 3.2: Batch history
"Build a query that shows every event for a batch, in time order."
Data
| extend Payload = todynamic(RawData)
| where tostring(Payload.batchId) == "112A"
| project EnqueuedTime, DeviceID, EventType = tostring(Payload.eventType), Zone = tostring(Payload.zone)
| order by EnqueuedTime asc
A warm query can declare parameters, so the batch id can be passed on each call instead of written in.
Step 3.3: Pressure threshold
"Create a query that flags any pressure reading above 1.5 bar in the mixing zone."
Data
| extend Payload = todynamic(RawData)
| where tostring(Payload.zone) == "MixingZone" and todouble(Payload.pressure) > 1.5
| project EnqueuedTime, DeviceID, Pressure = todouble(Payload.pressure)
| order by EnqueuedTime desc
Phase 4: Call your queries over REST
Every warm query is a REST endpoint.
- Open APIs -> API Manager and its Warm Queries tab.
- Under Configured Queries, each saved warm query has its own card, with ready-to-copy cURL, TypeScript and Python.
- Get a key from APIs -> API Keys.
curl -X GET 'https://openx.fathym.com/ox-api/warm-queries/temp-compliance' \
-H 'Authorization: Bearer YOUR_TOKEN'
| System | Integration |
|---|---|
| LIMS | A REST call on batch completion |
| Dashboard | Polling the endpoint |
| Alerting | Polling the threshold query |
Phase 5: Connect any AI over MCP
The OpenX MCP Server is at https://openx.fathym.com/ox-api/mcp. Sign in through the browser:
- Claude.ai or ChatGPT: add a custom connector, paste the URL, sign in with OpenX, pick the workspace and tick the rights to share.
- Coding agents: run
fai mcp install https://openx.fathym.com/ox-api/mcp --name openxand sign in when the browser opens.
Setup for each client is in Bring Any AI. Then ask:
"Was batch 112A within its temperature limits?"
The AI reads your saved queries with call_api and answers from them. If it wants to build something new, it
proposes it with manage_proposals, and a person accepts.
What you built
| Component | Status |
|---|---|
| Historian connection | Built on Deploy, sending data |
| Cleanroom surface | Organizing your data |
| Compliance queries | Three saved warm queries |
| API endpoints | One per warm query |
| MCP | Any client reading the same queries |
AZI
Your factory did not change. Your control systems did not change. But every answer now comes from a saved query anyone on the team can read.
Before and after
| Before | After |
|---|---|
| "The AI said it was fine" | The saved query the answer came from |
| Data scattered in silos | One workspace, organized by surface |
| AI tied to one vendor | Any MCP client reads the same queries |
For what OpenX records about changes, and what it does not, see the Compliance matrix.
Next steps
| If you want to... | Go to... |
|---|---|
| Try the full track | Full track |
| See query patterns | Query Patterns |
| Connect more AI clients | Bring Any AI |
| Learn more about Azi | Meet Azi |
On this page
- Hybrid Track: Add OpenX Without Replacing Anything