Building Perspective with an LLM

I would suggest you don't get Claude to process your json files, but create tools in scripts (eg python) that will do what you want, and enable deterministic repetition at the same time

IMO Gemini is surprisingly good at working with Json files but you also have to approach it appropriately. I use a lengthy detailed GEMs instruction (~10 pages). Then also feed it in an example structure and it's quite good at making edits. I've also used it to create a few thousand line tag structure and one shot it. But as with everything, need to always verify the results.

What the MCP allows me to do is enable a code AI to handle a project that the AI ​​didn't start—for example, a project started by a vendor who has stopped working with my client.

The AI ​​summarizes technical aspects of the "how" in just a few minutes, aspects that would take me several days to figure out.

Furthermore, it allows me to learn much faster, as it has ideas and applies quite sophisticated solutions to problems I'm unable to solve.

It's clear that it's not a direct relation between LLM->Ignition->a lot of money.... by the moment, that much is obvious, but when used correctly and with a clear understanding of what it's doing and how it's doing it, it allows me to develop screens much faster than before.

And regarding the generated code, it's not obfuscated at all; quite the opposite, it's commented, structured, well-organized, and above all, highly reusable across different projects.

But I understand your opinions, and it's true that you can't use LLM for everything, because in the end we'll become stupid and won't know how to do anything ourselves.

Thanks a lot

Carlos

I’ve had pretty good results with this by using SKILL.md files instead of trying to solve everything with one giant prompt.

Fo those that dont know a skill.md is a small context file that teaches the agent how a specific thing works.

For my setup, I built a Web Dev API in Ignition 8.1+ so the agent could interact with the gateway instead of guessing. Then I had a loop where one agent would write tests, another would improve the skill, and another would add API routes when the agent needed a new way to inspect or validate something.

So this created a feedback loop.

The agent would try something, run it against the gateway, check logs/screenshots/API responses, figure out which assumption was wrong, update the skill, and try again.

That helped a lot with things like:

  • not inventing fake system.* functions
  • not writing Python 3 when the gateway needs Jython
  • learning what valid Perspective JSON actually looks like
  • learning module-provided scripting functions instead of guessing them
  • testing assumptions before treating them as rules

I used the same approach for Perspective pages, Jython scripts, SQL helpers, UDT import/export, creating importable perspective zip files, MQTT module scripting functions, expression language, alarms, logs, and a few other areas.

it won’t solve everything. But for 80% use cases it works and as of now i have not had a halluciantion.

For Ignition 8.1+, I had to build the API myself with the Web Dev module. For Ignition 8.3, the built-in API looks like a good starting point, though you may still need extra routes depending on what you want the agent to inspect or validate.

I made a YouTube walkthrough called “Building Perspective Pages in Ignition 8.1 with AI Agents” if you want to see the setup and demo. No link here because I don’t want to trip any filters, but it should come up if you search that title.

Long thread, so I'll try to add something concrete instead of another opinion.

The skepticism up top is mostly correct and I want to start there, because over the last several months I hit every failure mode listed here:

- invented `system.*` calls that don't exist

- Python 3 idioms in scripts that have to run as Jython

- 8.1 answers to 8.3 questions, and the reverse

- Perspective view JSON that is structurally plausible and functionally wrong — `propConfig` in the wrong place, missing `paramDirection` on a parameterized view, embedded views with the wrong component type

- bindings written against a tag path that was true two PLC rebuilds ago

- `[default]` instead of `[PLC]`, which *reads*, just not from the provider you meant

@pturmel's niche point is the root cause of all of it. There isn't enough Ignition in the training data, and the little that's there includes every broken snippet ever pasted into this forum. No amount of prompting fixes that.

What changed things for us was giving up on making the model *know* Ignition, and instead making the environment tell it and then prove it. Two halves.

1. Written knowledge, in one place, that the agent has to read first

We keep a reference vault in the repo — 14 documents, about 6,700 lines: bindings, view JSON wire format, components, tags, scripting, stylesheet/CSS, REST endpoints, OPC-UA, plus a patterns-and-gotchas file that's organized symptom → root cause with a triage table at the top. That one is at 99 entries and it's the one that gets read most.

The rules around it mattered more than the content:

One file per subject, and new findings edit the existing file. No parallel gotcha files, ever. The moment there are two documents that both talk about bindings, the model finds the stale one about a third of the time.

Separate static doctrine from mutable policy. Anything that has ever flipped lives in exactly one living file, and every other document points at it instead of restating it. Concrete example: our null-guard policy has reversed three times — guard everything, then strip the guards because red nulls are useful signal, then guard device templates only. While that rule was written down in three places we got the wrong version regularly. Now the convention doc literally says "whether to guard is set by the living policy, see the brief," and the brief is the only copy.

