PI Agent Installation Guide
The MaestroHub PI Agent is a standalone Windows service that bridges MaestroHub to an AVEVA PI Data Archive. It runs inside the plant network, speaks to PI on your behalf, and exposes a WebSocket endpoint that the AVEVA PI System connector connects to.
MaestroHub ──── WebSocket (TCP 45283) ───► PI Agent ──── PI protocol ───► PI Data Archive
(Windows) (TCP 5450/5457)
MaestroHub dials out to the agent. The agent never needs access to MaestroHub — MaestroHub needs access to the agent.
1. Requirements
| OS | Windows 10/11 or Windows Server 2016+, x64. There is no 32-bit build and no Linux build. |
| .NET | None. The agent ships self-contained; the runtime is inside the executable. |
| Native prerequisite | Microsoft Visual C++ Redistributable (x64). Most Windows Server builds already have it. Without it the agent still starts, and states clearly that no PI operation will succeed. |
| PI client software | Not required. The agent does not need PI SMT or any PI client, and does not read the machine's known-servers list. |
| Disk | ~200 MB, plus a small state file |
| Memory | Allow ~300 MB |
| Network — outbound | Must reach the PI Data Archive on TCP 5450, and PI AF on TCP 5457 |
| Network — inbound | Must accept TCP 45283 from wherever MaestroHub runs |
What to collect before you start
| You need | Notes |
|---|---|
| PI Data Archive server name | A name, not an IP — the agent resolves it by DNS |
| PI AF server and database | Only needed to browse the asset tree |
| PI username and password | Only if the agent host is not domain-joined to the PI server |
| PI domain or machine name | Ask explicitly which it is — see the warning in step 4 |
Choose a topology
| A — one machine | B — agent on a separate host | |
|---|---|---|
| Where | Agent and MaestroHub on the same Windows machine | Agent on a plant or server box, MaestroHub elsewhere |
| TLS | Can be off (loopback only) | Required |
| Certificate | None needed | A certificate on the agent, and a CA (or skip-verify) in MaestroHub |
| Firewall | Nothing to open | TCP 45283 from the MaestroHub host |
| Use for | A first run, or a local trial | Anything real |
Both are covered below.
2. Download and extract
Download the agent package from the MaestroHub portal:
https://portal.maestrohub.com/downloads/plugins
You get a zip and a checksum file beside it:
MaestroHubPiAgent-<version>-win-x64.zip
MaestroHubPiAgent-<version>-win-x64.zip.sha256
Verify the download, then extract it to a permanent folder:
Get-FileHash .\MaestroHubPiAgent-1.0.0-win-x64.zip -Algorithm SHA256
Get-Content .\MaestroHubPiAgent-1.0.0-win-x64.zip.sha256
Expand-Archive .\MaestroHubPiAgent-1.0.0-win-x64.zip -DestinationPath C:\MaestroHub\PiAgent
The two checksums must match. If they do not, stop and download it again.
Use a permanent location — not Desktop or Temp. This becomes the installation directory: the agent reads its configuration from here and writes its recovery state here. Do not put it in a folder that syncs to another machine, because the configuration file will hold secrets.
After extracting you should have:
C:\MaestroHub\PiAgent\
MaestroHubPiAgent.exe the agent — everything is inside it
appsettings.sample.json the annotated configuration template
install-service.ps1 registers it as a Windows service
uninstall-service.ps1 removes the service
README.md the full operator manual
LICENSE.txt
ThirdPartyNotices.txt
The executable is around 150 MB. That is expected — it carries the .NET runtime and the PI libraries.
appsettings.json must sit beside the executableThe agent reads its configuration from the folder the executable is in — never from your current directory. This matters because a Windows service starts in C:\Windows\System32, so anything resolved against the working directory would land somewhere surprising.
The same rule applies to every relative path inside the file, including the TLS certificate.
3. Generate an API token
This is the shared secret MaestroHub presents when it connects. Generate a strong one:
[Convert]::ToBase64String((1..32 | ForEach-Object { Get-Random -Maximum 256 }))
Keep the result — you need the same string in the agent's configuration and in the MaestroHub connection. The agent refuses to start on a token shorter than 16 characters.
4. Configure the agent
Copy the shipped template and edit it:
cd C:\MaestroHub\PiAgent
Copy-Item .\appsettings.sample.json .\appsettings.json
notepad .\appsettings.json
appsettings.sample.json is heavily commented — every setting, its default, and what changing it does. Keys beginning // are comments and are ignored. Anything you do not need to change can be deleted.
Only two settings have no usable default: ApiToken and PiDataArchive.
Topology A — one machine, TLS off
{
"AgentSettings": {
"Port": 45283,
"ListenAddress": "0.0.0.0",
"ApiToken": "<the token from step 3>",
"EnableTLS": false,
"PiDataArchive": "<PI-ARCHIVE>",
"AfServer": "<PI-ARCHIVE>",
"AfDatabase": "<AF-DATABASE>",
"PiUser": "<PI-USER>",
"PiDomain": "<PI-DOMAIN>",
"PiAuthMode": "windows"
},
"Logging": {
"LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" }
}
}
Topology B — separate hosts, TLS on
The same file, with these three lines in place of "EnableTLS": false:
"EnableTLS": true,
"TlsCertPath": "certs\\agent.pfx",
"TlsCertPassword": "<certificate password>",
Step 5 covers the certificate itself.
What the values mean
| Field | What to put, and why |
|---|---|
ApiToken | The string from step 3. Minimum 16 characters, and it must match the MaestroHub connection field character for character. |
PiDataArchive | The Data Archive's server name, not an IP address. Resolved by DNS; needs no PI client software. |
AfServer / AfDatabase | Only needed to browse the asset tree. The two go together — set one without the other and the agent refuses to start. Leave both empty if you only use plain PI point tags. |
PiUser | Set only if the agent host is not domain-joined to the PI server. Leave empty to connect as the Windows account the agent runs under, which is the cleaner option for a real deployment. |
PiDomain | For a local Windows account on the PI host, this is that host's machine name — not a Windows domain and not a DNS suffix. |
PiAuthMode | One of windows, piuser, openid, none. windows is correct for both a domain service account and a local account on the PI host. |
ListenAddress | 0.0.0.0 means every interface. 127.0.0.1 makes the agent unreachable from any other machine — the agent warns you at startup if you set it. |
Port | Default 45283. Must match Agent Port in the MaestroHub connection. |
PiDomain is the most common cause of a failed connectionAsk explicitly whether the PI account is a domain account or a local account on the PI host. If it is local, PiDomain is the PI host's machine name.
Getting this wrong produces an error that reads exactly like a wrong password — and a burst of failed logons can lock out the account for everyone using it. If authentication fails twice, stop and confirm the username, password and domain rather than guessing again.
Keeping secrets out of the file
Any setting can come from an environment variable instead. The name is PIAGENT_ followed by the JSON path with two underscores per level:
| Setting | Environment variable |
|---|---|
AgentSettings:PiPassword | PIAGENT_AgentSettings__PiPassword |
AgentSettings:TlsCertPassword | PIAGENT_AgentSettings__TlsCertPassword |
AgentSettings:ApiToken | PIAGENT_AgentSettings__ApiToken |
For a foreground test run, set it in the same PowerShell window you will start the agent from — it lasts for that session only:
$env:PIAGENT_AgentSettings__PiPassword = '<PI-PASSWORD>'
For a Windows service, it must outlive your session, so set it machine-wide from an elevated prompt and restart the service afterwards:
[Environment]::SetEnvironmentVariable('PIAGENT_AgentSettings__PiPassword', '<PI-PASSWORD>', 'Machine')
The agent will start with the password in appsettings.json, but it logs a warning: a plant credential in a settings file gets copied into backups, support tickets and screenshots.
5. Set up TLS
TLS is on by default and should stay on. This WebSocket carries both your process data and the API token; over plaintext the token is readable and replayable by anyone on the network path.
Option 1 — a certificate from your own CA (any real deployment)
You need a PKCS#12 (.pfx) file whose subject or SAN matches the hostname MaestroHub will use to reach the agent. An internally issued certificate is fine; it does not need a public authority.
"EnableTLS": true,
"TlsCertPath": "certs\\agent.pfx",
"TlsCertPassword": "<certificate password>",
certs\agent.pfx means C:\MaestroHub\PiAgent\certs\agent.pfx, not a path relative to your shell. This is deliberate, because a Windows service starts in C:\Windows\System32. Absolute paths work too.
Create the folder and restrict the file, because its private key is inside:
New-Item -ItemType Directory -Path C:\MaestroHub\PiAgent\certs -Force
icacls "C:\MaestroHub\PiAgent\certs\agent.pfx" /grant "<service-account>:(R)"
Grant read access to the account the service will run as. If you are running in the foreground as yourself, you already have access.
Option 2 — a self-signed certificate (lab rig)
From an elevated PowerShell:
$cert = New-SelfSignedCertificate -DnsName "pi-agent.plant.local" `
-CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(2)
$pw = ConvertTo-SecureString -String "<choose a password>" -Force -AsPlainText
New-Item -ItemType Directory -Path C:\MaestroHub\PiAgent\certs -Force
Export-PfxCertificate -Cert $cert -FilePath "C:\MaestroHub\PiAgent\certs\agent.pfx" -Password $pw
-DnsName must match the hostname MaestroHub will dial, or the handshake fails.
Then in MaestroHub, either paste the certificate into CA Certificate (PEM) or enable Skip Certificate Verification — one or the other, never both.
Option 3 — TLS off (loopback only)
"EnableTLS": false,
Legitimate only when MaestroHub and the agent are on the same machine, or on an isolated lab network. The agent logs a loud warning at startup whenever TLS is off, and that warning is correct. Turn Use TLS off on the MaestroHub side to match.
6. Start the agent
Run it in the foreground first. It takes ten seconds and the output is far easier to read than the Event Log:
cd C:\MaestroHub\PiAgent
.\MaestroHubPiAgent.exe --console
--console runs it in the foreground with the log on screen. Stop it with Ctrl+C — that is a clean stop, and the agent flushes its recovery positions on the way out.
If any setting is wrong, the agent names every problem at once and exits without starting, so you fix them in one pass rather than one restart at a time.
Read the startup banner
The first thing the agent prints is a block of facts. Most misconfigurations are visible right here, before anything has connected.
MaestroHub PI Agent 1.0.0
protocol version : 2
runtime : win-x64 (64-bit)
content root : C:\MaestroHub\PiAgent
listening on : ws://0.0.0.0:45283/ws
health : http://0.0.0.0:45283/health
PI Data Archive : <PI-ARCHIVE>
PI AF : <PI-ARCHIVE> / <AF-DATABASE>
PI identity : <PI-DOMAIN>\<PI-USER> (windows authentication)
| Line | What to check |
|---|---|
protocol version | The connector requires version 2. A 1 means the agent package is too old. |
content root | The folder appsettings.json was read from. If your settings appear to be ignored, the file is not in this folder. |
listening on | ws:// when TLS is off, wss:// when on. This must agree with Use TLS in MaestroHub. |
PI identity | Shows DOMAIN\user. If it says the service's own Windows account, PiUser was not picked up. |
TLS ... DISABLED warning | Expected on a loopback rig. Alarming anywhere else. |
A second or two later, a line reports the PI connection is established. If PI is unreachable the agent keeps running and retries with backoff rather than exiting — deliberate, because an agent that will not start cannot tell anybody why.
Confirm it is ready
In a second PowerShell window:
curl.exe http://127.0.0.1:45283/health
Use curl.exe with the extension — in Windows PowerShell, plain curl is an alias for a different command. With TLS on, use curl.exe -k https://<agent-host>:45283/health; -k skips the certificate check for this one diagnostic call.
What you want back:
{"ready":true,"piState":"Connected","sessionConnected":false,"agentVersion":"1.0.0","protocolVersion":2,"uptimeSeconds":42}
| Field | Meaning |
|---|---|
ready | true only once PI is connected. This endpoint reports readiness, not liveness — HTTP 503 with ready:false is the correct answer while PI is down. |
piState | Connected is what you want. Connecting or Disconnected means read the agent log. |
sessionConnected | Whether MaestroHub is currently attached. false is correct before you create the connection. |
protocolVersion | Must be 2. |
ready is trueEvery symptom past this point would just be this one wearing a different hat.
7. Install as a Windows service (optional)
For a functional test you can leave the agent running in its console window. Install the service when you want it to survive a reboot.
Do this after the foreground run has proved the configuration is good — the script refuses to run without an appsettings.json beside the executable, precisely so a service cannot be registered on a configuration that will not start.
From an elevated PowerShell, in the installation folder:
cd C:\MaestroHub\PiAgent
.\install-service.ps1
That registers MaestroHubPiAgent for automatic start, configures it to restart after a crash, starts it, and waits for it to report healthy.
Useful options:
# Run under a dedicated service account, and open the firewall to the MaestroHub host only.
.\install-service.ps1 -ServiceAccount (Get-Credential DOMAIN\svc-maestrohub) `
-MaestroHubAddress <maestrohub-host-ip>
# Replace an existing installation. Your appsettings.json and state folder are kept.
.\install-service.ps1 -Force
| Option | What it does |
|---|---|
-ServiceAccount | The Windows account the service runs as, prompted for securely. The agent connects to PI as this identity when PiUser is empty, so a dedicated account is what makes PI's audit trail name the agent. The script grants it "Log on as a service" if missing. Omit it and the service runs as LocalSystem. |
-MaestroHubAddress | Creates an inbound firewall rule for the agent's port, scoped to that one address. Omit it to make no firewall change. |
-Force | Stops and deletes the existing service before reinstalling. Configuration and state are left alone. |
There is deliberately no -ApiToken parameter: a secret passed on a command line is written into the PowerShell history of whoever ran it.
Afterwards:
Get-Service MaestroHubPiAgent # is it running?
Restart-Service MaestroHubPiAgent # pick up a configuration change
.\uninstall-service.ps1 # remove the service
After editing appsettings.json, restart the service — or, in console mode, Ctrl+C and start it again. "I changed the setting and nothing happened" is almost always a missing restart.
A service does not see $env: variables set in your PowerShell window. If you supplied the PI password that way, set it machine-wide before installing the service, or the service will start and fail to authenticate to PI while the console run worked fine.
8. Connect MaestroHub to the agent
In MaestroHub, go to Connect → New Connection → AVEVA PI System:
| Tab | Field | Value |
|---|---|---|
| Connection | Agent Host | 127.0.0.1 for topology A; the agent's hostname for topology B — the same name as the certificate's DNS name |
| Connection | Agent Port | 45283, or whatever you set as Port |
| Security | API Token | The exact ApiToken string from appsettings.json |
| Security | Use TLS | Must match the agent's EnableTLS |
| Security | CA Certificate (PEM) | The CA that signed the agent's certificate, if it is not already trusted |
Press Test Connection, then save. Watch the agent's console — you should see a session open, and the health endpoint's sessionConnected should become true.
The full field reference is in the AVEVA PI System connection guide.
9. Troubleshooting
| What you see | What it is |
|---|---|
| Exits immediately naming a field, exit code 78 | Configuration is invalid. The message names the field and the fix. Code 78 means specifically a human must edit a file — restarting will not help. |
ApiToken ... is only N characters | The minimum is 16. |
TlsCertPath points at a file that does not exist | Wrong path, or a relative path resolved against the wrong folder — relative means beside the executable. |
Starts on defaults, complains ApiToken / PiDataArchive are empty | appsettings.json is not beside MaestroHubPiAgent.exe. Check the content root line in the banner. |
Starts, but /health stays ready:false with piState: Disconnected | PI is unreachable (VPN? port 5450?) or the credential is wrong. The agent log names the PI error. |
Windows authentication trial failed because the authentication method was not tried | Reads like a permissions problem; is not. Either PiUser / PiPassword / PiDomain are not all set, or PiDomain is wrong. |
The credentials supplied to the package were not recognized | Same family. Usually PiDomain again. |
the AVEVA AF SDK could not be loaded | Install the Visual C++ Redistributable (x64). The agent deliberately starts anyway so that /health can tell you this, instead of the service simply vanishing. |
| Port 45283 already in use | Another copy of the agent is running. Only one can hold the port. |
| MaestroHub connects, then drops when a second instance connects | The agent serves one session and prefers the newest. Point only one MaestroHub connection at each agent. |
The agent also writes to the Windows Event Log, which is where to look if the service starts and then stops before creating a log file.
A burst of failed logons can lock the PI account for everyone using it. If authentication fails twice, stop and confirm the username, the password and — most likely — the PiDomain with whoever issued the credential.