Version-stamp everything. Directly to @Nol's point about 7.9 vs 8.3 — a doc that doesn't say which version it describes is worse than no doc.

Never bind from memory. Our PLC tag map has been through three shape generations. Anything the model "remembers" about it is wrong. The standing rule is: resolve the path live against the gateway, *then* write the binding. Same for tag existence, data type, and OPC item path.

Harvest at session close. There's a routine pass at the end of a working session that takes whatever went wrong that day and files it into the right vault document. That's the part that makes the vault grow instead of rot, and it's the step I see most people skip.

2. A verification loop it isn't allowed to skip

@Rudy.Ind.Automation's WebDev API + skill files approach is essentially where we landed too. The thing that made ours stick was making verification a program with an exit code rather than something the agent decides it has done:

- deploy — dry run by default, `--apply` to actually copy, with a backup and an abort-before-scan guarantee

- hermetic unit tests that `exec` the *real* gateway script source against a mocked `system` scope, so they catch drift but never touch a gateway, clock, file, or network

- live read-back of tag/OPC values through a WebDev endpoint, strictly read-only

- a headless Chrome screenshot of the actually-rendered page

Exit 0 is green. Exit 1 is a real bug: diagnose, fix, loop, three strikes then stop. Exit 2 is a blocker — expired trial, dead endpoint, auth failure — and the agent is explicitly **not permitted to work around a 2**. It stops and reports to a human.

That last rule killed more bad behavior than anything else in the stack. An agent that can't route around an obstacle has to tell you about the obstacle.

The screenshot step also mattered more than I expected. "The JSON is valid" and "the screen looks right" are completely different claims, and until the agent could see the rendered page it kept confidently shipping the first one and calling it the second.

@nminchin's advice upthread is the right instinct and I'd push it further: anywhere a deterministic tool can do the job, write the tool and take the model out of the path entirely. Push and scan, tag reads, binding coverage checks, screenshots, trial status — all plain Python, all repeatable. The model decides *what* to do and writes the view. Every fact it reasons from comes from a tool.

On review fatigue

@bkarabinchak.psi's post 20 is the objection I take most seriously, and "don't worry, I review everything" isn't an honest answer — the research he's pointing at is right, review quality decays. Our answer is to shrink the surface that needs reviewing:

- One base-path template plus a parameter, instead of N per-device views with hand-wired tags. You review the template once; the instances are mechanical and wrong-or-right as a set.

- Semantic style classes, never inline color. A palette decision is one file, not nine hundred components.

- Small focused faceplates rather than one all-encompassing one. We learned that expensively — ended up with `_Mod`, `_ModV2`, `_ModV3` of the same faceplate before admitting the mega-component was the mistake.

Our last interaction-language pass touched roughly 900 components. I did not review 900 components. I reviewed one pattern, and then walked the live screens.

On safety

@robertm's leaky roof concern is fair, and the answer can't be discipline — it has to be a boundary enforced by the tooling.

The PLC owns interlocks, sequencing, coordination, and restart guards. The HMI sends individual requests: one button, one drive. The AI works on the view and request layer only, and it does not write ladder.

On the controller side, our tooling is read-only at the PLC boundary *by construction*. There is no download command, no online tag write, no controller mode change, no safety signature mutation. Not "we have a policy against that" — those commands do not exist in the tool, so there is nothing to talk an agent out of. Online rung import, where it exists at all, defaults to leaving edits pending and requires a separate explicit approval to accept.

And green tests don't make anything field-ready. Green means it's ready for me to look at in a live session. That gate has never moved.

The other direction

Half of the interesting work has been pointing the same approach at the PLC rather than the HMI, to answer the one question every operator and every maintenance tech actually asks and the HMI has never been able to answer: *why is this not on?*

Not the fifty conditions that are satisfied. The one that isn't.

No LLM anywhere in the trace path, and read-only at the controller, forever. I don't know how much detail I can go into, but it's the part I'm most interested in, and it's the clearest illustration of the split that makes any of this work: use the LLM to build the tool, then let the tool — not the LLM — answer the question.

Where it still doesn't work

- Genuinely novel architecture. It's very good at "build this the way the other forty are built" and mediocre at deciding how the forty-first should have been built in the first place.

- Day one on a new gateway is slow. The entire payoff lives in the accumulated vault, and on day one you don't have one.

- It is **not** faster for a one-off screen. Drag and drop wins, and @bkarabinchak.psi is right about that. It pays off across hundreds of screens and repetitive conversion work — which happens to be exactly the work that's most miserable to do by hand.

- The base model still doesn't know Ignition. Everything above is scaffolding around that fact, not a fix for it.

Happy to get into specifics on any of it.