OT-AIops
OT-AIops is a governed, vendor-neutral industrial OT data tap and AI-powered troubleshooting server that lets AI agents safely read (and in limited cases write) industrial control systems across 14+ field protocols, with a cross-protocol intelligence layer for diagnostics, root-cause analysis, and compliance.
Broad Protocol Connectivity Read tags, registers, coils, and data points from OPC-UA (browse, HDA, alarms), Modbus (holding/input/coils/discrete, byte-order auto-detect, vendor templates), Siemens S7comm (DB/M/I/Q areas), Mitsubishi MC (word/bit devices, CC-Link), Omron FINS (DM/CIO/W/H/A/EM), EtherNet/IP (Logix/SLC/PCCC), EtherCAT (SDO, PDO, slave scan), PROFINET (DCP discovery), MTConnect (current/sample/assets), MQTT/Sparkplug B (full decode, UNS governance), SECS/GEM (SVIDs, ECIDs, alarms, process programs), BACnet/IP (points, trend logs, COV), HART-IP (primary/dynamic variables), and IO-Link (master/device info, ISDU). Also integrates with Ignition Gateway (tag browse/read, alarm status, tag history) and BAS controllers like Metasys/Niagara (point list/read, alarms, trends).
AI-Powered Diagnostics & Root-Cause Analysis
Downtime RCA Copilot: correlates alarms, tag samples, dataflow verdicts, and machine-state series into evidence-cited advisory hypotheses with confidence scores
Live RCA: gathers its own evidence before running the copilot
Downtime Triage: one-call composition of first-out alarm cascade + RCA + PdM precursor forecasts
Diagnose Dataflow: localizes "no data" breaks (network down vs. stale vs. flatline)
ISA-18.2 Alarm Flood Analysis: flood episodes, chattering, standing alarms, suppression advice, rationalization worksheets
Tag Health, Historian Health, Subscription Health, and Heartbeat liveness checks
Predictive Maintenance & Baselines Theil-Sen trend fitting with ETA to warn/alarm limits and RUL estimation; conservative per-tag baseline learning (p1/p99/median/MAD) with sustained-violation detection and operator change segmentation.
OEE & Downtime Analytics Compute OEE (Availability × Performance × Quality) with Six Big Losses breakdown and optional energy/carbon inputs; detect and categorize downtime events; aggregate OEE across machine × part × shift dimensions; changeover/SMED analysis.
Asset & Tag Management Active fingerprinting of all configured endpoints into an asset register; fuse multi-protocol tag feeds into a unified cross-protocol semantic asset model with canonical aliases; adopt/diff alias baselines; bounded change-of-value monitoring.
Data Quality & UNS Governance Fleet data-trust scorecards (staleness, dead heartbeat, bad-quality, flatline, gaps); UNS topic-tree naming conformance, sprawl governance, and Sparkplug schema drift detection (none/additive/breaking).
Historian & Data Export Push telemetry to SQLite, TDengine, or IoTDB; query historical samples and coverage; export to CSV, SQLite, or Parquet; publish collected points or RCA events to NATS message bus (egress-gated); narrate RCA verdicts via a local Ollama LLM for air-gapped environments.
PLC Program Analysis Parse exported ST/AWL/L5X programs to outline structure and call graph, cross-reference symbols with cited source lines, retrieve named block source text, and assess maintainability/risk (documentation coverage, dead code, complexity hotspots, risky constructs).
Compliance & Governance Self-assessment mapping against China's 工控系统防护指南, 等保 2.0 (二级/三级 delta analysis), and IEC 62443; generate deliverable compliance reports and hash-chain verified audit-evidence bundles. All tools operate under strict governance: full audit trail, MOC-gated writes with dry-run and undo support, and a no-egress mode for air-gapped environments.
Industry-Specific Editions Tailored editions available for Fab, Factory, Process, Building, Water, Warehouse, Clinical, Renewables, and PLCnext environments with specialized advisory tools and pre-selected protocol sets.
Reads from and writes to Mitsubishi Electric PLCs via the MC protocol (3E frame). Supports word and bit devices, CPU status, and random reads. Write operations are gated by MOC (Management of Change) with dry-run and undo.
Interacts with MQTT brokers and Sparkplug B payloads. Supports reading topic values, bounded subscriptions, node discovery, and UNS (Unified Namespace) browsing. Publish operations are high-risk and require MOC approval.
Connects to Siemens S7 PLCs (S7-300/400/1200/1500) via RFC1006. Provides CPU info, read/write access to DB, M, I, Q areas. Write operations are high-risk with MOC, dry-run, and undo support.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@OT-AIopsDiagnose dataflow break on OPC-UA tank 101"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Industrial-AIOps
English · 中文
Ask an AI agent why the line stopped — and get an answer that cites its evidence.
A vendor-neutral, read-first data tap for the factory floor. It speaks 14 field protocols, correlates what it reads across them, and hands your agent an evidence-cited verdict instead of a guess. Every call is audited, and no reading ever phones home.
pip install "iaiops[opcua]" # pick your protocol — or [all]
iaiops init # write ~/.iaiops/config.yaml
iaiops doctor # check the setup before you trust itPrefer a container? The published image is cosign-signed and runs non-root. It speaks MCP over stdio, so keep stdin open and mount a volume for the audit store:
cosign verify --key deploy/margo/cosign.pub ghcr.io/industrial-aiops/iaiops:0.27.0-factory
docker run -i --rm -v iaiops-state:/home/iaiops/.iaiops \
ghcr.io/industrial-aiops/iaiops:0.27.0-factoryFor a hardened or air-gapped deployment (read-only rootfs, cap_drop: ALL, no-new-privileges,
optional on-box LLM) use deploy/margo/compose.yaml and
deploy/airgap/. The analysis engine needs no GPU and no model API — it is
deterministic; an LLM is optional and only phrases the verdict.
What you get
Reads | OPC-UA (+ Historical Access, tag auto-discovery) · Modbus TCP/RTU · S7comm · Mitsubishi MC · Omron FINS · MTConnect · MQTT/Sparkplug B · EtherNet/IP · EtherCAT · PROFINET · SECS/GEM · HART-IP · BACnet/IP · IO-Link — plus read-only REST layers for BAS supervisors (Metasys / Niagara) and Ignition Gateway |
Figures out | downtime root cause (the flagship copilot), alarm floods (ISA-18.2), broken dataflows, data trustworthiness, OEE, asset inventory, legacy PLC program explainer (ST/AWL/L5X) |
Governs | audit · budget · risk-tier · undo — on every call, through one engine, from both MCP and CLI |
Stays yours | no telemetry, no phone-home. Six tools can send data off-box by design ( |
Nine per-industry editions ship in this package — fab · factory · process · building · water ·
warehouse · clinical · renewables · plcnext — each adding its own read-only advisory checks.
Substation / utility telecontrol (IEC-104 · DNP3 · IEC-61850) ships separately as
iaiops-energy.
Related MCP server: @inscada/mcp-server
Your first five minutes
Four commands. Only one of them touches a device, and it prints what it will send before it sends anything.
pip install "iaiops[modbus]" # pick the protocol you actually have, or [all]
iaiops onboard status # ← run this first. Contacts NOTHING.
iaiops doctor # config, secrets, reachability — and the version
iaiops readiness # every scenario and what each gap needsonboard status answers the smaller question you have first: which of the six
steps is this site on, and what is the one command that advances it? The six
were always there and nothing stated the order. It is derived from your store and
config.yaml every time, so there is no onboarding state to go stale — edit
config.yaml by hand and the answer stays true.
readiness reads your config and local store and answers one question: which
scenarios can this site run today, and what does each gap need? Every gap comes
with the command that closes it, ranked by how much it unlocks. No agent, no
cloud, no account, and nothing on the wire.
Then the path, in the order that matters — survey what is there, take a bounded sample, and only then explain it:
contacts a device? | ||
Survey |
| preview sends nothing; the run itemises every packet class it sent |
Configure |
| no — it reads the stored scan, and writes nothing |
Tap |
| yes — and it reports what it saw and what it missed |
Declare |
| no — the |
Explain |
| no — all over collected history |
See the whole thing run against a real device in about two minutes, including
a genuine mid-run outage, with ./demo/oee-line/run_demo.sh — no hardware, no
configuration, nothing written outside a temporary directory.
demo/oee-line/ explains what each step is for and what the
numbers do and do not claim.
Why read-first
OT is exactly where you want an agent on a tight leash. The read paths are the product; the few write paths are OT-dangerous, off by default, and gated by MOC discipline — dry-run, one-shot approval, undo capture, hash-chained audit.
Proving the analysis needs no model
The analysis layers cannot reach a language model. That is a guard, not a slogan:
tests/test_brain_is_llm_free.py scans eight packages — brain, discovery, runtime,
readiness, collect, knowledge, retain, connectors — for any import that could reach one,
and an empty result is the guarantee. A model is used in exactly two places, and neither is
load-bearing: rca_narrate rephrases a verdict that was already computed and already cited, and an
agent front-end decides which tool to call. Remove both and the numbers are the same numbers.
That guard is static — it proves nothing can call a model. For a validation team the sentence they are asked to accept is the executed one, so it is executed:
iaiops verify determinism --out determinism-record.jsonA pinned in-repo dataset goes through availability, production counts, the Six Big Losses,
ISA-18.2 alarm load, control charts, the conservative baseline and the RCA copilot. Each result is
canonically encoded and digested; the suite runs twice in this process and once in each of two
fresh interpreters started at different PYTHONHASHSEED values — the arm that catches a set or
dict iteration order reaching a result, which a single run never can. The socket API raises
throughout, so a computation that reached for a device or a hostname fails here instead of quietly
working on a machine that happened to be online. Afterwards the run is asked what it pulled in:
a model library that was already loaded (an MCP server holds iaiops.core.llm for the opt-in
narration tool) is recorded, not judged — only what the suite itself imported can condemn it.
The record separates result (identical every run — the part to sign) from context (when and
where this run happened). Two good runs are not byte-identical records, and someone will diff
them, so the halves are named rather than mixed.
This is the form the claim has to take to be usable: not "our model is accurate", which is not
evidence in a GxP context, but a test case someone can write into an IQ/OQ protocol — remove the
model, block the network, re-run the standard dataset, compare the hash — execute, and sign.
verify_determinism is the same check from the MCP side; iaiops verify suite lists what it
covers without running it.
How far it's actually been verified
Short version: verified against real protocol libraries, containers and in-process servers — not yet against real plant gear. We grade evidence rather than saying "tested", because a real container round-trip and a synthetic fixture are not the same claim.
Rung | What it means | Status |
Real libraries / containers / in-process servers | OPC-UA (incl. cert | ✅ |
Mock-verified (protocol logic exercised, no real device) | Omron FINS, IO-Link, BAS (Metasys / Niagara), Ignition Gateway, EtherNet/IP PCCC, Sparkplug B, S7 / MC / SECS-GEM | ⚠️ |
Real gear | physical RS-485 devices, EtherCAT slaves, live HART gateways, live HVAC / BAS / Ignition, real PLCs | zero, for every protocol |
Per-protocol evidence — including what each test does not cover — is in
docs/VERIFICATION-RECORD.md, one row per protocol, naming the test
behind each claim. Every 待核实 is hardware-gated, not forgotten — each one names the equipment that would settle it.
🧪 测试与共创 / Beta testing & co-creation
我们在找现场测试伙伴。 软件里能验证的我们都验证了(真实 in-process 服务器、真实协议库、Docker 容器 loopback)——剩下的 待核实 清单只有真设备能回答:物理 Modbus-RTU(RS-485)、EtherCAT 从站、HART 网关、在线 BACnet 楼宇设备、在线 Metasys/Niagara BAS 控制器、在线 Ignition 网关、国产 PLC(汇川/信捷)、真机 PLCnext、真实变电站 RTU/IED、欧姆龙 FINS 真机、IO-Link 主站。如果你是 OT 工程师、系统集成商或工厂团队,手上有任何这类设备:装上 iaiops,对你的设备跑一遍 iaiops doctor,把结果告诉我们。经你验证的设备会署名写进支持矩阵;现场反馈的问题我们优先分诊;功能可以通过 GitHub Issues/Discussions 直接共创。
We're looking for field-testing partners. Everything software-verifiable has been verified; what's left on the honest 待核实 list only real equipment can answer — physical Modbus-RTU (RS-485), EtherCAT slaves, HART gateways, live BACnet HVAC, live Metasys/Niagara BAS controllers, live Ignition gateway, domestic PLCs (Inovance/Xinje), live PLCnext, substation RTUs/IEDs, live Omron FINS PLCs, IO-Link masters. If you're an OT engineer, integrator, or factory team with access to any of these: install iaiops, run iaiops doctor against your gear, and tell us what happened. Verified-equipment reports get credited in the support matrix, field-reported issues get fast triage, and features are co-designed in the open via GitHub Issues/Discussions.
👉 参与入口 | Start here: open an issue with the protocol and device model in the title, or email zhouwei008@gmail.com. Either reaches a person, and a report gets answered against the current release.
Consolidated capability matrix
Protocol | Tool | Operation | R/W | risk_tier | Returns (key fields) |
OPC-UA |
| server status | R | low | state, product_name, namespaces |
OPC-UA |
| browse node tree | R | low | [{node_id, browse_name, depth}] |
OPC-UA |
| read one node | R | low | value, datatype, source_timestamp, good |
OPC-UA |
| batch read | R | low | [{node_id, value, ...}] |
OPC-UA |
| bounded sample | R | low | {collected, samples[]} |
OPC-UA |
| alarm surfacing | R | low | {active_alarms[], active_count} |
OPC-UA |
| Historical Access (HDA) | R | low | {supported, count, values[]} |
OPC-UA |
| connection triage | R | low | {verdict, checks[]} |
OPC-UA |
| tag auto-discovery → semantic asset model | R | low | {tag_count, assets[], naming_report} |
OPC-UA |
| threshold classify (was | R | low | {overall, counts, offenders[]} |
OPC-UA |
| stddev outliers (was | R | low | {mean, stddev, outliers[]} |
Modbus |
| FC03 | R | low | {raw_registers, decoded[]} |
Modbus |
| FC04 | R | low | {raw_registers, decoded[]} |
Modbus |
| FC01 | R | low | {bits[]} |
Modbus |
| FC02 | R | low | {bits[]} |
Modbus |
| byte/word-order auto-detect | R | low | {best_order, candidates[]} |
Modbus |
| vendor register templates | R | low | {templates[]} |
Modbus |
| decode block via template | R | low | {values:{name: engineering_value}} |
Modbus |
| threshold classify | R | low | {overall, counts, offenders[]} |
S7comm |
| CPU id + run/stop | R | low | {cpu_status, cpu_info} |
S7comm |
| read DB/M/I/Q | R | low | {items:[{address, value}]} |
S7comm |
| read data block | R | low | {items:[{address, value}]} |
S7comm |
| batch addresses | R | low | {items:[{address, value}]} |
S7comm |
| write data block | W | high/MOC | {before, written, _undo_id} |
Mitsubishi MC |
| CPU type | R | low | {cpu_type, cpu_code} |
Mitsubishi MC |
| word devices | R | low | {words[]} |
Mitsubishi MC |
| bit devices | R | low | {bits[]} |
Mitsubishi MC |
| random read | R | low | {words[], dwords[]} |
Mitsubishi MC |
| write words | W | high/MOC | {before, written, _undo_id} |
Omron FINS |
| controller data read (0501) | R | low | {controller_model, controller_version} |
Omron FINS |
| controller status (0601) | R | low | {run_mode, status} |
Omron FINS |
| memory-area word read (DM/CIO/W/H/A/EM) | R | low | {words[]} |
Omron FINS |
| memory-area bit read | R | low | {bits[]} |
Omron FINS |
| batch reads | R | low | {items[]} |
Omron FINS |
| memory-area write | W | high/MOC | {before, written, _undo_id} |
MTConnect |
| device model | R | low | {devices:[{components:[{data_items}]}]} |
MTConnect |
| latest values | R | low | {observations[]} |
MTConnect |
| bounded stream | R | low | {observations[]} |
MTConnect |
| assets | R | low | {assets[]} |
MTConnect |
| OEE inputs | R | low | {availability, execution, verdict} |
MQTT/Sparkplug |
| bounded read | R | low | {messages:[{topic, payload}]} |
MQTT/Sparkplug |
| bounded SpB sample (full decode) | R | low | {samples:[{sparkplug, payload:{metrics[]}}], seq_gap_count} |
MQTT/Sparkplug |
| decode raw SpB payload | R | low | {metrics:[{name, alias, datatype, value, is_historical}]} |
MQTT/Sparkplug |
| node discovery + state | R | low | {nodes:[{group_id, edge_node_id, online, devices}], primary_hosts[]} |
MQTT/Sparkplug |
| topic-tree browse | R | low | {topics[], tree{}} |
MQTT/Sparkplug |
| UNS naming + sprawl governance | R | low | {verdict, sprawl_findings, findings{casing_collisions[], scattered_leaves[], …}} |
MQTT/Sparkplug |
| Sparkplug schema-drift (baseline vs current) | R | low | {verdict (none/additive/breaking), node_changes[]} |
MQTT/Sparkplug |
| live UNS audit (bounded broker sample) | R | low | {verdict, findings{}} |
MQTT/Sparkplug |
| live NBIRTH schema snapshot | R | low | {nodes[], metrics[]} |
MQTT/Sparkplug |
| live drift vs stored baseline | R | low | {verdict, node_changes[]} |
MQTT/Sparkplug |
| publish/command | W | high/MOC | {published_bytes, applied} |
EtherNet/IP |
| Logix controller id | R | low | {controller:{vendor, product_name, revision, serial}} |
EtherNet/IP |
| tag discovery | R | low | {tag_count, tags:[{name, data_type, structure}]} |
EtherNet/IP |
| read one tag/array | R | low | {tag, value, type, good} |
EtherNet/IP |
| batch read | R | low | {items:[{tag, value, type}]} |
EtherNet/IP |
| write tag | W | high/MOC | {before, written, _undo_id} |
Diagnostics |
| localize no-data | R | low | {verdict, diagnosis, hops[]} |
Diagnostics |
| ISA-18.2 flood | R | low | {flood_verdict, top_offenders[]} |
Diagnostics |
| offender ranking | R | low | {overall, offenders[]} |
Diagnostics |
| gap/flatline | R | low | {verdict, gaps[]} |
Diagnostics |
| sequenced-feed loss/reorder/overload | R | low | {verdict, missed_count, overloaded_channels[]} |
Diagnostics |
| AI downtime RCA copilot (cited, advisory) | R | low | {verdict, primary_cause, hypotheses:[{cause, confidence, evidence[]}]} |
Diagnostics |
| RCA copilot that gathers its own live evidence | R | low | {…downtime_root_cause…, collected_evidence} |
Diagnostics |
| learn per-site RCA cause weights from labeled incidents | R | low | {cause_weights{}, rationale} |
Diagnostics |
| fleet data-trust rollup | R | low | {fleet_score, fleet_status, issue_breakdown, worst_tags[], endpoints[]} |
Diagnostics |
| cross-endpoint fleet view | R | low | {fleet_score, endpoints[]} |
Diagnostics |
| heartbeat/watchdog liveness | R | low | {alive, distinct_transitions, longest_stall_s, reason} |
Alarm (ISA-18.2) |
| flood episodes / chattering / stale / summary | R | low | {episodes[], chattering[], stale[], summary{}} |
Alarm (ISA-18.2) |
| CSV-exportable rationalization rows | R | low | {rows[], csv_path?} |
Baseline |
| conservative change-log baseline (refuses thin history) | R | low | {band{p1,p99,median,mad} | insufficient_data} |
Baseline |
| silent-by-default violation check | R | low | {status, violations[] (cited)} |
Baseline |
| record operator change (restarts learning) | R | low | {recorded, change_point} |
Baseline |
| no_baseline / learning / ok / violation | R | low | {status, window} |
Historian |
| read history back out of sqlite/TDengine/IoTDB | R | low | {rows[], truncated} |
Historian |
| per-tag row counts + first/last ts | R | low | {tags:[{tag, rows, first, last}]} |
PLC program |
| structure of exported ST/AWL/L5X program | R | low | {blocks[], call_graph, timers[]} |
PLC program |
| symbol/address cross-reference (cited lines) | R | low | {sites:[{kind, source_file, line, quote}]} |
PLC program |
| one named block's source (≤200 lines) | R | low | {text, source_file} |
Export |
| export local store → CSV/SQLite/Parquet | R | low | {path, row_count, preview[]} |
Analytics |
| OEE = A×P×Q | R | low | {availability, performance, quality, oee, oee_pct} |
Analytics |
| stoppage detect + categorize | R | low | {event_count, total_downtime_s, by_category, events[]} |
Analytics |
| OEE machine×part×shift | R | low | {matrix[], worst_performers[], mean_oee} |
Analytics |
| active fingerprint | R | low | {assets:[{protocol, vendor, model, firmware, reachable}]} |
Analytics |
| merge discovered tags into one asset model | R | low | {assets[], tag_count} |
Analytics |
| tag alias-map adopt/diff | R | low | {aliases{}, changes[]} |
Analytics |
| bounded change-of-value | R | low | {change_count, changes:[{value, previous, wall_clock}]} |
EtherCAT |
| master/WKC + slave count | R | low | {master_state, expected_working_counter, slaves_found, slaves_expected} |
EtherCAT |
| bus scan | R | low | {slave_count, slaves:[{index, name, vendor_id, product_code, state}]} |
EtherCAT |
| slave detail | R | low | {sync_managers[], fmmus[], object_dictionary[], input_bytes} |
EtherCAT |
| CoE SDO upload | R | low | {index, byte_length, hex, as_uint} |
EtherCAT |
| input PDO snapshot | R | low | {working_counter, input_hex, input_byte_length} |
EtherCAT |
| CoE SDO download | W | high/MOC | {before, written, applied} |
EtherCAT |
| AL-state transition | W | high/MOC | {before, requested, reached, applied} |
PROFINET |
| DCP IdentifyAll (segment-wide) | R | low | {station_count, stations:[{name_of_station, mac, ip, vendor_id, device_roles[]}]} |
PROFINET |
| identify by name-of-station | R | low | {found, name_of_station, mac, ip, device_family} |
PROFINET |
| targeted DCP Get (by MAC) | R | low | {found, name_of_station, ip, netmask, gateway} |
PROFINET |
| DCP asset register | R | low | {asset_count, io_controller_count, assets[]} |
PROFINET |
| DCP Set (station name / IP suite) | W | high/MOC | {before, applied, _undo_id} |
SECS/GEM |
| GEM link + identity (S1F1/F2) | R | low | {communication_state, are_you_there} |
SECS/GEM |
| SVID namelist (S1F11/F12) | R | low | {count, status_variables[]} |
SECS/GEM |
| SVID values (S1F3/F4) | R | low | {svids, values[]} |
SECS/GEM |
| ECID namelist (S2F29/F30) | R | low | {count, equipment_constants[]} |
SECS/GEM |
| ECID values (S2F13/F14) | R | low | {ecids, values[]} |
SECS/GEM |
| alarm list (S5F5/F6) | R | low | {count, alarms[]} |
SECS/GEM |
| PPID directory (S7F19/F20) | R | low | {count, process_programs[]} |
BACnet (building) |
| Who-Is device discovery | R | low | {device_count, devices:[{device_id, address}]} |
BACnet (building) |
| a device's objects | R | low | {object_count, objects:[{object_type, instance}]} |
BACnet (building) |
| one object property | R | low | {object_type, instance, property, value} |
BACnet (building) |
| all present-values (HVAC snapshot) | R | low | {point_count, points:[{object_type, instance, present_value}]} |
BACnet (building) |
| bounded COV capture (always unsubscribes) | R | low | {notifications[], terminated_reason} |
BACnet (building) |
| TrendLog readRange (bounded) | R | low | {records:[{timestamp, value}]} |
BACnet (building) |
| present-value write (priority) | W | high/MOC | {before, written, _undo_id} |
HART-IP (process) |
| cmd 0 identity | R | low | {manufacturer, device_type, revision} |
HART-IP (process) |
| cmd 1 PV | R | low | {value, unit} |
HART-IP (process) |
| cmd 3 PV/SV/TV/QV + loop current | R | low | {variables[], loop_current} |
HART-IP (process) |
| bounded burst-variable sampling | R | low | {samples[]} |
IO-Link |
| master identity | R | low | {vendor, product, serial} |
IO-Link |
| ≤32-port sweep (mode/status/device id) | R | low | {ports[]} |
IO-Link |
| per-port device identity | R | low | {vendor_id, device_id, product_name} |
IO-Link |
| process-data-in (raw hex + bytes) | R | low | {hex, bytes[]} |
IO-Link |
| ISDU acyclic parameter read | R | low | {index, subindex, value} |
IO-Link |
| master + all connected devices | R | low | {master{}, devices[]} |
BAS (Metasys/Niagara) |
| supervisory point directory | R | low | {point_count, points:[{id, name, type}]} |
BAS (Metasys/Niagara) |
| read one supervisory point | R | low | {point, value, unit, status} |
BAS (Metasys/Niagara) |
| active controller alarms | R | low | {alarm_count, alarms:[{id, priority, state}]} |
BAS (Metasys/Niagara) |
| trend/history samples (bounded) | R | low | {records:[{timestamp, value}]} |
BAS (Metasys/Niagara) |
| supervisory command (default-OFF; life-safety object denylist refuses fire/smoke/egress/pressurization before any I/O) | W | high/MOC | {before, written, _undo_id} |
Ignition |
| Gateway + module health | R | low | {state, version, modules:[{name, state}]} |
Ignition |
| tag-tree browse | R | low | {tags[], tree{}} |
Ignition |
| current tag values | R | low | {values:[{path, value, quality, timestamp}]} |
Ignition |
| active alarms | R | low | {alarm_count, alarms:[{path, priority, state}]} |
Ignition |
| tag-history query (bounded) | R | low | {rows:[{path, timestamp, value}]} |
信创 / compliance |
| 《工控网络安全防护指南》↔ iaiops | R | low | {pillars[], status_summary, controls:[{pillar, status, gap}]} |
信创 / compliance |
| 等保 2.0 + IEC 62443 FR1–6 crosswalk | R | low | {controls:[{crosswalk}]} |
信创 / compliance |
| 等保 二级 baseline vs 三级 增量 | R | low | {pillars:[{l2, l3_delta, status}]} |
信创 / compliance |
| deliverable compliance report (md/html) | R | low | {markdown | out_path} |
信创 / compliance |
| audit-evidence zip (hash-chain verified) | R | low | {bundle_path, manifest} |
信创 / historian |
| push telemetry to sqlite/TDengine/IoTDB | R(→historian) | low | {sink, received, written, skipped_non_numeric} |
Self |
| capability map | R | low | {protocols[], diagnostics[], analytics[]} |
(The energy protocols — IEC-104 / DNP3 / IEC-61850 — moved to iaiops-energy in 0.8.0; their tool matrix lives in that repo.)
196 governed tools = 183 read + 10 MOC-gated device writes + historian_push (a write, to a historian rather than to a device: [WRITE][risk=low]) + the 2 deprecated aliases below. The device writes are (s7_write_db, mc_write_words, fins_write_words, mqtt_publish, eip_write_tag, ethercat_write_sdo, ethercat_set_state, profinet_dcp_set, bacnet_write_property, bas_command). The read side now includes two vendor-REST read-only layers above the field protocols — a BAS controller layer (Metasys/Niagara, building edition) and an Ignition Gateway MES/SCADA layer (factory edition). ¹ The 2 deprecated aliases are the two deprecated brain aliases health_summary / anomaly_scan, renamed to opcua_health_summary / opcua_anomaly_scan in 0.10.0 — the deprecated aliases are still registered and will be removed in a future release (target: 1.0.0). Read-only per-edition tools load ONLY under their edition (see per-edition tool modules below), so a bare protocol / single-edition surface is smaller than this line-wide total. The table above is representative, not exhaustive; run protocols_supported() (or iaiops protocols) for the live map.
Per-protocol reference
OPC-UA
Versions/variants: binary
opc.tcp://viaasyncua(sync facade). Security: anonymous + username/password, plus application-certificate message security (Sign / SignAndEncrypt) — setclient_cert+client_key(+ optionalserver_cert) and the client opens a signed/encrypted secure channel (no cert ⇒ the anonymous / username path is unchanged). Validated end-to-end against an in-process asyncua server (tests/test_opcua_security.py) for Basic256Sha256 in both Sign and SignAndEncrypt modes:server_certpinning and client-side server-cert auto-discovery are exercised, and the test asserts the negotiated policy URI + message-security mode on the live encrypted channel (plus a negative test that anonymous is refused by a secure-only server).Connection params:
endpoint_url,username(password encrypted),security_mode,security_policy; for cert securityclient_cert/client_key/ optionalserver_cert(PEM or DER paths; aliasescertfile/keyfile).Alarms & Conditions:
opcua_alarm_events— bounded event subscription +ConditionRefresh, events carry the server's own timestamps (verified against an in-process asyncua server; third-party A&C servers待核实). Untimed fallback:opcua_read_alarmsbrowses alarm-like boolean nodes.Not supported / planned (
待核实): cert-security interop with third-party / vendor servers (KEPServerEX / Prosys / Siemens / real PLCs), the other policies (Aes128Sha256RsaOaep / Aes256Sha256RsaPss / Basic128Rsa15 / Basic256), strict server-side certificate-trust enforcement, and cert-based user identity (X509 identity token, distinct from channel security).
Modbus-TCP / Modbus-RTU
Versions/variants: Modbus-TCP and Modbus-RTU (serial RS-485/232) via
pymodbus(+pyserial). Read function codes FC01 (coils), FC02 (discrete), FC03 (holding), FC04 (input). Write FCs (FC05/06/15/16) = not implemented (read-only).Connection params: TCP —
host,port(502),unit_id. RTU —transport: rtu,serial_port(e.g./dev/ttyUSB0),baudrate,unit_id. Registers are untyped 16-bit words →decodehint (uint16/int16/uint32/int32/float32/raw);modbus_detect_byte_orderauto-detects the byte/word order (AB/BA · ABCD/DCBA/BADC/CDAB) from hint values — pure logic, no extra device load.Vendor register templates (
modbus_list_templates/modbus_apply_template): named register maps decoding a block into engineering values — energy meters (Eastron SDM630, Schneider PM5xxx, Carlo Gavazzi EM24), PV inverters (Huawei SUN2000, Growatt), Phoenix PLCnext process data, and water-industry templates (E+H Promag, Hach SC controller, generic dosing pump). Each template carries an explicit待核实caveat — no invented "verified" addresses.Coverage: many domestic 国产 PLCs (汇川 Inovance / 信捷 Xinje / 和利时 Hollysys / 台达 Delta) and any Modbus vendor. RTU framing is live-verified over a real serial link (socat PTY + pymodbus RTU server); specific physical RS-485 devices stay
待核实.
S7comm (Siemens + 仿西门子 国产)
Versions/variants:
pyS7(pure-Python, ISO-on-TCP / RFC1006 — no nativelibsnap7). S7-300/400/1200/1500 and compatible clones. Memory areas DB / M (merker) / I / Q. No protocol auth (CPU gates via "Permit access with PUT/GET").Connection params:
host,port(102),rack,slot(0/1 for 1200/1500; 0/2 common for 300/400).Write:
s7_write_db= high risk_tier, MOC, dry-run default, captures BEFORE value + undo.Not supported / planned: optimized/symbolic DB access on 1500 with "optimized block access" can require absolute-addressing config on the CPU.
Mitsubishi MC
Versions/variants:
pymcprotocol— MC 3E frame (binary) only. 1E / 4E frames = not supported. PLC types Q / L / QnA / iQ-R / iQ-L. Devices: D/W/R (word), M/X/Y/B (bit).Connection params:
host,port(5007 default; set to the module's open MC port),plctype.Write:
mc_write_words= high/MOC/dry-run default, captures BEFORE + undo.
Omron FINS (CS/CJ/CP/NX-via-FINS)
Versions/variants: in-repo, stdlib-only FINS client (no third-party dependency — the
iaiops[fins]extra pins nothing): 10-byte FINS header framing, FINS/UDP (default port 9600) and FINS/TCP (node-address handshake per Omron W342), SID matching, bounded response parsing, end-code table per W227/W342. Commands: 0101 memory-area read (words/bits over DM/CIO/W/H/A/EM), 0102 write, 0501 controller data read, 0601 controller status.Connection params:
host,port(9600),transport(udpdefault /tcp), FINS network/node/unit addressing.Write:
fins_write_words= high/MOC/dry-run default, captures BEFORE + undo; CLI double-confirm on--apply.Validation: verified against an in-repo mock FINS UDP/TCP responder (
tests/test_fins.py); live Omron PLC behaviour and banked-EM access stay待核实.
IO-Link (master JSON integration — read-only)
Versions/variants: sensor-level visibility via the IO-Link master's HTTP/JSON interface (IO-Link consortium "JSON Integration"), both dialects selectable per endpoint via
flavor:—iotcore(ifm IoT-Core POST envelope, default) andrest(plain-REST GET, Balluff/Turck-style). Reads: master identity, bounded ≤32-port sweep, per-port device identity, process-data-in (raw hex + bytes), ISDU acyclic parameter read. NO write tools. Bounded/size-capped HTTP (256 KiB response cap), schema-checked JSON with teaching errors. Reuses the MTConnect HTTP pin (iaiops[iolink]→requests).Connection params: master
host/URL,flavor,timeout_s.protocol: iolink.Validation: in-process mock master in both flavors (
tests/test_iolink.py); live master datapoint paths stay待核实.
HART-IP (process instrumentation — read-only)
Versions/variants: HART universal commands over HART-IP UDP (default, port 5094) or TCP (
transport: tcp, length-delimited framing) via an in-tree transport; the HART command codec is verified vshart-protocol. Tools:hart_device_identity(cmd 0),hart_primary_variable(cmd 1),hart_dynamic_variables(cmd 3, PV/SV/TV/QV + loop current),hart_burst_sample(bounded sampling of burst-published variables). No write / device-specific commands exposed (OT-dangerous on live instruments).Connection params:
host(HART-IP server/gateway),port(5094),transport(udp default / tcp).Validation: TCP transport loopback-verified (in-process HART-IP server, real long-frame ACK through the real codec path); live gateway behaviour and a true unsolicited burst subscription stay
待核实.
MTConnect (ALL CNC machine tools)
Versions/variants: agent REST + XML (
requests+xml.etree), namespace-agnostic (parses MTConnect 1.x Devices/Streams/Assets schemas). Endpoints:/probe,/current,/sample,/assets. Read-only by specification. XML parsing is hardened (DTD/entity declarations rejected — XXE/billion-laughs defense).Connection params:
agent_url(e.g.http://host:5000).Not supported / planned: MTConnect streaming (long-poll
interval=); only boundedcount=samples.
MQTT / Sparkplug B / UNS
Versions/variants:
paho-mqtt— MQTT 3.1.1 & 5. Sparkplug B topic conventionspBv1.0/{group}/{type}/{edge}/[device](NBIRTH/DBIRTH/NDATA/DDATA/NDEATH/DDEATH/STATE). TLS + username/password supported.Full Sparkplug B decode (no optional extra): payloads are protobuf-decoded with a vendored, byte-for-byte copy of the official Eclipse Tahu
sparkplug_b.protogenerated module (depends only onprotobuf). Per metric you get name, alias (resolved to its name via the BIRTH model), datatype (Int8…Int64/UInt…/Float/Double/Boolean/String/DateTime/Text/UUID/DataSet/Bytes/File/Template/PropertySet…), value, timestamp, and theis_historical/is_nullflags. A birth/death + seq model tracks node/device online state (NBIRTH/DBIRTH ↔ NDEATH/DDEATH), builds the alias→name map from BIRTH, applies NDATA/DDATA by alias, and flagsseqgaps / out-of-order. Primary-host awareness:STATE/<host_id>topics surface insparkplug_node_list.sparkplug_decode_payloaddecodes a single raw payload (base64/hex) offline.Connection params:
host/broker,port(1883 / 8883 TLS),topic,use_tls,username(password encrypted).Command:
mqtt_publish= high/MOC/dry-run default. A transient publish has no automatic inverse (delivered is delivered); a retained one overwrites durable broker state, so it captures the prior retained payload and records an inverse.
EtherNet/IP (Rockwell / Allen-Bradley)
Supported: ControlLogix / CompactLogix (and GuardLogix) via CIP / EtherNet-IP using
pycomm3(pure-Python — no native deps). Tag-based, symbolic access: read/write tags by name (Conveyor.Speed,Array[3],Program:Main.X) and discover the controller's tag list at runtime (eip_list_tags, the headline feature).eip_controller_inforeads the controller identity.Connection params:
host,slot(0 for CompactLogix; the CPU slot for a ControlLogix chassis),port(44818).protocol: ethernetip(aliaseip).Write:
eip_write_tag= high risk_tier, MOC, dry-run default, captures BEFORE value + undo.Not supported / planned: PLC-5 / SLC-500 (PCCC) and Micro800 are not supported = roadmap (Logix tag model only).
EtherCAT (pysoem / SOEM fieldbus master)
Supported: a real EtherCAT master via
pysoem(the Python binding for the SOEM C stack). CoE SDO read (ethercat_read_sdo, acyclic mailbox upload) + SDO write (ethercat_write_sdo, download), input PDO read (ethercat_read_pdo, one bounded cyclic snapshot), bus scan / slave enumeration (ethercat_slaves,ethercat_slave_info— identity, SM/FMMU mapping, object-dictionary summary), master/working-counter state (ethercat_master_state), and AL-state transitions INIT↔PREOP↔SAFEOP↔OP (ethercat_set_state).HARD REQUIREMENTS (no way around them): Linux, root or
CAP_NET_RAW, a dedicated NIC cabled to the bus, and real EtherCAT slave hardware.pysoemis an OPTIONAL extra:pip install iaiops[ethercat]— the base package installs and imports without it, and every EtherCAT tool then degrades to a teaching error (never crashes, never imports pysoem at module load).NOT supported: no software simulator exists (unlike OPC-UA / Modbus) — EtherCAT is hardware-only and not testable in mock-only CI; macOS is unsupported. EoE / FoE / SoE mailbox protocols and full PDO-mapping decode/expansion = roadmap.
Connection params:
nic(the dedicated interface name, e.g.eth1; aliasinterface), optionalexpected_slaves(a sanity check vs the bus scan).protocol: ethercat.Operations matrix:
Tool
Op
R/W
risk
Capture/notes
ethercat_master_statemaster + WKC state, slave count
R
low
expected vs found
ethercat_slavesbus scan / enumerate
R
low
index/vendor/product/rev/addr/AL-state
ethercat_slave_infoone-slave detail
R
low
SM/FMMU + OD summary
ethercat_read_sdoCoE SDO upload
R
low
hex + uint interpretation
ethercat_read_pdoinput PDO snapshot
R
low
single cycle, never loops
ethercat_write_sdoCoE SDO download
W
high/MOC
before-value (SDO read-back) + undo
ethercat_set_stateAL-state transition
W
high/MOC
before-state + undo; can start/stop motion
Write/state safety:
ethercat_write_sdo(hex little-endian bytes) andethercat_set_stateare high risk_tier, MOC, dry-run by default, capture the BEFORE value/state for undo, and need a CLI double-confirm. Changing EtherCAT state can START or STOP machine motion — treat with extreme care. 未经授权勿对生产控制系统写入.
PROFINET (DCP discovery / identify + gated DCP Set)
Supported: layer-2 PROFINET-DCP via
pnio-dcp—profinet_discover(DCP IdentifyAll: one broadcast surfaces every station on the segment — name-of-station, MAC, IP, vendor/device id, role — closer to passive discovery than a per-device fingerprint),profinet_identify_station(by name-of-station),profinet_station_params(targeted DCP Get by MAC → name + IP suite), andprofinet_asset_inventory(a register with IO-controller vs IO-device role decoding).Write:
profinet_dcp_setre-addresses one station (name-of-station and/or IP suite, by MAC) — high risk_tier, MOC, dry-run default, captures the BEFORE addressing + undo descriptor. Re-addressing a live station can disrupt its IO connection.Scope (deliberate): no RT cyclic process data (that needs an IO-controller/IO-device stack and hard real-time — out of scope and unsafe to tap); the blink / factory-reset DCP services stay unexposed.
HARD REQUIREMENTS: raw-socket access (root / admin /
CAP_NET_RAW) on the NIC on the PROFINET subnet.pnio-dcpis an OPTIONAL extra:pip install iaiops[profinet]— the base package installs/imports without it, and every tool then degrades to a teaching error.Connection params:
host— THIS machine's IP on the PROFINET subnet (the DCP broadcast goes out on it).protocol: profinet.Preview caveat: validated against a mocked
pnio-dcpDCP — not verified against live PROFINET devices yet.
Energy edition (electrical substation / utility telecontrol) → iaiops-energy
The energy vertical — IEC 60870-5-104 / DNP3 / IEC 61850 MMS read-only monitoring for substation RTUs/IEDs — moved to its own package in 0.8.0: iaiops-energy (pip install iaiops-energy), built on iaiops.core (shared governance / brain / runtime). Its protocol reference, support matrix, and validation status live in that repo.
Building edition (facility / HVAC / 厂务)
The building vertical adds BACnet/IP (ASHRAE 135) — the dominant building-automation protocol for HVAC, lighting, metering, and facility plant. Install with pip install iaiops[building] and expose with IAIOPS_MCP=building (bundle: bacnet + modbus + opcua + iolink).
BACnet/IP (
BAC0over bacpypes3):bacnet_discover(Who-Is device discovery),bacnet_object_list(a device's objects),bacnet_read_property(one object property),bacnet_read_points(present-value of all analog/binary/multistate points — the HVAC snapshot),bacnet_cov_subscribe(bounded change-of-value capture — capped by count AND wall-clock, always unsubscribes),bacnet_read_trend_log(TrendLog buffered records via one bounded readRange). Config:host= THIS machine's BACnet/IP interface (iporip/mask) /port(47808).Write:
bacnet_write_property(present-value at a BACnet priority 1..16, or relinquish) = high risk_tier, MOC, dry-run default, BEFORE-value read-back + undo. Overriding a live building-control point can move real HVAC/plant.Validation: the read path is verified against a real bacpypes3 virtual BACnet/IP device through the actual async BAC0 stack (
tests/test_bacnet_live.py); COV / trend-log / writes on live HVAC gear stay待核实.
Water treatment edition (水处理)
IAIOPS_MCP=water (or iaiops-mcp-water, pip install iaiops[water]) exposes modbus + opcua + hart + the brain — the protocol set waterworks / wastewater plants actually run. Adds water-domain tag semantics (溶解氧 DO / ORP / 余氯 chlorine / 氨氮 ammonia / TSS/MLSS / 跨膜压差 TMP / UV / 加药 dosing / 曝气 aeration) and water-industry Modbus templates (E+H Promag, Hach SC controller, generic dosing pump — all with explicit 待核实 caveats).
Warehouse / intralogistics edition (仓储 / 物料搬运)
IAIOPS_MCP=warehouse (or iaiops-mcp-warehouse, pip install iaiops[warehouse]) exposes eip + profinet + modbus + opcua + sparkplug + the brain — conveyor & sorter drives over EtherNet/IP (Rockwell) and Profinet (Siemens), VFD / energy meters over Modbus (conveyor_vfd / agv_battery templates), WMS/WCS gateways over OPC-UA, and AMR/IoT telemetry over MQTT-Sparkplug. Edition tools (read-only, advisory): line_bottleneck (Theory-of-Constraints throughput bottleneck across stations) + sortation_health. PdM (pdm_forecast), downtime_triage and OEE are reused as-is.
Clinical-facility edition (医疗设施)
IAIOPS_MCP=clinical (or iaiops-mcp-clinical, pip install iaiops[clinical]) exposes bacnet + modbus + opcua + the brain — hospital facilities as a distinct patient-safety vertical over the building brain. Edition tools (read-only, advisory): isolation_room_check (负压/正压 isolation-room pressurization), medical_gas_check (medical-gas alarm-panel safety), or_environment_check (OR temperature / humidity / pressure envelope). BACnet BMS + Modbus gas-alarm panels + OPC-UA plant SCADA.
Pharmaceutical-manufacturing edition (制药)
IAIOPS_MCP=pharma (or iaiops-mcp-pharma, pip install iaiops[pharma]) exposes bacnet + modbus + hart + opcua + the brain. No new protocol — that is the point: no field protocol is specific to pharma. Cleanrooms run BACnet, purified-water systems run Modbus and HART, filling and lyophilization run S7, DCS and bioreactors run OPC-UA, and all of it was already here. What pharma needed was semantics: the water edition's indicators are municipal (DO, ORP, chlorine, turbidity) and the clinical edition grades one room's pressure, where Annex 1 inspects the cascade.
Edition tools (read-only, advisory): cleanroom_pressure_cascade (EU GMP Annex 1, door by door — adjacency is declared, never inferred from a room list), cleanroom_particle_check, pharma_water_check (USP <645> stage-1 procedure: the non-temperature-compensated reading, the measured temperature rounded down to the tabulated step, and exceeding stage 1 reported as proceed to Stage 2 rather than as a failure).
No compendial limit tables are shipped. The particle limits, the stage-1 conductivity table and the TOC limit belong to the site's qualified specification at its compendial revision. A transcription nobody in this repository can verify would end up deciding whether a batch environment passed — and the error that hurts is the flattering one, since a limit set too loose reads as "in specification". Limits are passed in and cited back; anything not declared is reported no_limit / not_graded and named, never counted as passing. Known gaps are listed in the edition's skill: no PI historian connector, S7 without hardware verification, no GxP (Annex 11 / Part 11) crosswalk yet, and LIMS / QMS deliberately out of scope — they run REST and databases, not field protocols.
Renewables edition (光伏 / 风电)
IAIOPS_MCP=renewables (or iaiops-mcp-renewables, pip install iaiops[renewables]) exposes modbus + opcua + sparkplug + the brain — PV inverters (SUN2000 / Growatt templates) + wind-turbine controllers over Modbus, OPC-UA plant SCADA, and MQTT-Sparkplug telemetry. Edition tool (read-only, advisory): pv_performance (PV string performance vs expectation). Device-level monitoring + PdM via baseline / RCA.
PLCnext packaging edition (Phoenix Contact vPLC)
IAIOPS_MCP=plcnext (or iaiops-mcp-plcnext, pip install iaiops[plcnext]) exposes opcua + modbus + the brain — the Phoenix Contact PLCnext virtualized PLC reached over its built-in OPC-UA server (opc.tcp 4840, Arp.Plc.Eclr address space) + Modbus-TCP process-data server; no new connector. Route-verified in-process; live PLCnext hardware reads stay 待核实 (see How far it's actually been verified).
信创 / China entry (offline · 国产 TSDB · compliance)
For 自主可控 / 信创 deployments — see docs/CHINA.md for the full guide.
Air-gapped install: pure-Python core + per-protocol optional extras → install from a local wheelhouse with
pip install --no-index --find-links ./wheelhouse "iaiops[...]"; secrets stay local (encrypted store), no cloud KMS.National TSDB historian sink (
historian_push, CLIiaiops historian push): write collected telemetry to TDengine (iaiops[tdengine]) or Apache IoTDB (iaiops[iotdb]) — domestic, controllable; we don't build our own store or bind InfluxDB. Data egress to the operator's own historian, not a control write.Compliance mapping (
compliance_mapping, CLIiaiops compliance): an honest 《工控系统网络安全防护指南》 ↔ iaiops self-assessment across 分区隔离 / 可审计 / 双向认证 / 最小权限 / 数据保护 / 自主可控, with per-control status (addressed / partial / 待核实) and the named gap.国产 PLC: 汇川 / 台达 / 信捷 over the existing Modbus-TCP / S7 connectors.
⚠️ 待核实: 国产 OS (麒麟/统信) · 芯 (鲲鹏/海光) · PLC validation and the TSDB write paths are documented but not yet hardware-verified — see the validation matrix in docs/CHINA.md.
OEE / downtime analytics (cross-protocol, read-only)
oee_compute— OEE = Availability × Performance × Quality from production inputs (planned time, run time, ideal cycle, total/good counts). Each factor is reported raw + clamped to [0,1]; acappedperformance >1.0 flags an optimistic ideal cycle.downtime_events— auto-detects running→stopped transitions in a{timestamp, state}series and produces stoppage events with durations, categorized (changeover / material / mechanical / quality / break / unknown, by keyword heuristics or a{state: category}override).oee_multidim— aggregates OEE across machine × part × shift (or any dimensions) from labelled records → the matrix + worst performers.Operate over provided/collected inputs (fully testable without a plant).
mtconnect_oee_snapshotsurfaces the live MTConnect availability/execution inputs that feed these.
Active asset inventory / fingerprint (read-only)
asset_inventory— for each configured (or named) endpoint, actively connects with our own protocol client and reads its identity call (S7s7_cpu_info, EtherNet/IPeip_controller_info, OPC-UA server build info, Modbus Device Identification FC43/0x2B, Mitsubishi CPU type, MTConnect device model), aggregating vendor / model / firmware / serial / reachable / last_seen into an asset register.Honest scope (IEC 62443-flavored): this is ACTIVE fingerprinting via our client connections, NOT passive SPAN/tap discovery — it only finds devices we are configured to reach and adds light load to each. Passive, traffic-mirroring discovery is roadmap.
OPC-UA Historical Access (HDA)
opcua_read_history— reads stored historical values for a node over a[start,end]ISO-8601 window via the server's HistoryRead service (asyncuaread_raw_history), bounded bymax_points(≤2000). Returns{supported:false, note}gracefully when the server does not historize the node (no crash). Read-only.
Change-of-value (CoV) monitor
monitor_changes— bounded deadband report: polls a point and returns only the value CHANGES (with timestamps), not every sample. Works over OPC-UA / Modbus / S7 / Mitsubishi MC / EtherNet-IP. Never an infinite loop — hard-capped by bothduration_s(≤120) andmax_changes(≤500). Read-only.
Cross-protocol brain — 0.9/0.10 additions (all read-only)
Conservative baseline learning (
baseline_learn/check/record_change/status, CLIiaiops baseline …) — a change-log baseline, explicitly NOT black-box anomaly detection: robust p1/p99 + median/MAD band over the local history, refuses thin history (<100 samples or <24h) with an explicitinsufficient_dataverdict, restarts at recorded operator changes, and is **silent by default** — a violation needs >3×MAD beyond the band AND ≥3 consecutive samples, and every violation cites its baseline window and offending samples.Historian READ integration (
historian_query/historian_coverage, CLIiaiops historian query|coverage) — query history back out of the sqlite/TDengine/IoTDB sinks; an optional per-sitehistorian:config block lets the RCA copilot pull the 2h pre-incident window as one more cited evidence class (strictly additive — without the config, RCA output is byte-identical, test-proven).Legacy PLC program explainer (
plc_program_outline/xref/section, CLIiaiops program …) — structural extraction over exported program files (Siemens SCL/ST.scl/.st, AWL/STL.awl, Rockwell Studio 5000.L5X— never a live PLC upload); every element carriessource_file+ line (rung for L5X) so the explaining agent must cite real locations. XXE-hardened, ≤5 MB, extension allowlist.ISA-18.2 alarm flood deep-dive (
alarm_flood_analysis/alarm_rationalization_worksheet, CLIiaiops diag alarm-flood|alarm-worksheet) — flood episodes (≥10 alarms/10 min), chattering, stale/standing (>24h), percent-time-in-flood vs target, and a CSV-exportable rationalization worksheet; over injected events or a live OPC-UA active-condition scan.Open-format export + metrics bridge —
iaiops export csv|sqlite|parquet(from the local SQLite sink; Parquet viaiaiops[export]) / MCPexport_data;iaiops metrics serve --port 9184exposes Prometheus/metrics(latest tag values + counters, binds 127.0.0.1 by default) — Grafana recipe indocs/GRAFANA.md.Compliance deliverables —
iaiops compliance report(等保 2.0 L2/L3 status + IEC 62443 FR1–6 crosswalk + honest gap list, md/html) andiaiops compliance evidence(audit-evidence zip with hash-chain verification + manifest); MCPcompliance_report/compliance_evidence_bundle. Onboarding aids, 非认证.
Cross-protocol brain & editions — 0.11/0.12 additions (all read-only)
Downtime triage copilot (
downtime_triage) — composes alarm cascade + RCA verdict + PdM precursors into one triage and cross-checks whether the first-out alarm agrees with the diagnosed cause; advisory, cite-first (builds on the earlieralarm_cascadefirst-out reconstruction andpdm_forecasttime-to-threshold early-warning).Legacy-PLC maintainability (
plc_program_visibility) — a risk/maintainability read over an exported ST/AWL/L5X program (size, block count, xref density, undocumented sections), never a live upload — pairs with theplc_program_outline/xref/sectionexplainer.Per-edition tool modules (
EDITION_MODULESinmcp_server/profiles.py) — a named edition can carry its own@mcp.toolgroup that loads only when that edition is selected — never for a bare protocol key and never in the always-on brain, so edition-specific tools stay off other surfaces and don't inflate the base. Every edition tool is read-only, cite-first, advisory:warehouse —
line_bottleneck(Theory-of-Constraints throughput bottleneck) +sortation_healthclinical —
isolation_room_check(负压隔离病房 pressurization) +medical_gas_check+or_environment_checkbuilding —
economizer_check(AHU economizer FDD) +zone_comfortprocess —
control_loop_health(PID oscillation/offset/saturation) +heat_exchanger_foulingfab —
spc_check(SPC control-chart rules) +defect_paretofactory —
changeover_analysis(SMED)water —
disinfection_ct+water_quality_compliancerenewables —
pv_performance(PV string performance)
Agent skills — the repo ships a router skill (
skills/iaiops) plus ten per-edition skills (iaiops-fab/iaiops-factory/iaiops-process/iaiops-building/iaiops-water/iaiops-warehouse/iaiops-clinical/iaiops-pharma/iaiops-renewables/iaiops-plcnext) that route an agent to the right MCP server and document the tool surface.
Deployment & ecosystem fit (edge-native / Margo)
iaiops is designed to ride on a hardened, centrally-managed edge host as a portable, governed edge application — not to own the host or the fleet manager. It maps naturally onto the Margo edge-interoperability roles: the host/device is the immutable edge OS, a compliant orchestrator places workloads by desired-state, and iaiops is the OT-domain application — read-first tap + cross-protocol RCA, exposed as governed MCP tools, with an optional on-box LLM brain for a fully air-gapped diagnostic path (data never leaves the plant).
Honest status: iaiops is a natural Margo edge application but is NOT Margo-compliant yet — a container image + application description + a published conformance-toolkit result are roadmap
⏳(see docs/MARGO-ALIGNMENT.md anddocs/ROADMAP.md). No material claims Margo-compliant until that test result exists.
A container + application-description skeleton lives in deploy/margo/
(hardened Dockerfile · compose · 待核实-marked app descriptor); per-host distribution overlays
that reuse it live under deploy/ (one folder per candidate edge host).
Install
Protocol client libraries are optional extras — install only the 1–2 protocols a site actually runs (every protocol library is imported lazily; the base package installs and imports without any of them, and a call to a not-installed protocol returns a teaching error pointing at the right extra):
uv tool install "iaiops[opcua,modbus]" # just the protocols you need
# or one per site: pip install "iaiops[s7]" · everything: pip install "iaiops[all]"
# or a per-industry edition bundle: pip install "iaiops[fab]"
iaiops init # interactive: add endpoints, store passwords encrypted
iaiops doctor # config + per-protocol connectivity probe (point at simulators)
iaiops protocols # the capability mapProtocol extras: opcua · modbus · s7 · mc · fins (stdlib — pins nothing) · eip · mtconnect · sparkplug · secsgem · ethercat · profinet · bacnet · hart · iolink · bas (BAS supervisory REST — reuses the mtconnect HTTP pin) · ignition (Ignition Gateway read layer — reuses the mtconnect HTTP pin) · plus tdengine · iotdb · influxdb (historian sinks) · nats (stream egress) · ollama (on-box LLM narration) · export (Parquet) · all (every pip-installable connector).
Adapter belt (
docs/ADAPTERS.md): iaiops is a small neutral core (ingress → normalize/govern/RCA → egress) with pluggable, lazily-imported adapters — bind no store/bus/host/model, install only what a site runs. The RCA core is deterministic + cited, not a black box (docs/RCA.md); footprint is small by design (docs/FOOTPRINT.md).
Edition bundles (match the same-named IAIOPS_MCP profiles — install the protocols a vertical runs):
fab (secsgem + opcua + s7 + modbus) · factory (the discrete-manufacturing set: opcua + modbus + s7 + mc + fins + eip + mtconnect + sparkplug + ethercat + profinet + iolink + ignition) · process (opcua + modbus + hart) · building (bacnet + modbus + opcua + iolink + bas) · water (modbus + opcua + hart) · warehouse (仓储/物料搬运: eip + profinet + modbus + opcua + sparkplug) · clinical (医疗设施: bacnet + modbus + opcua) · renewables (光伏/风电: modbus + opcua + sparkplug — PV inverters (SUN2000/Growatt) + wind turbines + plant SCADA; device-level monitoring + PdM via baseline/RCA) · plcnext (opcua + modbus). The grid/substation energy bundle (IEC-104/DNP3/61850) ships in iaiops-energy.
Master password
Secrets (per-endpoint passwords, MQTT credentials) are never stored in plaintext — they live in ~/.iaiops/secrets.enc (Fernet + scrypt). Export IAIOPS_MASTER_PASSWORD so the MCP server/CLI can unlock non-interactively:
export IAIOPS_MASTER_PASSWORD='…'Example ~/.iaiops/config.yaml (one block per protocol)
endpoints:
- name: line1
protocol: opcua
endpoint_url: opc.tcp://plc.lan:4840
# username: operator # password stored encrypted via init/secret set
tags:
- { ref: "ns=2;i=5", label: temp, warn_high: 70, alarm_high: 90 }
- name: plc2
protocol: modbus
host: 10.0.0.5
port: 502
unit_id: 1
- name: press1
protocol: s7
host: 10.0.0.6
rack: 0
slot: 1 # S7-1200/1500
- name: cell3
protocol: mc
host: 10.0.0.7
port: 5007
plctype: iQ-R
- name: meter1
protocol: modbus # Modbus-RTU (serial): set transport + serial_port
transport: rtu
serial_port: /dev/ttyUSB0
baudrate: 9600
unit_id: 1
- name: omron1
protocol: fins # Omron FINS (UDP default; transport: tcp for FINS/TCP)
host: 10.0.0.11
port: 9600
- name: xmtr1
protocol: hart # HART-IP gateway (read-only; udp default / transport: tcp)
host: 10.0.0.20
- name: iolm1
protocol: iolink # IO-Link master JSON integration (read-only)
host: 10.0.0.21
flavor: iotcore # ifm IoT-Core (default) | rest (Balluff/Turck-style)
- name: vmc1
protocol: mtconnect
agent_url: http://10.0.0.8:5000
- name: uns
protocol: mqtt
host: broker.lan
use_tls: true # → port 8883
topic: spBv1.0/#
# username: edge1 # password stored encrypted
- name: cell5
protocol: ethernetip # alias: eip
host: 10.0.0.9
slot: 0 # 0 for CompactLogix; CPU slot for ControlLogix
- name: bus1
protocol: ethercat # Linux + root/CAP_NET_RAW + pip install iaiops[ethercat]
nic: eth1 # dedicated NIC cabled to the EtherCAT bus
expected_slaves: 8 # optional sanity check vs the bus scaniaiops init walkthrough (per protocol)
$ iaiops init
Step 1 — master password: ********
Step 2 — add an endpoint
Endpoint name (e.g. line1): press1
Protocol ('opcua','modbus','s7','mc','mtconnect','mqtt') [opcua]: s7
S7 PLC host (IP/FQDN): 10.0.0.6
Port [102]: 102
Rack (0 for S7-1200/1500) [0]: 0
Slot (1 for S7-1200/1500, 2 for S7-300/400) [1]: 1
✓ Saved endpoint 'press1'.(MQTT prompts add TLS/topic/username; MTConnect prompts for agent_url; EtherCAT prompts for the nic + expected_slaves and warns about the Linux/root/NIC/optional-extra requirement; OPC-UA/MQTT prompt for a hidden password stored encrypted.)
Test against a simulator (per protocol)
OPC-UA — an
asyncuademo server (the test suite runs a real in-process one).Modbus — ModbusPal or a
pymodbusserver simulator.S7 — a pyS7/snap7 S7 server sim (Snap7 server) on
:102.MTConnect — the public MTConnect demo agent, or a local agent.
MQTT — a local
mosquittobroker (+ a Sparkplug edge for SpB topics).Mitsubishi MC — GX Simulator / an MC 3E server sim.
EtherNet/IP — a pycomm3-compatible CIP/Logix simulator (or a spare CompactLogix).
Omron FINS — the in-repo mock FINS UDP/TCP responder (
tests/test_fins.py) or a spare CP/CJ PLC.IO-Link — the in-process mock master (
tests/test_iolink.py, both JSON dialects) or any ifm/Balluff/Turck master on the bench.EtherCAT — no simulator exists (hard-real-time, raw-Ethernet). Validate only on Linux, as root / with
CAP_NET_RAW, on a dedicated NIC wired to real slaves (e.g. a Beckhoff EK1100 coupler + EL terminals).iaiops doctorreports a clear "needs Linux/root/NIC/pysoem" status off the bus rather than failing.
Usage
Site survey — find what is on a network you have not been given a list for
Every other command needs an endpoint you already configured. scan answers the
question that comes first. It has no full-port mode, no raw sockets, no
half-open SYNs, and no write path of any kind; what it may touch is a fixed
industrial port allowlist, and how fast is capped by a ceiling the caller cannot
raise.
iaiops scan profiles # what each posture does
iaiops scan plan --targets 10.0.0.0/24 # sends NOTHING — the artifact you get signed
iaiops scan run --targets 10.0.0.0/24 --site "Line 1" \
--approved-by "J. Controls" --ticket CHG-91 \
--report survey.html # scan → store → one HTML file
iaiops scan list # stored surveys
iaiops scan report --out survey.html # re-render the latestscan plan puts nothing on the wire. It prints every host and port that
would be touched, every class of packet that would be sent, the worst-case
duration, and the explicit list of what this tool never does — so you can run it
against a network before you have permission to scan it, and hand the output to
whoever grants that permission. scan run shows the same preview and asks once
before it sends anything (--yes to skip).
Postures run from passive (reads the local ARP cache, emits nothing at all) to
legacy-safe (reachability only, one host at a time, five connects a second —
for 1990s controllers where even a well-formed identify request is a risk).
standard and deep refuse to run without a recorded sign-off.
The HTML report is self-contained: no fonts, scripts, styles or images from anywhere, and no network request when opened. Its first section is what the scan touched — per-class emission counts, including requests that failed — followed by the list of things it never does. The device table comes after that.
From a survey to a measured OEE — the path the site actually walks
scan answers what is out there. These answer what can I do with it, and what
is the number. Each step is a real command; nothing here is a roadmap item.
iaiops readiness # contacts NOTHINGWhat this installation can run today, and for each thing it cannot, the specific input that is missing — ranked by how much supplying it would unlock. It touches no device, so you can run it against a site you have not been authorised to probe, which is the site that most needs the answer. It reports gaps; it never fills one in (§9.4/D16 — a guessed production counter yields a plausible-looking OEE, which is worse than an error).
iaiops collect plan line1 --duration 7d --interval-ms 1000 # contacts NOTHING
iaiops collect run line1 --duration 7d --interval-ms 1000
iaiops collect run line1 --duration 7d --resume # after a closed lid
iaiops store status # what the store holds
iaiops store prune --sealed-before 2026-08-01 --apply # refuses without a sealA bounded assessment run — capped at 14 days, and the operator must state the end. There is deliberately no run-forever mode: a resident process on an OT network needs change management, a laptop running for a week does not (D21). Every run records the windows it could not see, so a gap is never silently readable as a stoppage.
To get an OEE out of it, three tags have to be declared — which value means running, which register counts parts, and (for Quality) which counts good ones:
endpoints:
- name: line1
ideal_cycle_time_s: 0.1
tags:
- {ref: "0", role: run_state, running_when: [2]} # 2 = running
- {ref: "10", role: total_count}
- {ref: "11", role: good_count}running_when is declared, never inferred. On the 0=stopped 1=idle 2=running 3=fault status word most PLCs expose, "any non-zero means running"
counts three states of four as production.
iaiops oee measure line1 --reported 97 # against the figure the site keeps
iaiops oee measure line1 --since 2026-03-02T06:00:00Z --until 2026-03-09T06:00:00Z
iaiops oee measure line1 --report oee.html --lang zh --site "一号厂区"Scope the measurement with --since / --until, together. Without them the
period is everything the store holds for that endpoint — fine for one assessment
run, wrong the moment there are two: the idle weeks between a March run and an
August one become one enormous blind span and neither run can be measured.
The window is charged for in full. The parts of it that were never sampled — before the first sample and after the last — count as blind exactly like a gap in the middle, so narrowing the question to the minutes that happen to have data cannot raise your coverage. Ask about a shift you observed two hours of, and the answer is 25% coverage and a refusal, not "100% of what we saw".
Availability measured over the time the collector could see, with blind windows excluded rather than counted as downtime; plus Performance, Quality and the Six Big Losses. Each factor is reported only when its inputs were declared — a partial OEE that names what is missing beats a whole one with a guess inside it.
--report writes one self-contained HTML file — no fonts, scripts, styles or
images from anywhere, and no network request when opened, so it works on an
air-gapped laptop and survives being forwarded as an attachment. Its first
section is what the measurement could see (coverage, blind time, sample cadence),
before the number, and it carries the row a sales deck usually leaves out: what
had to be declared to produce each figure, and what is still missing.
iaiops case open line1 --min-stop-s 300 # one case per long stoppage
iaiops case list # each carries what someone DID after it
iaiops case causes # the vocabulary a confirmation may use
iaiops case confirm <id> --cause material_starvation --by wei
iaiops case agreement # >90% agreement is a WARNING, not a score
iaiops diag learn-weights --site default # learn a per-site cause profile
iaiops diag rca --input bundle.json --from-case <id> # a person's answer reaches the verdictThe label is a by-product of work already being done: the audit trail already recorded that someone ran a write four minutes after the line stopped, so the case shows it. Confirmation is one choice from a fixed vocabulary, never free text, and a dismissal is a label too. Whether an answer counts as independent is derived from whether the tool had suggested it — the answerer cannot claim it.
The investigation itself — eight steps, and what each one needs
readiness answers which scenarios this site can run. This answers the next
question down: if something stopped tomorrow, how far could we actually get?
iaiops investigate plan # contacts NOTHINGEight evidence steps — define the incident, collect the evidence, normalize and check it, compress and rank, correlate the timeline, test the hypotheses, check against known mechanisms, conclude and close. For each one it cannot walk, it says whether that is something you have not supplied (with the command that would) or something this product cannot express at all. Those two send a person to very different places.
iaiops investigate open line1 --start <iso> --end <iso> --asset "Line 1"
iaiops investigate show <id> # the state it was left in
iaiops investigate listThe same eight steps over a real past window, persisted so it can be re-read and advanced later. No device is contacted — the window is already over, and its evidence is whatever was collected at the time.
Any of the three writes the forwardable version — one self-contained HTML file that opens on an air-gapped laptop in a plant office:
iaiops investigate plan --report readiness.html --lang zh
iaiops investigate open line1 --start <iso> --end <iso> --report incident.htmlUnlike oee measure --report, which refuses to write a file for a refused
measurement, this one writes for a blocked investigation on purpose. An OEE
report is a number, so a file existing at all claims one was measured. This
report's content is how far this got and what each step still needs — which
makes the blocked case the one most worth handing over, and for a site nobody has
instrumented yet it is the whole deliverable. What it will not do is let a
blocked investigation look finished: the headline is always the walk (2 / 8),
never a conclusion, and no step's own words appear above it.
From a scan to a config
Everything on the path existed; nothing joined it. A site could scan forty devices and then retype all forty by hand, and nothing anywhere said which of the six commands came next.
iaiops onboard status # where am I, and what is the ONE next command
iaiops onboard draft # the newest scan → config.yaml endpoints
iaiops onboard draft --out draft.yaml # ...to a file you can review and mergedraft writes nothing into config.yaml — you merge it, exactly as with
tags apply. What it emits is constrained on purpose:
Only CONFIRMED protocols become endpoints. An open 502 means something is listening, not that it is a Modbus device, and a config that said so would be believed. Those hosts are listed as skipped, with the reason.
Every value names the observation that justifies it — and the interesting half is what the scan learned that you would otherwise have hunted for: the S7 slot the CPU actually answered on, the MELSEC CPU's own
plctype, whether an OPC-UA server advertises an unsecured endpoint or will need credentials.A field the scan could not settle goes out commented, saying what it is waiting for — never omitted. Omission lets the protocol default apply in silence, which is how a Modbus gateway gets read at unit 1 and shows a confident number for the wrong machine.
tags:comes out empty. A scan finds devices; it establishes nothing about what their data means. That step is the next one, below.Absence is not evidence. The draft states what it structurally cannot contain — BACnet/FINS/HART are UDP and never swept; MQTT and the supervisory layers are never identified, by design.
status is derived from the store and config.yaml every time. There is no
onboarding state file, so a hand-edited config or a restored backup still gets a
true answer rather than a remembered one — and a step that is genuinely done
stays done even if you did the steps out of order.
For the point-list step it names the command for your protocol: opcua browse, eip tags, mtconnect probe, iolink ports, mqtt browse, bacnet objects, ethercat slaves, hart dynamic, or modbus templates. Where there
genuinely is nothing to ask — an S7 CPU exposes no symbol table on the wire, and
MELSEC and Omron memory carry none either — it says so in that protocol's own
terms and tells you where the addresses do come from, rather than one sentence
covering everything that is not OPC-UA.
Confirming what the point list means
The one thing this product refuses to infer, and until now the only way to supply
it was hand-editing role: in a config file — which is exactly what stops working
at a hundred rows.
iaiops tags export sheet.csv # every monitored tag; `role` column EMPTY
# a person fills in role + running_when
iaiops tags apply sheet.csv --by wei # prints the exact config.yaml editThe role column comes out empty even next to a tag called
GoodPartsCounter. A name is not a declaration; plenty of plants have one that
counts something else, and a wrong production counter yields a plausible OEE —
worse than an error (D16).
apply emits the patch rather than writing it. config.yaml stays the single
source of truth: oee measure reads roles off the config tag objects, so a
parallel store would let readiness call the mapping met while oee measure
still could not run. A run_state with no running_when is refused here, for
the same reason MonitorTag refuses it — "anything non-zero" counts idle and
fault as production.
Or tick it through in a page instead of a spreadsheet:
iaiops tags page confirm.html --lang zhHLD §13.9's App front end, delivered as a file rather than a served app. A
localhost server inside an OT box has to answer which address it binds and who
authenticates — and since every declaration here requires --by, a page with no
identity cannot record who confirmed a tag, which is the one thing this step
exists to capture. So the page collects, and the author is supplied at apply.
The page re-implements no refusal. run_state needing running_when, a ref
having to be monitored, a role claimed twice — reproducing any of those in
JavaScript is how they drift from the ones that actually gate the config, and a
page that says "looks fine" while apply refuses is worse than no page. It ships
script (it is a form) but makes no network request: it works with the cable
out.
There is deliberately no MCP tool for this. An agent filling in the role column is precisely the guess D16 exists to forbid.
Two of the steps need something a person has to state:
iaiops relations declare press oven --by wei # which asset feeds which
iaiops relations downstream press # nearest firstThe second axis of root-cause analysis. With time alone, an upstream stoppage produces a string of equally-confident downstream false causes — on a line, downstream co-occurrence is guaranteed whatever the cause. That guarantee is why this is declared and not inferred (D25). Without it the timeline still runs; it degrades to a single asset and says so.
iaiops knowledge mount mechanisms.yaml --by wei # what is known about this equipment
iaiops knowledge check sensor_fault --protocol modbusA fault-mechanism library, shaped by ISO 14224: the failure mode (what you saw), the mechanism (what to go and check) and the cause (what to fix) stay separate, because they answer different questions. Entries attach to the seven taxonomy causes; they never add new ones — past roughly forty codes, two operators stop picking the same one.
It may exclude and never confirm. A mechanism that cannot apply to this equipment rules the candidate out, which is the strong move a ranker cannot make:
✗ sensor_fault — excluded
every mounted mechanism for 'sensor_fault' applies only to hart, opcua — not to modbusAnd a cause the library has never heard of reports nothing known — never "no objection". A knowledge base that knows nothing about something has not cleared it.
Program change baseline — has the approved logic moved?
A control program is a controlled document, and the usual way an undocumented change to one gets noticed is that somebody remembers. Record the version you consider approved, then ask a later export whether anything moved:
iaiops program snapshot ~/exports/Line3.scl --name Line3 --label "approved v3.2 / MOC-118"
iaiops program drift ~/exports/Line3_today.scl --name Line3The snapshot stores the file's SHA-256 plus a per-block structural fingerprint — name/kind/language, declared variables, calls, branch conditions, timers — and deliberately excludes line numbers, comments and block order, so adding one comment at the top of a file does not report the whole program as changed. What is stored on disk is block names, hashes and counts; never a declaration, a source line or a comment, so the baseline store is not a second copy of your program.
Three verdicts, and each word is load-bearing:
Verdict | Means |
| The same SHA-256. Nothing else earns the word. |
| The extracted structure differs — reported per block, naming which of |
| The bytes differ and every block fingerprint matched. |
That third one is the honest one. It is usually comments or formatting — but these parsers extract structure, they do not parse a grammar, so a real change inside a construct they do not model looks identical from here. Calling it "documentation only" would be the comfortable reading of evidence that does not support it, so it is not called that: line and comment counts are reported beside it and the verdict still says look. A drift report is a reason to read the diff, never a clearance.
iaiops program history lists what is tracked; iaiops program compare <name> <before> <after>
diffs two stored snapshots. Deleting history is iaiops program forget and is CLI-only — an
agent should not be one call away from removing change-control evidence. Nothing is pruned
automatically. The name (not the path) is the identity, because the export directory changes every
time somebody opens the engineering station and the program does not; absent --name the file stem
is used and the output says so. No device is touched at any point — this reads a file a person
exported.
CLI (read)
iaiops opcua read "ns=2;i=5" -e line1
iaiops modbus holding 0 -e plc2 --count 4 --decode float32
iaiops s7 read-db 1 REAL 4 -e press1 --count 2
iaiops mc words D100 -e cell3 --count 8
iaiops fins words 100 --area DM -e omron1 --count 8 # Omron FINS memory-area read
iaiops hart pv -e xmtr1 # HART primary variable
iaiops iolink scan -e iolm1 # IO-Link master + connected devices
iaiops mtconnect oee -e vmc1
iaiops mqtt nodes -e uns --timeout-s 15
iaiops eip tags -e cell5 # Logix tag discovery
iaiops eip read "Conveyor.Speed" -e cell5
iaiops ethercat slaves -e bus1 # EtherCAT bus scan (Linux+root)
iaiops ethercat read-sdo 0 4120 --subindex 1 -e bus1 # CoE SDO 0x1018:1
iaiops opcua history "ns=2;i=5" -e line1 --start 2026-06-28T08:00:00Z # HDA
iaiops opcua monitor "ns=2;i=5" -e line1 --duration-s 20 --deadband 0.5 # CoV
iaiops diag dataflow -e line1 --ref "ns=2;i=5" --freshness-s 30
iaiops analytics oee 28800 25200 2.0 12000 11800 # OEE from five numbers you already have
# (for a measured one, see `oee measure` above)
iaiops analytics asset -e press1 -e cell5 # active asset registerCLI (write — dry-run by default, double-confirm on --apply)
iaiops s7 write-db 1 INT 0 42 -e press1 # dry-run preview
iaiops s7 write-db 1 INT 0 42 -e press1 --apply # double-confirm prompt
iaiops mqtt publish factory/line1/cmd '{"setpoint":50}' -e uns --apply
iaiops eip write-tag Setpoint 42 -e cell5 --apply # Logix tag write (double-confirm)
iaiops fins write-words 100 42 --area DM -e omron1 --apply # Omron FINS write (double-confirm)
iaiops ethercat write-sdo 0 24698 e8030000 -e bus1 --apply # CoE SDO 0x607A download
iaiops ethercat set-state PREOP --slave 0 -e bus1 --apply # AL-state (can stop motion!)MCP tool calls (JSON args → sample structured return)
s7_read_db:
{ "db": 1, "dtype": "REAL", "start": 4, "endpoint": "press1", "count": 2 }{ "endpoint": "press1", "area": "DB", "db": 1, "dtype": "REAL", "start": 4,
"count": 2, "items": [ {"address": "DB1,REAL4", "value": 20.5},
{"address": "DB1,REAL8", "value": 4.2} ] }s7_write_db (dry-run):
{ "db": 1, "dtype": "INT", "start": 0, "value": 42, "endpoint": "press1" }{ "address": "DB1,INT0", "dry_run": true, "before": 7, "would_write": 42,
"note": "Dry run — nothing written. Re-run with dry_run=false AND a recorded approver…" }mtconnect_oee_snapshot:
{ "availability": "AVAILABLE", "execution": "ACTIVE", "controller_mode": "AUTOMATIC",
"program": "O1234", "available": true, "running": true, "verdict": "running" }eip_read_tag:
{ "tag": "Conveyor.Speed", "endpoint": "cell5" }{ "endpoint": "cell5", "tag": "Conveyor.Speed", "value": 1500.0, "type": "REAL",
"error": "", "good": true }eip_write_tag (dry-run):
{ "tag": "Setpoint", "value": 42, "endpoint": "cell5" }{ "endpoint": "cell5", "tag": "Setpoint", "dry_run": true, "before": 7,
"would_write": 42, "note": "Dry run — nothing written. Re-run with dry_run=false AND a recorded approver…" }ethercat_read_sdo (CoE SDO upload):
{ "slave": 0, "index": 4120, "subindex": 1, "endpoint": "bus1" }{ "endpoint": "bus1", "slave": 0, "index": "0x1018", "subindex": 1,
"byte_length": 4, "hex": "9a020000", "as_uint": 666 }ethercat_set_state (dry-run; can start/stop motion):
{ "state": "OP", "slave": 0, "endpoint": "bus1" }{ "endpoint": "bus1", "scope": "slave[0]", "dry_run": true, "before": "SAFEOP",
"would_request": "OP", "note": "Dry run — no state change. … Changing EtherCAT state can start/stop machine motion." }sparkplug_decode_payload (full SpB metric decode):
{ "payload": "CAESBwoDYWJjEAE=", "encoding": "base64" }{ "encoding": "sparkplug_b", "seq": 0, "metric_count": 2, "historical_count": 0,
"metrics": [ {"name": "Temperature", "alias": 1, "datatype": "Double", "value": 21.5,
"is_historical": false, "is_null": false} ] }oee_compute:
{ "planned_time_s": 28800, "run_time_s": 25200, "ideal_cycle_time_s": 2.0,
"total_count": 12000, "good_count": 11800 }{ "availability": {"raw": 0.875, "value": 0.875, "capped": false},
"performance": {"value": 0.952381}, "quality": {"value": 0.983333},
"oee": 0.819444, "oee_pct": 81.94 }asset_inventory (active fingerprint):
{ "endpoints": ["press1", "cell5"] }{ "asset_count": 2, "reachable_count": 2, "method": "active_fingerprint",
"assets": [ {"endpoint": "press1", "protocol": "s7", "vendor": "Siemens/compatible",
"model": "CPU 1511-1 PN", "firmware": "2.8", "reachable": true,
"last_seen": "2026-06-28T10:00:00+00:00"} ] }Diagnostics (multi-dimensional JSON for an agent to visualize)
diagnose_dataflow(endpoint="line1", ref="ns=2;i=5", freshness_threshold_s=30):
{ "verdict": "comms_ok_value_stale",
"diagnosis": "Connected with good status, but the value is STALE (age 412s > 30s) — the source/field upstream has stopped updating this point.",
"recommended_action": "Trace upstream: the device serves the last value fine, so suspect the source/scanner/field signal that should refresh it.",
"hops": [ {"hop":"connect","protocol":"opcua","ok":true,"detail":"OPC-UA state=0"},
{"hop":"read_tag","ref":"ns=2;i=5","ok":true,"detail":"5.0"},
{"hop":"freshness","evaluated":true,"stale":true,"age_seconds":412.0} ] }alarm_bad_actors(events=[…]):
{ "event_count": 55, "window_minutes": 0.82, "alarms_per_hour": 4024.4,
"isa_18_2": {"ok_max":6,"manageable_max":12,"flood_min":30},
"flood_verdict": "flood",
"priority_distribution": {"high":50,"low":5},
"pareto_sources_for_80pct": ["FIC101"],
"top_offenders": [ {"source":"FIC101","count":50,"share_pct":90.9,"chattering":true,"standing":false} ],
"chattering": ["FIC101"], "standing": [] }tag_health(tags=[…]):
{ "evaluated": 4, "overall": "alarm", "offender_count": 3,
"offenders": [ {"ref":"hot","latest":99,"flags":["out_of_range_alarm"],"severity":3},
{"ref":"flat","latest":5,"flags":["flatline"],"severity":2},
{"ref":"bad","latest":null,"flags":["bad_quality"],"severity":3} ] }AI downtime root-cause copilot (flagship)
downtime_root_cause correlates whatever evidence you can hand over — alarm
events, tag samples, a diagnose_dataflow verdict, a machine-state series —
around an incident window and returns an evidence-cited, advisory verdict.
Read-first: it proposes a human-approved, MOC-gated, undoable action and executes
nothing. Anti-hallucination by design — it cites only signals actually present in
the input, weights them by temporal proximity to onset (a cause precedes its
effect), and downgrades to insufficient_evidence (with a recommended_next_data
list) rather than guessing when evidence is thin.
downtime_root_cause(window={"start":"2026-06-28T10:00:00Z","asset":"line1"}, alarms=[{"source":"M1_DRIVE","timestamp":"2026-06-28T09:59:52Z","message":"motor overload trip"}], tags=[{"ref":"DRV1.Torque","samples":[10,11,99,99],"alarm_high":80}], dataflow={"verdict":"healthy"}):
{ "window": {"start":"2026-06-28 10:00:00+00:00","asset":"line1","duration_s":300.0},
"verdict": "root_cause_identified",
"primary_cause": {
"cause": "mechanical_fault", "confidence": 0.722, "confidence_band": "high",
"evidence": [
{"signal":"alarm","ref":"M1_DRIVE","at":"2026-06-28 09:59:52+00:00","lead_time_s":8.0,
"detail":"motor overload trip","weight":0.4959},
{"signal":"tag","ref":"DRV1.Torque","detail":"flags=out_of_range_alarm severity=3","weight":0.45} ],
"recommended_action": "Dispatch maintenance to inspect the faulting unit; if a latch/interlock is set, the reversible step is to clear the fault and reset the latch (MOC-approved, undo captures the prior latch state)." },
"evidence_summary": {"alarms_supplied":1,"tags_supplied":1,"dataflow_verdict":"healthy","total_evidence_items":2},
"anti_hallucination": "Advisory only — nothing is executed. Every cited signal is present in the supplied evidence …" }The same copilot is on the CLI: iaiops diag rca --input bundle.json where the
bundle is {window, alarms?, tags?, dataflow?, state_series?}.
Let it gather its own evidence. downtime_root_cause_live (CLI iaiops diag rca-live) takes just an endpoint + window + the refs to look at, then pulls the
evidence itself — a cross-protocol diagnose_dataflow probe, a short sampled
series per ref (so flatline / bad-quality / anomaly surface via tag_health),
and active OPC-UA conditions — before running the same advisory, read-only copilot.
The gathered bundle is echoed back under collected_evidence (no hidden inputs):
iaiops diag rca-live -e line1 --start 2026-06-28T10:00:00Z \
--asset line1 --ref "ns=2;i=5" --ref "ns=2;i=6"Data-quality watchdog & UNS governance (read-only intelligence)
Two more pure-analysis layers — fully testable without live gear, and they feed the RCA copilot.
data_quality_scorecard(CLIiaiops diag dataquality) — a fleet data-TRUST rollup: scores each tag 0-100 on whether its data can be believed — staleness, dead heartbeat (first-class), bad-quality, flatline, gaps, anomaly — then rolls up per endpoint and across the fleet with an issue breakdown and ranked worst offenders. Distinct from process health: it asks "can I trust this number," not "is this number alarming."heartbeat_health(CLIiaiops diag heartbeat) is the standalone watchdog-liveness check (a flatlined heartbeat = dead upstream even when comms look fine).uns_topic_audit(CLIiaiops mqtt uns-audit) — governs a UNS topic tree: naming conformance (allowed roots / min depth) + topic sprawl (casing collisions of the same logical name, leaf metrics scattered under many parents, depth outliers, duplicates) → aclean/minor/sprawlingverdict.uns_schema_drift(CLIiaiops mqtt uns-drift) — compares two Sparkplug NBIRTH-style snapshots and classifies the changenone/additive/breaking(a metric removed or its datatype changed). Positions the UNS as a governable neutral data source, not just a broker.
MCP server
IAIOPS_MCP=opcua iaiops-mcp # stdio transport (`iaiops mcp` is equivalent)Menu — expose only the protocols a site runs. A fab usually runs 1–2 protocols;
exposing all 14 floods the model with tools it can't use. Set IAIOPS_MCP to a
comma-list of protocols and/or a named profile. There is no default (since
0.10.0): a bare iaiops-mcp prints the selection menu (profiles, protocol keys,
tool counts) to stderr and exits 2 instead of silently exposing 100+ tools. The
cross-protocol brain (OEE / downtime / diagnostics / asset / analysis) is included
by default with every selection.
IAIOPS_MCP=menu iaiops-mcp # print the menu (selections + tool counts)
IAIOPS_MCP=opcua,modbus iaiops-mcp # two protocols + brain
IAIOPS_MCP=fab iaiops-mcp # named profile (secsgem+opcua+s7+modbus)
IAIOPS_MCP=opcua iaiops-mcp # effectively a single-protocol MCP
IAIOPS_MCP=all iaiops-mcp # everything — explicit opt-in only
# (logs a tool-flood warning above 100 tools)Named entry-point sugar. For the common single-protocol / single-edition case there is a pre-scoped console script per protocol and per named profile — no env var to set. Each is a thin shim over the same server:
iaiops-mcp-opcua # == IAIOPS_MCP=opcua iaiops-mcp
iaiops-mcp-modbus # == IAIOPS_MCP=modbus iaiops-mcp
iaiops-mcp-fab # == IAIOPS_MCP=fab iaiops-mcp (per-edition)
iaiops-mcp-building # == IAIOPS_MCP=building iaiops-mcp
iaiops-mcp-brain # == IAIOPS_MCP=brain iaiops-mcp (brain only, 0 protocols)Multi-process sites — 1 brain MCP + N protocol MCPs. Running several protocol
servers side by side (e.g. iaiops-mcp-opcua + iaiops-mcp-modbus) would duplicate
the ~30 brain tools in every server. Instead run one dedicated iaiops-mcp-brain
and set IAIOPS_MCP_NO_BRAIN=1 on the protocol servers to strip the brain from
them — the protocols_supported discovery tool stays exposed everywhere:
iaiops-mcp-brain # the one cross-protocol brain server
IAIOPS_MCP_NO_BRAIN=1 iaiops-mcp-opcua # lean protocol server, no brain
IAIOPS_MCP_NO_BRAIN=1 iaiops-mcp-modbusWrite authorisation is not the tap's job. iaiops does not withhold write
tools behind a server switch. Whether a write is allowed is the caller's
decision — the agent's judgement or account/permission management — and the tap's
job is to make that write accurate, efficient, and un-bypassably audited.
Every call, read or write, on either front-end (MCP tool and iaiops CLI),
goes through @governed_tool and leaves a row in ~/.iaiops/audit.db. Writes are
additionally HIGH risk_tier and MOC-gated (dry-run + double confirmation + undo
capture + a recorded approver). protocols_supported reports this posture so the
model is told the rules rather than left to infer them.
Since 0.20.3 that promise is held by contract tests over the real tool
surface rather than by synthetic stand-ins: every one of the ten high-risk writes
is driven end to end and must be denied without an approver with the connector
never reached — "it raised" only proves an exception, not that nothing reached the
device. Two things those tests exposed on the way in: a call that failed was
audited as ok (tools return the canonical {error, hint} envelope rather than
raising, so the governance wrapper saw an ordinary return), which also told the
pattern circuit breaker "success" on every failure; and the runaway guard, blind to
a caller retrying a denial forever, let 500 identical denied writes through a
ceiling of 10. Both are fixed and pinned.
Sealed sites — make the data-shipping tools cease to exist.
IAIOPS_NO_EGRESS=1 removes every tool whose job is to transmit local or plant
data to a destination the caller names, at registration time so a weak or
prompt-injected model cannot call what it cannot see:
IAIOPS_NO_EGRESS=1 iaiops-mcp-factory # 134 tools -> 129; 5 withheldWithheld: stream_publish, stream_publish_event (NATS message bus),
uns_publish (MQTT broker / Unified Namespace),
historian_push (external TSDB), mqtt_publish (broker), rca_narrate (POSTs
the RCA verdict — plant tags, values and citations — to a caller-supplied model
base_url). This is a data-exfiltration / airgap axis, not read/write
authorisation: historian_push is risk_level="low" — it changes no plant state
— yet it ships telemetry off-box, so this switch withholds it. It gates MCP tools
only, and is not a firewall (reads still open sockets to plant devices).
protocols_supported reports each posture independently.
Scope, stated plainly — this is not a firewall:
It gates MCP tools only.
iaiops audit forward(SIEM) is a CLI path no registry gate can reach; block it at the host if the box must be sealed.Reads still open outbound sockets. iaiops is a network tap — it must talk to PLCs, brokers and historians to read anything at all. The gate removes the tools whose purpose is sending data outward, not the network itself.
It does not police arguments. A tool is present or absent as a whole; nothing is inspected at call time (that would be the call-time refusal this design rejects). This is why a tool with a caller-supplied destination is withheld even when its default points at localhost — the model picks the argument.
Local file writes are not egress:
export_dataandcompliance_evidence_bundlestay exposed. The bytes never leave the box; getting them off it afterwards is a host-level concern.Both switches cover the
iaiops-mcpserver only (including its per-protocol / per-edition entry-point shims).iaiops-energy-mcpis a separate server in a separate package and does not honour them yet — it mirrors in the base brain/compliance tools, soIAIOPS_NO_EGRESS=1there still leaveshistorian_push,rca_narrate,stream_publishandstream_publish_eventexposed oniaiops-energy0.1.6 and earlier. Fixed iniaiops-energy0.1.7, which pinsiaiops>=0.17for exactly this reason. Said out loud because a switch believed to be on is worse than one known to be absent.
Named profiles: all · brain · fab · factory · process · building ·
plcnext · water · renewables · warehouse · clinical. In an MCP client (e.g. Claude Desktop) set IAIOPS_MCP per
server entry — or point the entry straight at the matching iaiops-mcp-<name>
script — one entry per site/line, each a lean single- or dual-protocol server.
Safety & governance
Read-first. 185 of the 196 tools are read-only, and
historian_pushwrites to a historian rather than to a device. The 10 write/command tools (s7_write_db,mc_write_words,fins_write_words,mqtt_publish,eip_write_tag,ethercat_write_sdo,ethercat_set_state,profinet_dcp_set,bacnet_write_property,bas_command) are OT-dangerous: governed at high risk_tier, off by default (dry-run), require a double-confirm in the CLI, and a recorded approver (one-shotiaiops approvetokens; with norisk_tiersconfigured, high/critical operations default to thedualtier) — MOC discipline. All ten declare an undo (no exemptions since 0.20.3); a successful write captures the BEFORE value/state and registers an inverse descriptor. The inverse honestly reports "none" where none exists — a transient (retain=False)mqtt_publishcannot be unsent, andethercat_set_state's+ERR/NONE/BOOTare not cleanly re-requestable AL-states. An undo that over-promises is worse than none, because someone will replay it onto live equipment.ethercat_set_statecan START or STOP machine motion. 未经授权勿对生产控制系统写入.Read/write authorisation is the caller's, not the tap's. iaiops does not encode "this server may not write" by hiding tools — that decision belongs to the agent's judgement or account/permission management. The tap's guarantee is un-bypassable audit on both front-ends: every call, read or write, via an MCP tool or the
iaiopsCLI, runs through@governed_tooland leaves a row in~/.iaiops/audit.db. Writes are additionally highrisk_tier, MOC-gated, and undo-captured (see above). High/critical calls fail closed when the audit DB cannot be written.No-egress mode is enforced at registration.
IAIOPS_NO_EGRESS=1withholds the 6 tools that ship data off-box (stream_publish,stream_publish_event,uns_publish,historian_push,mqtt_publish,rca_narrate), fail-closed, for airgap/sealed-box deployments. This is a data-exfiltration axis, not authorisation —historian_pushis low-risk (it changes nothing) yet pushes telemetry to an external TSDB, so this switch withholds it. Which tools count is derived from@governed_tool(egress=True)metadata and guarded by an AST scan in CI, so the next egress tool cannot silently escape the gate.Do not point this at a production control system without authorization. OT networks are safety-critical; even reads add load. Test against a simulator first.
All endpoint-returned text is sanitized (prompt-injection defense); secrets are never returned by any tool; MTConnect XML is parsed with DTD/entity declarations refused.
Every tool runs through the vendored governance harness: SQLite audit (
~/.iaiops/audit.db, SHA-256 hash-chained rows +iaiops audit verify; audit fails closed for high/critical writes), token/call budget + runaway breaker, risk-tier gate (policy engine fails closed on a brokenrules.yaml), undo recording. The MCP server refuses to start if any registered tool lacks the governance marker.
Roadmap
Four items that used to sit here had in fact shipped — including two this same
README already listed as verified, three sections above. Listing built work as
future work is the same defect as claiming unbuilt work, so they are gone:
EtherNet/IP PCCC (PLC-5/SLC-500) and Micro800, passive asset discovery
(iaiops scan --posture passive, ARP-cache only, emits nothing),
OPC-UA certificate security, and MTConnect streaming long-poll.
What is genuinely open:
EtherCAT EoE / FoE / SoE mailbox protocols and full PDO-mapping decode (CoE SDO/PDO read+write and AL-state landed in 0.3.0 via the optional
pysoemextra).Sparkplug B Template deep expansion (DataSet landed in 0.17.0).
Contextual baselines — one normal band per tag today, but an OT normal range moves with shift, product and start-up. Learn per bucket, and refuse a bucket with too few samples rather than falling back to a global band, which would disguise "never seen this regime" as "this regime is normal".
Relationship-aware root cause — evidence is weighted by time only, so one upstream stoppage yields a run of equally-confident downstream false causes. A human-declared line order is enough to start.
Passive discovery from a SPAN/tap — the ARP-cache posture is built; reading a mirror port is not.
Missing a protocol, device, or feature? 缺功能提 issue/PR 欢迎留言 — open a GitHub issue or PR.
License
MIT © wei
Available Tools
153 toolsadopt_alias_mapARead-only
[READ][risk=low][PERSIST] Adopt + persist the canonical alias map for a site.
Writes a local owner-only advisory JSON file (NOT an OT-device write — hence
risk=low); see the persistence note below.
Runs the cross-protocol asset model over ``feeds``, extracts the adopted map
``{canonical_alias: {ref, protocol, asset, name, class}}``, and persists it as
the site's baseline (owner-only JSON under the iaiops home). Re-running
overwrites the baseline. Advisory — the map is a SUGGESTION, never a
server-side rename (OT-dangerous).
Args:
feeds: Per-protocol tag feeds ``[{protocol, source, asset?, tags:[...]}]``,
the SAME shape ``cross_protocol_asset_model`` takes.
site: Site label (a safe file leaf: alphanumeric/_/-). Default 'site'.
Returns dict: {site, path, tag_count, adopted:{alias: {...}}}.
Example: adopt_alias_map(feeds=[{"protocol":"opcua","source":"l1","tags":[...]}],
site="plant").
| Name | Required | Description | Default |
|---|---|---|---|
| site | No | ||
| feeds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses that it writes a local file (persistence), is non-destructive, and re-running overwrites baseline. Annotations already indicate readOnly, but description clarifies it's a safe local write, adding value.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Structured with intro, details, args, returns, example. Some redundancy in advisory messaging, but overall efficient and front-loaded with risk and purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers key aspects: persistence, advisory nature, return structure, parameter details. Lacks error handling or edge cases, but sufficient for a moderate-complexity tool with no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 0% coverage, but description explains feeds shape (referencing sibling) and site constraints. Adds default and format, compensating for lack of schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it adopts and persists the canonical alias map for a site. It distinguishes from siblings by noting it runs cross_protocol_asset_model and is advisory, not server-side rename.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides context that it writes a local advisory file and is not an OT-device write, implying when not to use. However, lacks explicit alternatives or exclusions beyond the warning.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
alarm_bad_actorsARead-only
[READ][risk=low] ISA-18.2 alarm-flood analysis over a list of alarm events.
Args:
events: Alarm/condition events — {source, timestamp (ISO-8601), priority?,
state? (ACTIVE/RTN/ACK)}.
window_minutes: Analysis window; omitted → inferred from event timestamps.
chatter_window_s: A source with >=3 transitions inside this window chatters.
standing_s: An alarm active longer than this is 'standing/stale' (default 24h).
top_n: How many top offenders to return.
Returns dict: {event_count, window_minutes, alarms_per_hour,
isa_18_2:{ok_max:6, manageable_max:12, flood_min:30},
flood_verdict ('ok'|'manageable'|'over_target'|'flood'),
priority_distribution, pareto_sources_for_80pct, top_offenders:[{source,
count, share_pct, chattering, standing}], chattering:[...], standing:[...]}.
Example: alarm_bad_actors(events=[{"source":"FIC101","timestamp":"...",
"priority":"high"}, ...]).
| Name | Required | Description | Default |
|---|---|---|---|
| top_n | No | ||
| events | Yes | ||
| standing_s | No | ||
| window_minutes | No | ||
| chatter_window_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds significant behavioral details beyond annotations, including analysis thresholds (chatter window, standing time, flood limits), return structure, and risk level. It discloses defaults and algorithm behavior, giving the agent a clear understanding of side effects and safety.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a summary line, parameter list, return dict, and example. It is slightly verbose due to redundant example details, but every sentence serves a purpose and it is front-loaded with key context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the absence of an output schema and the moderate complexity (5 params, no enums), the description provides a complete understanding: all parameters are explained, return format is detailed with example values, and context signals (readOnly, low risk) are reinforced.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully explains all 5 parameters—their purpose, expected format (e.g., ISO-8601 timestamps), defaults, and constraints (e.g., chatter_window_s logic). This compensates completely for the missing schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it performs 'ISA-18.2 alarm-flood analysis over a list of alarm events', specifying the standard and action. The [READ] tag confirms the operation type. It differentiates from siblings like 'alarm_flood_analysis' by referencing the specific standard and parameterization.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains what the tool does and provides an example, but lacks explicit guidance on when to use this tool versus alternatives (e.g., alarm_flood_analysis, alarm_cascade). It does not state prerequisites or exclusion criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
alarm_cascadeARead-only
[READ][risk=low] Collapse an alarm flood into cascades + each cascade's first-out root.
Answers "which alarm to look at first" when 100+ alarms hit in minutes: groups annunciations
into cascades (a new cascade starts after a quiet gap > window_s) and reports the FIRST-OUT
alarm (earliest in the burst) as the likely root, plus downstream members and any chattering
sources. First-out is a transparent heuristic cited by timestamp — NOT causal (use
downtime_root_cause for causality). Pass 'events' for pure analysis, or an endpoint to collect
live via the OPC-UA active-condition scan. Read-only; bounded.
Args:
endpoint: Endpoint name from config (used only when events is omitted).
duration_s: Live collection window in seconds (1..300, default 60).
window_s: Quiet gap (seconds) that separates one cascade from the next (default 60).
min_cascade: Minimum annunciations for a group to count as a cascade (default 2).
events: Injected alarm events — {source, timestamp (ISO-8601), state?}; skips live collect.
Returns dict: {cascade_count, total_activations, cascades:[{root:{source, ts}, size,
distinct_sources, span_s, members[], chattering[]}], collected?}.
Example: alarm_cascade(events=[{"source": "PT101", "timestamp": "2026-06-28T10:00:00Z"}, ...]).
| Name | Required | Description | Default |
|---|---|---|---|
| events | No | ||
| endpoint | No | ||
| window_s | No | ||
| duration_s | No | ||
| min_cascade | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the agent knows it's safe. The description adds valuable behavioral context: the first-out heuristic is transparent ('cited by timestamp'), cascades are separated by a quiet gap, and it mentions chattering sources. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a front-loaded purpose statement, clear usage guidance, and a parameter list. While slightly verbose, every sentence adds value. The example and return dict description enhance usability without unnecessary fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (5 parameters, no output schema, no schema descriptions), the description covers all needed context: use cases, parameter details, return format (dict structure), example, and relationship to siblings. It leaves no gaps for an agent to misunderstand.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description fully compensates by explaining each parameter: `endpoint` (used only when `events` omitted), `duration_s` (live window 1-300s), `window_s` (quiet gap), `min_cascade` (minimum annunciations), and `events` (format `{source, timestamp, state?}`). Defaults and constraints are also provided.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Collapse an alarm flood into cascades + each cascade's first-out root.' It specifies the resource (alarm events) and the unique output (cascade root identification). It distinguishes from sibling `downtime_root_cause` by explicitly stating it is not causal.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance: use when '100+ alarms hit in minutes' to find 'which alarm to look at first.' It tells when not to use ('NOT causal – use downtime_root_cause for causality') and describes two usage modes (pass `events` or `endpoint`), covering both analytical and live scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
alarm_event_clustersARead-only
[READ][risk=low] Collapse ten phrasings of one fault into one row.
`alarm_bad_actors` ranks by SOURCE, which answers "which instrument is
noisiest" and not "which fault is noisiest". A plant that words one condition
ten ways — `PT-101 HIGH`, `PT-102 HIGH`, `PT-103 high alarm` — gets ten bad
actors and no sign that they are one problem, so a rationalization meeting
works the list top-down and fixes the same thing three times. This groups the
same events by what they SAY instead of by who said it.
Clustering is **exact equality of a normalized string, not similarity**: case,
punctuation and embedded numbers are removed, and what remains must match
exactly. That is deliberately dumber than it could be, and it is why the
result needs no model and can be checked — two messages land together only
when they are literally the same sentence with the identifiers taken out.
Every cluster carries the distinct wordings and sources it merged, so you can
see what was combined. It does **not** claim two differently-worded alarms
mean the same thing; a person decides that.
Events carrying no message text are counted separately and excluded from the
shares, rather than being lumped together as one type.
Args:
events: [{source?, message|description|text|condition|type, ...}].
top_n: Clusters returned, largest first (default 20, capped at 100).
min_count: Only report clusters with at least this many events (default 1 —
a one-off is still reported, not tidied away).
Returns dict: {events_supplied, events_clustered, events_without_text,
cluster_count, collapsed_count, clusters:[{signature, count, share_pct,
distinct_wordings, distinct_sources, variants:[{text, count}],
sources:[{source, count}]}], note}.
Example: alarm_event_clusters(events=[{"source":"PT-101","message":"pressure HIGH"},
{"source":"PT-102","message":"Pressure high!"}]).
| Name | Required | Description | Default |
|---|---|---|---|
| top_n | No | ||
| events | Yes | ||
| min_count | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the operation read-only and non-destructive, but the description adds substantial behavioral detail: exact equality after normalization of case, punctuation, and embedded numbers; events without message text are excluded from shares; and each cluster retains distinct wordings and sources. It also explicitly states what the tool does NOT claim, preventing over-interpretation of cluster meanings.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence earns its place: it opens with a one-line summary and risk marker, explains motivation and algorithm, details all three parameters, and lists the return structure. The contrast with alarm_bad_actors is front-loaded, and the example grounds the explanation without bloat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there is no output schema, the description compensates by fully specifying the return dict fields, including clusters, signatures, counts, shares, distinct wordings, and sources. It also addresses edge cases like events without text and one-off clusters. Combined with the sibling context and annotations, an agent has everything needed to select and invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description fully carries the burden. It explains the events parameter with accepted message field aliases, top_n with default and cap, and min_count with default and behavior. It even provides a concrete example call showing expected parameter shapes.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first line states a specific action and resource: 'Collapse ten phrasings of one fault into one row.' The description then explicitly contrasts this with alarm_bad_actors, clarifying that this tool answers 'which fault is noisiest' rather than 'which instrument is noisiest.' This clearly differentiates it from the closest sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives concrete when-to-use context: when multiple wordings of the same underlying fault inflate a bad-actor list. It names the alternative alarm_bad_actors and explains the distinction in terms of SOURCE versus message content. It also cautions that clustering is exact-equality based, not semantic similarity, so a human must decide whether different wordings mean the same thing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
alarm_flood_analysisARead-only
[READ][risk=low] ISA-18.2 deep alarm-flood analysis: episodes + chattering + stale + advice.
Deepens alarm_bad_actors: detects flood *episodes* (start/end/count/peak rate/
top contributors + each episode's first-out annunciation, per ISA-18.2's >=10
alarms per 10 min per operator), alarms chattering ACTIVE↔CLEARED, standing/
stale alarms, and percent-time-in-flood vs the ISA-18.2 targets (~1-2 alarms/
10 min steady state, <1% time in flood). Also returns an ISA-18.2 'load_profile'
(per-bucket rate band + peak period + trend) and per-source 'suppression_advice'
(deadband/on-off-delay for chatter, time-limited shelve for standing alarms).
The suppression advice is ADVISORY ONLY — starting values for a human to review
and approve via your ISA-18.2 / management-of-change process; this tool never
applies suppression, shelving, deadband, or delay changes. Pass 'events' for
pure analysis, or an endpoint to collect live via the same OPC-UA active-
condition scan the RCA copilot uses (polled over duration_s; other protocols
contribute no alarms). Output is bounded; 'truncated' flags say when caps bit.
Args:
endpoint: Endpoint name from config (used only when events is omitted).
duration_s: Live collection window in seconds (1..300, default 60).
window_s: Flood analysis window in seconds (ISA-18.2 default 600).
threshold: Annunciations per window that start a flood (default 10).
events: Injected alarm events — {source, timestamp (ISO-8601), state?
(ACTIVE/RTN/CLEARED)}; skips live collection entirely.
stale_after_s: Continuously-active age that marks a standing alarm (default 24h).
max_episodes: Cap on returned flood episodes (default 20).
max_rows: Cap on chattering / stale / suppression-advice / worksheet rows (default 50).
load_bucket_s: Load-profile bucket width in seconds (ISA-18.2 default 600 = 10 min).
Returns dict: {event_count, summary:{insufficient_data, percent_time_in_flood,
avg_alarms_per_10min, peak_alarms_per_10min, isa_18_2_targets, ...},
load_profile:{overall_band, peak_bucket, band_distribution, trend,
busiest_buckets:[...], ...}, flood_episodes:[{start, end, ..., top_contributors,
first_out:{source, ts}}], chattering:[{source, cycles, cycles_per_hour, ...}],
stale_standing:[{source, active_since, active_for_s}], suppression_advice:[{source,
kind, technique, suggested_on_delay_s, suggested_off_delay_s, suggested_shelve_max_s,
basis, advisory}], worksheet_preview:[...], advisory_note, truncated:{...}, collected?}.
Example: alarm_flood_analysis(events=[{"source":"FIC101",
"timestamp":"2026-06-28T10:00:00Z","state":"ACTIVE"}, ...]).
| Name | Required | Description | Default |
|---|---|---|---|
| events | No | ||
| endpoint | No | ||
| max_rows | No | ||
| window_s | No | ||
| threshold | No | ||
| duration_s | No | ||
| max_episodes | No | ||
| load_bucket_s | No | ||
| stale_after_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description starts with '[READ][risk=low]' aligning with readOnlyHint=true annotations, explicitly states the tool never applies suppression (non-destructive), and describes output bounds and 'truncated' flags, adding behavioral context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a front-loaded summary, detailed body, bulleted 'Args', return dict, and example. While lengthy, every sentence adds value due to the tool's complexity. Structure is excellent but slightly verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description thoroughly explains the return dict, ISA-18.2 context, relationship with alarm_bad_actors, and edge cases like truncated flags. It is fully complete for a complex tool with 9 parameters.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema coverage, the description fully explains each parameter in the 'Args:' section, including purpose, defaults, constraints (e.g., duration_s 1..300), and the events format, providing meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool performs ISA-18.2 deep alarm-flood analysis covering episodes, chattering, stale alarms, and suppression advice. It distinguishes from sibling 'alarm_bad_actors' by stating 'Deepens alarm_bad_actors', providing a specific verb and resource.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use 'events' for pure analysis vs an endpoint for live collection, and warns that suppression advice is advisory only and never applied. It also notes that other protocols contribute no alarms, giving clear application context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
alarm_rationalization_worksheetARead-only
[READ][risk=low] ISA-18.2 alarm-rationalization worksheet (CSV or inline rows).
One row per alarm source, count-descending: count, % of total annunciations,
chattering?, flood contributor?, and a recommendation stub — the starting
document for an ISA-18.2 rationalization review. Pass 'events' for pure
analysis, or an endpoint to collect live via the same OPC-UA active-condition
scan the RCA copilot uses. With out_path the full worksheet is written as CSV
and the path returned; otherwise bounded inline rows (truncation noted).
Args:
endpoint: Endpoint name from config (used only when events is omitted).
duration_s: Live collection window in seconds (1..300, default 60).
events: Injected alarm events — {source, timestamp (ISO-8601), state?}.
window_s: Flood analysis window in seconds (ISA-18.2 default 600).
threshold: Annunciations per window that start a flood (default 10).
out_path: Optional CSV destination; parent directory must exist.
Returns dict: {row_count, columns:[alarm_id, count, pct_of_total, chattering,
in_flood, recommendation], csv_path? , rows?:[...], truncated (bool)}.
Example: alarm_rationalization_worksheet(events=[...], out_path="worksheet.csv").
| Name | Required | Description | Default |
|---|---|---|---|
| events | No | ||
| endpoint | No | ||
| out_path | No | ||
| window_s | No | ||
| threshold | No | ||
| duration_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description discloses behavioral details: the tool is read-only ([READ][risk=low]), outputs inline rows with truncation, writes CSV when out_path is provided, and returns a structured dict. It also references the same OPC-UA scan as the RCA copilot. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured, starting with a one-line summary and a [READ][risk=low] tag, then detailing parameters and return format. It is slightly verbose for a single tool but remains focused and front-loaded. Every sentence adds value, though some redundancy could be trimmed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the 6 optional parameters, no output schema, and the presence of annotations, the description covers all important aspects: parameter roles, defaults, return dict fields (row_count, columns, csv_path, rows, truncated), and an example call. It references the ISA-18.2 standard and explains truncation behavior, leaving no major gaps for a rationalization worksheet tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by explaining each parameter: endpoint (optional, for live collection), duration_s (1-300 default 60), events (injected alarm events), window_s (flood analysis window, default 600), threshold (10), and out_path (optional CSV destination). It provides defaults, constraints, and usage context, making the parameter meaning clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool generates an ISA-18.2 alarm-rationalization worksheet with one row per alarm source. It specifies the output includes count, percentage, chattering, flood contribution, and recommendations. This distinguishes it from sibling alarm tools like alarm_flood_analysis or alarm_cascade, making the purpose highly specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains two usage modes: pass 'events' for pure analysis or an endpoint for live collection via OPC-UA. It implies use when a rationalization worksheet is needed but does not explicitly contrast with alternatives or specify when not to use. The guidance is clear but lacks exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
anomaly_scanARead-only
[DEPRECATED → opcua_anomaly_scan][READ][risk=low] Statistical outlier scan.
Samples a node over a bounded window and flags statistical outliers.
Computes mean/stddev/min/max and flags samples outside mean ± sigma*stddev.
Simple statistics only — no ML, no persisted model.
Args:
node_id: The OPC-UA node id to scan.
endpoint: Endpoint name from config.
samples: Max samples (capped server-side).
interval_ms: Delay between samples in milliseconds.
sigma: Outlier band width in standard deviations.
| Name | Required | Description | Default |
|---|---|---|---|
| sigma | No | ||
| node_id | Yes | ||
| samples | No | ||
| endpoint | No | ||
| interval_ms | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations (readOnlyHint=true) align with description's [READ] tag. Discloses algorithm: mean/stddev/min/max, flags outliers outside sigma*stddev. Adds behavioral context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with deprecation, tags, brief summary, then bullet-like args. Slightly verbose but clear and front-loaded with key info.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 5 params and no output schema, description covers algorithm, parameters, and deprecation adequately. Agent can decide to use or switch to opcua_anomaly_scan.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but description documents all 5 parameters with brief explanations (e.g., 'sigma: Outlier band width in standard deviations'). Adds meaning beyond schema defaults/titles.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly describes statistical outlier scan for OPC-UA nodes. Distinguishes from sibling via deprecation notice pointing to opcua_anomaly_scan, but no explicit functional comparison.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly deprecated with alternative named. States 'Simple statistics only — no ML, no persisted model', guiding when to use. Doesn't provide when-not-to-use beyond deprecation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
asset_inventoryARead-only
[READ][risk=low] Actively fingerprint endpoints into an asset register.
Connects to each target with our own protocol client and reads its identity
call (S7 CPU info, EtherNet/IP controller info, OPC-UA server build info,
Modbus device identification FC43, Mitsubishi CPU type, MTConnect device
model), aggregating vendor/model/firmware/serial per device.
Honest scope: ACTIVE fingerprinting (we connect to each device), NOT passive
SPAN/tap discovery. Only finds devices we are configured to reach.
Args:
endpoints: Endpoint names to fingerprint; omit to fingerprint ALL
configured endpoints.
Returns dict: {asset_count, reachable_count, unreachable_count, method:
'active_fingerprint', assets:[{endpoint, protocol, address, vendor, model,
firmware, serial, reachable, last_seen, error}]}.
Example: asset_inventory(endpoints=["press1","cell5"]).
| Name | Required | Description | Default |
|---|---|---|---|
| endpoints | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds that it connects to each target, reads identity calls, aggregates vendor/model/firmware/serial. No contradictions. It could mention rate limits or permissions, but current info is sufficient.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a quick summary, then details about the method, scope, arguments, return value, and an example. Every sentence adds value and is efficiently written.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with one parameter, clear annotations, and no output schema, the description is very complete. It explains the return format in detail and provides an example, leaving little ambiguity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter 'endpoints' is clearly explained: it expects endpoint names, and omitting it fingerprints all configured endpoints. Schema description coverage is 0%, so the description fully compensates.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool 'actively fingerprint endpoints into an asset register,' which is a specific verb-resource combination. This distinguishes it from protocol-specific siblings like profinet_asset_inventory, modbus_*, etc.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains the scope as active fingerprinting only, not passive discovery, and that it only finds devices it can reach. It provides an example usage and indicates when to omit endpoints. However, it does not explicitly compare with sibling tools, though the context helps.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
baseline_checkARead-only
[READ][risk=low] Check recent local samples against the learned baseline.
Reads the last window_s seconds from ~/.iaiops/data.db (no device I/O) and
judges them against the stored band. Conservative by design: a violation is
reported ONLY when values are beyond p1/p99 by more than 3×MAD AND sustained
for >=3 consecutive samples — a single spike is never flagged. Every
violation cites the baseline window (from/to ts, n samples), the band
values, and the offending samples' timestamps/values. No stored baseline →
an explicit no_baseline answer (never a guess). Bounded output (<=10
violations, <=20 cited samples each).
Args:
tag: Tag name to check, e.g. 'line1.temp'.
endpoint: Only samples from this endpoint label.
window_s: Recent window to check, seconds (60..604800; default 3600).
Returns dict: {status: 'ok'|'violation'|'no_baseline', tag, checked_samples,
thresholds, baseline_citation, violations:[{direction, from_ts, to_ts,
consecutive_samples, samples:[{ts,value}], baseline}], note}.
Example: baseline_check(tag="line1.temp", window_s=7200).
| Name | Required | Description | Default |
|---|---|---|---|
| tag | Yes | ||
| endpoint | No | ||
| window_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses the detection algorithm (p1/p99, 3×MAD, consecutive samples), data source, bounded output, and no_baseline behavior. This adds significant context beyond annotations (readOnlyHint, destructiveHint), which are consistent (no contradiction).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a headline, behavioral paragraph, Args section, Returns dict, and example. It is front-loaded with purpose and every sentence is informative without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description details the return dict structure and handles edge cases (no baseline, bounded violations). Given the tool's complexity and existing annotations, the description is complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully explains each parameter: tag (example), endpoint (filtering), window_s (range and default). This adds meaning beyond the schema types and defaults.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool checks recent local samples against a learned baseline, and distinguishes it from sibling baseline tools (e.g., baseline_learn, baseline_record_change) by focusing on checking. The verb 'check' and resource 'baseline' are specific.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains the context (reads local data, no device I/O) and the conservative detection logic, but does not explicitly state when not to use or compare with alternatives. It implies usage for baseline checking but lacks exclusionary guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
baseline_check_in_contextARead-only
[READ][risk=low] Check readings against the band for ONE declared context.
A reading whose context was never learned comes back `unknown_context` and
stops there. It is **not** compared against the global band or the nearest
one, and that refusal is the entire point of the tool: borrowing a band turns
"we have never seen this regime" into "this regime is normal" — a silent
pass, in the direction nobody reports. The response lists the contexts that
do have bands so the gap is actionable.
Otherwise the usual conservative rules apply: a violation needs values beyond
the band by more than `margin_mad` × MAD AND sustained over `sustain_n`
consecutive samples, and every flag cites the baseline it was judged against.
Args:
samples: [{ts, value, ...}] readings to check.
contextual: A `baseline_learn_contextual` result.
context: Which declared context these readings belong to.
margin_mad: MAD margin beyond the band before flagging (default 3.0).
sustain_n: Consecutive samples required (default 3 — no single-spike flags).
Returns dict (known context): the `baseline_check` shape plus {context,
context_key}. (unknown): {status:"unknown_context", tag, context,
known_contexts, checked_samples, reason, note}.
Example: baseline_check_in_context(samples=[...], contextual={...}, context="recipe-B").
| Name | Required | Description | Default |
|---|---|---|---|
| context | Yes | ||
| samples | Yes | ||
| sustain_n | No | ||
| contextual | Yes | ||
| margin_mad | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag read-only, but the description adds the crucial unknown_context refusal, the no-borrowing rule, margin_mad × MAD and sustain_n requirements, and the fact that flags cite their baseline. It also explains why the response lists known_contexts, making the tool's behavior genuinely predictable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every section earns its place: purpose, critical refusal behavior, rule thresholds, Args, return shapes, and an example. The risk tag and core action are front-loaded, and the structure is easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description fully specifies both known-context and unknown_context return shapes, plus example usage. An agent has enough to decide whether and how to invoke the tool correctly, including what happens for unlearned contexts.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema coverage, the description carries full responsibility and does so thoroughly: every parameter is explained, including the relationship between contextual and baseline_learn_contextual, the shape of samples, and the meaning/defaults of margin_mad and sustain_n. This far exceeds the bare schema titles.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb/resource and scope: 'Check readings against the band for ONE declared context.' It also draws an explicit contrast with uncontextual or nearest-band behavior, so an agent can distinguish it from baseline_check and other siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes clear this tool is for checking samples against one declared contextual band and expects a baseline_learn_contextual result, but it never names an alternative tool to use for global or non-contextual checks. That gives clear context without explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
baseline_learnARead-only
[READ][risk=low] Learn a conservative per-tag normal band from local history.
Source is ~/.iaiops/data.db — the local store written by
historian_push(sink="sqlite") — NOT a live device read. Learns robust
percentiles (p1/p99 + median/MAD, no ML) from the tag's own samples,
segmented at the latest change recorded via baseline_record_change (the band
reflects only the post-change regime). REFUSES with an explicit
insufficient_data verdict (listing exactly what is missing) below 100 usable
samples or under 24h of span — it never invents a band from thin data. On
success the band is persisted to ~/.iaiops/baselines.json (owner-only local
metadata, not an OT write).
Args:
tag: Tag name to learn, e.g. 'line1.temp'.
endpoint: Only samples from this endpoint label.
since: Only samples at/after this ISO-8601 time.
Returns dict: {status: 'ok'|'insufficient_data', tag, band:{p1,p99,median,mad},
n_samples, window:{from_ts,to_ts,span_s}, segment, missing?:[...], note}.
Example: baseline_learn(tag="line1.temp", since="2026-06-01T00:00:00").
| Name | Required | Description | Default |
|---|---|---|---|
| tag | Yes | ||
| since | No | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations set readOnlyHint=true, but description states the tool writes to ~/.iaiops/baselines.json. This is a direct contradiction, forcing a score of 1 per rubric. The description itself is transparent about the write side effect, but the inconsistency with annotations is serious.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections (risk, source, method, args, returns, example) and front-loads the READ tag. While slightly verbose, every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, but the description provides a detailed Returns dict with fields and refusal conditions. It also explains the data source, persistence, and relationship to baseline_record_change, making the tool's operational context complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description bears full burden. It explains all three parameters (tag, endpoint, since) with examples and semantics, adding significant meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Learn a conservative per-tag normal band from local history', using specific verb and resource. It distinguishes from siblings by noting the data source (~/.iaiops/data.db) and relationship to baseline_record_change, and clarifies it is not a live device read.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description specifies when to use (learning a band) and explicitly states refusal conditions (<100 samples or <24h span). It does not mention alternatives to this tool but implies context via sibling relationships.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
baseline_learn_contextualARead-only
[READ][risk=low] Learn one conservative band per declared context, not one per tag.
One band per tag is wrong the moment a tag has more than one normal. A dryer
running recipe A at 180 °C and recipe B at 240 °C gets a band spanning both,
after which neither regime can go wrong — the band is too wide to catch a
real excursion and too mixed to mean anything. OT normal ranges move with
shift, product/recipe, and start-up versus steady state.
**The context is declared, never inferred** (D16). Each sample carries a
label under `context_key`; nothing here guesses which shift a timestamp falls
in or clusters values into regimes it then treats as real. Each context is
handed to the same learner as a global baseline, so it refuses on the same
terms — a thin context is left without a band rather than borrowing another
context's samples. Samples with no label are counted and named, not pooled
into a default bucket, because a default bucket is that same fallback.
Pass samples in (as with `spc_check` / `tag_health`). The local store's
`samples` table has no context column, so there is deliberately no
`iaiops baseline learn --context` yet; wiring one is a schema change and is
not done.
Args:
samples: [{ts, value, quality?, tag?, <context_key>}] rows.
tag: The tag being learned.
context_key: Field that declares the context (default "context").
min_samples: Per-context minimum before a band is learned (default 100).
min_span_s: Per-context minimum history span in seconds (default 86400).
Returns dict: {tag, context_key, contexts:{label: learn_baseline result},
learned_contexts, refused_contexts, uncontexted_samples, note}.
Example: baseline_learn_contextual(samples=[{"ts":"...","value":181.0,
"context":"recipe-A"}], tag="dryer.temp").
| Name | Required | Description | Default |
|---|---|---|---|
| tag | Yes | ||
| samples | Yes | ||
| min_span_s | No | ||
| context_key | No | context | |
| min_samples | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnly/destructive annotations by explaining refusal behavior for thin contexts, counting rather than pooling uncontexted samples, and deliberately avoiding a default fallback bucket. It even discloses why there is no `--context` CLI wiring due to the local store schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than typical but every paragraph carries meaningful design rationale or invocation detail, and it is well structured with Args, Returns, and an Example. The dryer example earns its place by clarifying the failure mode the tool avoids.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only learning tool with no output schema, the description provides the full return dict shape, parameter semantics, example call, and behavioral edge cases such as refused and uncontexted contexts. Nothing important is missing for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by documenting the sample row shape, `tag`, `context_key` as the declared-context field, `min_samples` as a per-context minimum, and `min_span_s` as a per-context history span with defaults. This gives the agent everything it needs beyond the raw JSON schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb and resource: 'Learn one conservative band per declared context, not one per tag.' The dryer example and contrast with per-tag learning make it clearly distinguishable from siblings like `baseline_learn`.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clearly describes when contextual baselines are needed: when a tag has multiple normal regimes due to shift, product/recipe, or start-up vs steady state. It also explains that contexts must be declared, not inferred, and shows how to pass samples, but it does not explicitly name the sibling alternative to use instead or provide an explicit when-not-to-use statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
baseline_record_changeARead-only
[READ][risk=low] Record an operator change-log entry for a tag (local only).
Writes ONLY local metadata (~/.iaiops/baselines.json, owner-only) — never an
OT device write, hence risk=low. A recorded change (setpoint moved, valve
replaced, probe swapped) marks a regime boundary: the next baseline_learn
uses only samples AFTER the latest change, so the band never mixes
pre-change and post-change behavior. This operator change log — not a
black-box score — is what makes the baseline trustworthy.
Args:
tag: Tag whose process changed, e.g. 'line1.temp'.
note: What changed (required), e.g. 'setpoint 60→70C'.
Returns dict: {tag, change:{ts, note}, changes_recorded}.
Example: baseline_record_change(tag="line1.temp", note="setpoint 60→70C").
| Name | Required | Description | Default |
|---|---|---|---|
| tag | Yes | ||
| note | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description states 'Writes ONLY local metadata', indicating a write side effect, but the annotations declare readOnlyHint=true, which contradicts this. The description adds useful behavioral context (local write, effect on baseline), but the contradiction forces a low score per guidelines.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a concise summary, behavioral explanation, structured Args/Returns/Example sections, and no wasted words. Every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's low complexity (2 required params, no output schema), the description covers purpose, usage, parameters, return format, example, and impact on baseline learning. It is fully complete for an agent to select and invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description fully compensates by explaining both parameters in the Args section with examples. It defines tag as 'Tag whose process changed' and note as 'What changed', adding meaning beyond the schema's type and title.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool records an operator change-log entry for a tag, specifying the verb 'record' and the resource 'change-log entry'. It distinguishes itself from sibling tools like baseline_learn by explaining how recorded changes affect baseline learning.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use the tool: to mark a regime boundary for baseline learning. It provides context that the next baseline_learn will only use samples after the latest change. While it does not explicitly state when not to use it, the example and explanation give clear guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
baseline_statusARead-only
[READ][risk=low] Baseline status for one tag, or a bounded listing of all.
Read from the local store only (no history scan, no device I/O) and never
guesses: 'no_baseline' (nothing learned, no refused attempt), 'learning'
(last learn refused — still accumulating history), 'ok' (band learned, last
check clean), 'violation' (last check flagged a sustained excursion). With
no tag, lists every tracked tag (bounded to 100 entries).
Args:
tag: Optional tag name; omit to list all tracked tags.
Returns dict: {tag, status, band?, baseline_window?, changes_recorded?, ...}
for one tag, or {tracked_tags, listed, truncated, tags:[...]} for all.
Example: baseline_status(tag="line1.temp").
| Name | Required | Description | Default |
|---|---|---|---|
| tag | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds significant context beyond annotations: explains it reads from local store only, never guesses, and defines statuses. Contradicts no annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with summary, details, args, returns, and example. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Complete for a simple tool with one optional parameter and no output schema. Explains return structure and includes an example.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 0% coverage, but description fully explains the 'tag' parameter: optional, omit to list all tracked tags. Adds meaning beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it reads baseline status for one tag or lists all tracked tags. Specific verb 'Read' and resource 'baseline status'. Distinguishes from sibling tools like baseline_learn and baseline_check.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Describes when to use: for reading baseline status from local store only, no history or device I/O. Explains status values. Could be more explicit about when to choose this over other read tools but is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
changeover_analysisARead-only
[READ][risk=low] Changeover / SMED durations between products.
Breaks out what OEE availability only aggregates: each changeover is the gap
between the last good part of one product and the first good part of the next
— the setup/adjustment time SMED shrinks. Measures every changeover, ranks the
longest, and totals the lost time, worst-first, each duration cited by its two
bounding timestamps. Pure analysis over readings you pass in (a good-part
completion stream from the MES / PLC counters); read-only, advisory.
Args:
good_parts: [{timestamp (ISO-8601), product}] — one per good part, any
order (sorted by time). A changeover is recorded at each product change.
Returns dict: {good_parts, ignored, changeover_count, changeovers:[{from, to,
start, end, durationS}], longest, avgDurationS, totalChangeoverS, note}.
Example: changeover_analysis(good_parts=[{"timestamp":"2026-07-12T08:00:00Z","product":"A"},
{"timestamp":"2026-07-12T08:45:00Z","product":"B"}]).
| Name | Required | Description | Default |
|---|---|---|---|
| good_parts | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it as readOnlyHint=true, and the description reinforces that it is 'read-only, advisory' and 'Pure analysis.' It explains the data requirement (good parts stream) and output structure. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
While well-structured with summary, args, returns, and example, the description is verbose. It includes repetitive phrases ('worst-first, each duration cited by its two bounding timestamps') that could be tightened. A 3 reflects adequate but not optimal conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With one required parameter and no output schema, the description covers all necessary context: input format, output dict structure with example, and clarifying notes. It is fully sufficient for an agent to use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description provides a detailed parameter description: 'good_parts: [{timestamp (ISO-8601), product}]' with ordering notes and an example. This fully compensates, making the parameter's semantics crystal clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it analyzes changeover/SMED durations between products. It explains what it measures (gap between last good part and first good part of next product) and how it relates to OEE. This distinct purpose makes it clear among sibling tools like oee_compute and downtime_events.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description specifies it works on a 'good-part completion stream' and labels it 'read-only, advisory.' It contrasts with OEE availability aggregations. However, it does not explicitly state when not to use it or list alternatives, so it falls just short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
compliance_dengbao_levelsARead-only
[READ][risk=low] 等保 2.0 二级 vs 三级 per-pillar deltas + honest iaiops posture.
等保 2.0 (GB/T 22239) is graded — the same control tightens as the level rises.
Per governance pillar this shows the 二级 baseline, what 三级 additionally requires,
and how far iaiops moves you toward it (with the honest per-control status/gap).
An onboarding/self-assessment aid, NOT a certification.
Args:
level: Focus on one level — 'l2'/'l3', '二级'/'三级', or '2'/'3'. Omit for both.
Returns dict: {framework, levels:[{id,name,note}], selected_level, pillar_count,
deltas:[{pillar, l2_requires?, l3_adds?, iaiops, iaiops_status, gap}], note}.
Example: compliance_dengbao_levels(level="三级").
| Name | Required | Description | Default |
|---|---|---|---|
| level | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only and non-destructive behavior. The description adds that it returns honest per-control status/gap, warns it is not a certification, and outlines the return dict structure. This goes beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is verbose but well-structured: a concise heading, explanatory paragraph, parameter details, return dict, and example. Every sentence adds value, though could be slightly tighter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (compliance framework with pillars) and lack of output schema, the description provides a complete return dict structure, parameter options, and usage context. It covers all necessary information for an AI agent to use it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description fully explains the parameter 'level': accepted values ('l2'/'l3', '二级'/'三级', '2'/'3'), default behavior (omit for both), and an example. This adds complete meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it shows per-pillar deltas between 等保 2.0 level 2 and level 3, with honest iaiops posture. It distinguishes itself from sibling tools like compliance_frameworks or compliance_report by focusing on level comparison and self-assessment. The verb is implicit but clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description indicates it is an onboarding/self-assessment aid, not a certification, suggesting use during compliance preparation. It does not explicitly list exclusions or alternatives but provides enough context to inform usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
compliance_evidence_bundleARead-only
[READ][risk=low] Export the audit-evidence bundle (zip) for an auditor.
Packages the governance evidence trail into one deterministic zip:
audit_rows.jsonl (secrets already redacted upstream), chain_verification.json
(SHA-256 hash-chain walk result), rules.yaml (if present), doctor_summary.json
(non-probing config/secret-store facts), and manifest.json. Path is validated
(no '..' traversal; parent created 0700).
Args:
out_path: Destination zip path (must end in .zip).
since: Optional ISO-8601 floor on the audit row timestamp (inclusive).
until: Optional ISO-8601 ceiling on the audit row timestamp (inclusive).
Returns dict: {path, row_count, chain{ok, checked, unhashed, ...}, files[],
since, until}.
Example: compliance_evidence_bundle(out_path="/tmp/evidence.zip",
since="2026-06-01T00:00:00+00:00").
| Name | Required | Description | Default |
|---|---|---|---|
| since | No | ||
| until | No | ||
| out_path | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and destructiveHint=false. The description elaborates on behavior: non-destructive, deterministic zip creation, path validation (no '..' traversal), parent directory creation with 0700 permissions, and redacted secrets. This adds useful context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with a clear purpose, a bullet-like list of package contents, parameter details, and an example. It is slightly verbose but front-loaded with the main action. Could be tightened slightly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description includes the return dict structure (path, row_count, chain, files, etc.). It covers all aspects needed for correct invocation: inputs, outputs, side effects (file creation), and an example. Comprehensive for a 3-parameter tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, but the description fully compensates by defining each parameter: out_path must end in .zip, since and until are optional ISO-8601 timestamps. An example further clarifies usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool exports an audit-evidence bundle (zip) for auditors, listing included files and deterministic nature. It distinguishes itself from sibling tools like compliance_report or export_data by specifying the bundle's content and purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description mentions it is for auditors with a READ risk level, indicating a safe read operation. While it doesn't explicitly state when not to use it or name alternatives, the context and sibling tools list imply it for compliance evidence gathering.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
compliance_frameworksARead-only
[READ][risk=low] 跨框架对照: 防护指南 ↔ 等保 2.0 (GB/T 22239) ↔ IEC 62443.
One row per governance pillar, showing the matching 《工控系统网络安全防护指南》
requirement, 等保 2.0 control class, IEC 62443 foundational requirement, and the
current iaiops status. Companion to compliance_mapping (which carries the honest
per-control gap); use this to answer "which 等保 / 62443 clause does this satisfy".
Returns dict: {frameworks:[{id,name,region,kind}], framework_count, pillar_count,
crosswalk:[{pillar, gjzn, dengbao, iec62443, iaiops_status}], note}.
Example: compliance_frameworks().
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds value by specifying it is a read operation with [READ][risk=low] and detailing the return structure, including the dict format and the crosswalk array. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is efficient, with a clear opening line, second paragraph explaining usage, and an example. It could be slightly more concise but every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters and no output schema, the description explains the return structure in detail, mentions companion tools, and gives an example. It is complete for a zero-parameter read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters, so schema coverage is 100%. The description adds value by providing an example call and explanation of the return value, meeting the baseline of 4 for zero-parameter tools.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it is a cross-framework comparison tool for 防护指南, 等保 2.0, and IEC 62443. It distinguishes itself from sibling compliance_mapping by noting that compliance_mapping carries per-control gaps while this tool provides the crosswalk.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells when to use this tool: 'to answer which 等保 / 62443 clause does this satisfy' and frames it as a companion to compliance_mapping. It lacks an explicit 'when not to use' but provides sufficient context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
compliance_mappingARead-only
[READ][risk=low] 《工控系统网络安全防护指南》 ↔ iaiops governance mapping.
An honest onboarding/sales self-assessment across the pillars 分区隔离 / 可审计 /
双向认证 / 最小权限 / 数据保护 / 自主可控. Each control names how iaiops addresses
it, an honest status (addressed / partial / 待核实), and the remaining gap.
Returns dict: {framework, frameworks[], pillars[], control_count, status_summary
{addressed, partial, 待核实}, controls:[{pillar, requirement, iaiops, status,
gap, crosswalk{dengbao, iec62443}}]}. See compliance_frameworks for the full
cross-framework 对照.
Example: compliance_mapping().
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false, so the safety profile is clear. The description adds value by detailing the return structure (dict with keys and example) and the pillars covered, without contradicting the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is relatively concise, starting with a helpful risk label and including only necessary information. Some jargon (Chinese characters) may add clutter, but the structure is clear and example is provided, earning a 4.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description sufficiently explains the return format and provides an example. It references a sibling for more details. For a parameterless read-only tool, this is adequately complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, so the description is not required to explain parameter semantics. According to guidelines, a baseline of 4 is appropriate, and the description does not introduce any misleading parameter information.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool maps a specific Chinese industrial cybersecurity guide to iaiops governance, using a specific verb ('mapping') and resource. It distinguishes itself from sibling tools like compliance_frameworks by referencing that tool for full cross-framework comparisons, and the example call helps clarify its standalone usage.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides context for when to use this tool ('An honest onboarding/sales self-assessment') and references an alternative (compliance_frameworks) for broader framework views. However, it does not explicitly state when not to use it or provide exclusions for specific scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
compliance_reportARead-only
[READ][risk=low] Render the 等保 2.0 / IEC 62443 compliance report (Markdown).
Turns the compliance crosswalk into a deliverable document a CISO can read:
title-page metadata (site / date / iaiops version), per-pillar 等保 L2/L3 status
table, IEC 62443 FR1–6 crosswalk, honest gap list, and a governance-controls
appendix (audit hash chain / approval tokens / dry-run+undo / mTLS). An
onboarding/self-assessment aid, NOT a certification.
Args:
level: 等保 2.0 target level — 'l2'/'l3', '二级'/'三级', '2'/'3'. Omit for both.
site: Site / plant name stamped on the title page.
out_path: Optional file to write the markdown to (.md). Required when the
report exceeds the inline bound (~400 lines): without it the inline
markdown is truncated with a note.
Returns dict: {format, level, line_count, path?} plus either the full inline
{markdown} (when within bounds and no out_path) or {markdown (truncated),
truncated: true} with a hint to pass out_path.
Example: compliance_report(level="三级", site="示例水厂",
out_path="/tmp/compliance-report.md").
| Name | Required | Description | Default |
|---|---|---|---|
| site | No | ||
| level | No | ||
| out_path | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
[READ] tag and annotations (readOnlyHint=true) consistently indicate read-only. Description further details truncation behavior, inline vs file output, and return format, providing full transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with sections for purpose, args, returns, and example. Slightly long but every sentence adds value; no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, description covers return dict and behavior. With strong annotations and parameter details, the tool is fully understandable for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 0% schema coverage, description adds full parameter semantics: accepted values for level, purpose of site, and condition for out_path. Example clarifies usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description explicitly states it renders compliance reports for 等保 2.0 / IEC 62443 in Markdown, with clear verb+resource. Distinguishes from siblings by specifying it produces a deliverable document, unlike compliance_frameworks or compliance_mapping.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Describes use as an onboarding/self-assessment aid (NOT certification) and explains out_path requirement for large reports. Lacks explicit mention of alternative tools, but context is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cross_protocol_asset_modelARead-only
[READ][risk=low] Fuse per-protocol tag feeds into ONE unified asset model.
Unifies the two per-protocol tag models (OPC-UA address-space discovery +
Modbus register templates) into one cross-protocol asset/tag/alias model. Tags
are re-classified with the SAME semantic classifier the OPC-UA layer uses,
grouped into assets ACROSS protocols (a ``Line1`` OPC-UA folder + a ``Line1``
Modbus block become one asset), and each gets a canonical alias
``<site>.<asset>.<class_or_name>``. Advisory only — aliases are SUGGESTIONS,
never a server-side rename (OT-dangerous).
Args:
feeds: List of per-protocol feeds, each
``{protocol, source, asset?, tags:[...]}``. ``tags`` may be OPC-UA
discovery descriptors (from opcua_discover_tags), Modbus template tags
(from modbus_apply_template), or already-normalized tags. A feed-level
``asset`` is applied to its tags that don't carry their own.
site: Site prefix for canonical aliases (default 'site').
Returns dict: {site, protocols, tag_count, asset_count, assets:[{asset,
protocols, tag_count, classes, tags:[{protocol, source, name, ref, asset,
unit, klass, canonical_alias, suggested_alias}]}], naming_quality:
{alias_collisions, cross_protocol_overlaps, cryptic_names, verdict}}.
Example: cross_protocol_asset_model(feeds=[
{"protocol":"opcua","source":"line1","tags":[...]},
{"protocol":"modbus","source":"meter1","asset":"Line1","tags":[...]}],
site="plant").
| Name | Required | Description | Default |
|---|---|---|---|
| site | No | ||
| feeds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false. Description adds that it's advisory only, aliases are suggestions, and never performs server-side rename (OT-dangerous). This provides good context beyond annotations, but lacks details on error handling or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections (Args, Returns, Example) and a front-loaded summary. It is slightly verbose but each sentence is informative and necessary for clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description details the return dict structure completely. It covers purpose, parameters, output, and an example, making it contextually complete for a tool with 2 parameters and complex behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description thoroughly explains both parameters: 'feeds' with detailed object structure and 'site' with default. It adds significant meaning that is absent from the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it fuses per-protocol tag feeds into a single cross-protocol asset model, distinguishing it from per-protocol tools like opcua_discover_tags and modbus_apply_template. It specifies actions like reclassification, grouping, and alias assignment.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use when unifying multiple protocol feeds into a single asset model. It provides an example but does not explicitly state when not to use or list alternatives. However, the sibling tools context suggests per-protocol alternatives exist.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
data_quality_fleet_rollupARead-only
[READ][risk=low] Cross-endpoint fleet rollup of data-TRUST: worst tags + bad quality.
Builds on data_quality_scorecard to give a fleet-wide view: endpoints ranked by
their single worst tag, bad-quality tag counts aggregated across every endpoint,
and a first-class liveness rollup (dead-heartbeat / flatline). Staleness and gap
budgets are configurable per tag (staleness_s / gap_threshold_s) and per feed,
so a slow daily counter is not judged like a 1Hz sensor. Pure analysis.
Args:
feeds: Per-endpoint feeds — {endpoint, staleness_s?, tags:[{ref, label?,
samples:[scalars or {value, good|quality, timestamp?}], expected_update_s?,
staleness_s?, gap_threshold_s?, flatline_after_s?, heartbeat?}]}.
default_staleness_s: Fallback max sample-age (seconds) before 'stale' when a
tag/feed sets no staleness_s/expected_update_s (default 300).
now: ISO-8601 reference time for staleness (deterministic); omit for now-UTC.
top_n: How many endpoints / bad-quality rows to return (default 10).
Returns dict: {evaluated_endpoints, evaluated_tags, fleet_score (0-100),
fleet_status, endpoints_ranked_by_worst_tag:[...], bad_quality_rollup:
{total_bad_quality_tags, endpoints_affected, by_endpoint:[{endpoint,
bad_quality_tags, fully_bad, partial_bad}]}, liveness_rollup:
{dead_heartbeat_count, flatline_count, dead_heartbeats[], flatlines[]},
issue_breakdown{}}.
Example: data_quality_fleet_rollup(feeds=[{"endpoint":"line1","tags":[{"ref":"t",
"samples":[{"value":None,"good":false}]}]}]).
| Name | Required | Description | Default |
|---|---|---|---|
| now | No | ||
| feeds | Yes | ||
| top_n | No | ||
| default_staleness_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and destructiveHint=false. The description adds that this is 'Pure analysis' and explains the deterministic behavior of the 'now' parameter. It also describes configurable thresholds, providing context beyond what annotations offer.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a one-line summary, Args section, Returns section, and Example. While it is relatively long, every part adds value. The Args section could be slightly more concise, but overall it is efficiently organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (nested parameters, no output schema), the description is complete. It details the return dictionary with all key fields (evaluated_endpoints, fleet_score, endpoints_ranked_by_worst_tag, bad_quality_rollup, liveness_rollup, issue_breakdown). It covers configuration and provides an example, ensuring the agent can understand and use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, but the description compensates fully. Each parameter (feeds, default_staleness_s, now, top_n) is explained in detail in the Args section, including the nested structure of feeds and default behaviors. An example further clarifies usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a clear summary: 'Cross-endpoint fleet rollup of data-TRUST: worst tags + bad quality.' It specifies the verb (rollup), resource (fleet-level data quality), and scope (worst tags, bad quality). It also distinguishes itself from sibling tools like data_quality_scorecard, indicating it builds on that tool for a fleet-wide view.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains that it gives a fleet-wide view and builds on data_quality_scorecard. It mentions configurable staleness and gap budgets, indicating when to adjust parameters. However, it doesn't explicitly state when not to use this tool or list alternatives, missing some guidance for selecting between siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
data_quality_scorecardARead-only
[READ][risk=low] Fleet data-TRUST scorecard across endpoints' tag feeds.
Scores each tag 0-100 on whether its data can be BELIEVED — staleness, dead
heartbeat, bad-quality, flatline, gaps, anomaly — then rolls up per endpoint
and across the fleet. NOT process health (it does not score whether a value is
alarming, only whether it is trustworthy). Pure analysis over provided feeds.
Args:
feeds: Per-endpoint feeds — {endpoint, tags:[{ref, label?, samples:[scalars
or {value, good|quality, timestamp?}], expected_update_s?, heartbeat?}]}.
default_staleness_s: Max sample-age before 'stale' when a tag sets no
expected_update_s (default 300).
now: ISO-8601 reference time for staleness (deterministic); omit for now-UTC.
Returns dict: {evaluated_endpoints, evaluated_tags, fleet_score (0-100),
fleet_status, issue_breakdown{}, worst_endpoints[], worst_tags[],
endpoints:[{endpoint, score, status, status_counts, worst_tag}]}.
Example: data_quality_scorecard(feeds=[{"endpoint":"line1","tags":[{"ref":"hb",
"heartbeat":true,"samples":[5,5,5,5]}]}]).
| Name | Required | Description | Default |
|---|---|---|---|
| now | No | ||
| feeds | Yes | ||
| default_staleness_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only and non-destructive. The description adds details about the analysis nature, deterministic now, and the scoring factors (staleness, dead heartbeat, etc.). No contradiction with annotations; it enhances transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: first sentence states purpose, then details, then parameter definitions, return description, and an example. Every sentence adds value, and it is front-loaded with key information. No redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity and absence of an output schema, the description adequately covers input parameters and return structure (dict with fields). An example is provided. It could be slightly more explicit about the return types, but it is sufficient for an agent to understand usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 0% schema description coverage, the description's Args section fully explains all three parameters: feeds structure (endpoint/tags/samples), default_staleness_s meaning and default, and now as ISO-8601 reference time. This compensates comprehensively.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool evaluates data trustworthiness for each tag (0-100) and rolls up per endpoint and fleet. It explicitly contrasts with process health, providing a specific verb-resource pair and distinguishing from siblings like alarm tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use: for assessing data trustworthiness, not process health. It provides context but does not explicitly name alternative tools like tag_health or heartbeat_health. However, the clear purpose implicitly guides usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
device_advisory_checkARead-only
[READ][risk=low] Which scanned devices fall inside a mounted advisory's stated range.
`iaiops scan` already reads vendor / model / firmware / serial and then does
nothing with them. This closes that loop — and deliberately stops short of
where a vulnerability scanner would go.
**It reports that a device falls inside an advisory's stated range. Nothing
more.** Not "vulnerable", not "exploitable", no severity score. Whether a
published issue is reachable on a particular machine depends on
configuration, network position and compensating controls that a read-only
scan cannot see — and in OT most advisories against a protocol stack are not
findings at all, because the stack is not reachable from anywhere that
matters. A report full of red text that ignores that gets switched off by the
site, and then the real one is missed too.
**No database ships with this.** A bundled CVE feed is a maintenance
commitment this repo has not made, and a stale one that looks current is
worse than none — so the library is a file the site controls, which also
makes it work air-gapped. Every entry must carry a source, and one bad entry
refuses the whole file rather than half-mounting it.
Four verdicts, and the middle two are the point: `in_affected_range`,
`version_unknown` (model matches, no firmware read — neither a hit nor a
pass), `version_unparsed` (a firmware string it will not invent an ordering
for), `not_affected`. A device no advisory mentions is **absent** from the
findings, not reported clean: "nothing known" is not "nothing there".
Args:
devices: [{ip?, vendor, model, firmware?}] — e.g. the `hosts` of a scan.
library_path: Path to the advisory file (YAML or JSON) this site mounted;
entries are {id, vendor, model, source, affected_below|affected_from|
affected_versions, title?}.
Returns dict: {devices_checked, advisories_mounted, devices_with_findings,
summary:{in_affected_range, version_unparsed, version_unknown,
not_affected}, findings:[{ip, vendor, model, firmware, advisory_id, title,
source, status, detail}], truncated, advisory_note, note}.
Example: device_advisory_check(devices=[{"ip":"10.0.0.5","vendor":"Siemens",
"model":"S7-1500","firmware":"2.8.1"}], library_path="~/advisories.yaml").
| Name | Required | Description | Default |
|---|---|---|---|
| devices | Yes | ||
| library_path | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, and the description aligns with them without contradicting them. It adds substantial behavior beyond annotations: four verdicts, the 'absent means nothing known' semantics, the strict library-file validation ('one bad entry refuses the whole file'), and the explicit refusal to infer vulnerability or severity.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long and includes a somewhat discursive OT-site anecdote, but the extra length is all relevant: it prevents misuse by over-eager agents. The structure is front-loaded with purpose, then warnings, verdicts, parameters, returns, and example, so an agent can stop after the first section if needed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema and 0% schema coverage, the description is unusually complete. It documents the exact return dict fields, the verdict semantics, the advisory library format, the absent-device behavior, the read-only safety profile, and usage prerequisites. No critical call-time information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the full burden, and it delivers. It explains the shapes of `devices` and `library_path`, lists the advisory entry fields, enumerates the affected-range field options, and includes a concrete example call. Without this, the schema's minimal types would leave agents guessing.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening line names a specific verb and resource: 'Which scanned devices fall inside a mounted advisory's stated range.' It also distinguishes itself from a vulnerability scanner by insisting it reports range membership only, not 'vulnerable' or 'exploitable'. This is clear and unique among the siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear usage context: it closes the loop after `iaiops scan` has read vendor/model/firmware/serial, and it deliberately stops short of vulnerability scanning. It does not name an explicit alternative sibling tool, but it provides enough context to know when this tool is appropriate and what it will not do.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
diagnose_dataflowARead-only
[READ][risk=low] Localize a 'no data' break across an endpoint's reachable hops.
Probes connect → read(ref) → freshness → variance and returns a verdict with
per-hop detail and a recommended action. The #1 OT triage: distinguishes
"cannot connect" (network/PLC down) from "comms OK but value stale"
(upstream/field/source) from "good status but flatline" (sensor stuck).
Args:
endpoint: Endpoint name from config (any protocol).
ref: Tag/node/address/device to read (OPC-UA node id, Modbus address,
S7 address string, MELSEC device). Omit to test connectivity only.
freshness_threshold_s: Max value-age (seconds) before 'stale' (default 60).
series: Optional injected samples (scalars or {value,timestamp}) for
flatline/variance reasoning when a live historian is out of reach.
flatline_eps: Spread at/below which a series counts as flatline.
Returns dict: {verdict ('cannot_connect'|'comms_ok_value_unreadable'|
'comms_ok_bad_quality'|'comms_ok_value_stale'|'comms_ok_flatline'|
'healthy'), diagnosis, recommended_action, hops:[{hop, ok, detail}]}.
Example: diagnose_dataflow(endpoint="line1", ref="ns=2;i=5", freshness_threshold_s=30).
| Name | Required | Description | Default |
|---|---|---|---|
| ref | No | ||
| series | No | ||
| endpoint | No | ||
| flatline_eps | No | ||
| freshness_threshold_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint, destructiveHint false; description adds '[READ][risk=low]' and details the probing steps (connect, read, freshness, variance). Discloses verdict categories and recommended action, going well beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections, uses formatting, includes an example, and every sentence adds value. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 5 parameters, no output schema, and no nested objects, the description covers all aspects: purpose, parameters, return value (including verdict enum and hop details), and an example. Complete and actionable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description explains every parameter in detail (e.g., ref can be various address types, series for injected samples, flatline_eps definition). Also provides an example call, fully compensating for the schema gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Localize a 'no data' break across an endpoint's reachable hops.' It distinguishes between different failure modes and clearly differentiates from sibling tools by focusing on data flow triage.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says it's the '#1 OT triage' for no-data issues and explains when to use it (e.g., omit ref to test connectivity only). Provides clear context for selection among many diagnostic siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
diff_alias_mapARead-only
[READ][risk=low] Diff a fresh discovery run against the adopted baseline.
Loads the site's previously adopted alias map, re-runs the cross-protocol
asset model over ``feeds``, and reports how the address space moved: tags
added / removed / renamed (same ref, new alias) / reclassified (same ref+alias,
new semantic class), plus a stable|changed verdict. Adopt a baseline first
with ``adopt_alias_map``.
Args:
feeds: Fresh per-protocol tag feeds (same shape as adopt_alias_map).
site: Site label whose baseline to diff against. Default 'site'.
Returns dict: {site, verdict, counts:{added,removed,renamed,reclassified},
added:[...], removed:[...], renamed:[...], reclassified:[...]}.
Example: diff_alias_map(feeds=[{"protocol":"opcua","source":"l1","tags":[...]}],
site="plant").
| Name | Required | Description | Default |
|---|---|---|---|
| site | No | ||
| feeds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, destructiveHint=false, aligning with the description's '[READ][risk=low]' tag. The description adds process details ('loads previous map, re-runs model, reports changes'), which goes beyond the annotations and provides useful behavioral context without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (overview, Args, Returns, Example), front-loaded with the core purpose. Every sentence adds value; no redundancy. It is appropriately sized for the complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description documents the return dict with keys and example values. It covers all necessary context: purpose, parameters, return format, prerequisite, and example usage. Complete for a read-only diff tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by explaining both parameters: 'feeds' as per-protocol tag feeds with shape reference, and 'site' including its default value. This adds significant meaning beyond the minimally typed schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses specific verbs ('diff', 'loads', 're-runs', 'reports') and clearly identifies the resource ('fresh discovery run against the adopted baseline'). It distinguishes itself from the sibling tool 'adopt_alias_map' by stating that adoption is a prerequisite.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly mentions the prerequisite ('Adopt a baseline first with adopt_alias_map') and provides an example. It implicitly tells when to use (after adoption) but does not explicitly state when not to use, though the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
downtime_attributionARead-only
[READ][risk=low] Which stoppage started it, and which ones were downstream of it.
RCA weights evidence by TIME alone — a signal before onset counts, one after
counts less. That is the honest half of the axis. Run `downtime_root_cause`
per asset after one upstream stop and every downstream machine comes back
with its own confident local root cause: each internally consistent, each
citing real signals, and all but one about a machine that stopped because it
was starved. The distinguishing fact is not in the evidence — it is the
line's topology.
Two rules decide an attribution and both must hold: the candidate must be
**declared upstream** of the asset, and it must have **stopped first**. An
upstream asset that stopped later cannot have caused an earlier stop, however
upstream it is.
Topology is declared, never inferred (D25). Co-occurrence on a production
line is guaranteed — everything stops together — so mining it for edges would
manufacture the causality this exists to remove. With no relations declared
every row comes back `not_evaluable` and the reason names the command that
fixes it. Assets the topology does not connect are left `unattributed` rather
than folded into the origin's column.
This ranks the stoppages; it does not diagnose the origin. Run
`downtime_root_cause` on the origin asset for that.
Args:
stoppages: [{asset, start, end?}] for one incident window (ISO-8601).
site: Which declared line topology to use (default "default").
max_lead_s: A downstream stop is attributed only if it began within this
many seconds of the upstream one (default 900).
Returns dict: {site, stoppages_evaluated, relations_declared, max_lead_s,
verdict ('origin'|'multiple_origins'|'unattributed'|'not_evaluable'),
origins, consequence_count, attributions:[{asset, start, status,
origin_asset?, hops_upstream?, lead_s?, explains?, detail}], advisory}.
Example: downtime_attribution(stoppages=[{"asset":"filler","start":"2026-01-05T06:00:00Z"},
{"asset":"capper","start":"2026-01-05T06:01:00Z"}]).
| Name | Required | Description | Default |
|---|---|---|---|
| site | No | default | |
| stoppages | Yes | ||
| max_lead_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it readOnly and non-destructive, and the description adds substantial behavioral detail beyond that: evidence is weighted by time alone, topology is declared never inferred, co-occurrence is deliberately not mined, unconnected assets are left unattributed, and the tool ranks rather than diagnoses. No contradiction exists between description and annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but earns its length: the motivating RCA example explains why topology matters, the two rules are crisp, and the Args/Returns/Example block is cleanly organized and front-loaded with purpose and risk. No sentence is redundant; the vivid explanatory paragraph clarifies behavior rather than padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema present, the description thoroughly documents the return dict, edge-case statuses like not_evaluable and unattributed, and the exact effect of missing topology declarations. It also gives an example call. This is complete enough for an agent to select and invoke the tool correctly without additional context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description fully compensates: it defines stoppages as [{asset, start, end?}] for one ISO-8601 incident window, explains site as the declared line topology with default 'default', and specifies max_lead_s as the downstream attribution window with default 900. It also documents the return dictionary structure and provides a concrete example.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear question that defines the tool's role — identifying which stoppage started an incident and which were downstream — and later states 'This ranks the stoppages; it does not diagnose the origin,' drawing a crisp boundary against downtime_root_cause. It names the specific resource (stoppages) and action (attribution/ranking), making it easy for an agent to distinguish from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly routes between this tool and downtime_root_cause: 'Run downtime_root_cause on the origin asset for that' and explains the failure mode when no relations are declared, including that the reason names the fixing command. It also states both rules that must hold, so an agent knows exactly when a candidate qualifies.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
downtime_eventsARead-only
[READ][risk=low] Detect running→stopped transitions and categorize stoppages.
Args:
series: Timestamped samples — {timestamp (ISO-8601), state} where state is
a string (RUNNING/IDLE/FAULT…), a bool, or a number.
category_map: Optional {state_label: category} override (else keyword
heuristics map to changeover/material/mechanical/quality/break/unknown).
min_duration_s: Ignore stoppages shorter than this (seconds).
Returns dict: {samples, event_count, total_downtime_s, by_category:{cat:
{count, downtime_s}}, events:[{start, end, duration_s, state, category}]}.
Example: downtime_events(series=[{"timestamp":"2026-06-28T08:00:00Z","state":"RUNNING"},
{"timestamp":"2026-06-28T08:05:00Z","state":"FAULT"}, ...]).
| Name | Required | Description | Default |
|---|---|---|---|
| series | Yes | ||
| category_map | No | ||
| min_duration_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds significant behavioral context beyond annotations: it declares risk level ([READ][risk=low]), explains categorization heuristics, the min_duration_s filtering, and the full return structure. No contradictions with annotations (readOnlyHint, openWorldHint, destructiveHint).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with summary, args, returns, and an example. It is slightly verbose, particularly the example, but every sentence is informative. It could be more front-loaded, but overall effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of the tool (3 parameters, no output schema), the description covers all necessary aspects: input format, optional overrides, threshold behavior, and the complete return structure. It provides enough detail for an agent to use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema description coverage at 0%, the description fully compensates by explaining each parameter in detail: series format, category_map override logic, and min_duration_s purpose. This adds substantial meaning beyond the schema structure.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool detects 'running→stopped transitions' and categorizes stoppages, using a specific verb and resource. It distinguishes itself from sibling tools like 'downtime_root_cause' or 'downtime_triage' by focusing on the detection and categorization step.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for use via the Args section, detailing the required series input. However, it does not explicitly state when not to use this tool or name alternative tools for different purposes (e.g., root cause analysis).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
downtime_root_causeARead-only
[READ][risk=low] AI downtime root-cause copilot — cited verdict, ADVISORY only.
Correlates whatever evidence you supply around a downtime/incident window —
alarm events, tag samples, a diagnose_dataflow verdict, a machine-state series —
ranks candidate root causes, and cites the REAL signals behind each. Read-first:
it proposes a human-approved, undoable (MOC-gated) action but executes nothing.
Anti-hallucination: only signals present in the input are cited; thin evidence
downgrades to 'insufficient_evidence' with a 'recommended_next_data' list rather
than a confident guess. Confidence combines independent, time-correlated evidence
(signals BEFORE onset outweigh signals during it).
Args:
window: {start (ISO-8601), end? (ISO-8601), asset?, category?}. If 'end' is
omitted but state_series is given, the first running→stopped span bounds it.
alarms: Alarm/condition events — {source, timestamp, message?, priority?, state?}.
tags: Per-tag samples — {ref, samples:[scalars or {value, good|quality}],
warn_high?, alarm_high?, ...} (scored via tag_health).
dataflow: A diagnose_dataflow result dict (its 'verdict' localizes comms vs field).
state_series: {timestamp, state} samples to bound the window if 'end' is absent.
lead_window_s: How far before onset a signal may sit and still count as a cause
(default 300s); signals after onset are treated as consequences.
cause_weights: Optional per-site {cause: multiplier} override (e.g. from
learn_cause_weights) — scales each cause's evidence (1.0 = neutral
default) before the noisy-OR. Unknown causes / non-numeric weights are
rejected; values are clamped. Omit for the shipped default weighting.
include_graph: When true, also return a 'graph' block — the SAME verdict
re-projected as a causal graph {nodes, edges, mermaid, meta} (signal →
cause → downtime) for a frontend/Grafana. Pure re-shape: signal→cause
edge weights are the evidence contribution scores, cause→symptom edge
weights are the hypothesis confidences — no new reasoning. Omit for the
flat verdict only (default).
When a per-site 'historian:' block is configured (~/.iaiops/config.yaml, A7),
the 2h pre-incident window is additionally pulled from that reader and scored
as historian trend evidence — cited with its source ('historian:<name>'),
window, and sample count. Without the config, behaviour is unchanged.
Returns dict: {window, verdict ('root_cause_identified'|'multiple_candidates'|
'insufficient_evidence'), primary_cause, hypotheses:[{cause, confidence (0..1),
confidence_band, evidence:[{signal, ref, at?, lead_time_s?, detail, weight}],
recommended_action}], evidence_summary, recommended_next_data?,
anti_hallucination, graph? (when include_graph): {nodes:[{id, kind
(signal|cause|symptom), label, score, ...}], edges:[{from, to, weight,
relation (supports|attributed_to)}], mermaid, meta}}.
Example: downtime_root_cause(window={"start":"2026-06-28T10:00:00Z","asset":"line1"},
alarms=[{"source":"M1_DRIVE","timestamp":"2026-06-28T09:59:50Z",
"message":"motor overload trip"}], dataflow={"verdict":"healthy"}).
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | ||
| alarms | No | ||
| window | Yes | ||
| dataflow | No | ||
| state_series | No | ||
| cause_weights | No | ||
| include_graph | No | ||
| lead_window_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description goes beyond by detailing anti-hallucination behavior, confidence combining, the advisory nature, and the historian config integration. It also mentions that actions are 'human-approved, undoable (MOC-gated)'. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured, with clear sections and a bold opening statement. It uses formatting to separate parameter details and return value. While some redundancy exists (e.g., repeating keywords), the complexity of the tool justifies the length. Minor improvements could improve conciseness without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 8 parameters, 6 optional inputs, nested objects, no output schema, and a large sibling context, the description covers all aspects comprehensively. It explains return value in detail, includes an example, and describes edge cases (historian config, cause_weights validation, include_graph behavior). The anti-hallucination and confidence logic are also detailed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries full burden for parameter semantics. It provides extensive explanations for each parameter, including window format, alarms, tags, dataflow, state_series, lead_window_s, cause_weights, and include_graph. The example further clarifies usage. This far exceeds minimal schema information.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it is an AI downtime root-cause copilot, read-only and advisory. It specifies it correlates evidence, ranks candidates, and cites real signals. The '[READ][risk=low]' prefix and 'ADVISORY only' make the purpose unambiguous, and it distinguishes from siblings like 'downtime_root_cause_live' by focusing on historical evidence analysis.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when you have evidence around a downtime window and need a cited verdict. It mentions it is read-only and advisory, but does not explicitly contrast with similar sibling tools like 'downtime_triage' or 'downtime_root_cause_live'. However, the detailed parameter descriptions and example provide enough context for appropriate usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
downtime_root_cause_liveARead-only
[READ][risk=low] AI downtime RCA copilot that GATHERS its own live evidence.
Same advisory, read-only, evidence-cited contract as downtime_root_cause — but
instead of hand-injecting evidence you give an endpoint + incident window and it
pulls the evidence itself: a cross-protocol diagnose_dataflow probe, a short
sampled series per ref (so flatline/bad-quality/anomaly surface via tag_health),
and active OPC-UA conditions. Light read load; non-destructive; nothing executed.
The gathered bundle is echoed under 'collected_evidence' (no hidden inputs).
Args:
endpoint: Endpoint name from config (any protocol). Omit for the default.
window: {start (ISO-8601), end?, asset?, category?, freshness_threshold_s?}.
refs: Tags/nodes/addresses to sample for this incident (first is also the
diagnose_dataflow target). Capped at 20.
sample_count: Reads per ref to build its series (1..60, default 8).
interval_ms: Delay between reads (>=50ms, default 200).
include_alarms: Surface active OPC-UA conditions as alarm evidence (OPC-UA only).
lead_window_s: Causal lead window before onset (default 300s).
include_graph: When true, also return the 'graph' block (same {nodes, edges,
mermaid, meta} causal-graph re-projection as downtime_root_cause). Pure
re-shape of the verdict; no new reasoning. Omit for the flat verdict.
Returns dict: same shape as downtime_root_cause plus 'collected_evidence'
{endpoint, protocol, refs_sampled, alarms_found, dataflow_verdict}.
Example: downtime_root_cause_live(endpoint="line1",
window={"start":"2026-06-28T10:00:00Z","asset":"line1"},
refs=["ns=2;i=5","ns=2;i=6"]).
| Name | Required | Description | Default |
|---|---|---|---|
| refs | No | ||
| window | No | ||
| endpoint | No | ||
| interval_ms | No | ||
| sample_count | No | ||
| include_graph | No | ||
| lead_window_s | No | ||
| include_alarms | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds significant detail: 'Light read load; non-destructive; nothing executed', 'gathered bundle echoed under collected_evidence (no hidden inputs)', and explains the probe types. This far exceeds the annotation baseline and provides complete behavioral disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a header, explanatory paragraph, bulleted list, return shape, and example. While slightly lengthy, every sentence adds value and the key information is front-loaded. Minor redundancy could be trimmed, but overall effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (8 params, no output schema), the description covers the return dict shape, parameter roles, and an example. It lacks full details on window subfields and error handling, but provides enough for correct invocation. The contrast with sibling and safety notes add completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description fully compensates by detailing all 8 parameters with types, defaults, and constraints (e.g., refs capped at 20, interval_ms >=50ms). Each parameter has clear meaning and purpose, making the schema's lack of descriptions irrelevant.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool is an 'AI downtime RCA copilot that GATHERS its own live evidence', with a specific verb (gathers) and resource (root cause analysis). It explicitly contrasts with the sibling tool downtime_root_cause by noting the evidence-gathering method, making its purpose distinct.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear guidance: use this tool when you have an endpoint and want automatic evidence gathering, as opposed to hand-injecting evidence. It names the alternative downtime_root_cause. However, it does not explicitly state when not to use it, leaving some ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
downtime_triageARead-only
[READ][risk=low] One-call downtime triage: first-look alarm + RCA cause + precursors.
Answers the operator's three simultaneous questions on a stopped line — which
alarm to look at first, the likely cause, and whether anything warned us —
then cross-checks whether the first-out alarm agrees with the RCA verdict.
Composes alarm_cascade + downtime_root_cause + pdm_forecast over ONE incident;
every field traces to a sub-report echoed under 'cascade'/'rca'/
'precursor_forecasts'. Read-first and advisory: it proposes but executes
nothing. Thin evidence downgrades honestly rather than guessing.
Args:
window: {start (ISO-8601), end?, asset?, category?}. If 'end' is omitted
but state_series is given, the first running→stopped span bounds it.
alarms: Alarm/condition events — {source, timestamp, message?, priority?,
state?}. Feeds BOTH the first-out cascade and the RCA.
tags: Per-tag samples — {ref, samples:[...], warn_high?, ...} (via tag_health).
dataflow: A diagnose_dataflow result dict (localizes comms vs field).
state_series: {timestamp, state} samples to bound the window if 'end' is absent.
precursors: Signals to check for a pre-incident trend — [{signal, series:
[scalars or {value, timestamp}], warn_high?, alarm_high?, warn_low?,
alarm_low?}]; each is run through pdm_forecast and kept only when it was
degrading/imminent before the trip.
cascade_window_s: Quiet gap (s) separating alarm cascades (default 60).
lead_window_s: Causal lead window before onset (default 300s).
cause_weights: Optional per-site {cause: multiplier} RCA override.
imminent_within_s: ETA horizon that marks a precursor 'imminent' (default 24h).
include_graph: When true, the echoed 'rca' sub-report also carries a 'graph'
block — the SAME verdict re-projected as a causal graph {nodes, edges,
mermaid, meta} (signal → cause → downtime) for a frontend. Pure re-shape;
no new reasoning. Omit to keep the flat rca summary (default).
Returns dict: {window, triage:{first_look:{source, ts, cascade_size, basis},
likely_cause:{cause, verdict, confidence, confidence_band,
recommended_action}, cross_check:{status ('corroborated'|'diverging'|
'no_alarm_root'|'no_rca_primary'), detail}, precursors_missed:[{signal,
status, direction, eta_to_limit, unit, limit}], recommended_next_data},
cascade:{...}, rca:{verdict, primary_cause, top_hypotheses, graph?},
precursor_forecasts:[...], anti_hallucination}.
Example: downtime_triage(window={"start":"2026-06-28T10:00:00Z","asset":"line1"},
alarms=[{"source":"M1_DRIVE","timestamp":"2026-06-28T09:59:50Z",
"message":"motor overload trip"}],
precursors=[{"signal":"M1_temp","series":[...],"warn_high":80}]).
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | ||
| alarms | No | ||
| window | Yes | ||
| dataflow | No | ||
| precursors | No | ||
| state_series | No | ||
| cause_weights | No | ||
| include_graph | No | ||
| lead_window_s | No | ||
| cascade_window_s | No | ||
| imminent_within_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and destructiveHint=false, and the description reinforces this by stating it 'proposes but executes nothing.' It adds context about evidence handling (downgrading on thin evidence) and cross-checking (first-out vs RCA). No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured: summary, parameter details, return format, example. It is front-loaded with the core purpose. While every section is informative, some minor redundancy exists (e.g., repeating 'Read-first' in both summary and args). Still efficient for a complex tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 11 parameters, no output schema, and nested objects, the description comprehensively covers inputs, outputs (return dict structure with sub-reports), and example usage. It addresses edge cases like missing 'end' window and optional graph output. This fully equips the agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries full burden. The 'Args' section explains each parameter's structure, purpose, and defaults in detail (e.g., window bounds, alarms events, precursor signals). This adds significant semantic meaning beyond the bare schema types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it performs 'One-call downtime triage: first-look alarm + RCA cause + precursors' and explains it composes alarm_cascade, downtime_root_cause, and pdm_forecast. This distinguishes it from sibling tools like alarm_cascade or downtime_root_cause individually.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description says 'Read-first and advisory: it proposes but executes nothing' and 'Thin evidence downgrades honestly rather than guessing.' It implies usage for initial triage, but lacks explicit when-to-use vs alternatives. However, the context of sibling tools and the tool's purpose makes it reasonably clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
eip_controller_infoARead-only
[READ][risk=low] Controller identity (proves the CIP link).
Args:
endpoint: Endpoint name from config (protocol 'ethernetip'/'eip'); omit for default.
plctype: Driver selector override — 'logix' (default), 'slc' (PLC-5/SLC-500/
MicroLogix, PCCC), or 'micro800'. Omit to use the endpoint's configured plctype.
Returns dict: {endpoint, host, slot, plctype, controller, info_error}. For
logix/micro800 controller carries {vendor, product_type, revision, serial,
product_name, name, ...}; for slc it carries {processor_type}.
Example: eip_controller_info(endpoint="slc05", plctype="slc").
| Name | Required | Description | Default |
|---|---|---|---|
| plctype | No | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial behavioral context beyond annotations by detailing return structure for different plctypes, the presence of info_error, and risk level. It fully discloses what the tool does and its outputs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a header, arguments, returns, and an example. Every sentence adds value, and it is appropriately sized without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of output schema and 0% schema coverage, the description is complete: it explains all parameters, return fields for different plctypes, and provides an example.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description compensates by fully explaining both parameters: endpoint (from config, default option) and plctype (override with possible values and default). This adds essential meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool retrieves controller identity to prove the CIP link. It distinguishes itself from sibling tools like eip_read_tag or eip_list_tags by focusing on identity rather than tag operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for reading controller identity but does not explicitly state when to use this tool versus alternatives. No direct comparison or exclusion criteria are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
eip_list_tagsARead-only
[READ][risk=low] Discover the controller's tags (Logix) or PCCC data files (SLC).
Logix/Micro800: enumerate the controller's symbol table without prior
knowledge (program-scoped tags appear as 'Program:<prog>.<tag>'). SLC/PCCC has
no symbol table, so the data-file directory (N7/B3/F8/... with element counts)
is returned instead.
Args:
endpoint: Endpoint name from config.
plctype: Driver selector override — 'logix' (default), 'slc', or 'micro800'.
Returns dict: logix → {endpoint, plctype, tag_count, tags:[{name, data_type,
tag_type, structure, dimensions}]}; slc → {endpoint, plctype, file_count,
files:[{file, elements, length}], directory_error, note}.
Example: eip_list_tags(endpoint="cell5"); eip_list_tags(endpoint="slc05", plctype="slc").
| Name | Required | Description | Default |
|---|---|---|---|
| plctype | No | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations, the description details divergent behaviors for Logix (symbol table) and SLC (data-file directory), mentions program-scoped tag notation, and outlines return structure, adding significant context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized, starting with a clear one-liner, then explaining PLC-specific behavior, parameter docs, return format, and examples, without unnecessary verbosity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite lacking an output schema, the description provides detailed return structures for both PLC types and example calls, covering most relevant aspects for a list tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema coverage at 0%, the description compensates by explaining endpoint and plctype parameters, including defaults and allowed values (logix, slc, micro800), adding meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists tags or PCCC data files, distinguishes between Logix/Micro800 and SLC/PCCC behaviors, and differentiates from sibling tools like eip_read_tag and eip_read_many.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implicitly indicates use for discovery, but does not explicitly state when to use vs alternatives or provide exclusions. It lacks direct guidance on selecting this tool over others.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
eip_read_manyARead-only
[READ][risk=low] Batch-read many tags/addresses in one request.
Args:
tags: Logix tag names (["Speed", "Temp", "Array[0]"]) OR SLC/PCCC
data-table addresses (["N7:0", "F8:0", "B3:0/0"]).
endpoint: Endpoint name from config.
plctype: Driver selector override — 'logix' (default), 'slc' (PCCC), or 'micro800'.
Returns dict: {endpoint, plctype, count, items:[{tag, value, type, error, good}]}.
Example: eip_read_many(tags=["Speed","Temp"], endpoint="cell5");
eip_read_many(tags=["N7:0","F8:0"], endpoint="slc05", plctype="slc").
| Name | Required | Description | Default |
|---|---|---|---|
| tags | Yes | ||
| plctype | No | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description includes '[READ][risk=low]' upfront, aligning with annotations (readOnlyHint=true, destructiveHint=false). It details the return format (dict with endpoint, plctype, count, items) and explains the meaning of each parameter. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, using a clear docstring structure. It front-loads key information (READ, risk low) and provides an example. Every sentence adds value without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (3 parameters, no output schema), the description is complete: it explains parameters, return format, and usage examples. It sufficiently covers what the agent needs to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully explains all three parameters: tags (with examples of Logix and PCCC formats), plctype (driver selector with enumerated values), and endpoint (name from config). This adds essential meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool is for batch-reading many tags/addresses in one request, specifying both Logix and SLC/PCCC address types. It includes a structured format with Args, Returns, and Example, making the purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for batch reads with 'Batch-read many tags/addresses in one request,' but does not explicitly state when to use this tool versus single-read alternatives like eip_read_tag. The example provides practical guidance, and sibling context partly fills the gap.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
eip_read_tagARead-only
[READ][risk=low] Read one tag/address with its type.
Args:
tag: Logix tag ('Conveyor.Speed', 'Array[3]', 'Program:Main.X') OR an
SLC/PCCC data-table address ('N7:0' int, 'B3:0/0' bit, 'F8:0' float,
'T4:0.ACC', 'N7:0{10}' slice).
endpoint: Endpoint name from config.
plctype: Driver selector override — 'logix' (default), 'slc' (PCCC), or 'micro800'.
Returns dict: {endpoint, plctype, tag, value, type, error, good}.
Example: eip_read_tag(tag="Conveyor.Speed", endpoint="cell5");
eip_read_tag(tag="N7:0", endpoint="slc05", plctype="slc").
| Name | Required | Description | Default |
|---|---|---|---|
| tag | Yes | ||
| plctype | No | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations (readOnlyHint=true, destructiveHint=false) align with the description. The description adds detail on the tag format, endpoint, driver override, and return dict structure, fully disclosing behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with header, Args, Returns, and Example. Each sentence is informative and concise, with no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description explains the return dict and provides examples, making the tool's usage complete and understandable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All three parameters (tag, endpoint, plctype) are clearly explained with examples and allowed values, even though schema coverage is 0%. Tag format includes Logix and SLC variants.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Read one tag/address with its type', specifying the action and resource. It distinguishes from sibling tools like eip_write_tag and eip_read_many.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies single-tag/address reading but does not explicitly state when to prefer this over other read tools (e.g., modbus_read_holding) or which protocols it supports beyond Logix/SLC/Micro800.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
eip_write_tagADestructive
[WRITE][risk=HIGH][MOC] Write ONE value to a tag/data-table address (off by default).
OT-DANGEROUS. Defaults to dry_run=True (nothing written). Captures the BEFORE
value (read-back) and records an undo descriptor so the change is reversible.
Set dry_run=False AND record an approver (OPCUA_AUDIT_APPROVED_BY) to apply.
未经授权勿对生产控制系统写入.
Args:
tag: Logix tag name OR SLC/PCCC data-table address ('N7:0', 'F8:0', 'B3:0/0').
value: Value to write (pycomm3 coerces to the tag's CIP/PCCC type).
endpoint: Endpoint name from config.
plctype: Driver selector override — 'logix' (default), 'slc' (PCCC), or 'micro800'.
dry_run: When True (default) returns a preview without writing.
Returns dict: dry-run → {tag, plctype, dry_run:true, before, would_write, note};
applied → {tag, plctype, dry_run:false, before, written, applied:true, _undo_id}.
Example (preview): eip_write_tag(tag="Setpoint", value=42, endpoint="cell5").
| Name | Required | Description | Default |
|---|---|---|---|
| tag | Yes | ||
| value | Yes | ||
| dry_run | No | ||
| plctype | No | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (readOnlyHint=false, destructiveHint=true), the description reveals: the tool is destructive by default unless dry_run is used; it captures the BEFORE value and creates an undo descriptor; it requires an approver for actual writes. This adds critical behavioral context that is not present in annotations alone, especially for a high-risk operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with Args, Returns, and Example sections, and it is front-loaded with a compact header. While it is long, every sentence serves a purpose—safety warnings, parameter details, return schemas. Minor suggestion: the Chinese line could be omitted without loss of clarity for English readers, but it does not detract significantly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (industrial write with high risk, no output schema, 5 parameters), the description covers purpose, safety, parameter semantics, return behavior (dry-run vs applied), and an example. It addresses all likely questions an AI agent would need to use the tool correctly and safely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates fully: it explains each parameter (tag: format examples, value: pycomm3 coercion, endpoint, plctype: valid values 'logix'/'slc'/'micro800', dry_run: behavior). This provides all necessary semantic information that the schema lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a clear verb-resource pair: 'Write ONE value to a tag/data-table address.' It specifies the scope (one value) and resource type, and the header '[WRITE][risk=HIGH][MOC]' immediately conveys the action and risk. The tool's name 'eip_write_tag' aligns perfectly with the description, and it is distinct from siblings like 'eip_read_tag' and 'eip_read_many'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states that by default dry_run=True (no writing), and that to actually write, one must set dry_run=False and record an approver. It includes a Chinese safety warning and 'OT-DANGEROUS' label. While it does not compare to alternative tools, the guidance on when to apply (and the safety precautions) is clear and sufficient for safe usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ethercat_master_stateARead-only
[READ][risk=low] Open the master on the configured NIC; report bus state.
Needs Linux + root/CAP_NET_RAW + a dedicated NIC + real slaves (pysoem extra).
Degrades to a teaching error dict if pysoem/permission/NIC/bus is missing.
Args:
endpoint: Endpoint name from config (protocol 'ethercat'); omit for default.
Returns dict: {endpoint, nic, master_state (INIT/PREOP/SAFEOP/OP/...),
expected_working_counter, slaves_found, slaves_expected, slave_count_ok}.
Example: ethercat_master_state(endpoint="bus1").
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=true, openWorldHint=true, destructiveHint=false. The description adds context about resource requirements and failure modes, which annotations do not cover. There is no contradiction; 'Open' refers to establishing a connection, not modifying data.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured, starting with a bold summary, then requirements, parameter info, return format, and an example. Every sentence provides necessary information without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with one optional parameter and no output schema, the description covers purpose, prerequisites, behavior, parameter, return value, and an example. It is fully self-contained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates by explaining the parameter 'endpoint' as 'Endpoint name from config (protocol 'ethercat'); omit for default.' This adds meaning beyond the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's action: 'Open the master on the configured NIC; report bus state.' It specifies a verb ('Open','report') and resource ('master on configured NIC'), and distinguishes from sibling tools like 'ethercat_slaves' by focusing on master state.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit prerequisites: 'Needs Linux + root/CAP_NET_RAW + a dedicated NIC + real slaves (pysoem extra).' It also describes degradation behavior: 'Degrades to a teaching error dict if pysoem/permission/NIC/bus is missing.' It does not explicitly contrast with alternatives but gives clear context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ethercat_read_pdoARead-only
[READ][risk=low] One cyclic snapshot of a slave's input process-data image.
Does a single send/receive cycle (never loops) and returns the input image.
Args:
slave: Zero-based slave index.
endpoint: Endpoint name from config.
Returns dict: {endpoint, slave, working_counter, input_byte_length, input_hex,
output_byte_length}.
Example: ethercat_read_pdo(slave=0, endpoint="bus1").
| Name | Required | Description | Default |
|---|---|---|---|
| slave | Yes | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds that it does a single cycle (never loops), which is informative beyond annotations. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely concise with clear sections: header, functionality, args, returns, and example. No unnecessary words, well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, behavior (single cycle), arguments, and return fields despite no output schema. Lacks error handling but overall sufficient for a read-only tool with good annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description explains each parameter: slave as zero-based index and endpoint from config. This adds meaning beyond type info, though it omits default values or constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it reads one cyclic snapshot of a slave's input process-data image with a single send/receive cycle. This distinguishes it from siblings like ethercat_read_sdo (SDO) or ethercat_slave_info (general info).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an example usage but does not explicitly state when to use this tool versus alternatives like ethercat_read_sdo or when not to use it. Context is clear but lacks exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ethercat_read_sdoARead-only
[READ][risk=low] CoE SDO upload: read one object-dictionary entry (acyclic).
Args:
slave: Zero-based slave index.
index: CoE object index (decimal, e.g. 0x1018 → 4120).
subindex: Sub-index (default 0).
size: Expected byte size (0 = let SOEM size it).
endpoint: Endpoint name from config.
Returns dict: {endpoint, slave, index, subindex, byte_length, hex, as_uint}.
Example: ethercat_read_sdo(slave=0, index=0x1018, subindex=1, endpoint="bus1").
| Name | Required | Description | Default |
|---|---|---|---|
| size | No | ||
| index | Yes | ||
| slave | Yes | ||
| endpoint | No | ||
| subindex | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false; the description adds value by noting 'risk=low', acyclic nature, and specifying the return dictionary format (endpoint, slave, index, subindex, byte_length, hex, as_uint), without contradicting annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise with only 6 lines, front-loaded with a [READ] tag and risk level, and includes an example. No redundant sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an acyclic read tool with 5 parameters and no output schema, the description covers purpose, parameters, and return value structure. It is sufficient to use the tool correctly without needing additional context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%; the description explains all 5 parameters in the Args section with details such as slave index being zero-based, index being decimal (e.g., 0x1018 → 4120), and size default behavior (0 = let SOEM size it), which the schema does not provide.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states '[READ] CoE SDO upload: read one object-dictionary entry (acyclic)', specifying the verb (read) and resource (object-dictionary entry), and distinguishes from siblings like ethercat_write_sdo and ethercat_read_pdo.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for acyclic reads via CoE SDO, but does not explicitly state when to use this tool versus alternatives like ethercat_read_pdo or ethercat_write_sdo, or provide exclusion criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ethercat_set_stateADestructive
[WRITE][risk=HIGH][MOC] Request an AL-state transition (off by default).
OT-DANGEROUS: moving to/from OP can START or STOP machine motion. Defaults to
dry_run=True. ``slave`` < 0 applies to the master (all slaves). Captures the
CURRENT state for undo. Set dry_run=False AND record an approver to apply.
未经授权勿对生产控制系统写入.
Args:
state: Target AL-state: INIT | PREOP | SAFEOP | OP (or a numeric code).
slave: Zero-based slave index, or -1 (default) for the whole master.
endpoint: Endpoint name from config.
dry_run: When True (default) returns a preview without changing state.
Returns dict: dry-run → {scope, dry_run:true, before, would_request, note};
applied → {scope, dry_run:false, before, requested, reached, applied:true}.
Example (preview): ethercat_set_state(state="OP", slave=0, endpoint="bus1").
| Name | Required | Description | Default |
|---|---|---|---|
| slave | No | ||
| state | Yes | ||
| dry_run | No | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses write nature, high risk, destructive hint, dry-run behavior, scope option, and current state capture. Complements annotations (readOnlyHint=false, destructiveHint=true) with additional context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with sections for warning, behavior, args, returns, and example. No redundant sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, description fully explains return dict for dry-run and applied cases. Covers edge cases like slave=-1 and default dry_run=True. Complete for a high-risk tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All four parameters are described with meaning and acceptable values (state: target AL-state; slave: zero-based or -1; endpoint: from config; dry_run: preview vs apply). Schema coverage 0% but description fully compensates.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it requests an AL-state transition for EtherCAT, specific states listed, and distinguishes from sibling tools like ethercat_slaves or ethercat_read_sdo by being a write operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly warns about risk of starting/stopping machine motion, defaults to dry_run, instructs to set dry_run=false and record approver for apply. Does not mention alternative tools for same operation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ethercat_slave_infoARead-only
[READ][risk=low] Detail one slave: identity, SM/FMMU config, OD summary.
Args:
slave: Zero-based slave index (from ethercat_slaves).
endpoint: Endpoint name from config.
Returns dict: {endpoint, index, name, vendor_id, product_code, revision,
config_addr, state, input_bytes, output_bytes, sync_managers[], fmmus[],
object_dictionary:[{index, name, entry_count}]}.
Example: ethercat_slave_info(slave=0, endpoint="bus1").
| Name | Required | Description | Default |
|---|---|---|---|
| slave | Yes | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true. The description adds a return format and risk tag, but does not elaborate on behavioral traits like side effects, authorization needs, or rate limits. The openWorldHint is not explained.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise: a one-line summary, followed by arg descriptions, return dictionary, and an example. Every sentence adds value, and the summary is front-loaded with the risk tag and purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and medium complexity, the description provides a detailed return structure covering endpoint, slave identity, config, sync managers, FMMUs, and OD summary. It lacks explanations of SM/FMMU semantics but provides an example, making it reasonably complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, but the description compensates by explaining 'slave' as a zero-based index from ethercat_slaves and 'endpoint' as an endpoint name from config. This adds meaningful context beyond the schema's type and default.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it details one slave's identity, SM/FMMU config, and OD summary. It uses a specific verb 'Detail' and resource 'one slave', distinguishing it from sibling tools like ethercat_slaves (list slaves) and ethercat_read_sdo (read SDO).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage after obtaining a slave list from ethercat_slaves, as it mentions 'from ethercat_slaves'. However, it does not explicitly state when to use this tool versus alternatives like ethercat_read_sdo or ethercat_read_pdo, nor does it provide when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ethercat_slavesARead-only
[READ][risk=low] Bus scan: enumerate every slave on the segment.
Args:
endpoint: Endpoint name from config (protocol 'ethercat').
Returns dict: {endpoint, slave_count, slaves:[{index, name, vendor_id,
product_code, revision, config_addr, state}]}.
Example: ethercat_slaves(endpoint="bus1").
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and destructiveHint=false. Description adds '[READ][risk=low]' and details return dict structure, example call. It does not contradict annotations and provides useful behavioral context beyond them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is extremely concise: two-sentence intro, then clear Args/Returns/Example sections. No wasted words, front-loaded with key info.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, parameter, return structure (with fields), and example. For a simple enumeration tool with no output schema, this is sufficient. Lacks details on possible slave states but acceptable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 0% description coverage, so description must compensate. It defines 'endpoint: Endpoint name from config (protocol "ethercat").' This adds meaning beyond schema (just 'string' with default null), clarifying the parameter's source and protocol constraint.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description starts with '[READ][risk=low] Bus scan: enumerate every slave on the segment.' This clearly states a read operation to enumerate all slaves, with specific verb 'enumerate' and resource 'slaves'. It distinguishes from sibling tools like 'ethercat_slave_info' (specific slave) and 'ethercat_master_state' (master state).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Description implies usage as a general bus scan but does not explicitly state when to use this tool versus alternatives like 'ethercat_slave_info' or 'ethercat_master_state'. No guidance on when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ethercat_write_sdoADestructive
[WRITE][risk=HIGH][MOC] CoE SDO download: write one OD entry (off by default).
OT-DANGEROUS. Defaults to dry_run=True (nothing written). ``value`` is a hex
string of the raw little-endian bytes (e.g. 'e803' = 1000 as uint16). Captures
the BEFORE value (SDO read-back) and records an undo descriptor. Set
dry_run=False AND record an approver to apply. 未经授权勿对生产控制系统写入.
Args:
slave: Zero-based slave index.
index: CoE object index (decimal, e.g. 0x607A → 24698).
value: Hex string of raw little-endian bytes to write.
subindex: Sub-index (default 0).
endpoint: Endpoint name from config.
dry_run: When True (default) returns a preview without writing.
Returns dict: dry-run → {slave, index, dry_run:true, before, would_write, note};
applied → {slave, index, dry_run:false, before, written, applied:true}.
Example (preview): ethercat_write_sdo(slave=0, index=0x607A, value="e8030000").
| Name | Required | Description | Default |
|---|---|---|---|
| index | Yes | ||
| slave | Yes | ||
| value | Yes | ||
| dry_run | No | ||
| endpoint | No | ||
| subindex | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate destructiveHint=true and readOnlyHint=false. The description confirms with 'OT-DANGEROUS' and explains the dry-run mechanism, capture of BEFORE value, and undo descriptor. No contradictions. It adds context about the high risk and safety features beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is relatively long but well-structured with a header, warning, parameter list, and return format. It is front-loaded with risk and purpose. Some redundancy (e.g., repeating 'dry_run') but justified for safety-critical tool. Could be slightly tighter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema, but the description explains the return dict for both dry-run and applied cases. Includes an example. Provides complete context for a complex write operation with safety implications. Leaves no major gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description explains all key parameters: slave (zero-based), index (decimal with example), value (hex string little-endian with example), dry_run (default true, behavior), subindex (default), endpoint (from config). It fully compensates for the missing schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the tool does a 'CoE SDO download: write one OD entry'. The prefix '[WRITE][risk=HIGH][MOC]' and the verb 'write' clarify the action. It distinguishes from siblings like ethercat_read_sdo.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description says 'Defaults to dry_run=True (nothing written)' and 'Set dry_run=False AND record an approver to apply.' This gives clear when-to-use guidance. It also includes a Chinese warning about unauthorized writes. It could explicitly mention when not to use, but the safety precautions are strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_dataARead-only
[READ][risk=low] Export collected samples from the LOCAL SQLite sink to a file.
Source is ~/.iaiops/data.db — the local queryable store written by
historian_push(sink="sqlite") — NOT a live device read. Writes csv (Excel),
sqlite (SQL browser / Power BI) or parquet (pandas/Spark; needs
pip install 'iaiops[export]'), and returns the file path + row count with a
bounded inline preview (first 200 rows max) so the response never floods.
Args:
fmt: 'csv' | 'sqlite' | 'parquet'.
since/until: Optional ISO-8601 time bounds (inclusive).
endpoint: Only samples from this endpoint label.
tag: Only samples for this tag.
limit: Max rows exported (1..100000; default 10000).
out_path: Output file; default ~/.iaiops/exports/iaiops-export-<ts>.<ext>.
Returns dict: {format, path, rows, preview_rows:[{ts, endpoint, protocol, tag,
value, quality, unit}] (≤200), preview_truncated}.
Example: export_data(fmt="csv", tag="line1.temp", since="2026-07-01T00:00:00").
| Name | Required | Description | Default |
|---|---|---|---|
| fmt | Yes | ||
| tag | No | ||
| limit | No | ||
| since | No | ||
| until | No | ||
| endpoint | No | ||
| out_path | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses behavioral traits beyond the annotations: it writes files (not destructive but creates files), returns file path and row count with a bounded preview, has a pip install dependency for parquet, and includes limits and defaults. This adds significant context that annotations alone (readOnlyHint, destructiveHint) do not cover.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a clear summary, source explanation, output details, parameter list, and example. While informative, it could be slightly more concise (e.g., the pip install detail might be secondary), but overall it efficiently communicates essential information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (7 parameters, no output schema but described return dict) and the rich annotations, the description is complete—it covers source, behavior, constraints, parameter defaults, output structure with preview, and an example. No critical gaps remain for successful invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by explaining each parameter: fmt with format options, since/until as optional ISO-8601 time bounds, endpoint/tag for filtering, limit with range and default, and out_path with default path. It also includes an example usage, making the parameters highly actionable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool exports collected samples from a local SQLite sink to a file, specifying the source and output formats. It distinguishes from sibling tools like historian_query (which returns data inline) and historian_push (which writes to sink) by explicitly noting the local store and file output.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description effectively explains when to use the tool: for exporting data from the local SQLite store to a file, not for live reads. It provides parameter details and an example, but lacks explicit exclusion criteria or direct comparisons to alternatives, such as noting that for real-time data, other tools like historian_query should be used.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fins_cpu_infoARead-only
[READ][risk=low] Omron CPU model/version via FINS 0501 (proves the link).
Args:
endpoint: Endpoint name from config (protocol must be 'fins'); omit for default.
Returns dict: {endpoint, model, version}.
Example: fins_cpu_info(endpoint="line2").
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Description adds context beyond annotations: specifies the FINS 0501 command, the 'proves the link' purpose, and the return dict structure. Annotations already declare readOnlyHint=true and destructiveHint=false; description adds concrete behavioral details without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two-line summary followed by Args, Returns, and Example. Every sentence is informative. No waste. Front-loaded with purpose and risk level.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with one optional parameter and annotations present, the description covers purpose, usage, parameter details, return shape, and example. No gaps given the low complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter with 0% schema coverage. Description adds meaning: endpoint name from config, protocol must be 'fins', and omit for default. This compensates for the lack of schema description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description explicitly states it reads Omron CPU model/version via FINS 0501 and proves the link. The verb 'reads' and specific resource 'CPU model/version' are clear. Distinguishes from siblings like s7_cpu_info by specifying protocol FINS.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clear that it is a read operation with low risk, and the usage context is implied by protocol FINS and the 'proves the link' phrase. However, no explicit when-to-use vs alternatives or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fins_cpu_statusARead-only
[READ][risk=low] Omron controller status via FINS 0601 (run/stop, mode, errors).
Args:
endpoint: Endpoint name from config (protocol must be 'fins').
Returns dict: {endpoint, status, mode, fatal_error_data, non_fatal_error_data}.
Example: fins_cpu_status(endpoint="line2").
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true and destructiveHint=false. The description adds that it reads via FINS 0601 and returns specific dictionary keys (status, mode, error data), which enriches understanding beyond the annotations. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: a one-line header, then Args and Returns sections, plus an example. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With one parameter, no output schema, and rich annotations, the description fully covers what the tool does, the input, and the output format. It is complete for effective use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must explain the parameter. It does: 'endpoint: Endpoint name from config (protocol must be fins).' This adds significant meaning about valid values, compensating for missing schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool reads Omron controller status via FINS 0601, covering run/stop, mode, and errors. It distinguishes from sibling tools like fins_cpu_info or fins_read_words by specifying the specific command and resource.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description mentions the endpoint must be from config with protocol 'fins' and provides an example, but does not explicitly state when to use this tool over alternatives like fins_cpu_info or fins_read_words. No when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fins_read_bitsARead-only
[READ][risk=low] Read bits from an Omron memory area (FINS 0101, bit codes).
Args:
area: Bit-capable area: "CIO", "W", "H", "A", or "DM".
address: Word address the first bit lives in, e.g. 0 for CIO 0.00.
bit: Bit number within the word (0..15).
endpoint: Endpoint name from config.
count: Number of consecutive bits (1..256).
Returns dict: {endpoint, area, address, bit, count, bits:[bool,...]}.
Example: fins_read_bits(area="CIO", address=0, bit=0, count=16).
| Name | Required | Description | Default |
|---|---|---|---|
| bit | No | ||
| area | No | CIO | |
| count | No | ||
| address | No | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds the FINS command code 0101 and 'risk=low', and details return format, providing behavioral context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: a title line, args list, return description, and example. Every sentence adds value with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 5 parameters and no output schema, the description explains parameters, return dict, and provides an example. It lacks only an explicit note on openWorldHint (external state dependency) but is otherwise thorough.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description provides clear, detailed explanations for all five parameters (area, address, bit, endpoint, count), including valid values and example. This fully compensates for missing schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Read' and the resource 'bits from an Omron memory area (FINS 0101, bit codes)'. It distinguishes from sibling tools like fins_read_words and fins_read_many by specifying bit-level reading.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for bit reads but does not explicitly state when to use this tool versus alternatives like fins_read_words or fins_read_many. Sibling differentiation is implied but not direct.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fins_read_manyARead-only
[READ][risk=low] Batched word reads over one FINS session (bounded).
Args:
endpoint: Endpoint name from config.
items: Read specs, each {"area": "DM", "address": 100, "count": 2}
(max 20 items, count capped at 500 each).
Returns dict: {endpoint, reads:[{area, address, count, words:[int,...]}]}.
Example: fins_read_many(items=[{"area":"DM","address":100,"count":2},
{"area":"CIO","address":0,"count":1}]).
| Name | Required | Description | Default |
|---|---|---|---|
| items | No | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds that it's bounded and risk low, providing context beyond annotations. It does not cover error behavior but is adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with Args, Returns, and an example, making it easy to parse. It is slightly verbose but still efficient for its content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description provides the return format. It covers input and output but omits error handling. Given the tool's simplicity and annotations, it is mostly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description fully explains both parameters: endpoint as a config name and items with a detailed structure including constraints (max 20 items, count capped at 500). This compensates fully.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it performs 'Batched word reads over one FINS session (bounded)', includes a READ tag, and distinguishes it from single-read siblings like fins_read_words and fins_read_bits.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description indicates it's for batched reads with explicit limits (max 20 items, count capped at 500), implying when to use it. It does not explicitly list alternatives, but the context is clear enough for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fins_read_wordsARead-only
[READ][risk=low] Read 16-bit words from an Omron memory area (FINS 0101).
Args:
area: Memory area: "DM", "CIO", "W", "H", "A", or "EM" (current bank).
address: Word address to start at, e.g. 100 for DM100.
endpoint: Endpoint name from config.
count: Number of consecutive words (1..500, capped server-side).
Returns dict: {endpoint, area, address, count, words:[int,...]} (unsigned 16-bit).
Example: fins_read_words(area="DM", address=100, count=8).
| Name | Required | Description | Default |
|---|---|---|---|
| area | No | DM | |
| count | No | ||
| address | No | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only and safe operation. The description adds behavioral detail: server-side capping of count (1..500) and the specific FINS command. It does not contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Structured layout with Args, Returns, Example. Every sentence adds value, no redundancy. Front-loaded with purpose and risk level.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers essential information: return format, parameter constraints, server-side cap. Lacks error conditions or handling of invalid inputs, but annotation openWorldHint suggests some flexibility. Sufficient for a read-only tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully explains all four parameters: area (with allowed values), address (example format), endpoint (from config), and count (range). Example reinforces usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a clear action verb 'Read' and specifies the resource '16-bit words from an Omron memory area', explicitly referencing the FINS 0101 command. This distinguishes it from sibling tools like fins_read_bits and fins_read_many.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives such as fins_read_bits or fins_read_many. The description implies usage for word-sized data, but lacks when-not or alternative recommendations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fins_write_wordsADestructive
[WRITE][risk=HIGH][MOC] Write 16-bit words to an Omron area (off by default).
OT-DANGEROUS. Defaults to dry_run=True. Captures the BEFORE values (read-back
of the same range) and records an undo descriptor. Set dry_run=False AND
record an approver (OPCUA_AUDIT_APPROVED_BY) to apply.
未经授权勿对生产控制系统写入.
Args:
area: Memory area to write: "DM", "CIO", "W", "H", "A", or "EM".
address: Word address to start at, e.g. 100 for DM100.
values: List of 16-bit word values to write (length 1..500).
endpoint: Endpoint name from config.
dry_run: When True (default) returns a preview without writing.
Returns dict: dry-run → {area, address, dry_run:true, before, would_write, note};
applied → {area, address, dry_run:false, before, written, applied:true, _undo_id}.
Example (preview): fins_write_words(area="DM", address=100, values=[1,2,3]).
| Name | Required | Description | Default |
|---|---|---|---|
| area | Yes | ||
| values | Yes | ||
| address | Yes | ||
| dry_run | No | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond annotations by detailing the dry_run safety mechanism, BEFORE value capture, undo descriptor recording, and requirement for an approver to apply writes. Annotations have destructiveHint=true, but the description enriches this with actionable safety behaviors. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a tag line, safety warnings, parameter details, return format, and example. Every sentence adds value; no fluff. The Chinese warning is context-specific but not excessive. Front-loaded with purpose and risk.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description thoroughly explains return values for both dry-run and applied modes, including undo descriptor. It covers safety protocol, parameter semantics, and provides an example. It is comprehensive for an agent to use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by explaining each parameter's meaning: area lists valid options, address gives an example, values specifies length bounds, dry_run explains default and effect, and endpoint indicates source. This is essential for correct usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool writes 16-bit words to an Omron area, with a specific verb ('Write'), resource ('16-bit words'), and scope ('Omron area'). It differentiates from siblings like fins_read_words and mc_write_words by specifying the protocol and data type. The [WRITE] tag reinforces the action.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides strong usage context: it's a dangerous operation defaulting to dry_run, requiring an approver to apply, and offering undo capability. However, it does not explicitly compare to sibling tools like fins_read_words or mc_write_words, leaving the agent to infer when to use this over alternatives. The 'OT-DANGEROUS' label and safety instructions give clear context but lack exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fleet_incidentsARead-only
[READ][risk=low] Roll up active RCA incidents across sites → fleet-wide top causes.
Aggregates the incidents each site reports into a fleet picture: how many incidents, which sites
are affected, and the most common root causes across the whole fleet. Read-only; no device I/O.
Args:
sites: Per-site reports carrying incidents: [{site, incidents:[{cause|primary_cause,
confidence?}]}].
Returns dict: {total_incidents, sites_with_incidents, affected_sites[], top_causes[]}.
Example: fleet_incidents(sites=[{"site":"plant-sh","incidents":[{"cause":"network"}]}]).
| Name | Required | Description | Default |
|---|---|---|---|
| sites | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true and destructiveHint=false. The description adds value by explicitly stating 'Read-only; no device I/O' and describing the aggregation behavior and return structure. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a summary tag and then provides structured sections (Args, Returns, Example). It is comprehensive without excessive wordiness. Each sentence contributes useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (single parameter, no output schema), the description fully covers the purpose, parameter structure, return format, and provides an example. No gaps remain for an agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, so the description must carry the full burden. It explains the 'sites' parameter as an array of objects with 'site' and 'incidents' fields, detailing the incident structure. This adds meaning beyond the bare schema. A slight deduction for informal formatting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Roll up' and the resource 'active RCA incidents across sites' to produce 'fleet-wide top causes'. It explains the aggregation purpose well. However, it does not explicitly distinguish this tool from similar sibling tools like 'fleet_status' or 'downtime_root_cause', so a perfect score is not warranted.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description indicates when to use the tool (to get a fleet overview of RCA incidents) and notes it is read-only with no device I/O. However, it does not mention when not to use it or suggest alternative tools for specific scenarios, leaving some ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fleet_statusARead-only
[READ][risk=low] Roll up per-site status reports into one fleet health view.
The tier above data_quality_fleet_rollup (per-endpoint within one site): this aggregates across
many edge SITES for central management. A site is 'offline' if its last_seen is older than
stale_after_s; fleet_status is the worst site status present. Read-only, pure; no device I/O.
Args:
sites: Per-site reports, each
[{site, location?, profile?, status?, score?, issues?, last_seen?}]; status ∈
ok|degraded|critical|offline (else derived from score); score 0..1.
stale_after_s: A site with no report newer than this is 'offline' (default 300).
now: Optional ISO-8601 'now' for deterministic staleness (default: current UTC).
Returns dict: {site_count, fleet_status, fleet_score, by_status, worst_sites[], sites[]}.
Example: fleet_status(sites=[{"site":"sh","score":0.9},{"site":"bj","status":"critical"}]).
| Name | Required | Description | Default |
|---|---|---|---|
| now | No | ||
| sites | Yes | ||
| stale_after_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true, openWorldHint=true, destructiveHint=false. Description adds 'Read-only, pure; no device I/O', aligns with annotations, and explains staleness logic and status derivation, adding value beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is well-structured with sections (Args, Returns, Example) and front-loaded with key tags [READ][risk=low]. Slightly verbose but every sentence adds value; could be slightly more concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, description details the return dict structure. All parameters are explained, an example is provided, and annotations cover safety. Completeness is high for a tool of this complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but description fully covers all three parameters: sites (structure, valid fields, derived status), stale_after_s (default 300), now (optional ISO-8601). Provides meaning, defaults, and constraints that the schema lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description explicitly states it rolls up per-site status reports into fleet health view, distinguishing from sibling data_quality_fleet_rollup (per-endpoint within one site) by specifying aggregation across sites.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Description clarifies it is the tier above data_quality_fleet_rollup, providing context for when to use this tool over alternatives, though it does not explicitly state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
health_summaryARead-only
[DEPRECATED → opcua_health_summary][READ][risk=low] Classify OPC-UA tags.
Classifies tag node-ids against warn/alarm thresholds. Returns
ok/warn/alarm/unknown counts plus the offending tags. Thresholds
come from config tags, or per-ref overrides in ``thresholds``.
Args:
endpoint: Endpoint name from config.
node_ids: Tag node ids to evaluate; omit to use configured tags.
thresholds: Optional {ref: {warn_high, alarm_high, warn_low, alarm_low}}.
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No | ||
| node_ids | No | ||
| thresholds | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, making the tool's safety profile clear. The description adds that it returns ok/warn/alarm/unknown counts and offending tags, and mentions that thresholds come from config or overrides, which enriches transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with deprecation and purpose, then provides a structured Args section. It is comprehensive but slightly verbose; however, the deprecation note and parameter details are all necessary. Well-organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 3 parameters and no output schema, the description adequately explains the return values (counts and offending tags) and how thresholds are set. It covers what the agent needs to know to use it correctly, given the absence of output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Since schema description coverage is 0%, the description carries the full burden for parameter semantics. It provides clear explanations for all three parameters: endpoint (from config), node_ids (omit for configured), and thresholds (optional with specific structure). This adds substantial meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: classify OPC-UA tags against thresholds and return counts. The resource is specified as tag node-ids, and it distinguishes from siblings via the deprecation note pointing to opcua_health_summary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The deprecation note explicitly tells the agent to use opcua_health_summary instead, providing clear alternative guidance. The context for use is implied by the classification function, but there is no explicit when-not-to-use statement, though the deprecation covers it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
heartbeat_healthARead-only
[READ][risk=low] Is a heartbeat/watchdog tag still alive? (liveness check).
A heartbeat must keep CHANGING; a flatlined one means the upstream is dead even
when comms/quality look fine. With timestamped samples + max_interval_s, also
flags the longest stall.
Args:
series: Heartbeat samples — scalars or {value, timestamp?} (a counter/toggle).
max_interval_s: Max allowed gap between changes; exceeding it = not alive.
Returns dict: {alive (bool), samples, distinct_transitions, spread,
longest_stall_s, reason}.
Example: heartbeat_health(series=[1,2,3,4,5], max_interval_s=10).
| Name | Required | Description | Default |
|---|---|---|---|
| series | Yes | ||
| max_interval_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds valuable behavioral context: it is a read operation with low risk, explains the flatlining concept, and that it also flags longest stall. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections for summary, args, returns, and example. It is slightly lengthy but each sentence adds value. Could be trimmed slightly, but overall efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (2 params, no output schema), the description covers input, output, behavior, and example comprehensively. It explains the concept of heartbeat liveness, making it complete for an agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by explaining both parameters: series (heartbeat samples as scalars or with timestamps) and max_interval_s (max allowed gap). It also provides an example, adding significant meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool checks if a heartbeat/watchdog tag is alive (liveness check). It explains the need for change to indicate liveness, distinguishing it from general health checks, but does not explicitly differentiate from similar sibling tools like tag_health.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for heartbeat tags that must change, but it does not provide explicit guidance on when to use this tool versus alternatives or when not to use it. Usage context is clear but lacks exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
historian_coverageARead-only
[READ][risk=low] Per-tag history coverage — what history do we actually have.
Answers the question every RCA starts with: which tags have stored history,
how many rows, and over what time span — per tag {rows, first_ts, last_ts}
from the same store historian_push writes. Read-only, bounded (tag list is
capped with a truncation flag); no device I/O.
Args:
reader: 'sqlite' | 'tdengine' | 'iotdb'. Omit to use the per-site
'historian:' block in ~/.iaiops/config.yaml, else the local sqlite
store. TSDB readers need their extra: pip install iaiops[tdengine|iotdb].
limit: Max tags returned (1..2000; default 500).
Returns dict: {reader, source, tag_count, tags:[{tag, rows, first_ts,
last_ts}], truncated} plus the standard return envelope
(items_returned, items_total, items_total_is_exact, is_truncated,
truncation_note).
Example: historian_coverage().
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| reader | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses behavioral traits beyond annotations: '[READ][risk=low]', bounded with truncation flag, no device I/O, and details on default reader configuration. Matches readOnlyHint=true without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with purpose, args, returns, example. Slightly longer due to thoroughness but every sentence adds value. Front-loaded with purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Complete for a read-only tool with 2 params and no output schema: covers purpose, arguments, return format, truncation behavior, and gives example.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Adds full meaning beyond schema: describes reader options (sqlite/tdengine/iotdb) with config fallback and pip install notes, and limit range (1-2000) with default. Compensates for 0% schema description coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states purpose: 'Per-tag history coverage — what history do we actually have.' Specifies verb 'Answers the question' and resource 'tags with stored history, rows, time spans.' Distinguishes from siblings like historian_push (write) and historian_query (query).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides usage context: 'Answers the question every RCA starts with' and notes it's read-only, bounded, no device I/O. Implicitly distinguishes from alternatives but lacks explicit when-not or alternatives list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
historian_healthARead-only
[READ][risk=low] Bad-tag / flatline / gap detection over a provided series.
Pure analysis over an injected sample series — no live historian needed.
Args:
series: Samples — scalars or {value, timestamp (ISO-8601), quality|good}.
gap_threshold_s: Time gap (seconds) between consecutive samples that counts
as a data gap (default 60).
flatline_eps: Spread at/below which the series counts as flatline.
Returns dict: {samples, numeric_samples, bad_quality_count, flatline (bool),
gap_count, gaps:[{after, gap_seconds}], stdev,
verdict ('ok'|'degraded'|'gappy'|'flatline'|'bad_tag')}.
Example: historian_health(series=[{"value":10,"timestamp":"2026-06-28T10:00:00Z"}, ...]).
| Name | Required | Description | Default |
|---|---|---|---|
| series | Yes | ||
| flatline_eps | No | ||
| gap_threshold_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses that the tool is a pure analysis (read-only) with low risk and no destructive actions. It explains that it operates over an injected series and details the return dictionary structure. This adds significant context beyond the annotations ('readOnlyHint': true, 'destructiveHint': false).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a clear header, purpose statement, parameter details, return value explanation, and an example. It is concise but comprehensive, with every sentence adding value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of an output schema, the description fully explains the return dictionary structure. All three parameters are described with details. The context signals (3 params, 1 required, 0% schema coverage) are compensated by the thorough description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description includes an 'Args' section that explains the meaning of each parameter, including defaults, format (ISO-8601 timestamps), and the 'quality' key in series elements. This goes well beyond the input schema, which only provides titles and types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool performs bad-tag, flatline, and gap detection over a provided series. It specifies a specific verb+resource combination and distinguishes itself from sibling tools like historian_query and tag_health by focusing on analysis over an injected sample series without requiring a live historian.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'no live historian needed,' indicating when this tool is appropriate for pure analysis. However, it does not provide explicit when-not-to-use or alternative recommendations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
historian_pushA
[WRITE][risk=low][→historian] Push collected telemetry to a national TSDB.
Writes already-collected points to a domestic historian (信创) — TDengine or
IoTDB — instead of binding InfluxDB. Data egress to the operator's OWN database,
NOT a control-system write. Non-numeric points are skipped (numeric value column).
Args:
points: Collected points — {ref|metric, value|present_value, timestamp?, ...}
(e.g. the output of interrogate / integrity_poll / read_points / monitor).
sink: 'tdengine' or 'iotdb'.
host/port/user/password: TSDB connection params (sensible defaults per sink
when blank/0).
database: Target database (TDengine db / IoTDB storage group, e.g. 'root.iaiops').
Returns dict: {sink, received, written, skipped_non_numeric, database}.
Example: historian_push(points=[{"ref":"line1.temp","value":21.5}], sink="tdengine",
host="10.0.0.20", database="iaiops").
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | localhost | |
| port | No | ||
| sink | Yes | ||
| user | No | ||
| points | Yes | ||
| database | No | ||
| password | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false (write), openWorldHint=true (flexible input), and destructiveHint=false. The description adds important behavior: non-numeric points are skipped and data goes to the operator's own database. It does not cover error handling or limits, but the added context is valuable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with headings and bullet points. It is front-loaded with the purpose and provides an example. Minor redundancy exists (e.g., [WRITE] prefix repeated), but overall it is efficient and clear.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (7 params, write operation) and no output schema, the description covers the essential aspects: purpose, parameter behavior, and return format. It could include more on error handling or authentication, but the provided example and Returns section are adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description's Args section explains all 7 parameters, including points, sink, connection details, and database. It also provides an example. This fully compensates for the missing schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'push' and the resource 'telemetry to a national TSDB'. It distinguishes itself from sibling tools like historian_query by specifying it writes collected points to TDengine or IoTDB, and explicitly mentions it is not a control-system write.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides context for when to use the tool: after collecting points to push to a domestic historian. It states what it does not do (not InfluxDB, not control-system write) and that non-numeric points are skipped. However, it does not explicitly mention when not to use or list alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
historian_queryARead-only
[READ][risk=low] Query a tag's historical samples from a historian.
Reads history back OUT of the store the sinks write — the local SQLite
store (~/.iaiops/data.db), TDengine, or IoTDB — so the RCA copilot / an
agent can see real pre-incident windows instead of only short live samples.
Read-only over the operator's OWN historian; no device I/O. Bounded: rows
are capped and a truncation flag is set when more history exists.
Args:
tag: Tag/metric name as stored by historian_push (e.g. 'line1.temp').
since/until: Optional ISO-8601 time bounds (inclusive).
endpoint: Only samples from this endpoint label (sqlite reader only —
the TSDB layout stores no endpoint label).
reader: 'sqlite' | 'tdengine' | 'iotdb'. Omit to use the per-site
'historian:' block in ~/.iaiops/config.yaml, else the local sqlite
store. TSDB readers need their extra: pip install iaiops[tdengine|iotdb].
limit: Max rows returned (1..10000; default 1000).
Returns dict: {reader, source, tag, since, until, rows,
samples:[{ts, endpoint, protocol, tag, value, quality, unit}], truncated}
plus the standard return envelope (items_returned, items_total,
items_total_is_exact, is_truncated, truncation_note). Trust
`is_truncated`: an empty `samples` with is_truncated=false means the
history really is empty, NOT that the result was cut short.
Example: historian_query(tag="line1.temp", since="2026-07-02T06:00:00Z",
until="2026-07-02T08:00:00Z").
| Name | Required | Description | Default |
|---|---|---|---|
| tag | Yes | ||
| limit | No | ||
| since | No | ||
| until | No | ||
| reader | No | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds beyond annotations: 'Read-only over the operator's OWN historian; no device I/O', 'rows are capped and a truncation flag is set', and explains empty samples with is_truncated=false meaning truly empty. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized: purpose, args, returns, example. Each section adds value without redundancy. It uses clear formatting and avoids unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description provides a detailed return format including the standard envelope and trust expectations. It covers all parameters, behavior, and an example, making it complete for a 6-parameter complex tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description provides detailed explanations for all 6 parameters: tag (example), since/until (ISO-8601 inclusive), endpoint (sqlite only), reader (values and default behavior), limit (range and default). It adds constraints and examples, fully compensating for missing schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Query' and the resource 'a tag's historical samples from a historian'. It specifies the storage backends (SQLite, TDengine, IoTDB) and use case (pre-incident windows), distinguishing it from sibling tools like historian_push (write) and opcua_read_history (different source).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use this tool (historical analysis, read-only, no device I/O) and mentions bounding and truncation. It notes extra install requirements for TSDB readers. However, it does not explicitly list alternative tools for when not to use this one, such as live sampling tools or other history readers.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ignition_alarm_statusARead-only
[READ][risk=low] Active/acknowledged alarm list (normalized).
Args:
base_url: Gateway HTTP base URL.
flavor: Gateway API deployment dialect — 'webdev' or 'gateway'.
secret_name: Secret-store key holding the API token (omit if none).
verify_tls: Verify the Gateway's TLS certificate (default True). Passing False
is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1.
Returns dict: {flavor, base_url, alarm_count,
alarms:[{name, source, priority, state, label, timestamp}]}.
Example: ignition_alarm_status(base_url="https://gw:8043", flavor="webdev").
| Name | Required | Description | Default |
|---|---|---|---|
| flavor | No | webdev | |
| base_url | Yes | ||
| verify_tls | No | ||
| secret_name | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds valuable behavioral context beyond annotations: marks as READ with low risk, describes return structure, and documents security constraints for verify_tls and secret_name. No contradictions with annotations (readOnlyHint, openWorldHint, destructiveHint).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Efficiently structured: READ tag, risk, purpose, then Args, Returns, Example. No redundant sentences; every line adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 4 parameters (1 required), annotations present, and no output schema, the description provides complete context: parameter explanations, return format, and an example call. Sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Each parameter is explained in the Args section with clear semantics (e.g., flavor choices, verify_tls default and override condition). Despite 0% schema description coverage, the tool description fully compensates by detailing all 4 parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description explicitly states action ('list'), resource ('alarms'), and scope ('active/acknowledged', 'normalized'). Clearly distinguishes from sibling tools like alarm_bad_actors or alarm_flood_analysis which perform different analyses.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Description implies usage for retrieving alarm status but does not specify when to use this tool over related alarm tools (e.g., alarm_flood_analysis, alarm_cascade). No direct guidance on exclusions or context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ignition_gateway_statusARead-only
[READ][risk=low] Gateway/module health + reachability (the Gateway doctor step).
Talks to the vendor SCADA/MES platform's Gateway HTTP web API (not OPC-UA —
that stays on the opcua connector). The API token is resolved from the
encrypted secret store by key name, never passed inline. Token-egress guard:
with a secret set, base_url must point at an internal host (private IP /
single-label / .local-style name) or a host the operator allowlisted via
IAIOPS_TOKEN_EGRESS_HOSTS — public hosts are refused before any request
(prevents stored-token exfiltration).
Args:
base_url: Gateway HTTP base URL, e.g. 'https://gw-host:8043'.
flavor: Gateway API deployment dialect — 'webdev' or 'gateway'.
secret_name: Secret-store key holding the API token (omit if none).
verify_tls: Verify the Gateway's TLS certificate (default True). Passing False
is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1.
Returns dict: {flavor, base_url, reachable, gateway:{name, version, state},
module_count, modules:[{name, state, version}]}.
Example: ignition_gateway_status(base_url="https://gw:8043", flavor="webdev").
| Name | Required | Description | Default |
|---|---|---|---|
| flavor | No | webdev | |
| base_url | Yes | ||
| verify_tls | No | ||
| secret_name | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses significant behavioral traits beyond annotations: it is a read operation (consistent with readOnlyHint), explains token egress guard, refusal of public hosts, and TLS verification constraints. It adds context about authentication and security that annotations alone do not provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is detailed and well-structured with a READ header, bullet list of args, and return format. While it is lengthy, every sentence adds value and the most important information is front-loaded. It earns a 4 because it is slightly verbose but still efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 4 parameters with 0% schema coverage and no output schema, the description provides comprehensive information: parameter explanations, return dict structure, and security context. It leaves no obvious gaps for an agent to misuse the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description fully compensates. It explains each parameter's purpose: base_url with example, flavor as API dialect with possible values, secret_name as secret-store key, and verify_tls with default and conditions for insecure. This adds critical meaning beyond the schema titles.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it checks gateway/module health and reachability, calling it the 'Gateway doctor step'. It specifies it talks to the vendor SCADA/MES platform's Gateway HTTP web API, distinguishing it from OPC-UA tools. The verb+resource is specific and unique among siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use this tool (gateway health check) and explicitly contrasts it with the opcua connector. It also details token resolution and egress constraints, though it does not explicitly list when not to use it. The differentiation from sibling tools is adequate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ignition_tag_browseARead-only
[READ][risk=low] Browse the tag tree under a provider/path.
Args:
base_url: Gateway HTTP base URL.
provider: Tag provider name (e.g. 'default').
path: Folder path under the provider to browse (blank = root).
flavor: Gateway API deployment dialect — 'webdev' or 'gateway'.
secret_name: Secret-store key holding the API token (omit if none).
verify_tls: Verify the Gateway's TLS certificate (default True). Passing False
is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1.
Returns dict: {flavor, base_url, provider, path, node_count,
nodes:[{name, path, type, has_children}]}.
Example: ignition_tag_browse(base_url="https://gw:8043", provider="default",
path="Line1").
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | ||
| flavor | No | webdev | |
| base_url | Yes | ||
| provider | Yes | ||
| verify_tls | No | ||
| secret_name | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and destructiveHint=false, and the description confirms [READ][risk=low]. It adds valuable context about verify_tls behavior (requires IAIOPS_ALLOW_INSECURE_TLS=1 to disable), which is beyond annotations. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded. Structure with Args/Returns and example is clear. Every sentence adds value, but could be slightly more concise (e.g., 'Returns dict' could be shortened without loss). Overall well-organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 6 parameters, no output schema, and high parameter complexity, the description covers return format (dict with fields), parameter details, and an example. Lacks edge case handling (e.g., invalid path, network errors) but sufficient for typical use. Annotations are rich, reducing burden.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so description carries full burden. It explains each parameter meaningfully: base_url as 'Gateway HTTP base URL', provider as 'Tag provider name (e.g. default)', path as 'Folder path under the provider (blank = root)', flavor as 'Gateway API deployment dialect — webdev or gateway', secret_name as 'Secret-store key holding the API token (omit if none)', verify_tls with TLS certificate verification and env var override. Adds significant value beyond schema types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it 'Browse the tag tree under a provider/path.' with READ and risk=low annotations. It specifically distinguishes from siblings like ignition_tag_read and ignition_tag_history by focusing on browsing the tree structure rather than reading values or history.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives like opcua_browse or uns_browse. Does not specify prerequisites, limitations, or when not to use it. The description only explains what it does, not why choose it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ignition_tag_historyARead-only
[READ][risk=low] Historian query for one tag over a time window (aggregated).
Args:
base_url: Gateway HTTP base URL.
provider: Tag provider name (e.g. 'default').
tag_path: Tag path whose history to query.
start: Window start (ISO-8601 or the gateway's accepted time string).
end: Window end (ISO-8601 or the gateway's accepted time string).
count: Max samples to return (1..5000, capped server-side).
flavor: Gateway API deployment dialect — 'webdev' or 'gateway'.
secret_name: Secret-store key holding the API token (omit if none).
verify_tls: Verify the Gateway's TLS certificate (default True). Passing False
is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1.
Returns dict: {flavor, base_url, provider, tag_path, start, end,
sample_count, samples:[{timestamp, value, quality}]}.
Example: ignition_tag_history(base_url="https://gw:8043", provider="default",
tag_path="Line1/OvenTemp", start="2026-07-13T00:00:00Z",
end="2026-07-13T06:00:00Z", count=200).
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | ||
| count | No | ||
| start | Yes | ||
| flavor | No | webdev | |
| base_url | Yes | ||
| provider | Yes | ||
| tag_path | Yes | ||
| verify_tls | No | ||
| secret_name | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true, openWorldHint=true, destructiveHint=false. Description adds security caveat about verify_tls and server-side cap on count, providing extra behavioral context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is structured with Args, Returns, Example sections. Front-loaded with type and risk. Slightly lengthy but efficient for a 9-parameter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 9 parameters (5 required), no output schema, and security caveat, the description covers all necessary information including return format and edge case for TLS verification.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but description fully documents each parameter with purpose, defaults, and constraints. Includes an example illustrating typical usage. Adds significant meaning beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'Historian query for one tag over a time window (aggregated)', specifying verb, resource, and scope. Distinguishes from siblings like real-time read or multiple-tag queries.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool vs. alternatives like 'historian_query' or 'ignition_tag_read'. Usage context is implied but not explicitly stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ignition_tag_readARead-only
[READ][risk=low] Current value(s)/quality/timestamp for tag path(s).
Args:
base_url: Gateway HTTP base URL.
provider: Tag provider name (e.g. 'default').
tag_paths: Tag paths to read (from ignition_tag_browse).
flavor: Gateway API deployment dialect — 'webdev' or 'gateway'.
secret_name: Secret-store key holding the API token (omit if none).
verify_tls: Verify the Gateway's TLS certificate (default True). Passing False
is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1.
Returns dict: {flavor, base_url, provider, tag_count,
tags:[{path, value, quality, timestamp}]}.
Example: ignition_tag_read(base_url="https://gw:8043", provider="default",
tag_paths=["Line1/OvenTemp"]).
| Name | Required | Description | Default |
|---|---|---|---|
| flavor | No | webdev | |
| base_url | Yes | ||
| provider | Yes | ||
| tag_paths | Yes | ||
| verify_tls | No | ||
| secret_name | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds behavioral context: it explains the security constraint on verify_tls (requiring IAIOPS_ALLOW_INSECURE_TLS=1 to disable), the return dict structure, and the risk level. This goes beyond annotations and provides useful behavioral transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: a one-line summary with risk tag, followed by Args, Returns, and Example sections. Every sentence adds value. It is front-loaded with the core purpose and uses clear formatting. There is no redundant or extraneous text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers input parameters, return structure (including nested tags array), an example call, and a security constraint. It lacks information on error handling or edge cases (e.g., what happens if a tag path is invalid). For a read-only tool with good annotations (readOnlyHint, openWorldHint), this is fairly complete but not fully exhaustive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden. It explicitly explains all 6 parameters in the Args section: base_url, provider, tag_paths (with origin mention), flavor (with dialect options), secret_name (optional), and verify_tls (with default and special condition). This adds significant meaning and context beyond the schema's type/name information.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with '[READ][risk=low] Current value(s)/quality/timestamp for tag path(s).' This clearly states the tool's purpose: reading live tag data. The verb 'read' and noun 'current value(s)/quality/timestamp' specify the action and resource. The example further clarifies usage. It distinguishes itself from siblings like 'ignition_tag_browse' (listed in siblings) by focusing on reading current values rather than browsing tags.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description mentions 'tag_paths: Tag paths to read (from ignition_tag_browse),' which implies a sequential use: browse first, then read. However, it does not explicitly state when to use this tool versus alternatives (e.g., 'ignition_tag_history' for historical data) or provide exclusions. The guidance is implicit but not comprehensive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
investigation_listARead-only
[READ][risk=low] List saved investigations, newest first.
| Name | Required | Description | Default |
|---|---|---|---|
| site | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds value by stating the ordering behavior ('newest first') and that only saved investigations are returned, which are not visible in annotations or schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is one short, front-loaded sentence with a useful READ tag prefix. Every word contributes meaning, and there is no redundant boilerplate.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list tool, the description covers the core action and ordering. However, the undocumented 'site' parameter is a real gap, and with no output schema or parameter guidance, the description is only minimally complete rather than fully self-sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description does not mention the 'site' parameter at all. An agent cannot determine whether 'site' filters results, groups them, or is required for certain contexts, so the description fails to compensate for the bare input schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a clear verb and resource: 'List saved investigations' plus an ordering detail ('newest first'). It distinguishes itself from siblings like investigation_show and investigation_open by focusing on listing rather than viewing or opening a specific investigation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes it clear that this tool is for listing saved investigations, which gives an agent a reasonable context for when to call it. It does not explicitly name alternatives or state when not to use it, but the action is straightforward enough that no exclusion is strictly required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
investigation_openARead-only
[READ][risk=low] Open an investigation over one past window and walk what can be walked.
Contacts no device — the window is already past, and its evidence is whatever
was collected at the time. Each of the eight steps records its own outcome:
`done` (it ran, here is what it found), `refused` (it could not run HERE —
no samples, no alarm source; a site fact) or `not_possible` (this product
cannot do it at all).
The investigation is persisted, so it can be re-read and advanced later.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | ||
| site | No | default | |
| asset | No | ||
| start | Yes | ||
| endpoint | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already indicate readOnly/openWorld/non-destructive, and the description adds important non-obvious behavior: no device contact, evidence collected at the time, per-step outcomes, and persistence. These details go well beyond the structured fields and materially help an agent understand side effects and failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with [READ][risk=low]. Each sentence contributes a distinct fact: past window, no device contact, outcome semantics, and persistence. There is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is behaviorally rich and partially compensates for the absent output schema by enumerating outcome states. However, with no output schema and 0% parameter documentation, it leaves endpoint/site/asset semantics and the identity of the eight steps unclear, so an agent has incomplete invocation detail.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the description gives no direct parameter guidance. 'Past window' loosely implies start/end define the time range, but endpoint, site, and asset are left unexplained, and no formats or value constraints are provided. With five parameters, this is a substantial gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and object: 'Open an investigation over one past window and walk what can be walked.' It clearly distinguishes itself from sibling investigation tools by emphasizing the window is past and that no device is contacted. The outcome taxonomy (done/refused/not_possible) further clarifies what the tool produces.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear usage context: use it for a past window, it does not contact a device, and it persists the investigation for later re-reading and advancement. However, it does not explicitly name alternative tools or state when not to use this tool, so it falls just short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
investigation_readinessARead-only
[READ][risk=low] How far into an investigation this site could get, and what each gap needs.
`readiness` answers "which scenarios can this site run"; this answers the
next question down — if something stopped tomorrow, how many of the eight
evidence steps could actually be walked, and for each one that could not,
what is missing.
Contacts nothing: no device, no network, no historian. It is derived from
the config and the local store, which is what makes it usable on a site
nobody has been authorised to probe yet.
Each gap says whether it is *unmet* (you have not supplied it — the fix names
the command) or *not yet expressible* (this product offers no way to supply
it at all). Those two send a person to very different places.
| Name | Required | Description | Default |
|---|---|---|---|
| site | No | default |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and destructiveHint annotations, the description discloses that the tool contacts no device, network, or historian and is derived from config and local store, explaining why it is safe on unauthorized sites. It also explains the two possible gap outcomes, unmet vs not yet expressible, giving the agent a clear picture of result semantics. There is no contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a READ/risk tag and a one-line summary, then uses short paragraphs to cover scope, safety, and gap semantics. Each paragraph earns its place, though the first two sentences are slightly repetitive in expressing the 'how far can this site go' idea.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers core behavior, safety, and output distinction between unmet and not-yet-expressible gaps well. However, with only one input parameter, omitting parameter guidance entirely is a meaningful gap, and there is no output schema to fill that in. The eight evidence steps are also left unnamed, though that may be acceptable product-domain knowledge.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema contains one `site` parameter with a default, but the description never mentions it or explains how to populate it. With 0% schema description coverage, the description needed to compensate and did not. The parameter name and default are somewhat self-evident, but the description adds no meaning about valid values, site identity, or how the default affects the analysis.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that investigation_readiness evaluates how far into an evidence-gathering investigation a site can currently get, and identifies what each missing gap needs. It explicitly contrasts itself with `readiness` (site_readiness), saying readiness answers which scenarios a site can run while this tool answers the next question down. This makes the tool's purpose specific and distinguishable from its sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear when-to-use condition: 'usable on a site nobody has been authorised to probe yet' because the tool contacts nothing and derives data from config and local store. It also distinguishes from the site_readiness sibling by describing the relationship between the two tools. However, it does not explicitly name alternatives for cases where live device, network, or historian probing is desired, so exclusion guidance is mostly implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
investigation_showARead-only
[READ][risk=low] Re-read a saved investigation — the state it was left in.
| Name | Required | Description | Default |
|---|---|---|---|
| investigation_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description's '[READ][risk=low]' mostly repeats that. It adds some behavioral context with 'the state it was left in,' indicating the tool returns the previously saved snapshot, but it does not disclose details like error behavior or what happens for missing/invalid investigation IDs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One concise sentence with no wasted words, and the read/risk profile is front-loaded. It conveys the core purpose and key distinguishing detail efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a simple one-ID read tool with annotations covering safety, so the bar is lower. However, with no output schema, the description only vaguely indicates the return ('the state it was left in') and does not explain what fields or format the saved investigation state will be returned in. It is minimally adequate but leaves a small gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description needs to compensate. It does not explicitly define investigation_id beyond the schema's 'Investigation Id' title, though the phrase 'a saved investigation' implies the ID refers to a previously saved investigation. The single parameter is self-explanatory enough, but the description adds little direct semantic detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Re-read'), a clear resource ('a saved investigation'), and a distinctive semantic ('the state it was left in'). This differentiates it from siblings like investigation_open and investigation_list, which involve opening or listing rather than re-reading a saved investigation by ID.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'a saved investigation' implies this is for resuming or inspecting an existing investigation, but the description does not explicitly say when to use it over investigation_open or investigation_list, nor does it mention when not to use it. Usage guidance is mostly implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
iolink_device_infoARead-only
[READ][risk=low] Identity of the IO-Link device on one master port.
Args:
port: Master port number (1..32).
endpoint: Endpoint name from config.
Returns dict: {endpoint, port, device:{vendorid, deviceid, productname,
serial, status}, unavailable?:{field: error}}.
Example: iolink_device_info(port=1, endpoint="master1").
| Name | Required | Description | Default |
|---|---|---|---|
| port | Yes | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. Description adds READ label, risk=low, and return dictionary structure. Discloses potential unavailable field. No contradiction; enhances transparency beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely concise: one-line summary, args, returns, and example. No superfluous text. Every sentence serves a purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema, but description fully documents return dict keys including optional 'unavailable' field. Covers both parameters. Could elaborate on endpoint default behavior (null). But overall, sufficient for a simple read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but description includes an Args section explaining both parameters: port (range 1..32) and endpoint (endpoint name from config). This adds meaning beyond the schema's type and default fields, compensating for low coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description explicitly states 'Identity of the IO-Link device on one master port' with a clear verb (read) and resource (device identity on port). Distinguishes from siblings like iolink_master_info (master info) and iolink_ports (port status).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Description implies usage (to get device identity for a specific port) but provides no guidance on when to use vs alternatives or when not to use. No explicit mention of preferred scenarios or comparisons with siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
iolink_master_infoARead-only
[READ][risk=low] IO-Link master identity (productcode/serial/hw/sw revision).
Reads the master's /deviceinfo tree over its JSON interface (ifm IoT-Core
envelope or plain REST, per the endpoint's flavor).
Args:
endpoint: Endpoint name from config (protocol must be 'iolink').
Returns dict: {endpoint, flavor, master:{productcode, serialnumber,
hwrevision, swrevision}, unavailable?:{field: error}}.
Example: iolink_master_info(endpoint="master1").
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and destructiveHint=false. The description reinforces this with '[READ][risk=low]' and details the JSON interface and return structure, adding context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with tags, summary, Args, Returns, and Example. It is concise but could slightly reduce redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of output schema, the description adequately explains the return dict including fields and the 'unavailable' error field. The example adds practical context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter 'endpoint' is described in the Args section as requiring a valid config endpoint with protocol 'iolink', adding meaning beyond the schema's type and nullability.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it reads IO-Link master identity with specific fields (productcode, serial, hw/sw revision). It distinguishes from siblings like iolink_device_info which targets individual devices.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description specifies the endpoint must be from config with protocol 'iolink', and provides an example. However, it does not explicitly say when to use this vs. alternative tools like iolink_device_info.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
iolink_portsARead-only
[READ][risk=low] BOUNDED port sweep: mode/status + connected device identity.
Call this first to see which ports carry an IO-Link device before reading
process data.
Args:
endpoint: Endpoint name from config.
count: Ports to sweep (1..32, capped server-side).
Returns dict: {endpoint, ports_checked, ports_present, devices_connected,
ports:[{port, present, mode, device_connected, device_status, vendorid,
deviceid, productname}]}.
Example: iolink_ports(endpoint="master1", count=8).
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. Description adds that it is bounded, count capped server-side, and includes risk=low. Returns structure is detailed, but lacks specifics on rate limits or error behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is concise: front-loaded with purpose and READ tag, followed by usage note, parameter list, return dict, and example. No redundant sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so description fully lists return fields. For a 2-parameter, 0-required tool, this covers all necessary context: purpose, parameters, return structure, and example.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so description must compensate. It briefly explains count (ports to sweep, range 1-32, capped) and endpoint (from config), but does not elaborate on possible endpoint values or origin.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it performs a bounded port sweep, reading mode/status and connected device identity. It includes a directive to call this first before reading process data, distinguishing it from sibling tools like iolink_read_isdu or iolink_read_pdin.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises to call this first to see which ports carry an IO-Link device before reading process data, providing clear usage context. Does not explicitly list when not to use or name alternatives, but the sibling list implies the workflow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
iolink_read_isduARead-only
[READ][risk=low] ISDU acyclic parameter read (iolreadacyclic) — bounded.
Args:
port: Master port number (1..32).
index: ISDU parameter index (0..65535).
subindex: ISDU subindex (0..255, default 0).
endpoint: Endpoint name from config.
Returns dict: {endpoint, port, index, subindex, value} (value typically a
hex string of the parameter octets; master-dependent).
Example: iolink_read_isdu(port=1, index=16, endpoint="master1").
| Name | Required | Description | Default |
|---|---|---|---|
| port | Yes | ||
| index | Yes | ||
| endpoint | No | ||
| subindex | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnlyHint, destructiveHint). The description adds 'bounded' and return value details but does not disclose other behavioral traits like error handling or performance characteristics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, front-loads the purpose, and includes an example. Every sentence adds value without repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose, parameters, return format, and an example. It lacks some contextual details like error conditions or endpoint usage, but for a simple read tool, it is largely sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 0% schema coverage, the description explains each parameter with ranges and defaults, adding significant meaning beyond the schema's bare types. This fully compensates for the schema gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it's a read operation for ISDU acyclic parameters with a specific verb and resource. It includes a hint about boundedness and provides an example, making the tool's purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not explicitly guide when to use this tool versus its siblings (e.g., iolink_read_pdin). It implies usage for acyclic reads but lacks when-not or alternative references.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
iolink_read_pdinARead-only
[READ][risk=low] Process-data-in of one port: raw hex + decoded byte array.
The byte layout is device-specific — decode per the device's IODD.
Args:
port: Master port number (1..32).
endpoint: Endpoint name from config.
Returns dict: {endpoint, port, pdin_hex, bytes:[int], byte_count, note}.
Example: iolink_read_pdin(port=1, endpoint="master1").
| Name | Required | Description | Default |
|---|---|---|---|
| port | Yes | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds [READ][risk=low] which aligns and provides return format details. It does not disclose additional behaviors like potential errors or rate limits, but given the simple read operation, this is adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is highly concise: one-line purpose, a crucial note, argument list, return structure, and an example. It is well-structured and front-loaded, with no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's low complexity (2 parameters, no output schema), the description covers purpose, parameters, return format, and an example. It lacks mention of error conditions or prerequisites (e.g., port must be configured for IO-Link), but overall it is sufficiently complete for a simple read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 0% description coverage, but the description provides explicit meaning for both parameters: port is 'Master port number (1..32)' and endpoint is 'Endpoint name from config'. This adds necessary context beyond the schema's type and default.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool reads process-data-in (PDIn) from an IO-Link port, returning raw hex and decoded byte array. It distinguishes from siblings like iolink_read_isdu by focusing on PDIn specifically, and the [READ] tag clarifies it is a read operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides an example and explains that byte layout is device-specific. However, it does not explicitly guide when to use this tool versus alternatives (e.g., iolink_read_isdu for acyclic data, iolink_device_info for device information). Usage context is implied but not directly differentiated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
iolink_scanARead-only
[READ][risk=low] One-shot BOUNDED snapshot: master identity + all ports.
Args:
endpoint: Endpoint name from config.
count: Ports to sweep (1..32, capped server-side).
Returns dict: {endpoint, flavor, master:{...}, ports_checked, ports_present,
devices_connected, ports:[{port, present, mode, device_connected, ...}]}.
Example: iolink_scan(endpoint="master1").
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds behavioral context: it is a one-shot snapshot, count is capped server-side, and returns a comprehensive dictionary of master and port information. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise yet includes purpose, parameter details, return structure, and an example. It is front-loaded with the core action. The inclusion of the return dictionary makes it slightly longer but necessary given no output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 2 parameters, no output schema, and simple read-only semantics, the description covers the essential aspects: purpose, parameters, return format, and an example. It is sufficient for an agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description adds meaningful explanations: 'endpoint: Endpoint name from config' and 'count: Ports to sweep (1..32, capped server-side)'. This clarifies usage and constraints beyond the schema's type and defaults.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it is a 'one-shot BOUNDED snapshot' of master identity and all ports, with a [READ] tag and risk=low. This differentiates it from sibling tools like iolink_master_info and iolink_ports which provide more focused or continuous data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description identifies the tool as a bounded snapshot, implying use for a quick summary rather than detailed or ongoing monitoring. It provides an example call but does not explicitly state when to avoid or what alternatives to consider, though sibling context suggests other tools for specific needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
learn_cause_weightsARead-only
[READ][risk=low] Learn a per-site RCA {cause: weight} profile from history.
Derives a per-site cause-weight profile from a corpus of CONFIRMED past
incidents so downtime_root_cause adapts to what THIS site's evidence actually
predicts. Pure + explainable: each weight is the smoothed signal→cause
precision relative to chance (>1 = evidence for that cause is reliable here,
<1 = often misleading) — no black box. Anti-overfit: Laplace smoothing + a
per-cause min-sample guard, and a fall-back to the shipped defaults when the
corpus is too thin. Feed the returned 'cause_weights' to downtime_root_cause's
cause_weights argument. Advisory: it tunes ranking, never executes anything.
Args:
history: Confirmed incidents — [{cause, signals:[...]}] where 'cause' is the
known root cause and 'signals' are the cause labels the evidence pointed
at (both from the copilot taxonomy: mechanical_fault, comms_loss,
sensor_fault, material_starvation, quality_reject, changeover, utility_fault).
min_samples: Minimum confirmed incidents before adapting at all (default 8);
below it the defaults are kept.
smoothing: Laplace pseudo-count pulling each estimate toward chance (default 1.0).
Returns dict: {cause_weights:{cause: multiplier}, n_incidents, per_cause:{cause:
{support, hits, precision, weight, note}}, rationale}.
Example: learn_cause_weights(history=[{"cause":"mechanical_fault",
"signals":["mechanical_fault"]}, {"cause":"comms_loss","signals":["comms_loss"]}]).
| Name | Required | Description | Default |
|---|---|---|---|
| history | Yes | ||
| smoothing | No | ||
| min_samples | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and destructiveHint=false. The description adds detailed behavioral context: pure + explainable, no black box, anti-overfit with Laplace smoothing, and that it never executes anything. This exceeds what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is moderately long but well-structured with a headline, sections, and clear formatting. It is informative without being overly verbose, though it could be slightly more concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity and lack of output schema, the description fully explains the return value (dict with cause_weights, n_incidents, per_cause details, rationale) and provides an example. It is complete for effective use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so description compensates well. It lists arguments with defaults and explains history format: [{cause, signals:[...]}]. It doesn't describe each property in detail but gives sufficient context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool learns a per-site RCA cause-weight profile from history. It specifies the verb 'Learn', the resource 'per-site RCA cause-weight profile', and distinguishes itself by providing a statistical profile to adapt downtime_root_cause.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance: 'Feed the returned cause_weights to downtime_root_cause's cause_weights argument.' and advises it only tunes ranking, never executes. It mentions fall-back when corpus is thin but does not explicitly compare with sibling tools like rca_corpus_from_maintenance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
line_relation_declareBRead-only
[READ][risk=low] Record that one asset feeds another — the second RCA axis.
`[READ]` follows this repo's convention, where the tag is about PLANT state:
it touches no device, exactly like `baseline_record_change` and
`adopt_alias_map`, which are the same shape. It does write — a declaration
about the line, into the site knowledge base.
With time alone, an upstream stoppage produces a string of equally-confident
downstream false causes, because on a line downstream co-occurrence is
guaranteed whatever the cause. That guarantee is exactly why this is a
declaration and not something inferred (D25): a person stating the line
order needs no inference at all.
``by`` is required — a person is the evidence, and an edge with no author is
indistinguishable from a guess a year later. Self-loops and cycles are
refused here, where somebody can still fix them.
| Name | Required | Description | Default |
|---|---|---|---|
| by | Yes | ||
| site | No | default | |
| upstream | Yes | ||
| downstream | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description explicitly says 'It does write — a declaration about the line, into the site knowledge base,' while annotations carry readOnlyHint: true. This is a direct contradiction and forces an agent to guess whether side effects occur. The added details about `by` and cycle rejection are useful but cannot offset the contradictory read/write signal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The summary is front-loaded in one sentence, followed by organized paragraphs on convention, rationale, and constraints. It is longer than strictly necessary due to the root-cause reasoning, but each paragraph earns its place and the structure helps an agent parse the key points.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a four-parameter write-like tool with no output schema and no parameter descriptions, the description covers purpose, direction, author requirement, and cycle restriction. But it omits what the call returns, the role/default of `site`, and how asset identifiers are expressed, and the read/write contradiction leaves a core uncertainty.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description must compensate. It gives direction meaning to upstream/downstream ('one asset feeds another'), explains why `by` is required, and notes cycles are refused. However, it never describes the `site` parameter or value formats, so not all parameters receive adequate semantic coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence 'Record that one asset feeds another' names a specific verb and resource, and the rest clarifies it is a person-authored declaration about line order rather than an inference. It is clear about the core operation, though it does not explicitly contrast itself with the sibling line_relations_list or other RCA tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives useful context: a person is the evidence, this is a declaration rather than something inferred, and self-loops/cycles are refused. However, it does not explicitly name alternative tools or state a when-not-to-use condition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
line_relations_listBRead-only
[READ][risk=low] The declared line order for a site, and what each asset feeds.
| Name | Required | Description | Default |
|---|---|---|---|
| site | No | default |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description's [READ][risk=low] tag repeats that safety profile. It adds a little context by specifying that results are based on declared order and feed relationships, but it does not disclose open-world behavior, default-site handling, or what happens when no declarations exist. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One short sentence plus a safety tag, with no filler. The essential content—declared order and feed relationships—is front-loaded and every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-optional-parameter read-only list tool, this is a minimally viable description. It tells an agent what the tool returns, but with no output schema it omits the return shape, the effect of omitting site, and any relationship to line_relation_declare.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description should compensate for the undocumented site parameter, but it only repeats that the data is 'for a site.' It does not explain accepted site values, the meaning of the 'default' value, or how the parameter changes the response.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description identifies a specific resource—the declared line order for a site—and adds that each asset's feed relationship is included, so the purpose of returning line-relation data is clear. It does not explicitly contrast itself with sibling line_relation_declare, but the read-only wording and the tool name make the distinction reasonably inferable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The word 'declared' implies this tool reads previously declared line relations, and the sibling name line_relation_declare hints at the complementary write operation. However, the description gives no explicit when-to-use guidance, prerequisites, or direct comparison with alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mc_cclink_link_readARead-only
[READ][risk=low] Read a CC-Link refresh image (RX/RY/RWr/RWw) via the master PLC.
Zero network membership: reads the PLC-side refresh image of the CC-Link /
CC-Link IE link devices over the existing MC/SLMP connection (docs/CCLINK.md).
Args:
template: Template name (see mc_cclink_templates), e.g. "cclink_ie_field_default".
endpoint: Endpoint name from config (protocol must be 'mc'); the CC-Link MASTER PLC.
overrides: Remap area head devices per the project's refresh parameters,
e.g. {"rx": "X1200", "rwr": "W200:8"} ("HEAD" or "HEAD:COUNT").
Returns dict: {endpoint, template, network, areas:[{area, device, kind, count,
label, values}], caveat}.
Example: mc_cclink_link_read(template="cclink_classic_default", overrides={"rwr": "W0:8"}).
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No | ||
| template | Yes | ||
| overrides | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only and safe behavior. The description adds that it 'reads the PLC-side refresh image' with 'Zero network membership' and uses an existing connection, providing behavioral context beyond the annotations without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is structured with a header, explanation, parameter list, return info, and example. It is front-loaded with purpose. Slightly verbose but clear; could be more concise without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description provides a detailed return dict structure and an example. It covers key aspects but lacks discussion of errors, edge cases, or prerequisites beyond 'existing connection'. Adequate for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so description bears full responsibility. It explains all three parameters well: template (with reference to templates list), endpoint (protocol constraint and role), overrides (with format example). This fully compensates for the lack of schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (read) and resource (CC-Link refresh image) with specifics (RX/RY/RWr/RWw). It distinguishes itself from sibling tools by focusing on CC-Link refresh over an existing MC/SLMP connection, which is unique among the many read tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides context for use ('Zero network membership', 'over the existing MC/SLMP connection') and an example, but does not explicitly state when not to use or directly mention alternatives. Implicitly it is for reading CC-Link refresh, but lacks explicit guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mc_cclink_network_healthARead-only
[READ][risk=low] Per-station CC-Link data-link health from the master's SB/SW registers.
Decodes the master's link special registers (classic CC-Link: SW0080–; CC-Link IE
Field: SB0049 own-station error + SW00B0– per-station + SW00A0– baton pass) into one
row per station — network RCA evidence with zero CC-Link hardware (docs/CCLINK.md).
Args:
endpoint: Endpoint name from config (protocol must be 'mc'); the CC-Link MASTER PLC.
network: "cclink" (classic) or "cclink_ie_field".
stations: Station numbers to decode, 1..N (classic max 64, IE Field max 120).
Returns dict: {endpoint, network, stations_checked, own_station_error, stations:
[{station, ok}], stations_in_error, baton_pass_lost, healthy, registers, source}.
Example: mc_cclink_network_health(network="cclink", stations=32).
| Name | Required | Description | Default |
|---|---|---|---|
| network | No | cclink_ie_field | |
| endpoint | No | ||
| stations | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations (readOnlyHint=true, destructiveHint=false) already indicate safe read-only behavior. Description adds value by detailing register sources (SW0080, SB0049, etc.) and the return structure (dict with stations, error flags, etc.), which goes beyond annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured: summary line, then explanatory paragraph, then Args section, then return dict description, then example. Every sentence adds value, no filler. Front-loaded with main purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, parameters, return format, and references documentation (docs/CCLINK.md). Lacks error conditions or edge cases (e.g., what if network mismatch or station out of range). For a tool with no output schema, the return dict description is helpful.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description's Args section explains all three parameters (endpoint, network, stations) with details on their types, defaults, and constraints (e.g., station range). This compensates for the schema lack and provides clear semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool's purpose: 'Per-station CC-Link data-link health from the master's SB/SW registers.' It specifies verb ('decodes'), resource (SB/SW registers), and scope (per-station health). Distinguished from sibling tools like mc_cclink_templates and mc_cclink_link_read by focusing on network health.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides context for use: 'network RCA evidence with zero CC-Link hardware.' Implies diagnostic use but does not explicitly state when to use it versus alternatives (e.g., mc_cclink_link_read) or when not to use it. No guidance on prerequisites or exclusion conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mc_cclink_templatesARead-only
[READ][risk=low] List CC-Link refresh-image templates (master-PLC route, no device I/O).
CC-Link/CC-Link IE data is read THROUGH the Mitsubishi master PLC (SLMP/MC) — see
docs/CCLINK.md. Each template is a documented default RX/RY/RWr/RWw ↔ PLC-device
layout; the real refresh assignment is per-project (待核实 per site).
Returns dict: {templates:[{name, network, description, areas, caveat}]}.
Example: mc_cclink_templates().
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and destructiveHint, but the description adds behavioral context: low risk, per-project variability, and return format, without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise: three sentences plus return format and example. Front-loaded with risk label, no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Complete for a parameterless tool: explains templates, notes per-project assignment, provides return structure, example, and reference to docs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, and schema coverage is 100%, so the description adds no param info, which is appropriate. The example call adds clarity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it lists CC-Link refresh-image templates, specifying it's a read of master-PLC route with no device I/O, which distinguishes it from other CC-Link operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this is for retrieving template definitions before other CC-Link operations, but does not explicitly state when to use or when not to use compared to sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mc_cpu_statusARead-only
[READ][risk=low] MELSEC CPU type/code (proves the MC link is alive).
Args:
endpoint: Endpoint name from config (protocol must be 'mc'); omit for default.
Returns dict: {endpoint, plctype, cpu_type, cpu_code}.
Example: mc_cpu_status(endpoint="cell3").
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true. Description adds '[READ][risk=low]' and 'proves the MC link is alive', providing useful behavioral context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Concise: one-line purpose, compact parameter and return docs, example call. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, parameter, return dict, example. Missing error handling details, but for a simple read-only tool it's adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Single parameter 'endpoint' has 0% schema coverage. Description clarifies it must be from config with protocol 'mc', and defaults allowed—adds meaning the schema lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it reads MELSEC CPU type/code and proves MC link is alive. It distinguishes from siblings like mc_read_words/data tools by focusing on status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies use for checking CPU status/connectivity. Doesn't explicitly list when not to use, but context from siblings (status vs data read/write) makes it clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mc_read_bitsARead-only
[READ][risk=low] Batch-read bit devices from a head device.
Args:
headdevice: MELSEC bit device, e.g. "M0", "X10", "Y20", "B0".
endpoint: Endpoint name from config.
count: Number of consecutive bits (1..256).
Returns dict: {endpoint, headdevice, count, bits:[bool,...]}.
Example: mc_read_bits(headdevice="M0", count=16).
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| endpoint | No | ||
| headdevice | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is clear. The description adds that it is low risk and returns a dict with bits, but does not elaborate on permissions, rate limits, or error handling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single well-structured paragraph with a risk tag, argument list, return type, and example. Every sentence adds value without waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with 3 parameters, the description adequately covers input and output format, including an example. However, it does not discuss error conditions or behavior on missing devices, which is acceptable given the tool's straightforward nature.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description compensates well by explaining each parameter: headdevice with examples, endpoint as 'from config', and count with a valid range. Minor lack of detail on endpoint nullability or config source.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it batch-reads bit devices from a head device, with a [READ] tag and low risk. It implicitly distinguishes from sibling word-reading tools, but no explicit differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides an example and lists arguments but offers no guidance on when to use this tool vs alternatives like modbus_read_coils or mc_read_words. No when-not-to-use or alternative recommendations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mc_read_manyARead-only
[READ][risk=low] Random-read scattered word + dword devices in one request.
Args:
endpoint: Endpoint name from config.
word_devices: Word device names, e.g. ["D100", "D200", "M0"].
dword_devices: Double-word device names, e.g. ["D300", "D400"].
Returns dict: {endpoint, words:[{device, value}], dwords:[{device, value}]}.
Example: mc_read_many(word_devices=["D100","D101"], dword_devices=["D200"]).
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No | ||
| word_devices | No | ||
| dword_devices | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. Description adds '[READ][risk=low]' and return format, but no additional behavioral insights beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is concise with a clear structure (summary, args, returns, example). Slightly redundant but efficient overall.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, parameters, and return format adequately. Lacks error/edge case details, but acceptable given low complexity and no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but description fully explains each parameter (endpoint, word_devices, dword_devices) with examples, adding significant value beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it reads scattered word and dword devices in one request ('Random-read scattered word + dword devices'), distinguishing it from siblings like mc_read_words (contiguous reads) and mc_read_bits.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implied usage: use when needing to read scattered word/dword devices from a Mitsubishi controller. No explicit when-not-to-use or alternatives are mentioned among the many sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mc_read_wordsARead-only
[READ][risk=low] Batch-read 16-bit word devices from a head device.
Args:
headdevice: MELSEC word device, e.g. "D100", "W10", "R0".
endpoint: Endpoint name from config.
count: Number of consecutive words (1..256, capped server-side).
Returns dict: {endpoint, headdevice, count, words:[int,...]} (signed 16-bit).
Example: mc_read_words(headdevice="D100", count=8).
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| endpoint | No | ||
| headdevice | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and destructiveHint annotations, the description adds that it returns signed 16-bit integers, the count is capped server-side, and the operation is a batch read. This provides useful behavioral context without contradicting annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise, front-loading the risk tag and purpose, then using a clear Args/Returns/Example structure. Every sentence serves a distinct purpose with no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 3 parameters, no output schema, and 0% schema coverage, the description is complete. It explains all parameters, the return format, and even provides an example, matching the tool's moderate complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has no descriptions (0% coverage), but the description fully explains all three parameters: headdevice (with examples like D100), endpoint (from config), and count (range 1-256, capped). An example invocation is also provided, leaving no ambiguity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'batch-read' and identifies the resource '16-bit word devices from a head device'. It clearly distinguishes this tool from siblings by focusing on word device batch reading, unlike mc_read_bits for bits or mc_read_many for mixed types.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for reading multiple consecutive words from a head device, listing parameters and an example. While it doesn't explicitly state when not to use it, the context of sibling tools (e.g., mc_read_bits, mc_read_many) makes the specific use case clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mc_write_wordsADestructive
[WRITE][risk=HIGH][MOC] Write 16-bit words from a head device (off by default).
OT-DANGEROUS. Defaults to dry_run=True. Captures the BEFORE values (read-back
of the same range) and records an undo descriptor. Set dry_run=False AND
record an approver (OPCUA_AUDIT_APPROVED_BY) to apply.
未经授权勿对生产控制系统写入.
Args:
headdevice: MELSEC word device to start at, e.g. "D100".
values: List of 16-bit word values to write (length 1..256).
endpoint: Endpoint name from config.
dry_run: When True (default) returns a preview without writing.
Returns dict: dry-run → {headdevice, dry_run:true, before, would_write, note};
applied → {headdevice, dry_run:false, before, written, applied:true, _undo_id}.
Example (preview): mc_write_words(headdevice="D100", values=[1,2,3]).
| Name | Required | Description | Default |
|---|---|---|---|
| values | Yes | ||
| dry_run | No | ||
| endpoint | No | ||
| headdevice | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (destructiveHint: true), the description details the safety mechanism (dry_run default, before values capture, undo descriptor) and the need for explicit approval, fully disclosing the tool's behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with header, warnings, args, returns, and example. The Chinese language adds some redundancy but the key information is front-loaded and clear.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers all necessary aspects: input parameters, behavior (dry-run vs apply), return value structure in both modes, and an example. No output schema but the description adequately describes the output.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description explains each parameter in the Args section (headdevice, values length range, endpoint, dry_run default) and provides an example, adding significant meaning beyond the schema which has 0% description coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Write 16-bit words from a head device' and differentiates itself from siblings like mc_read_words by emphasizing the write action and high risk.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidelines: defaults to dry_run, requires dry_run=false and an approver to apply. However, no direct comparison to other write tools (e.g., fins_write_words) for when to choose this over alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mechanism_library_checkARead-only
[READ][risk=low] What a mounted fault-mechanism library says about one candidate cause.
Three answers, and the difference between the first two is the whole point:
* ``nothing_known`` — the library has never heard of this cause. **Not** "no
objection": a knowledge base that knows nothing about something has not
cleared it.
* ``known``, not excluded — mechanisms for it apply here, with what would
confirm each.
* ``known``, excluded — every mechanism for it is inapplicable to this
equipment, so the candidate can be ruled out. That is the strong move a
ranker cannot make.
It never confirms. Raising a candidate to `confirmed` comes from outside the
ranking — a measurement, a reproduction, or a person (D29).
| Name | Required | Description | Default |
|---|---|---|---|
| site | No | default | |
| cause | Yes | ||
| protocol | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and openWorldHint annotations, the description explains the operational meaning of open-world semantics: nothing_known is not a clearance, and known/excluded is the only strong ruling-out move. It also states plainly that the tool never confirms a cause, which is critical behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a summary line, bullets, and no wasted words. The final D29 reference is cryptic but does not undermine the overall clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The three-answer semantics are explained thoroughly, which is essential because there is no output schema. Missing parameter guidance for site and protocol and the absence of explicit sibling routing leave operational gaps at low schema coverage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description must supply parameter meaning. It clarifies cause as a candidate cause but does not explain site or protocol, both of which appear in the schema with no descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool queries a mounted fault-mechanism library about one candidate cause and enumerates the three possible answers. This distinguishes it from sibling mechanism_library_list, though it uses a noun phrase rather than a direct action verb.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description establishes when this tool belongs in the workflow: during ranking it can mark a cause known or excluded, but it never confirms a cause. It gives an explicit when-not, though it does not name a specific alternative tool to use for confirmation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mechanism_library_listCRead-only
[READ][risk=low] The fault mechanisms mounted for a site, and where each came from.
| Name | Required | Description | Default |
|---|---|---|---|
| site | No | default |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description's [READ][risk=low] tags simply repeat that. The 'where each came from' hint gives some output-context, but the description adds no behavioral detail beyond annotations such as pagination, filtering, or side-effect notes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The main sentence is compact and front-loaded with the core meaning. However, the '[READ][risk=low]' prefix is redundant with the annotations and adds noise, preventing a perfect score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with one optional parameter, this is minimally usable: it communicates the subject and what output to expect at a high level. But without an output schema, it should more clearly describe the return structure and what 'where each came from' means in practice.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for the undocumented 'site' parameter. It only weakly connects to the parameter with the phrase 'for a site', but gives no details about valid values, format, or behavior when omitted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the resource ('fault mechanisms mounted for a site') and adds the provenance scope ('where each came from'), which is specific enough to understand the tool's purpose. However, it does not explicitly differentiate itself from the sibling mechanism_library_check, so it loses the fifth point.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives such as mechanism_library_check. The phrase 'for a site' implies a contextual use, but no explicit conditions, exclusions, or alternative tools are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
modbus_apply_templateARead-only
[READ][risk=low] Read a register block and decode it into named tags via a template.
Args:
template: Template name (see modbus_list_templates).
endpoint: Endpoint name from config.
address: Absolute address of the first register read (aligns to offsets).
count: Registers to read; omit to use the template's span.
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| address | No | ||
| endpoint | No | ||
| template | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true and destructiveHint=false. The description adds a '[READ][risk=low]' label consistent with annotations, but does not disclose additional behavioral traits beyond the decoding process. No contradiction, but limited extra value.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise paragraph with a clear front-loaded purpose and bullet-like argument listing. Every sentence adds value, no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 4 parameters, no output schema, and annotations covering read-only/non-destructive, the description adequately covers purpose, parameters, and references a related tool. It does not detail return format, but that is acceptable given the template context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must fully explain parameters. It does: template (from list), endpoint (from config), address (absolute, aligns to offsets), count (optional, defaults to template span). This adds significant meaning beyond the bare schema types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action: 'Read a register block and decode it into named tags via a template.' It distinguishes from sibling tools like modbus_read_holding by emphasizing the template-based decoding. References modbus_list_templates for template names, providing clear context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains each argument and notes that 'count' is optional (defaulting to template's span). It implicitly guides when to use this tool (when you want decoded tags via a template) versus raw reads. Could be more explicit about when not to use it, but the context is adequate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
modbus_detect_byte_orderARead-only
[READ][risk=low] Auto-detect the word/byte order of a raw Modbus register block.
Pure decode logic (no device): decodes the raw registers under every candidate
order for the numeric type and scores them against a known/expected value
and/or a plausible range. Solves the "right registers, wrong endianness" pain.
Args:
registers: Raw 16-bit register values (e.g. from modbus_read_holding).
value_type: uint16|int16|uint32|int32|float32.
hint: A known/expected sample value to match against.
value_min: Lower bound of a plausible value band.
value_max: Upper bound of a plausible value band.
| Name | Required | Description | Default |
|---|---|---|---|
| hint | No | ||
| registers | Yes | ||
| value_max | No | ||
| value_min | No | ||
| value_type | No | float32 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds that it is 'pure decode logic (no device)' and explains the scoring mechanism, providing useful behavioral context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise with a header, a brief paragraph, and a bulleted parameter list. No unnecessary fluff, though slightly more compact could be possible.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description explains what the tool does and its parameters, but does not explicitly document the return value (detected order and scores). With no output schema, this omission reduces completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description includes a detailed 'Args:' section explaining each of the 5 parameters (registers, value_type, hint, value_min, value_max), compensating for the 0% schema description coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Auto-detect the word/byte order of a raw Modbus register block.' with a specific verb (detect) and resource (raw register block), differentiating from siblings that read from devices.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains 'Pure decode logic (no device)' implying it should be used when register values are already obtained. It mentions the pain point it solves, but does not explicitly exclude use cases or list alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
modbus_health_summaryARead-only
[READ][risk=low] Classify Modbus registers against warn/alarm thresholds.
Mirrors the OPC-UA health_summary classifier. Returns ok/warn/alarm/unknown
counts plus offenders.
Args:
endpoint: Endpoint name from config.
addresses: Register addresses to evaluate; omit to use configured tags.
thresholds: Optional {address_str: {warn_high, alarm_high, ...}}.
register_type: holding|input.
decode: uint16|int16 — how to interpret each register before
threshold comparison (int16 for bipolar/signed tags).
| Name | Required | Description | Default |
|---|---|---|---|
| decode | No | uint16 | |
| endpoint | No | ||
| addresses | No | ||
| thresholds | No | ||
| register_type | No | holding |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only, safe, non-destructive behavior. The description adds that it is a read operation with low risk, explains the decode parameter for signed registers, and mentions the return of counts and offenders. This goes beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, starting with a clear tag and purpose, followed by a bullet-like list for arguments. Every sentence adds value, and no unnecessary words are present. It is well-structured for quick parsing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of output schema and 0% schema coverage, the description adequately covers inputs and behavior. It explains what the tool returns (counts and offenders) but could benefit from more explicit output structure details. Nonetheless, it is sufficient for an agent to understand and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by explaining all 5 parameters in detail. It describes the endpoint, addresses (with note to omit for configured tags), thresholds (with format), register_type, and decode (including int16 for signed tags). This is comprehensive.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it classifies Modbus registers against thresholds, specifying a verb and resource. It distinguishes itself from siblings like 'opcua_health_summary' by explicitly targeting Modbus. The return of counts and offenders is also specified.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for Modbus register classification and notes it mirrors the OPC-UA version, but lacks explicit guidance on when to use it versus alternatives like 'health_summary' or other protocol-specific tools. However, the provided details are sufficient for an agent to understand its context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
modbus_list_templatesARead-only
[READ][risk=low] List built-in vendor register-map templates (name / type / tags).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true and destructiveHint=false; the description adds 'risk=low' and clarifies it returns template metadata, which is consistent and slightly extends transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence that is entirely on point, with no unnecessary words or content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only listing tool with annotations covering safety, the description suffices: it tells what the tool lists and confirms it is safe and low-risk.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, so schema coverage is 100%. The description does not need to add parameter meaning beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states 'List built-in vendor register-map templates' with specific fields (name / type / tags), clearly distinguishing it from siblings like modbus_apply_template which applies a template.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
While no explicit when-not-to-use or alternatives are stated, the name and description imply it is the tool to use when needing to see available templates before applying one, which is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
modbus_read_coilsARead-only
[READ][risk=low] Read coils (FC01) — digital outputs, read-only here.
Args:
address: Starting coil address.
endpoint: Endpoint name from config.
count: Number of coils.
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| address | Yes | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds 'READ', 'risk=low', and 'read-only here', reinforcing safety with additional context. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: a one-line purpose and three brief parameter explanations. Every sentence adds value, with no unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with no output schema, the description adequately covers what it does and the parameters. It could mention return format (e.g., list of booleans) but is sufficient for invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema coverage, the description fully explains all three parameters: address (starting coil address), endpoint (from config), and count (number of coils), adding clear meaning beyond the schema's bare types and defaults.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description specifies 'Read coils (FC01) — digital outputs, read-only here', using a specific verb and resource. It distinguishes from siblings like modbus_read_discrete by clarifying that it reads digital outputs, not inputs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not explicitly state when to use this tool versus alternatives like modbus_read_discrete or modbus_read_holding. It implies usage from the name and 'digital outputs', but lacks explicit guidance on context or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
modbus_read_discreteARead-only
[READ][risk=low] Read discrete inputs (FC02) — read-only digital inputs.
Args:
address: Starting discrete-input address.
endpoint: Endpoint name from config.
count: Number of inputs.
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| address | Yes | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds the risk level and confirms read-only, but these mostly replicate annotation info without deeper behavioral context like rate limits or connection requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: a header with risk, one-line purpose, and compact parameter list. Every sentence is necessary and front-loaded, with no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
While the description covers the basic function and parameters, it lacks details on return format, valid ranges for count, or error handling. Given the simple nature of this read tool and presence of annotations, it's adequate but not complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 0% schema description coverage, the description includes an Args section with brief explanations for address, endpoint, and count, adding meaning beyond the raw JSON schema (e.g., 'Starting discrete-input address').
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Read discrete inputs (FC02) — read-only digital inputs,' specifying the verb (read), resource (discrete inputs), and function code, distinguishing it from sibling tools like modbus_read_coils or modbus_read_holding.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for reading discrete inputs via Modbus FC02 but provides no explicit when-to-use or when-not-to-use guidance, nor does it reference alternatives among the many sibling read tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
modbus_read_holdingARead-only
[READ][risk=low] Read holding registers (FC03) with a decode hint.
Args:
address: Starting register address.
endpoint: Endpoint name from config.
count: Number of registers (capped server-side).
decode: raw|uint16|int16|uint32|int32|float32.
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| decode | No | uint16 | |
| address | Yes | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, and destructiveHint=false. The description adds useful behavioral context: count is 'capped server-side' and decode supports specific formats (raw, uint16, etc.), which is beyond what annotations provide. No contradictions detected.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is concise with a front-loaded '[READ][risk=low]' tag and a list of parameters. Every sentence adds value. Could be slightly more structured but is efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description does not mention return values or response format. For a tool reading Modbus holding registers, the agent would benefit from knowing what is returned (e.g., decoded values, list of registers). This omission reduces completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. The description lists parameters (address, endpoint, count, decode) with brief explanations and enumerates decode options. However, endpoint ('endpoint name from config') is vague, and address lacks detail on range or behavior. Adds some value but not comprehensive.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'Read holding registers (FC03) with a decode hint', specifying verb (read), resource (holding registers), and function code (FC03). This distinguishes it from sibling tools like modbus_read_input or modbus_read_coils, which read different register types.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not provide explicit guidance on when to use this tool versus alternatives such as modbus_read_input, modbus_read_coils, or modbus_read_discrete. No direct comparison or when-to-use/when-not-to-use information is present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
modbus_read_inputARead-only
[READ][risk=low] Read input registers (FC04) with a decode hint.
Args:
address: Starting register address.
endpoint: Endpoint name from config.
count: Number of registers (capped server-side).
decode: raw|uint16|int16|uint32|int32|float32.
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| decode | No | uint16 | |
| address | Yes | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=true. The description adds that it's a read operation with risk=low, specifies the protocol (FC04), and mentions server-side capping of count, providing useful context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, front-loading the purpose with a clear tag, and uses a bullet-style list for parameters. Every sentence is informative and there is no wasted text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has no output schema, and the description does not explain what the tool returns (e.g., decoded values or raw data). While the annotations cover safety and parameters are well-described, the missing return value description leaves a gap for effective tool use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries full burden. It explains all four parameters clearly: address (starting register address), endpoint (from config), count (capped server-side), and decode (with possible values). This adds significant meaning beyond the schema types and defaults.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it reads input registers using Modbus FC04, with a decode hint. This distinguishes it from sibling tools like modbus_read_holding and modbus_read_coils.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not explicitly state when to use this tool versus alternatives. While the name and protocol hint at intended use, no when-to-use or when-not-to-use guidance is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
monitor_changesARead-only
[READ][risk=low] Capture only the value CHANGES of a point over a bounded window.
Polls ``ref`` and returns only the changes (with timestamps), not every
sample — the OT deadband-report pattern. Works across OPC-UA / Modbus / S7 /
Mitsubishi MC / EtherNet/IP. Hard-capped by duration_s and max_changes (never
an infinite loop).
Args:
ref: Point to watch — OPC-UA node id, Modbus address, S7 address string,
MELSEC device, or Logix tag (per the endpoint's protocol).
endpoint: Endpoint name from config.
duration_s: Wall-clock window in seconds (1..120, capped server-side).
interval_ms: Poll interval in milliseconds (>=50).
deadband: Numeric change must exceed this to count (0 = any change).
max_changes: Stop after this many changes (1..500, capped server-side).
Returns dict: {endpoint, ref, duration_s, interval_ms, deadband, samples_polled,
change_count, changes:[{value, previous, source_timestamp, wall_clock}]}.
Example: monitor_changes(ref="ns=2;i=5", endpoint="line1", duration_s=20, deadband=0.5).
| Name | Required | Description | Default |
|---|---|---|---|
| ref | Yes | ||
| deadband | No | ||
| endpoint | No | ||
| duration_s | No | ||
| interval_ms | No | ||
| max_changes | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and destructiveHint=false. The description adds value by detailing the polling mechanism, deadband integration, and hard caps on duration and max changes, which are not evident from annotations alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a purpose statement, behavior explanation, parameter list, return format, and example. It is concise but covers all essential aspects without waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and moderate complexity, the description explains the return dictionary structure and key behaviors (capping, deadband). Minor gaps like error handling or edge cases exist, but overall it is sufficiently complete for agent usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description provides a comprehensive Args section with explanations for each of the 6 parameters, including types, defaults, and protocol-specific address formats. This fully compensates for the lack of schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Capture only the value CHANGES of a point over a bounded window.' It specifies supported protocols and contrasts with continuous reading, making the purpose unambiguous and distinct from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use the tool (deadband-report pattern) and mentions caps, but it does not explicitly state when not to use it or provide alternatives. Given the large sibling list, better exclusion guidance would help.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mqtt_publishADestructive
[WRITE][risk=HIGH][MOC] Publish/command to an MQTT topic (off by default).
OT-DANGEROUS. A command (e.g. Sparkplug NCMD/DCMD) can change a live control
system. Defaults to dry_run=True. Set dry_run=False AND record an approver
(OPCUA_AUDIT_APPROVED_BY) to send. 未经授权勿对生产控制系统下发指令.
Reversibility depends on retain: a transient (retain=False) command has NO
inverse — delivered is delivered. A RETAINED publish overwrites durable broker
state, so the prior retained payload is captured first (returned as `before`)
and an undo descriptor recorded, as the protocol write tools do.
Args:
topic: MQTT topic to publish to.
payload: Message payload (string; JSON is fine).
endpoint: Endpoint name from config.
qos: MQTT QoS 0..2.
retain: Set the broker retain flag.
dry_run: When True (default) returns a preview without publishing.
Returns dict: dry-run → {topic, dry_run:true, would_publish_bytes, note};
applied → {topic, dry_run:false, published_bytes, applied:true}, plus
before:{found, payload, binary} when retain=True (the captured prior
retained payload; _undo_id is added when an inverse was recorded).
Example (preview): mqtt_publish(topic="factory/line1/cmd", payload='{"setpoint":50}').
| Name | Required | Description | Default |
|---|---|---|---|
| qos | No | ||
| topic | Yes | ||
| retain | No | ||
| dry_run | No | ||
| payload | Yes | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond the annotations (destructiveHint=true) by explaining OT-DANGEROUS, dry-run default, reversibility tied to retain, prior retained payload capture, and undo descriptor. This is exactly the kind of behavioral context annotations alone do not provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is detailed but well-structured with warning, Args, Returns, and Example sections. Every sentence adds value, especially the critical dry-run and approval information. It is longer than average, but warranted for a high-risk write operation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description documents return formats for both dry-run and applied cases, including the `before` field. It includes an example call and covers security, reversibility, and parameter semantics, making it effectively complete for an agent to invoke and interpret results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the full burden. The Args list explains all six parameters in plain language (topic, payload, endpoint, qos, retain, dry_run), including defaults and the preview behavior. This adequately compensates for the missing schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with '[WRITE] Publish/command to an MQTT topic' which is a specific verb+resource. It clarifies the tool publishes to MQTT and supports commands (e.g., Sparkplug NCMD/DCMD), distinguishing it from siblings like mqtt_read_topic.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear usage context: 'Defaults to dry_run=True' and 'Set dry_run=False AND record an approver' tells the agent when it is safe to actually send. It implies the tool should be used for command writes, but does not explicitly name alternative tools for reading; however the safety gate is explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mqtt_read_topicARead-only
[READ][risk=low] Plain MQTT: collect a BOUNDED set of messages from a topic.
Subscribes, gathers up to ``count`` messages or until ``timeout_s``, then
disconnects — never an open-ended loop. Payloads are decoded as JSON/text;
binary (e.g. Sparkplug protobuf) is reported with a hex preview + hint.
Args:
endpoint: Endpoint name from config (protocol must be 'mqtt').
topic: Topic filter (default: the endpoint's configured topic or '#').
count: Max messages (1..500, capped server-side).
timeout_s: Max seconds to wait (1..60, capped server-side).
Returns dict: {endpoint, topic, message_count, messages:[{topic,
payload:{encoding, json|text|hex_preview}}]}.
Example: mqtt_read_topic(topic="factory/+/temperature", count=10, timeout_s=5).
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| topic | No | ||
| endpoint | No | ||
| timeout_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only and non-destructive. Description adds value by detailing subscription, disconnection after count/timeout, payload decoding (JSON/text), and binary handling with hex preview. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is concise at ~150 words, well-structured with summary, behavior, args, returns, and example. Each sentence adds value without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description fully explains return format. It covers behavior, parameter ranges, and edge cases (binary). Missing output schema is compensated. Complete for a bounded read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description compensates well by documenting all four parameters: endpoint, topic (with default), count (1-500 capped), timeout_s (1-60 capped). Defaults and ranges are specified.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states it collects a bounded set of MQTT messages from a topic, using 'READ' label and detailed behavior. It distinguishes from siblings like mqtt_publish and sparkplug_subscribe_sample by specifying 'Plain MQTT' and bounded nature.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clarifies it is not an open-ended loop, implying use for one-time data collection. It lacks explicit 'when not to use' or direct alternative names, but the bounded nature and mention of binary handling provide context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mtconnect_assetsBRead-only
[READ][risk=low] Assets the agent knows (cutting tools, fixtures, programs).
Args:
endpoint: Endpoint name from config.
Returns dict: {endpoint, asset_count, assets:[{asset_type, asset_id, timestamp}]}.
Example: mtconnect_assets(endpoint="vmc1").
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds a [READ][risk=low] tag consistent with readOnly and specifies the return format (dict with endpoint, asset_count, assets). It does not disclose further behavioral traits such as rate limits, authentication needs, or the meaning of 'agent knows'. With annotations covering the core safety profile, the description provides moderate additional context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise (3 sentences plus example) and front-loaded with heuristic tags. Every sentence adds value, defining purpose, parameters, return format, and an example. No redundant or wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with one optional parameter and no output schema, the description covers the basics: purpose, parameters, return structure, and example. However, it lacks details like what asset types are possible, how the agent determines 'known' assets, or error conditions. The completeness is adequate but not thorough.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has one optional parameter 'endpoint' with no description (0% coverage). The description mentions the parameter in the args list and gives an example, but does not explain its meaning, possible values, or where to obtain valid endpoints. Given the low schema coverage, the description should compensate more.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool returns assets (cutting tools, fixtures, programs) known to the agent, and specifies the return structure. It distinguishes from siblings like mtconnect_current which return time-series data, but does not explicitly differentiate from other asset-related tools like asset_inventory.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. It does not suggest when not to use it or mention other tools as alternatives. The user must infer usage from the read-only nature and asset focus.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mtconnect_currentARead-only
[READ][risk=low] Latest value of every data item (a snapshot of the machine now).
Args:
endpoint: Endpoint name from config.
Returns dict: {endpoint, observation_count, next_sequence,
observations:[{data_item_id, type, name, timestamp, sequence, value}]}.
Pass next_sequence as from_sequence to mtconnect_sample to stream from 'now'.
Example: mtconnect_current(endpoint="vmc1").
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds value by detailing the return structure (dict with fields like endpoint, observation_count, observations) and an example, and explicitly tags it as a low-risk read operation. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a concise docstring with summary, Args, Returns, and Example sections. It is front-loaded with the purpose and includes essential details in a structured format. Slightly redundant formatting (e.g., 'Args:' line) but overall efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with one optional parameter, the description combined with annotations (readOnlyHint, destructiveHint) provides complete context: purpose, usage pattern, return format, and example. No output schema needed as return structure is described.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% (no description in schema for endpoint). The description adds meaning with 'Endpoint name from config', indicating where the value comes from. This partially compensates for the lack of schema documentation, but more detail on config format would improve.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Latest value of every data item (a snapshot of the machine now)', specifying the verb (retrieve), resource (data items), and scope (current snapshot). It distinguishes from sibling mtconnect_sample by noting the streaming use of next_sequence.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on using the output as input to mtconnect_sample for streaming ('Pass next_sequence as from_sequence to mtconnect_sample to stream from now'). It implies usage context but does not explicitly state when not to use or list alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mtconnect_oee_snapshotARead-only
[READ][risk=low] Availability / Execution / mode / program (OEE inputs).
Surfaces the live data items an availability/performance calc needs. Does NOT
compute a single OEE % (needs planned-time + ideal-cycle context MTConnect
doesn't expose).
Args:
endpoint: Endpoint name from config.
Returns dict: {endpoint, availability, execution, controller_mode, program,
available (bool), running (bool), verdict ('running'|'available_idle'|'down')}.
Example: mtconnect_oee_snapshot(endpoint="vmc1").
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare the tool as read-only and non-destructive. The description adds valuable behavioral context: it surfaces live data items, requires an endpoint from config, and returns a dict with specific keys (including boolean flags and a verdict). No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: a header line with risk/scope, a brief explanation of what it does and does not, labeled Args/Returns/Example sections. Every sentence adds value without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple snapshot tool with one parameter and no output schema, the description is remarkably complete. It covers the input, the output structure with example, and the limitation (no OEE computation). The agent has all necessary information to use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema description coverage at 0%, the description compensates by explaining the single 'endpoint' parameter as 'Endpoint name from config.' This clarifies that the parameter is a config-based reference, adding meaning beyond the schema's string type and null default.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool surfaces live OEE input data (availability, execution, mode, program) and explicitly distinguishes itself by noting it does NOT compute a single OEE percentage. It also lists the returned fields and provides an example, making the purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implicitly guides usage by explaining it provides raw data needed for availability/performance calculations and does not compute OEE. This helps the agent understand when to use this tool (for OEE inputs) versus a tool like oee_compute (for final OEE %). However, it does not explicitly state alternative tools or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mtconnect_probeARead-only
[READ][risk=low] The device model: devices → components → data items.
The MTConnect 'schema' — what the machine can report. Call this first to
discover dataItem ids/types before reading values.
Args:
endpoint: Endpoint name from config (protocol must be 'mtconnect').
Returns dict: {endpoint, device_count, devices:[{name, uuid, component_count,
components:[{component, id, name, data_items:[{id, type, category, name, units}]}]}]}.
Example: mtconnect_probe(endpoint="vmc1").
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, and description reinforces with [READ] tag and details return structure. It explains the behavioral purpose (discovery of schema) without contradicting annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely concise: two sentences plus args/returns/example. Front-loads purpose and risk level. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, description provides detailed return structure and hierarchy. Includes example and accounts for open-world hint. Covers all necessary context for a simple probe tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 0% schema description coverage, the description adds essential meaning: 'endpoint from config (protocol must be mtconnect)'. This compensates fully for the single parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly identifies it as a read-only probe for MTConnect device model. It specifies discovering dataItem ids/types before reading values, distinguishing it from siblings like mtconnect_current and mtconnect_sample.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States 'Call this first to discover dataItem ids/types before reading values,' providing clear usage ordering. While it doesn't explicitly name alternatives, the context implies this is the prerequisite probe step.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mtconnect_sampleARead-only
[READ][risk=low] Recent observations — a bounded snapshot OR a bounded incremental long-poll stream. Both modes are read-only and can NEVER run unbounded.
Modes:
- snapshot (default): one /sample page of up to `count` observations. Pass
`from_sequence` for a single incremental page starting at that sequence.
- stream: set `max_samples` and/or `duration_s` to poll the agent
repeatedly, advancing by the header's nextSequence each round, until a
bound is hit. Feed the returned `next_sequence` back as `from_sequence`
to resume exactly where you stopped.
Args:
endpoint: Endpoint name from config.
count: Max observations per /sample page (1..500, capped server-side).
from_sequence: Start sequence for an incremental pull (use next_sequence
from mtconnect_current or a prior call). None = the most recent `count`.
interval_ms: Poll spacing between rounds in stream mode (0..10000; 0 =
back-to-back). Client-side spacing — NOT the agent's server-push interval.
max_samples: Total observation budget across rounds; >0 selects stream mode
(capped at 2000). 0 = snapshot.
duration_s: Wall-clock budget in seconds; >0 selects stream mode (capped 120).
Returns dict (snapshot): {endpoint, mode:'snapshot', requested_count,
from_sequence, next_sequence, first_sequence, last_sequence,
observation_count, observations:[{data_item_id, type, name, timestamp,
sequence, value}]}.
Returns dict (stream): {endpoint, mode:'stream', from_sequence, next_sequence,
observation_count, poll_count, stopped_reason, interval_ms, max_samples,
observations:[...]}.
Example (snapshot): mtconnect_sample(endpoint="vmc1", count=200).
Example (stream): mtconnect_sample(endpoint="vmc1", from_sequence=1500,
interval_ms=1000, max_samples=500, duration_s=30).
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| endpoint | No | ||
| duration_s | No | ||
| interval_ms | No | ||
| max_samples | No | ||
| from_sequence | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint and non-destructive; the description reinforces read-only behavior and adds critical details: both modes are bounded, stream polls with client-side spacing, and returns include stopping reason and sequence advancement. This goes well beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections, bullet points, and examples. It is somewhat lengthy but justified by the complexity of two modes and multiple parameters. A minor cut could enhance conciseness without losing key information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description covers return structures for both modes, including all fields and examples. It addresses all aspects: purpose, behavior, parameters, and usage context. The description is fully self-sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All six parameters are explained in detail, including defaults, caps, and mode selection logic. Since the input schema has 0% description coverage, the description fully compensates, making parameter semantics complete and actionable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: providing recent observations as a bounded snapshot or bounded incremental long-poll stream. It defines two modes (snapshot and stream) and distinguishes them, preventing confusion with sibling tools like mtconnect_current or mtconnect_probe. The verb 'sample' and resource 'observations' are specific and well-defined.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use each mode: snapshot for a single page, stream for continuous polling with bounds. It provides examples and mentions using from_sequence from mtconnect_current. However, it does not explicitly compare against other sibling tools for choosing between them, which slightly reduces clarity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
oee_computeARead-only
[READ][risk=low] OEE = Availability × Performance × Quality (+ loss/energy depth).
Args:
planned_time_s: Planned production time (seconds).
run_time_s: Actual running time (seconds) — planned minus downtime.
ideal_cycle_time_s: Ideal/nameplate cycle time per part (seconds).
total_count: Total parts produced.
good_count: Good (non-reject) parts produced.
breakdown_time_s: Optional — unplanned-stop seconds (splits availability loss).
setup_time_s: Optional — changeover/setup seconds (splits availability loss).
minor_stop_time_s: Optional — minor-stop seconds (splits performance loss;
the remainder is speed loss).
startup_reject_count: Optional — startup/warm-up rejects (splits quality
loss; the remainder is production rejects).
actual_kwh: Optional — measured energy for this run; enables the energy block.
baseline_kwh: Optional — expected/baseline energy for the actual-vs-baseline
deviation verdict.
emission_factor_kg_per_kwh: Optional — carbon factor (kg CO2e/kWh). Default is
a flagged placeholder (see the tool's carbon note); pass the grid's value.
energy_tolerance: ± band (fraction) for the over/under/on-target verdict.
Returns dict: OEE factors + oee/oee_pct + inputs + losses, plus
``six_big_losses`` (breakdown/setup/minor-stops/speed/startup/production-reject
time-ladder that sums with OEE to 100%) and, when ``actual_kwh`` is given,
``energy`` (kwh_per_unit, carbon, and baseline deviation).
Example: oee_compute(planned_time_s=28800, run_time_s=25200,
ideal_cycle_time_s=2.0, total_count=12000, good_count=11800,
setup_time_s=1800, actual_kwh=940, baseline_kwh=880).
| Name | Required | Description | Default |
|---|---|---|---|
| actual_kwh | No | ||
| good_count | Yes | ||
| run_time_s | Yes | ||
| total_count | Yes | ||
| baseline_kwh | No | ||
| setup_time_s | No | ||
| planned_time_s | Yes | ||
| breakdown_time_s | No | ||
| energy_tolerance | No | ||
| minor_stop_time_s | No | ||
| ideal_cycle_time_s | Yes | ||
| startup_reject_count | No | ||
| emission_factor_kg_per_kwh | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds value beyond annotations by detailing the return structure (six_big_losses, energy block) and explaining how optional parameters split losses. It explicitly declares '[READ][risk=low]', which aligns with the readOnlyHint = true annotation. There is no contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is detailed but well-organized: a formula header, labeled Args list, Returns section, and an example. Every sentence serves a purpose. Slightly long due to thoroughness, but not wasteful. The front-loaded formula quickly conveys the core calculation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (13 parameters, no output schema), the description is remarkably complete. It explains all inputs, return keys, loss decomposition, and energy computation. The example demonstrates typical usage. No gaps remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description fully compensates by explaining each parameter in detail (e.g., 'planned_time_s: Planned production time (seconds)'). It provides syntax, units, and behavior for all 13 parameters, including optional ones. This is excellent semantic help.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it computes OEE using the formula 'Availability × Performance × Quality' and lists inputs and outputs. It specifies the verb 'compute' and resource 'OEE', making the purpose very clear. However, it does not differentiate itself from sibling tools like 'oee_multidim', which might also compute OEE in a different dimension.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives. It does not mention prerequisites, context, or limitations. The description only explains what the tool does, not when it should be invoked.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
oee_multidimARead-only
[READ][risk=low] Aggregate OEE (+ optional energy) across dimensions.
Args:
records: Labelled records — {<dimension labels>, planned_time_s, run_time_s,
ideal_cycle_time_s, total_count, good_count} plus optional actual_kwh /
baseline_kwh to enable the energy rollup.
dimensions: Dimension keys to group by (default ['machine','part','shift']);
use ['shift'] for the classic by-shift energy comparison.
emission_factor_kg_per_kwh: Optional carbon factor (kg CO2e/kWh); default is a
flagged placeholder — pass the grid's published value.
energy_tolerance: ± band (fraction) for the actual-vs-baseline verdict.
Returns dict: {dimensions, group_count, mean_oee, worst_performers:[...],
matrix:[{dimensions, oee, oee_pct, availability, performance, quality,
energy?}]}. When any record carries energy, adds an ``energy_baseline`` block
that flags cross-group deviation anomalies (tolerance + robust-outlier rules).
Example: oee_multidim(records=[{"shift":"day","planned_time_s":28800,
"run_time_s":25000,"ideal_cycle_time_s":2,"total_count":12000,
"good_count":11800,"actual_kwh":940,"baseline_kwh":880}], dimensions=["shift"]).
| Name | Required | Description | Default |
|---|---|---|---|
| records | Yes | ||
| dimensions | No | ||
| energy_tolerance | No | ||
| emission_factor_kg_per_kwh | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds behavioral details: it explicitly states the risk level ('risk=low'), describes the return structure, and explains the conditional energy block. This adds value beyond annotations without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections for Args, Returns, and an Example. It is fairly long but each part adds value. It could be slightly more concise, but it remains readable and informative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 4 parameters, no output schema, and complex behavior, the description comprehensively covers inputs, outputs, and includes an example. It explains the return dict structure and the conditional energy block. It is sufficiently complete for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 0% description coverage for properties. The description fully compensates by explaining each parameter: what records must contain (fields like planned_time_s, run_time_s, etc.), the purpose of dimensions, the default for emission_factor_kg_per_kwh, and the role of energy_tolerance. This adds meaning well beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it aggregates OEE (plus optional energy) across dimensions. The verb 'Aggregate' and resource 'OEE' are specific. It distinguishes from siblings like 'oee_compute' by highlighting multi-dimension grouping and energy inclusion, but does not explicitly name alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides usage guidance: it explains the default dimensions and suggests using ['shift'] for classic by-shift energy comparison. It does not explicitly state when not to use this tool or name alternative tools, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opcua_alarm_eventsARead-only
[READ][risk=low] Timestamped Alarms & Conditions via a bounded event subscription.
Subscribes to the Server object for Condition-type events, optionally calls
ConditionRefresh so currently-retained conditions are re-announced WITH their
original event Time, listens for at most duration_s seconds, unsubscribes.
The timed complement to opcua_read_alarms: each event carries the server's own
timestamp, so RCA can time-localize alarm evidence. Requires a server that
implements A&C event subscriptions (待核实 per server); an empty result can mean
no events in the window OR no A&C support — pair with opcua_read_alarms.
Args:
endpoint: Endpoint name from config.
duration_s: Listen window in seconds (0..60, default 5).
refresh: Call ConditionRefresh to replay retained/active conditions (default true).
max_events: Stop after this many events (1..200).
Returns dict: {endpoint, duration_s, condition_refresh, refresh_error, event_count,
events:[{source, message, severity, state (ACTIVE|RTN|EVENT), timestamp}], note}.
Example: opcua_alarm_events(endpoint="line1", duration_s=5).
| Name | Required | Description | Default |
|---|---|---|---|
| refresh | No | ||
| endpoint | No | ||
| duration_s | No | ||
| max_events | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true, openWorldHint=true, destructiveHint=false. The description greatly expands beyond these by detailing the subscription lifecycle: subscribing to Server, optionally calling ConditionRefresh, listening for a bounded duration, and unsubscribing. It also explains the meaning of the returned timestamp field and potential reasons for empty results. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections (summary, usage notes, args, returns, example) and front-loaded with the core purpose. However, it is somewhat verbose, including a Chinese note (待核实 per server) and extra notes about RCA. Could be slightly more concise without losing clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 4 parameters, no output schema, and moderate complexity, the description covers all necessary aspects: parameter semantics, return format, side effects (unsubscribes), potential edge cases (empty results), and an example. No gaps are evident.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must define all parameters. It does so comprehensively: endpoint (from config), duration_s (0-60, default 5), refresh (default true, calls ConditionRefresh), max_events (1-200, stop after). Defaults, ranges, and behaviors are all explained. This adds full meaning beyond the schema's basic type definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Timestamped Alarms & Conditions via a bounded event subscription.' It uses specific verbs like 'Subscribes', 'listens', 'unsubscribes', and explicitly distinguishes itself from the sibling tool 'opcua_read_alarms' by calling itself 'the timed complement'. The scope and resource ('Condition-type events on Server object') are unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use: it requires a server that implements A&C event subscriptions. It warns about empty results meaning either no events in window OR no A&C support, and recommends pairing with 'opcua_read_alarms' for disambiguation. This covers both when-to-use and when-not-to, and offers an alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opcua_anomaly_scanARead-only
[READ][risk=low] Sample a node over a bounded window and flag statistical outliers.
Computes mean/stddev/min/max and flags samples outside mean ± sigma*stddev.
Simple statistics only — no ML, no persisted model.
Args:
node_id: The OPC-UA node id to scan.
endpoint: Endpoint name from config.
samples: Max samples (capped server-side).
interval_ms: Delay between samples in milliseconds.
sigma: Outlier band width in standard deviations.
| Name | Required | Description | Default |
|---|---|---|---|
| sigma | No | ||
| node_id | Yes | ||
| samples | No | ||
| endpoint | No | ||
| interval_ms | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Description adds context about computation (mean/stddev/min/max, outlier flagging, no persistence) beyond annotations, which already declare readOnlyHint=true, destructiveHint=false, openWorldHint=true. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with a header line, a brief statistics line, and a clear Args list. Every sentence adds value and there is no redundant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description explains the computation and parameters but does not describe the output format or return value. Given no output schema, this is a gap for a tool with moderate complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 0% coverage, but the description explains all 5 parameters in the Args section, adding meaning like 'capped server-side' and 'delay between samples', which compensates for lack of schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses specific verbs 'sample' and 'flag', and clearly identifies the resource as an OPC-UA node, distinguishing it from generic sibling tools like 'anomaly_scan'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States 'Simple statistics only — no ML, no persisted model', indicating when to use this tool over more complex alternatives. However, it does not explicitly mention when not to use it or name specific siblings in the guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opcua_browseARead-only
[READ][risk=low] Browse the OPC-UA node tree from a node id (bounded depth).
Args:
node_id: Root node id (default i=85, the Objects folder).
endpoint: Endpoint name from config.
depth: Bounded browse depth (capped server-side).
| Name | Required | Description | Default |
|---|---|---|---|
| depth | No | ||
| node_id | No | i=85 | |
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, covering safety. The description adds '[READ][risk=low]' and notes that depth is capped server-side, which gives useful behavioral context beyond annotations. However, it does not specify behavior for invalid node_id or endpoint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: a one-line header with risk tag and a brief action, followed by three bullet-point parameter descriptions. Every sentence adds value with no redundancy or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simplicity of a browse tool and that annotations cover safety, the description adequately explains purpose and parameters. However, the lack of an output schema means the description should ideally describe what the tool returns (e.g., a tree of nodes). It does not, leaving a gap for the agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 0% description coverage, so the description must compensate. It provides brief but meaningful explanations for all three parameters: node_id (with default and example), endpoint (from config), and depth (bounded). This adds sufficient semantic value for parameter understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'browse', the resource 'OPC-UA node tree from a node id', and adds 'bounded depth'. This effectively distinguishes it from sibling tools like opcua_read_node which read values, and opcua_discover_tags which may have different scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives (e.g., opcua_read_node, opcua_subscribe_sample). It does not mention prerequisites, exclusions, or typical use cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opcua_diagnose_connectionARead-only
[READ][risk=low] Diagnose why an OPC-UA endpoint won't connect — a classified verdict.
Attempts a connect (no writes, disconnects immediately) and classifies any
failure into the well-known OPC-UA buckets instead of returning a raw error,
each with a concrete next step:
certificate (server doesn't trust our client cert) · auth (user/password) ·
security_policy (policy/mode mismatch) · port_closed · dns · firewall_timeout ·
unreachable · config (bad endpoint_url / connector not installed) · ok.
Args:
endpoint: Endpoint name from config; omit to use the default endpoint.
Returns dict: {endpoint, reachable (bool), class, diagnosis, remediation, detail}.
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true and destructiveHint=false. The description adds significant behavioral context: it attempts a connect but no writes, disconnects immediately, and classifies failures into specific buckets. This goes beyond annotations and provides valuable transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a summary line, process explanation, failure categories, and Args section. It is informative without being overly verbose. A slight reduction could be possible, but every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description describes the return dict structure. It covers input, behavior, and output. Minor gaps: no explicit mention of what happens if endpoint is invalid or how the test is performed, but overall sufficient for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has one optional parameter with 0% description coverage. The description compensates fully by explaining the endpoint parameter: 'Endpoint name from config; omit to use the default endpoint.' This adds meaning beyond the schema's type/title.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool diagnoses why an OPC-UA endpoint won't connect, with a specific verb 'Diagnose' and resource 'OPC-UA endpoint connection'. It distinguishes well from sibling OPC-UA tools like opcua_browse or opcua_read_node by focusing on connection diagnosis.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use: to diagnose connection failures. It implies alternatives (e.g., other OPC-UA tools for different tasks) but does not explicitly exclude them or provide direct contrast. The failure classification and next steps give clear context for appropriate use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opcua_discover_tagsARead-only
[READ][risk=low] Auto-discover OPC-UA tags and build a semantic asset model.
Walks the address space, collects every Variable node, and enriches each with
datatype / value / engineering-unit / a heuristic semantic class (temperature,
pressure, flow, setpoint, alarm, state, …) and a suggested clean alias. Tags
are grouped into assets by their browse path, and a naming-quality report
flags alias collisions + cryptic names. Aliases are ADVISORY — nothing is
written back to the server (a server-side rename would be OT-dangerous).
Args:
endpoint: Endpoint name from config; omit to use the default endpoint.
root: Root node id to discover from (default i=85, the Objects folder).
max_depth: Bounded recursion depth (capped server-side at 8).
include_standard: Include OPC-UA namespace-0 server infrastructure
(default False — only real process tags in vendor namespaces).
Returns dict: {endpoint, root, tag_count, asset_count,
assets:[{asset, tag_count, classes, tags:[{node_id, browse_name,
browse_path, datatype, value, unit, writable, class, suggested_alias}]}],
naming_quality:{alias_collisions, cryptic_names, verdict}}.
| Name | Required | Description | Default |
|---|---|---|---|
| root | No | i=85 | |
| endpoint | No | ||
| max_depth | No | ||
| include_standard | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true, destructiveHint=false, and openWorldHint=true. The description adds valuable context: aliases are 'ADVISORY — nothing is written back', server-side rename is 'OT-dangerous', max_depth is 'capped server-side at 8', and it describes the exact actions taken (walk address space, collect nodes, enrich). This goes well beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a clear header, narrative paragraph, Args list, and Returns block. It is informative without being overly verbose, though the Args section could be slightly more compact. Every sentence adds value; no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 4 parameters, no output schema, and a complex return structure, the description provides a detailed Returns dict including endpoint, root, tag_count, asset_count, assets (with nested tag details), and naming_quality (with alias_collisions, cryptic_names, verdict). This gives the agent a complete picture of what to expect, fully compensating for the absent output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description provides extensive parameter documentation in the Args block: endpoint, root, max_depth, include_standard—including defaults, meanings (e.g., 'root: Root node id to discover from (default i=85, the Objects folder)'), and constraints (e.g., 'capped server-side at 8'). This fully compensates for the missing schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it 'Auto-discover OPC-UA tags and build a semantic asset model' with specific actions: walk address space, collect Variable nodes, enrich with metadata, group into assets, and report naming quality. It distinguishes from siblings like opcua_browse (which just browses nodes) and opcua_read_node (which reads specific nodes).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not explicitly state when to use this tool versus alternatives like opcua_browse or opcua_read_node. It implies usage for initial discovery through the '[READ][risk=low]' tag and the mention of 'advisory' aliases, but lacks explicit when-to-use or when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opcua_health_summaryARead-only
[READ][risk=low] Classify OPC-UA tag node-ids against warn/alarm thresholds.
Returns ok/warn/alarm/unknown counts plus the offending tags. Thresholds
come from config tags, or per-ref overrides in ``thresholds``.
Args:
endpoint: Endpoint name from config.
node_ids: Tag node ids to evaluate; omit to use configured tags.
thresholds: Optional {ref: {warn_high, alarm_high, warn_low, alarm_low}}.
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No | ||
| node_ids | No | ||
| thresholds | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds that it classifies and returns counts and offending tags, which is consistent. No contradictions and additional behavioral context is provided.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a summary line, explanation, and Args block. It is concise with no redundant information, though could be slightly more compact.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description explains the input and general output but lacks detail on the exact return format or behavior for edge cases (e.g., empty results). Without an output schema, more detail would help, but it is adequate for a straightforward read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the burden. It explains all three parameters (endpoint, node_ids, thresholds) with type and purpose, including the structure of thresholds. This adds significant meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a clear verb 'Classify' and resource 'OPC-UA tag node-ids', and specifies output (ok/warn/alarm/unknown counts and offending tags). This distinguishes it from sibling tools like opcua_read_alarms or opcua_anomaly_scan.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains that thresholds come from config or overrides, implying usage context. It does not explicitly list when not to use or compare with alternatives, but the purpose is clear enough for an agent to decide.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opcua_read_alarmsARead-only
[READ][risk=low] Best-effort surfacing of active alarm/condition booleans (untimed).
Browses the address space (bounded) for alarm-like boolean nodes reading
True. Untimed by nature — for servers with A&C event support use
opcua_alarm_events, which returns conditions WITH the server's timestamps.
Args:
endpoint: Endpoint name from config.
node_id: Root node id to scan from (default i=85).
depth: Bounded scan depth.
| Name | Required | Description | Default |
|---|---|---|---|
| depth | No | ||
| node_id | No | i=85 | |
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnly, openWorld, and non-destructive. The description adds context of 'best-effort', 'bounded scan', and 'untimed', but does not detail return format or error behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Highly concise: a one-line summary followed by a clear Args section. Every sentence adds value, no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, usage, parameters, and behavior adequately. No output schema exists, so return format is not detailed, but the description implies a list of active alarms.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 0% description coverage. The description explains all three parameters (endpoint, node_id, depth) with defaults and purpose, compensating for the schema gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it surfaces active alarm/condition booleans without timestamps, and distinguishes from the sibling opcua_alarm_events which provides timestamped events.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises using opcua_alarm_events when timestamped events are needed, and notes the untimed nature of this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opcua_read_historyARead-only
[READ][risk=low] OPC-UA Historical Access (HDA): raw historical values over a window.
Reads stored history for a node via the server's HistoryRead service, bounded
by ``max_points``. Returns a clear 'unsupported' note when the server does not
historize the node (no crash).
Args:
node_id: The OPC-UA node id to read history for (e.g. ns=2;i=5).
endpoint: Endpoint name from config.
start: ISO-8601 window start (default: 1 hour before end).
end: ISO-8601 window end (default: now).
max_points: Max points to return (capped server-side at 2000).
Returns dict: {node_id, supported (bool), start, end, count,
values:[{value, source_timestamp, status_code}]}.
Example: opcua_read_history(node_id="ns=2;i=5", start="2026-06-28T08:00:00Z").
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | ||
| start | No | ||
| node_id | Yes | ||
| endpoint | No | ||
| max_points | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (readOnlyHint, openWorldHint, destructiveHint), the description reveals that it returns an 'unsupported' note (no crash) and that max_points is capped server-side at 2000. This adds meaningful behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: a tag line, a one-sentence summary, parameter descriptions, return format, and an example. Every sentence is necessary and front-loaded with key information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers parameters, behavioral notes, and the return dict structure. It is largely complete given no output schema, though it could elaborate on status_code values.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully explains all 5 parameters: node_id, endpoint, start, end, max_points. It provides formats, defaults, and an example, adding significant value over the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with '[READ][risk=low] OPC-UA Historical Access (HDA): raw historical values over a window.' This clearly states the tool reads historical data and distinguishes it from other OPC-UA tools like browse or read node.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not explicitly state when to use this tool versus alternatives like historian_query or opcua_read_node. It mentions error handling for unsupported nodes, but no guidance on selection criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opcua_read_manyARead-only
[READ][risk=low] Batch-read multiple node ids in one session (bounded count).
Args:
node_ids: List of OPC-UA node ids to read.
endpoint: Endpoint name from config.
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No | ||
| node_ids | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds 'risk=low' and 'bounded count', providing useful limits. No contradictions. It complements annotations well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise, using a single line for the header and a brief Args section. Every sentence adds value, with no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and a simple input, the description covers the main semantics. However, it does not describe the return format (e.g., a list of values or statuses), which would help an agent anticipate results. The rich annotations partially compensate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains 'node_ids: List of OPC-UA node ids to read' and 'endpoint: Endpoint name from config', adding meaning beyond the schema's type-only definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action 'Batch-read multiple node ids' and the resource 'node ids', distinguishing it from single-read or browse tools. The prefix '[READ]' and 'risk=low' further clarify its purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description mentions 'in one session (bounded count)', implying efficient batch reading, but provides no explicit guidance on when to use this tool versus alternatives like opcua_read_node or opcua_browse. No exclusion criteria or context are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opcua_read_nodeARead-only
[READ][risk=low] Read one node: value, datatype, source timestamp, status code.
Args:
node_id: The OPC-UA node id to read (e.g. ns=2;i=5).
endpoint: Endpoint name from config.
| Name | Required | Description | Default |
|---|---|---|---|
| node_id | Yes | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint and non-destructive behavior. The description adds a '[READ][risk=low]' tag and explicitly lists the return fields (value, datatype, source timestamp, status code), providing additional behavioral context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise with two short sentences plus an Args list. It front-loads the purpose with '[READ]' and efficiently covers all necessary information without any redundant text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with well-described parameters and annotations covering safety, the description is complete. It explains what is read, how to specify the node, and the endpoint parameter, and implies the output fields. No output schema is needed given the succinctness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description fully compensates by explaining both parameters: node_id is described with an example format (ns=2;i=5) and endpoint as 'Endpoint name from config.' This adds meaningful context that the schema lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it reads one OPC-UA node and lists the returned fields (value, datatype, source timestamp, status code). This distinguishes it from sibling tools like opcua_read_many (reads multiple nodes) and opcua_browse (lists nodes).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for reading a single node but does not explicitly state when to use this tool versus alternatives such as opcua_read_many or when not to use it. No exclusions are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opcua_server_infoARead-only
[READ][risk=low] OPC-UA server status, build info, and namespace array.
Args:
endpoint: Endpoint name from config; omit to use the default endpoint.
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds behavioral context with '[READ][risk=low]' and lists specific data returned (status, build info, namespace array), aligning with and enriching the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: a front-loaded summary line and a parameter explanation. Every word is necessary, with no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a simple single-parameter tool with no output schema, the description covers purpose and parameter meaning. It could be improved by noting return format or error conditions, but is sufficient for a read-only server info query.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description compensates by explaining the 'endpoint' parameter pulls from config and has a default, adding meaning beyond the raw schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool reads OPC-UA server status, build info, and namespace array. The '[READ]' prefix and specific data types distinguish it from sibling tools like opcua_browse or opcua_read_node.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use for server metadata via the parameter instruction 'Endpoint name from config; omit to use the default endpoint.' It does not explicitly exclude other use cases or name alternatives, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opcua_subscribe_sampleARead-only
[READ][risk=low] Sample a node a BOUNDED number of times, then return (never loops).
Args:
node_id: The OPC-UA node id to sample.
endpoint: Endpoint name from config.
samples: Max number of readings (capped server-side).
interval_ms: Delay between readings in milliseconds.
timeout_s: Hard wall-clock cap in seconds (capped server-side).
| Name | Required | Description | Default |
|---|---|---|---|
| node_id | Yes | ||
| samples | No | ||
| endpoint | No | ||
| timeout_s | No | ||
| interval_ms | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only. The description adds that sampling is bounded and capped server-side, which goes beyond the annotations. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: one summary sentence followed by a clear list of arguments. No unnecessary words; every part adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
While the tool's behavior is well-described, the return format is not mentioned. With no output schema, the description should specify what is returned (e.g., list of values with timestamps). This omission reduces completeness for an agent needing to parse results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by explaining each parameter's role: node_id is the node, endpoint from config, samples max readings capped, interval_ms delay, timeout_s hard cap. This adds significant meaning beyond the schema's default values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool samples an OPC-UA node a bounded number of times and returns, never looping. The 'READ' tag and explicit boundedness distinguish it from continuous subscriptions and other read tools in the sibling list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use when a finite number of samples is needed rather than continuous monitoring. It does not explicitly exclude alternatives or mention related tools like opcua_read_node or sparkplug_subscribe_sample, but the bounded nature provides clear context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pdm_forecastARead-only
[READ][risk=low] Forecast a value's trend + time until it crosses a warn/alarm limit.
The predictive step above baseline_check (which flags a violation that already happened): fits a
robust Theil-Sen trend to the recent history and, if it continues, estimates the ETA to the
nearest limit in the direction of travel — the early warning that makes maintenance predictive
(inverter/turbine degradation, bearing drift, filter clogging). Refuses thin history; read-only,
pure over the provided series; no device I/O.
Beyond the trend, the result deepens into three explainable, stdlib-only views: a degradation
'pattern' (gradual vs sudden vs cyclic), a remaining-useful-life 'rul' block when degrading
(linear + exponential extrapolation to the limit, a confidence band from the slope spread, and a
fit R^2), and optional time-domain 'waveform' features (RMS/kurtosis/crest/... for
vibration-type signals). Each states its own uncertainty rather than guessing.
Args:
series: Time-ordered samples: [{value, timestamp?}] (timestamp ISO-8601; if all present the
ETA is in seconds, otherwise in samples). >= 30 numeric samples required.
warn_high/alarm_high/warn_low/alarm_low: Optional limits; the forecast targets the nearest
one in the trend's direction (rising → highs, falling → lows).
imminent_within_s: ETA (seconds) at/under which status is 'imminent' (default 86400 = 24h).
include_waveform: Add the time-domain 'waveform' feature block (default True). Set False for
slow trend-only signals where vibration features do not apply.
Returns dict: {status (insufficient_data|stable|degrading|imminent), samples, direction,
slope_per_unit, unit (s|samples), current, limit:{name,value}, eta_to_limit,
degradation:{pattern,confidence,rationale,metrics},
waveform:{rms,crest_factor,kurtosis,...} (when include_waveform),
rul:{linear,exponential,eta_band,recommended_model,confidence,...} (when degrading)}.
Example: pdm_forecast(series=[{"value": 62.1, "timestamp": "2026-07-12T00:00:00Z"}, ...],
warn_high=75, alarm_high=85).
| Name | Required | Description | Default |
|---|---|---|---|
| series | Yes | ||
| warn_low | No | ||
| alarm_low | No | ||
| warn_high | No | ||
| alarm_high | No | ||
| include_waveform | No | ||
| imminent_within_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses that the tool is read-only and performs no device I/O, consistent with annotations (`readOnlyHint: true`, `destructiveHint: false`). It also details the computational approach (robust Theil-Sen trend) and the conditions under which the tool returns `insufficient_data`. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured but somewhat verbose. It front-loads a concise one-line summary, then elaborates on context, parameters, and return structure. Some details (e.g., specific statistical method, mention of 'stdlib-only views') could be trimmed, but the overall clarity and organization justify a score of 4.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description thoroughly documents the return structure including `status`, `direction`, `degradation`, `waveform`, `rul`, etc. It covers parameter semantics, behavior, and an example, making the tool fully understandable for an AI agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by providing detailed explanations for each parameter: `series` (time-ordered, required, format), limits (optional, targeted by direction), `include_waveform` (default True, when to set False), and `imminent_within_s` (default 86400). An example is also given, adding significant meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool forecasts a value's trend and time until it crosses limits. It uses specific verbs and resources ('forecast a value's trend + time') and distinguishes itself from the sibling `baseline_check` by noting it is predictive rather than reactive.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states this tool is a predictive step above `baseline_check` and provides context for when it should be used (e.g., for inverter/turbine degradation, bearing drift). It also mentions it refuses thin history, giving implicit guidance on prerequisites. However, it does not explicitly state when not to use it or provide direct alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
plc_program_driftARead-only
[READ][risk=low] Has this program changed since its approved snapshot, and what moved?
Three verdicts, and the wording of each is load-bearing. **identical** means
the same SHA-256 and nothing else earns the word. **logic_changed** means the
extracted structure differs — reported per block, naming which categories
(variables / calls / branches / timers_counters) moved. **changed_outside_
extracted_structure** means the bytes differ while every block fingerprint
matched: usually comments or formatting, but these parsers extract structure
rather than parse a grammar, so a real change inside a construct they do not
model looks identical from here. Calling that "documentation only" would be
the comfortable reading of evidence that does not support it, so it is not
called that, and it is not a clearance — line and comment counts are reported
beside it so a reviewer can see which way it leans.
Nothing here decides whether a change was authorised; that is change control's
job. No device is touched — this reads a file a person exported.
Args:
path: The current exported program file to check.
name: Tracked program name (defaults to the file's stem).
against: Snapshot id to compare with; default is the latest.
Returns dict: {program, name_source, baseline:{snapshot_id, taken_at, label,
source_file}, current:{source_file}, verdict, content_changed,
structure_changed, content_sha256:{before, after}, blocks:{added[],
removed[], changed:[{block, kind, line, previous_line, changed[]}],
unchanged}, totals:{block_count, line_count, comment_count}, parse_errors,
note, advisory}.
Example: plc_program_drift(path="~/exports/Line3_today.scl", name="Line3").
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| path | Yes | ||
| against | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description discloses important behavior: no device is touched, the verdicts are load-bearing, and 'changed_outside_extracted_structure' does not mean 'documentation only' due to parser limitations. It also clarifies that this tool does not determine authorization. These are exactly the non-obvious behavioral traits an agent needs, and no annotation contradiction exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Though detailed, the description is well-structured and front-loaded: purpose, then verdict semantics, then caveats, then parameters, return format, and an example. Every section earns its place, especially the verdict definitions and parser caveat, which are essential for correct interpretation of results.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by listing the complete return dict structure, including nested fields like blocks and totals. It also covers parameters, defaults, example usage, and risk context. For a tool with this complexity, nothing essential is missing for an agent to select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries full responsibility for parameter meaning. It documents all three parameters — path, name, and against — including defaults ('file stem', 'latest'). It also explains what 'against' refers to as a snapshot id, which the schema alone does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening question states exactly what the tool does: determine whether a program changed since its approved snapshot and identify what moved. It defines the three verdicts precisely, making the tool's scope and semantics unambiguous. This clearly separates it from snapshot creation, history, and other PLC program analysis tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context: it operates on an exported file, touches no device, and does not decide whether changes were authorized. It implicitly tells the agent when to use this tool and explicitly warns against using it for change-control decisions. However, it does not name alternative sibling tools such as baseline_check or plc_program_history or state when to prefer them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
plc_program_historyARead-only
[READ][risk=low] Tracked programs, or one program's snapshot history.
Local read of the program-baseline store — no file is parsed and no device is
touched. Nothing is ever pruned automatically: a change-control history that
quietly drops last quarter's baseline is worse than one that grows, and a
stored row is block names, hashes and counts rather than source. Removing history is a
deliberate act and is CLI-only (`iaiops program forget`) — deleting
change-control evidence should not be one tool call away.
Args:
name: Tracked program name. Omit for the list of every tracked program.
Returns dict (listing): {store, program_count, programs:[{program,
snapshot_count, latest, latest_taken_at}]}; (one program): {store,
program, snapshot_count, snapshots:[{snapshot_id, taken_at, source_file,
content_sha256, label, note}]}.
Example: plc_program_history(name="Line3").
| Name | Required | Description | Default |
|---|---|---|---|
| name | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations, the description adds important behavioral details: no automatic pruning, removal is deliberately CLI-only, stored data contains block names/hashes/counts rather than source, and no file or device is touched. This substantially exceeds what the annotations already convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the read-only tag and core purpose, then uses clear sections for Args, Returns, and Example. The prose about pruning is somewhat elaborate, but it earns its place by explaining why history is never automatically dropped and why deletion is restricted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema present, the description fully documents both possible return shapes: the listing form and the single-program snapshot form. The optional parameter behavior and an example are also present, making the tool straightforward to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description fully compensates for the single parameter: it explains what `name` selects and the effect of omitting it. The example reinforces the expected invocation syntax.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies a specific verb ('read') and resource ('program-baseline store'), and the first sentence distinguishes between two behaviors: listing tracked programs versus viewing one program's snapshot history. It also differentiates from device-reading siblings by stating 'no file is parsed and no device is touched.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clear context is provided: this tool reads local program-baseline history, and the optional `name` behavior is explained. It does not explicitly name sibling tools to use instead, but the framing and scoping make the use case sufficiently clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
plc_program_outlineARead-only
[READ][risk=low] Structural outline of an EXPORTED PLC program file.
Parses one exported text file (Siemens SCL/ST .scl/.st, AWL/STL .awl,
Rockwell Studio 5000 .L5X — .txt is content-sniffed) and returns blocks
(FB/FC/OB/DB/routines/AOIs) with VAR sections, IF/CASE branch inventory,
timers/counters, and the call graph. Never uploads from a live PLC; reads
exactly the named file (≤5 MB). Every element cites source_file + line
(rung number for L5X ladder) — quote those citations when explaining.
Malformed sections degrade to entries in parse_errors, never a crash.
Args:
path: Exported program file (.st/.scl/.awl/.l5x/.txt; must exist, ≤5 MB).
Returns dict: {source_file, format, stats:{blocks, variables, call_edges,
branches, timers_counters, comments, lines, parse_errors},
blocks:[{name, kind, language, line, end_line, variables (≤100,
variables_truncated), calls, branches, timers_counters, networks,
comment}] (≤50, blocks_truncated), call_graph:[{caller, callee,
source_file, line}], parse_errors, citation_note}.
Example: plc_program_outline(path="~/exports/Line3_Conveyor.scl").
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnly and non-destructive. The description adds valuable details: file size limit, format detection, error handling (malformed sections yield parse_errors, not crashes), truncation limits, and citation requirements. This goes beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a clear [READ][risk=low] tag and a succinct summary sentence. It efficiently layers details about capabilities, parameters, return structure, and example, without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (parsing multiple PLC file formats, returning structured data with many fields) and absence of an output schema, the description fully covers the return structure, constraints, and error behavior, leaving no gaps for an AI agent to invoke incorrectly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter 'path' is described with full file type specifications, size limit, and an example. Schema coverage is 0%, so the description compensates well by adding meaning beyond the schema's bare type definition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns a 'structural outline of an EXPORTED PLC program file', specifies supported formats, and explicitly distinguishes from live PLC interactions, making its purpose distinct from siblings like plc_program_xref.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage context: 'Never uploads from a live PLC; reads exactly the named file (≤5 MB)' and lists supported file types. It implies when to use (offline file analysis) but lacks explicit alternatives or when-not-to-use scenarios, though sibling names offer clues.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
plc_program_sectionARead-only
[READ][risk=low] Source text of ONE named block from an exported program.
Returns the exact source of a single block (FB/FC/OB/DB name for SCL/AWL;
Program.Routine or routine name for L5X — rungs are rendered as
'[rung N] ...'), capped at 200 lines with an explicit truncated flag, so
the agent reads exactly the section it is explaining instead of guessing.
Unknown block names fail with the list of available blocks.
Args:
path: Exported program file (.st/.scl/.awl/.l5x/.txt; must exist, ≤5 MB).
block: Block/routine name (case-insensitive; quotes optional).
Returns dict: {source_file, format, block, kind, start_line, end_line,
lines_returned, truncated, source, parse_errors}.
Example: plc_program_section(path="~/exports/Line3.scl", block="FB_Conveyor").
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| block | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds significant behavioral details beyond annotations: read-only nature (though already in annotations), truncation at 200 lines with a flag, error handling (unknown block names return available list), and return format. Annotations already indicate readOnlyHint and destructiveHint, so no contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with an upfront summary tag, clear sentences, and a logical flow. Could be slightly more concise by omitting the argument list that mirrors the schema, but still efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Comprehensive for a read tool with no output schema: describes return dict fields, gives an example, explains error behavior, and covers constraints (file size, line limit, truncation). No gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 0% description coverage, so description must compensate. It adds constraints for 'path' (must exist, ≤5 MB) and 'block' (case-insensitive, optional quotes), providing meaning beyond type/required status alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it returns the source text of one named block from an exported program. Distinguishes from sibling tools like plc_program_outline and plc_program_xref by specifying it retrieves the exact source for a single block.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'so the agent reads exactly the section it is explaining instead of guessing', giving a clear use case. Does not explicitly state when not to use or mention alternatives, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
plc_program_snapshotARead-only
[READ][risk=low] Record an exported program's structure as a change baseline.
A control program is a controlled document, and the usual way an undocumented
change to one gets noticed is that somebody remembers. This gives the
comparison a number: the file's SHA-256, plus a per-block structural
fingerprint (name/kind/language, declared variables, calls, branch conditions,
timers) that deliberately excludes line numbers, comments and block order — so
adding a comment at the top of a file does not report the whole program as
changed. Stored locally under the iaiops home as block names, hashes and
counts — never a declaration, a source line or a comment — so the store is not
a second copy of the program. Reads the named EXPORTED file only; never a live
PLC upload.
Re-snapshotting a byte-identical file records nothing and says so — a history
padded with identical rows hides the rows that are not.
Args:
path: Exported program file (.st/.scl/.awl/.l5x/.txt; must exist, ≤5 MB).
name: Program identity across exports. Defaults to the file's stem, and
the result says which was used — the export path changes every time
somebody opens the engineering station, the program does not.
label: Short label, e.g. "approved v3.2 / MOC-118".
note: Free note recorded with the snapshot.
Returns dict: {status ('recorded'|'unchanged'), program, name_source,
snapshot:{snapshot_id, taken_at, source_file, content_sha256, label, note},
block_count, snapshot_count, previous_snapshot}.
Example: plc_program_snapshot(path="~/exports/Line3.scl", label="approved v3.2").
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| note | No | ||
| path | Yes | ||
| label | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=true and destructiveHint=false; the description adds substantial behavioral context: the fingerprint deliberately excludes line numbers/comments/block order so cosmetic edits don't flag a change, the store keeps only hashes and counts (never source), and re-snapshotting a byte-identical file records nothing and returns status 'unchanged'. This goes well beyond the annotations and matches them — no contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but visibly structured: purpose tag, rationale, behavioral notes, labeled Args/Returns sections, and a worked example. It is front-loaded with the core purpose. The controlled-document rationale paragraph is somewhat verbose, and the length is justified by the tool's nuanced baseline semantics, but it could be tightened without losing value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-parameter tool with no output schema, the description is complete: it documents every parameter with constraints, specifies the exact return dict shape including status values, discloses side-effect-free storage behavior, states the idempotency semantics, and gives a call example. There are no schema or annotation gaps left unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden — and it succeeds. Each parameter gets real meaning: path gains file extensions, existence and ≤5 MB constraints; name gains cross-export identity, stem default, and the name_source feedback behavior; label gets a concrete example; note gets a purpose. This fully compensates for the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The lead sentence states a specific verb and resource: 'Record an exported program's structure as a change baseline.' The scope is sharply differentiated from siblings like plc_program_drift (compare against a baseline) and plc_program_history (show past snapshots) by making the recording role explicit. The '[READ][risk=low]' tag and 'never a live PLC upload' also pin down what the tool is and is not.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool — establishing a baseline for a controlled program document — and states exclusions ('Reads the named EXPORTED file only; never a live PLC upload'). However, it never explicitly names sibling alternatives such as plc_program_drift or plc_program_history for the comparison side of the workflow, leaving the agent to infer the full workflow from the baseline semantics.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
plc_program_visibilityARead-only
[READ][risk=low] Maintainability / operational-risk profile of a legacy PLC program.
The "what am I inheriting?" view over one EXPORTED program (SCL/ST, AWL/STL,
Rockwell L5X): folds the structural outline into documentation coverage, the
least-commented blocks, blocks nothing references (possible dead code), the
complexity hotspots, risky constructs (unconditional JMPs, retentive RTO
timers, loops), and a TRANSPARENT additive risk score whose every point cites
its reason. Structural only — it anchors an engineer's review of a line
somebody else left behind, not a semantic understanding. Reads exactly the
named file (≤5 MB); never a live PLC upload. Every finding cites source_file +
line (rung number for L5X ladder).
Args:
path: Exported program file (.st/.scl/.awl/.l5x/.txt; must exist, ≤5 MB).
Returns dict: {source_file, fmt, stats:{blocks, call_edges, line_count,
comment_count, comment_ratio, variables, branches, timers_counters},
documentation:{comment_ratio, band ('well_commented'|'sparse'|
'undocumented'), uncommented_block_count, uncommented_blocks},
entry_points:[{name, kind}], unreferenced_blocks:[{name, kind,
source_file, line}], complexity_hotspots:[{block, kind, score, branches,
calls, timers_counters, source_file, line}], risky_constructs:{
unconditional_jumps, unconditional_jump_count, loops, loop_count,
retentive_timers, retentive_timer_count}, risk:{score (0..100), band
('low'|'medium'|'high'), reasons[]}, parse_errors, note}.
Example: plc_program_visibility(path="~/exports/Line3_Conveyor.scl").
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond readOnlyHint and destructiveHint, description adds key behavioral details: works only on exported files (no live upload), file size limit (≤5 MB), structural analysis only (no semantic understanding), every finding cites source file and line. Transparent about limitations and capabilities.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured: lead with risk level and purpose, then detailed explanation of outputs, Args, Returns dict, and example. Some redundancy (e.g., 'structural only' repeated) but overall efficient and front-loaded. Slightly lengthy yet justified by complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, description provides a comprehensive dictionary of return fields with types and descriptions. Includes examples, input constraints, and explicit risk scoring details. Adequate for an agent to correctly invoke and interpret results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema has 0% description coverage for path. Description compensates fully by specifying allowed extensions (.st, .scl, .awl, .l5x, .txt), existence requirement, and size constraint (≤5 MB). Provides essential context beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clear verb and resource: 'maintainability/operational-risk profile of a legacy PLC program'. Distinguishes from siblings like plc_program_outline by specifying it provides a comprehensive risk assessment including dead code, complexity hotspots, and risky constructs, and explicitly states it is structural only, not semantic.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implicit usage context: 'The "what am I inheriting?" view' and 'anchors an engineer's review of a line somebody else left behind.' However, no explicit comparison to sibling tools like plc_program_outline or plc_program_xref, nor guidance on when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
plc_program_xrefARead-only
[READ][risk=low] Cross-reference one symbol in an exported PLC program.
Finds every read/write/call/declare site of a symbol or absolute address
(e.g. Motor_Run, "FB_Conveyor", DB10.DBX0.1, M0.0, Tank[2].Level) in one
exported file, quoting the surrounding source line verbatim so the agent
cites real code. Access classification is heuristic (op/regex based, not
data-flow analysis): SCL ':='→write, '('→call; AWL T/=/S/R→write,
L/A/O…→read, CALL→call; L5X OTE/OTL/OTU/RES and MOV-dest→write. For L5X,
line is the rung number.
Args:
path: Exported program file (.st/.scl/.awl/.l5x/.txt; must exist, ≤5 MB).
symbol: Symbol / tag / absolute address to trace (word-bounded match).
Returns dict: {source_file, format, symbol, hit_count,
hits:[{symbol, access, block, source_file, line, source_line}] (≤200),
hits_truncated, by_access:{read, write, call, declare, reference}}.
Example: plc_program_xref(path="~/exports/OB1.awl", symbol="M10.0").
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| symbol | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds significant behavioral context beyond annotations: it explains the heuristic (op/regex based, not data-flow analysis), details access classification per format (SCL, AWL, L5X), and notes verbatim source line quoting. This complements the readOnlyHint annotation well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a tag, summary, heuristics, Args, returns, and example. It is front-loaded with the purpose. While somewhat lengthy, every sentence adds value, earning a 4.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description comprehensively explains the return dict, including fields like source_file, format, hits, by_access. It also covers file type constraints and heuristic behavior, making it complete for an agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by explaining both parameters: path includes file types, existence, and size constraint; symbol includes examples and word-bounded match requirement. This adds meaning beyond the schema's type definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool cross-references a symbol in an exported PLC program, finding every read/write/call/declare site. It distinguishes from sibling tools like plc_program_outline by focusing on symbol tracing rather than program structure.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for tracing symbol accesses in exported files but does not explicitly state when to use this tool over alternatives, nor does it provide exclusions or when-not-to-use guidance. The file size constraint is mentioned but not in a usage comparison context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
profinet_asset_inventoryARead-only
[READ][risk=low] PROFINET asset register from a DCP IdentifyAll sweep.
Segment-wide, read-only — no per-device connection. The DCP device-role bitmask
is decoded when the client exposes it; pnio-dcp does not, so roles and the
controller/device counts come back empty and 0. Names, MACs and IP suites are
unaffected — those are what the register is for.
Args:
endpoint: Endpoint name from config (protocol 'profinet').
Returns dict: {endpoint, asset_count, io_controller_count, io_device_count,
assets:[{name_of_station, mac, ip, vendor_id, device_id, roles[], family}],
method:'dcp_identify_all'}.
Example: profinet_asset_inventory(endpoint="cell1").
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond the annotations by disclosing specific behaviors: it is read-only and segment-wide, notes the DCP device-role bitmask limitation ('roles and the controller/device counts come back empty and 0'), and clarifies that 'Names, MACs and IP suites are unaffected.' This provides valuable context not available in readOnlyHint or destructiveHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections for READ/risk, overview, args, returns, and example. It is longer than strictly necessary, but the extra length is justified by the important caveat about role decoding. No wasted sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description provides a detailed return dictionary format and method name. It also covers limitations and gives an example. It does not mention error conditions or what happens if the endpoint is invalid, but for a simple one-parameter read tool, the coverage is quite complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has only one optional parameter (endpoint) with 0% description coverage, so the description carries the burden. It explains endpoint as 'Endpoint name from config (protocol 'profinet')' and provides an example call, which adds meaning. However, it does not clarify default behavior when endpoint is null or what valid endpoint names look like, so it is adequate but not thorough.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'PROFINET asset register from a DCP IdentifyAll sweep.' It specifies a concrete verb and resource, and distinguishes itself from sibling tools by emphasizing 'Segment-wide, read-only — no per-device connection.' This differentiates it from per-station tools like profinet_identify_station.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use the tool: 'Segment-wide, read-only — no per-device connection.' It implies this is for asset inventory across an entire segment rather than individual stations. It also highlights a limitation (roles may be empty with pnio-dcp), but it does not explicitly name alternative tools or state when not to use it, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
profinet_dcp_setADestructive
[WRITE][risk=HIGH][MOC] DCP Set — re-address one PROFINET station (off by default).
OT-DANGEROUS. Defaults to dry_run=True (nothing set). Re-addresses a live
station's name-of-station and/or IP suite via a unicast DCP Set (can disrupt the
IO connection). Captures the BEFORE addressing (by MAC) and records an undo
descriptor. Set dry_run=False AND record an approver (OPCUA_AUDIT_APPROVED_BY) to
apply. 未经授权勿对生产控制系统写入.
Args:
mac: Target station MAC, e.g. '00:1b:1b:12:34:56' (from profinet_discover).
set_name: New name-of-station (omit to leave unchanged).
set_ip: New IP address (omit to leave the IP suite unchanged).
netmask: New subnet mask (used with set_ip).
gateway: New default gateway (used with set_ip).
endpoint: Endpoint name from config (protocol 'profinet').
dry_run: When True (default) returns a preview without setting anything.
Returns dict: dry-run → {mac, dry_run:true, before, would_set, note};
applied → {mac, dry_run:false, before, set, applied:true, _undo_id}.
Example (preview): profinet_dcp_set(mac="00:1b:1b:12:34:56", set_name="plc-new").
| Name | Required | Description | Default |
|---|---|---|---|
| mac | Yes | ||
| set_ip | No | ||
| dry_run | No | ||
| gateway | No | ||
| netmask | No | ||
| endpoint | No | ||
| set_name | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond annotations by detailing the risky nature ('OT-DANGEROUS', 'can disrupt the IO connection'), the dry_run safety mechanism, and the undo capability. It also explains the return dict structure, providing full behavioral transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is detailed but well-structured, starting with the core action and risk, then dry_run behavior, parameter list, return format, and an example. While slightly long, it adds necessary information without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (7 params, no output schema), the description is highly complete. It covers safety, parameters, return values, undo mechanism, and includes an example. The Chinese warning adds context for potential users.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by explaining all 7 parameters: mac (with example), set_name, set_ip, netmask, gateway, endpoint, and dry_run (default behavior). It specifies which parameters are used together and provides a usage example.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 're-address one PROFINET station via a unicast DCP Set'. It specifies the action (DCP Set), resource (PROFINET station), and scope (name and/or IP suite). This distinguishes it from siblings like profinet_discover (discovery) and ethercat_set_state (EtherCAT).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use the tool (to re-address a station) and warns about disrupting IO connection. It notes the dry_run default and the need for an approver. However, it lacks explicit guidance on when not to use it or alternatives, though sibling context provides implicit differentiation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
profinet_discoverARead-only
[READ][risk=low] DCP IdentifyAll — every PROFINET station on the segment.
One layer-2 broadcast surfaces all stations without connecting to any. Needs
raw-socket access on the NIC on the PROFINET subnet (pnio-dcp extra); degrades
to a teaching error dict when pnio-dcp/permission/NIC is missing.
Args:
endpoint: Endpoint name from config (protocol 'profinet'); omit for default.
Returns dict: {endpoint, local_ip, station_count, stations:[{name_of_station,
mac, ip, netmask, gateway, vendor_id, device_id, device_role_raw,
device_roles[], device_family}]}. vendor_id/device_id/device_role* are
always empty — pnio-dcp does not expose them (see the connector note).
Example: profinet_discover(endpoint="cell1").
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the readOnly/openWorld annotations by labeling it as READ with low risk, clarifying it operates via a broadcast without connecting to any station, and disclosing the dependency on raw-socket permissions and pnio-dcp. It also transparently notes that vendor/device fields are always empty due to pnio-dcp limitations, and explains the degradation to an error dict when prerequisites are missing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is efficiently structured with a '[READ][risk=low]' tag, a concise explanation, requirements, argument documentation, return format, and an example. Every section adds value, and the information is front-loaded with the tool's primary purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Since there is no output schema, the description thoroughly explains the return dict and all its fields, including the caveat about always-empty vendor/device fields. It also covers prerequisites and error behavior, making the tool fully understandable without external references.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With zero schema description coverage, the description fully compensates by explaining that the endpoint parameter refers to the endpoint name from config with protocol 'profinet' and that omitting it uses the default. This gives the parameter clear semantic meaning beyond the raw schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as 'DCP IdentifyAll' that surfaces every PROFINET station on the segment via a layer-2 broadcast. It specifies the action (discover all stations), the resource (PROFINET devices), and distinguishes it from station-specific sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly explains the context for using this tool (to list all stations on the network) and specifies prerequisites like raw-socket access and the pnio-dcp extra. It does not explicitly mention alternative tools for single-station identification or parameter reading, but the broadcast scope and 'all stations' wording make the intended use clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
profinet_identify_stationARead-only
[READ][risk=low] Identify one station by its PROFINET name-of-station.
Args:
name_of_station: Exact (case-insensitive) PROFINET station name, e.g. 'plc1'.
endpoint: Endpoint name from config (protocol 'profinet').
Returns dict: {endpoint, found (bool), name_of_station, mac, ip, netmask,
gateway, vendor_id, device_id, device_roles[], device_family}.
Example: profinet_identify_station(name_of_station="et200sp-1", endpoint="cell1").
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No | ||
| name_of_station | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide readOnlyHint=true, destructiveHint=false, and openWorldHint=true. The description adds a [READ][risk=low] prefix and details the return dict, but doesn't disclose any additional behavioral traits beyond the annotations. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise, with clear sections for purpose, arguments, returns, and example. It is front-loaded with a risk tag and contains no unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's low complexity (two parameters, read-only, no output schema), the description provides complete information: purpose, parameters, return structure, and an example. Annotations cover safety, so no gaps remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries full responsibility. It explains both parameters: name_of_station (exact, case-insensitive, with example) and endpoint (from config, protocol hint). An example call is provided, adding significant value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool identifies one station by its PROFINET name-of-station, with a verb and specific resource. It distinguishes from sibling tools like profinet_discover (which lists all stations) and profinet_station_params (which gets parameters).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use this tool (to identify a specific station by name) but does not explicitly state when not to use it or provide alternatives. However, the context is clear, and the example usage sets expectations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
profinet_station_paramsARead-only
[READ][risk=low] Targeted DCP Get for one station (by MAC): name + IP suite.
Args:
mac: The station's MAC address, e.g. '00:1b:1b:12:34:56'.
endpoint: Endpoint name from config (protocol 'profinet').
Returns dict: {endpoint, mac, found (bool), name_of_station, ip, netmask, gateway}.
Example: profinet_station_params(mac="00:1b:1b:12:34:56", endpoint="cell1").
| Name | Required | Description | Default |
|---|---|---|---|
| mac | Yes | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, indicating a safe read operation. The description reinforces this with '[READ][risk=low]' and details the return dict, including a 'found' boolean. Since annotations carry the main behavioral burden, the description adds useful context about the return format and safety.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized with a title line, parameter list, return format, and example. It is concise (3 sentences plus the example line) with no wasted words. Every sentence serves a purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description explains the return dict structure. Parameter semantics are fully covered. The tool is low complexity with 2 parameters, and the example clarifies usage. It is complete enough for an agent to effectively invoke the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description fully compensates by explaining both parameters: 'mac: The station's MAC address, e.g. '00:1b:1b:12:34:56'' and 'endpoint: Endpoint name from config (protocol 'profinet')'. It also provides an example call, adding value beyond the schema's type-only definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it performs a 'Targeted DCP Get for one station (by MAC)', retrieving name and IP suite. This distinguishes it from sibling profinet tools like profinet_discover (likely for discovering all stations) and profinet_identify_station (for identification). The verb 'get' and resource 'station params' are specific.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use when targeting a specific station by MAC, and the example and parameter explanation provide context. However, it does not explicitly state when to use this tool instead of alternatives like profinet_discover or profinet_asset_inventory. The guidance is clear but not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
protocols_supportedARead-only
[READ][risk=low] Capability map — protocols, status, tools, connection params.
Call this to discover what iaiops can do before choosing a protocol/tool.
Lists implemented protocols (OPC-UA incl. HDA, Modbus, S7comm, Mitsubishi MC,
MTConnect, MQTT/Sparkplug B full-decode, EtherNet/IP Logix) and the EtherCAT
roadmap stub, plus cross-protocol analytics (OEE/downtime, asset inventory,
CoV), each with its read/write tools and the endpoint params it needs.
Also reports whether this server runs under the no-egress gate, so a model is
TOLD the posture instead of having to infer it from tools it cannot see.
Read/write authorisation is NOT a server posture here — it is the caller's
decision; every call (read or write, MCP or CLI) is audited.
Returns dict: {tool, posture, implemented_protocols:[...], roadmap_stubs:[...],
protocols:[{protocol, status, library, transport, auth, read_tools,
write_tools, params}], diagnostics:[...], analytics:[...], tool_counts,
safety, write_note, no_egress_mode, no_egress_note}.
Example: protocols_supported().
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds valuable behavioral context: it returns a rich dict with details, explains the no-egress gate, and clarifies that read/write authorisation is the caller's decision and all calls are audited.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is relatively long but well-structured with a summary, list of protocols, and return format. Every sentence provides value, though some brevity could be achieved without losing clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters and no output schema, the description provides a comprehensive return dict structure and explains key behaviors (no-egress gate, audit). It is complete for a discovery tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters with 100% schema coverage. The description does not need to add parameter details, and the baseline for 0 parameters is 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it is a 'capability map' to 'discover what iaiops can do before choosing a protocol/tool', with specific verb and resource. It distinguishes from sibling tools that are specific operations (e.g., modbus_read_holding) by being a discovery tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Call this to discover what iaiops can do before choosing a protocol/tool', providing clear usage context. It does not explicitly list when not to use, but the purpose is clearly for initial discovery.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rca_corpus_from_maintenanceARead-only
[READ][risk=low] Turn a CMMS/work-order export into the RCA incident corpus.
Auto-builds the labeled history learn_cause_weights needs from closed maintenance
records: an explicit taxonomy cause column wins; else a built-in EN/中文 CMMS
synonym table (extendable via 'synonyms'); else UNAMBIGUOUS keyword inference
over the row's free text using the copilot's own cause keywords. Rows it cannot
map land in 'unmapped' with the reason — never silently guessed. 'signals' come
from an explicit column or the symptom/alarm text (may stay empty — no fabricated
evidence). Pure + advisory; with learn=true the learned weights are included.
Args:
rows: Work-order records, one dict each. Recognized cause columns:
cause / root_cause / failure_class / category / problem_code; free-text
columns: description / problem / notes / comment / text / 故障描述;
signal text: symptom(s) / alarm(s) / 现象.
synonyms: Extra site vocabulary, e.g. {"spindle crash": "mechanical_fault"};
values must be taxonomy causes.
learn: Also run learn_cause_weights on the mapped corpus (default true).
min_samples: Passed to learn_cause_weights (default 8).
smoothing: Passed to learn_cause_weights (default 1.0).
Returns dict: {corpus:[{cause, signals}], n_rows, n_mapped, unmapped:[{row,
reason, excerpt}], mapped_via, weights?, next_step}.
Example: rca_corpus_from_maintenance(rows=[{"category":"轴承损坏",
"symptom":"drive overload alarm"}], synonyms={"spindle crash":"mechanical_fault"}).
| Name | Required | Description | Default |
|---|---|---|---|
| rows | Yes | ||
| learn | No | ||
| synonyms | No | ||
| smoothing | No | ||
| min_samples | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description provides detailed behavioral traits: it is read-only, rows that cannot be mapped are placed in 'unmapped' with reason (no silent guessing), and signals may stay empty. This goes beyond the annotations which only indicate readOnlyHint=true.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a header, paragraph, parameter list, return format, and example. It is slightly long but every sentence adds value, and the front-loading of purpose and risk helps the agent quickly understand the tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description includes a detailed return dict structure (corpus, n_rows, n_mapped, unmapped, mapped_via, weights?, next_step) and thoroughly explains the mapping logic. It covers all necessary details for a tool with 5 parameters and one required field.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema coverage, the description fully explains all 5 parameters: rows (lists recognized columns), synonyms (format and constraint), learn, min_samples, smoothing. It also includes an example, adding significant meaning beyond the schema's property names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Turn a CMMS/work-order export into the RCA incident corpus.' It explains the mapping process with priority order and distinguishes it from siblings by focusing on building the corpus needed for learn_cause_weights.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use it (to build labeled corpus for learn_cause_weights) and provides context such as the synonym table and keyword inference. However, it does not explicitly mention alternatives or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rca_narrateA
[READ][risk=low] Narrate a cited RCA verdict in plain language via an on-box LLM.
Air-gapped: hands the already-computed, already-cited verdict to a LOCAL model (Ollama) that
ONLY rephrases it — it never adds a cause, number, or citation (strict prompt; see docs/RCA.md).
Read-only; no device I/O. Needs the extra + a running local model: pip install iaiops[ollama].
Args:
verdict: An RCA verdict dict (e.g. the output of downtime_root_cause).
base_url: Ollama server URL (default http://localhost:11434).
model: Local model name (default 'llama3.1').
provider: LLM provider (currently 'ollama').
Returns dict: {provider, model, narration}.
Example: rca_narrate(verdict=<downtime_root_cause output>, model="llama3.1").
| Name | Required | Description | Default |
|---|---|---|---|
| model | No | llama3.1 | |
| verdict | Yes | ||
| base_url | No | http://localhost:11434 | |
| provider | No | ollama |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description claims 'Read-only; no device I/O' and tags [READ], but annotations set readOnlyHint=false, creating a direct contradiction. Per scoring rules, this warrants a score of 1 and flags annotation contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a header, paragraphs, and bulleted args. It front-loads key information (read-only, air-gapped). Could be slightly more concise, but clear and logical.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description details the return dict and provides an example. It covers prerequisites, dependencies, and usage context. Without the contradiction, it would be near complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It explains the verdict parameter as an RCA verdict dict from downtime_root_cause, and provides defaults for base_url, model, and provider. This adds meaningful context beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'narrate' and the resource 'RCA verdict', and distinguishes it from sibling tools like downtime_root_cause by explicitly linking as its companion. It is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use (after obtaining an RCA verdict), what it does (rephrase, never add causes), and prerequisites (pip install), but lacks an explicit 'when not to use' or comparison with alternatives, though implicit from context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
s7_cpu_infoARead-only
[READ][risk=low] S7 CPU identity + run/stop status (proves the link).
Args:
endpoint: Endpoint name from config (protocol must be 's7'); omit for default.
Returns dict: {endpoint, rack, slot, cpu_status (e.g. 'run'/'stop'),
cpu_info: {module, serial, version, ...}}.
Example: s7_cpu_info(endpoint="press1").
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false, so the agent knows it's safe. The description adds context like 'risk=low' and 'proves the link', which goes beyond annotations. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loaded with purpose. It uses a clear structure with Args and Returns sections. Every sentence contributes information without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple input (1 optional param) and no output schema, the description covers the return structure and provides an example. It could mention error handling for invalid endpoints, but overall it is complete enough for a low-complexity tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must add meaning. It explains that endpoint is optional, protocol must be 's7', and omitting uses default. An example is provided. This adds value beyond the schema definition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool reads S7 CPU identity and run/stop status, using specific verbs and resource. It distinguishes from sibling S7 tools by focusing on CPU info rather than memory areas. The phrase 'proves the link' adds context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no explicit guidance on when to use this tool vs alternatives like s7_read_db. It implies usage for connection verification, but does not mention exclusions or when not to use. With many sibling tools, more guidance would be helpful.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
s7_read_areaARead-only
[READ][risk=low] Read count items of a type from an S7 memory area.
Args:
area: Memory area — DB | M (merker/flag) | I (input) | Q (output).
dtype: S7 data type — BIT|BYTE|WORD|INT|DWORD|DINT|REAL|LREAL|CHAR.
start: Byte offset within the area/DB (0-based).
endpoint: Endpoint name from config.
db: Data block number (required when area=DB).
count: Number of consecutive items (1..100, capped server-side).
bit: Bit offset 0..7 (only when dtype=BIT).
Returns dict: {endpoint, area, db, dtype, start, count,
items:[{address, value}]}. ``value`` is bool/int/float per dtype.
Example: s7_read_area(area="DB", dtype="REAL", start=4, db=1, count=2).
| Name | Required | Description | Default |
|---|---|---|---|
| db | No | ||
| bit | No | ||
| area | Yes | ||
| count | No | ||
| dtype | Yes | ||
| start | Yes | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the agent knows this is a safe read operation. The description adds valuable behavioral context: the count parameter is 'capped server-side' (1..100), and it specifies the return type structure with address and value per data type. This goes beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections (Args, Returns, Example) and uses bullet-style lists. However, it is slightly verbose for a read operation; some redundancy (e.g., repeating 'count' in Returns) could be trimmed. Overall, it's well-organized and front-loaded with purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (7 parameters, no output schema), the description is largely complete: it explains all parameters, the return dictionary format, and provides a concrete example. However, it lacks guidance on how this tool relates to similar siblings (s7_read_db, s7_read_many) and does not mention potential errors or prerequisites like endpoint availability.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides no descriptions (0% coverage), so the description must compensate fully. It does so excellently: every parameter is explained with acceptable values (area enum, dtype list, start as byte offset, endpoint from config, db required when area=DB, count range 1..100, bit offset for BIT type). The example further clarifies usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Read') and resource ('S7 memory area') with specific verb and resource. It lists memory area types and data types, making the purpose unmistakable. However, it does not explicitly differentiate this tool from similar siblings like s7_read_db or s7_read_many, which could cause confusion for an AI agent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage through parameter examples (e.g., 'area=DB, dtype=REAL, start=4, db=1, count=2') but provides no explicit guidance on when to use this tool versus alternatives like s7_read_db or s7_read_many. No when-not-to-use or exclusionary context is given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
s7_read_dbARead-only
[READ][risk=low] Read count dtype items from data block db.
Args:
db: Data block number (e.g. 1 for DB1).
dtype: S7 data type — BIT|BYTE|WORD|INT|DWORD|DINT|REAL|LREAL.
start: Byte offset within the DB (0-based).
endpoint: Endpoint name from config.
count: Number of consecutive items (1..100).
Returns dict: {endpoint, area:'DB', db, dtype, start, count, items:[{address, value}]}.
Example: s7_read_db(db=1, dtype="INT", start=0, count=10).
| Name | Required | Description | Default |
|---|---|---|---|
| db | Yes | ||
| count | No | ||
| dtype | Yes | ||
| start | Yes | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds constraints (count 1..100, start 0-based) and specifies the return format. No contradictions; the description supplements the annotations with useful behavioral details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact with a clear structure: brief summary, parameter list, return format, and example. Every sentence serves a purpose without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 5 parameters, no output schema, and present annotations, the description covers the tool's behavior thoroughly—explaining all parameters, constraints, the return dict structure, and an example. No gaps remain for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no descriptions (0% coverage), but the description fully explains each parameter: db, dtype, start, endpoint, count. It provides examples and acceptable values (e.g., S7 data types list). This adds significant meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description starts with '[READ]' and clearly states 'Read count dtype items from data block db', specifying the verb and resource. It distinguishes from sibling tools like s7_read_area and s7_read_many by focusing on a specific data block read with explicit dtype and offset.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for reading items from a data block and provides an example, but does not explicitly state when to use this tool versus alternatives like s7_read_area or s7_read_many. No exclusions or conditions are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
s7_read_manyARead-only
[READ][risk=low] Batch-read raw pyS7 address strings in one request.
Args:
addresses: pyS7 addresses, e.g. ["DB1,REAL4", "DB1,X0.0", "MW10", "I0.0"].
endpoint: Endpoint name from config.
Returns dict: {endpoint, count, items:[{address, value}]}.
Example: s7_read_many(addresses=["DB1,REAL4","M0.0"]).
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | No | ||
| addresses | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint, openWorldHint, and destructiveHint. The description adds beyond these by specifying the return format (dict with endpoint, count, items) and confirming it is a read operation. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise with a clear structure: purpose line, Args section, Returns section, and Example. Every sentence adds value with no repetition or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description adequately explains the return format and provides a complete example. All parameters are described with sufficient detail for an agent to use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description fully compensates. It explains the 'addresses' parameter with examples like 'DB1,REAL4' and 'MW10' and defines 'endpoint' as 'Endpoint name from config', adding meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Batch-read raw pyS7 address strings' with a specific verb and resource. It distinguishes from sibling read tools like s7_read_area and s7_read_db by emphasizing 'raw pyS7 address strings' and batch operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a clear use case (batch-read multiple addresses) and an example. However, it does not explicitly state when not to use it or mention alternatives, leaving some ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
s7_write_dbADestructive
[WRITE][risk=HIGH][MOC] Write ONE value to an S7 data block (off by default).
OT-DANGEROUS. Defaults to dry_run=True (nothing written). Captures the BEFORE
value (read-back) and records an undo descriptor so the change is reversible.
Set dry_run=False AND record an approver (OPCUA_AUDIT_APPROVED_BY) to apply.
未经授权勿对生产控制系统写入.
Args:
db: Data block number.
dtype: S7 data type — BIT|BYTE|WORD|INT|DWORD|DINT|REAL|LREAL.
start: Byte offset within the DB.
value: Value to write (coerced to the dtype's Python type).
endpoint: Endpoint name from config.
dry_run: When True (default) returns a preview without writing.
Returns dict: dry-run → {address, dry_run:true, before, would_write, note};
applied → {address, dry_run:false, before, written, applied:true, _undo_id}.
Example (preview): s7_write_db(db=1, dtype="INT", start=0, value=42).
| Name | Required | Description | Default |
|---|---|---|---|
| db | Yes | ||
| dtype | Yes | ||
| start | Yes | ||
| value | Yes | ||
| dry_run | No | ||
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate destructivity, and the description adds crucial safety context: captures BEFORE value, records undo descriptor, requires approver for actual write. This goes beyond annotations, though it could be more explicit about error recovery.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Very concise and well-structured: summary line, risk note, behavior details, argument list, return dict format, and example. Every sentence adds value with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema, but description fully documents return format. Includes example and explains both dry-run and applied scenarios. Missing error handling or permission details, but overall complete for safe usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema coverage, the description provides meaningful parameter info: dtype lists exact types, start is 'Byte offset', value is coerced. The example further clarifies usage. Could add constraints like valid DB ranges.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Write ONE value to an S7 data block', specifying the verb and resource. It distinguishes from siblings like s7_read_db by emphasizing the write action and including a risk label. The summary line and examples reinforce the purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states default dry_run=True for preview, and that actual writing requires dry_run=False and an approver. Provides clear when-to-use guidance but does not explicitly contrast with alternative write tools (though siblings are mostly read tools).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
site_readinessARead-only
[READ][risk=low] Which scenarios THIS site can run today, and what each gap needs.
The companion to `protocols_supported`, one altitude down. That one says what
the product can do; this says what this installation can do — and calling the
first without the second is how an agent plans a scenario the site has no
inputs for.
Contacts nothing: no device, no network, no historian. It is derived from
`config.yaml` and the local store, which is what makes it runnable against a
site nobody has authorised you to probe — the site that most needs it.
Three states, and the middle one carries the value: `ready`, `degraded` (it
RUNS, on less than full evidence — root cause without a historian still ranks
causes, it just cannot see the two hours before the stoppage) and `blocked`.
`blocked_on` is the actionable half: one missing input usually unlocks several
scenarios, ranked by how many.
It never fills a gap in for you. Which tag is the production counter is
process knowledge, and a wrong guess yields plausible-looking OEE numbers —
considerably worse than an error (D16). Where a prerequisite cannot be
supplied at all yet, the row says `not_yet_expressible` rather than implying
somebody forgot to configure it.
`db` overrides the local store path; empty means the iaiops store.
| Name | Required | Description | Default |
|---|---|---|---|
| db | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite annotations already declaring readOnlyHint and non-destructive behavior, the description adds substantial behavioral context: 'Contacts nothing: no device, no network, no historian,' and that it is derived from `config.yaml` and the local store. It also clarifies the three possible states, explains that `blocked_on` is the actionable half, and discloses that it never fills gaps and uses `not_yet_expressible` rather than implying misconfiguration. No contradiction exists with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but dense and every section earns its place: summary, relationship to sibling, safety behavior, state semantics, actionable output, gap-handling philosophy, and the parameter override. It is front-loaded with the core purpose and risk posture, and the structure makes it easy for an agent to extract the key facts.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with one optional parameter and no output schema, the description is complete. It explains what the tool returns semantically (ready/degraded/blocked, blocked_on, not_yet_expressible), how to interpret the mid-state, and how the db parameter affects execution. An agent has enough to select, invoke, and interpret results correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the full burden for explaining the single parameter. It does so explicitly: '`db` overrides the local store path; empty means the iaiops store.' This clarifies both the override behavior and the default, which is exactly what the agent needs to invoke the tool correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Which scenarios THIS site can run today, and what each gap needs.' It clearly differentiates itself from the sibling `protocols_supported` by stating one altitude down: 'That one says what the product can do; this says what this installation can do.' No ambiguity remains about what the tool is for.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly names the companion tool `protocols_supported`, explains the relationship, and warns that calling the first without the second leads to planning a scenario the site has no inputs for. It also tells the agent when this tool is especially valuable: it can run against a site nobody has authorized probing. This is clear when-to-use and alternative-routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sparkplug_decode_payloadARead-only
[READ][risk=low] Decode a single raw Sparkplug B payload to structured metrics.
Full protobuf decode (vendored Eclipse Tahu schema): per metric returns name,
alias, datatype (Int/Float/Bool/String/DateTime/DataSet/Template…), value,
timestamp, and is_historical / is_null flags. Rich types expand: a DataSet
value decodes to {columns, types, rows} and a Template value to {template_ref,
is_definition, version, members, parameters} (members decoded recursively).
Args:
payload: Raw Sparkplug B protobuf bytes as a string, ``base64`` (default) or ``hex``.
encoding: 'base64' or 'hex'.
alias_map: Optional {alias: name} (from a prior BIRTH) so alias-only
NDATA/DDATA metrics resolve to names.
Returns dict: {encoding:'sparkplug_b', timestamp, seq, uuid, metric_count,
historical_count, metrics:[{name, alias, datatype, value, timestamp,
is_historical, is_null}]}. A DataSet ``value`` is {dataset:true, columns,
types, rows, row_count}; a Template ``value`` is {template:true,
template_ref, is_definition, version, members:[{name, type, value}],
parameters}.
Example: sparkplug_decode_payload(payload="CAESBwoDYWJjEAE=", encoding="base64").
| Name | Required | Description | Default |
|---|---|---|---|
| payload | Yes | ||
| encoding | No | base64 | |
| alias_map | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=true. The description adds valuable behavioral details: it uses a vendored Eclipse Tahu schema, returns flags like is_historical/is_null, and recursively expands DataSet and Template values. There is no contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a [READ][risk=low] tag, then concisely states purpose, then lists parameters, return format, and an example. While informative, it is slightly verbose in detailing return fields that are also summarized later; a bit of redundancy. Still efficient overall.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite lacking an output schema, the description provides a complete return structure including nested expansions for DataSet and Template values. It covers all parameters, encoding details, and alias usage. For a protobuf decode tool with 3 parameters and no output schema, this is thorough and sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, meaning the input schema provides no descriptions for the 3 parameters. The description fully compensates by explaining each parameter: 'payload' (raw bytes as base64 or hex default), 'encoding' (base64 or hex), and 'alias_map' (optional alias-to-name mapping). Also provides an example with an encoded payload.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Decode a single raw Sparkplug B payload to structured metrics.' It specifies the verb 'decode', the resource 'Sparkplug B payload', and the output 'structured metrics'. Among 100+ sibling tools, this uniquely targets raw payload decoding, contrasting with subscription, node listing, and generic MQTT tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains the tool's inputs and output but does not explicitly state when to use it vs. alternatives like sparkplug_subscribe_sample or sparkplug_node_list. Usage context is implied through the example and parameter details, but no 'when not to use' or exclusion guidance is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sparkplug_live_schemaARead-only
[READ][risk=low] Capture a LIVE Sparkplug schema (bounded) → drift-ready dict.
Subscribes, collects up to ``max_msgs`` messages or until ``duration_s``, decodes
NBIRTH/DBIRTH metrics, and returns ``schema`` = {node: {metric: datatype}} (node =
group/edge[/device]) — exactly the shape uns_schema_drift accepts. Use it as a
baseline or current snapshot.
Args:
endpoint: Endpoint name from config.
topic: Topic filter (default 'spBv1.0/#').
duration_s: Capture window in seconds (1..60).
max_msgs: Max messages to capture (1..500).
Returns dict: {endpoint, topic, message_count, birth_count, node_count,
schema:{node:{metric:datatype}}}.
Example: sparkplug_live_schema(topic="spBv1.0/Plant1/#", duration_s=15).
| Name | Required | Description | Default |
|---|---|---|---|
| topic | No | spBv1.0/# | |
| endpoint | No | ||
| max_msgs | No | ||
| duration_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only and non-destructive behavior. The description adds detail about subscribing, collecting messages, and decoding, which is consistent with annotations. No contradiction found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a summary, parameter list, return format, and example. It is front-loaded and every sentence serves a purpose without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only tool with four parameters and no output schema, the description covers the core functionality, return shape, and provides an example. It lacks error handling or edge-case details but is sufficient for the intended use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, but the description lists each parameter with a brief explanation, including defaults and the topic filter syntax. This adds meaning beyond the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool captures a LIVE Sparkplug schema, decodes NBIRTH/DBIRTH metrics, and returns a dict. It uses specific verbs and resources, and the purpose is distinct from sibling tools like sparkplug_decode_payload or sparkplug_subscribe_sample.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description suggests using it as a baseline or current snapshot, providing clear usage context. However, it does not explicitly state when not to use it or mention alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sparkplug_node_listARead-only
[READ][risk=low] Discover edge nodes/devices + online state + primary-host STATE.
Builds the birth/death + seq model from BIRTH/DATA/DEATH/STATE topics: each
node reports online/born, its devices, learned metric aliases, and seq gaps;
STATE topics surface primary-host status.
Args:
endpoint: Endpoint name from config.
timeout_s: Observation window in seconds (1..60). Longer catches infrequent nodes.
count: Max messages to inspect (1..500).
Returns dict: {endpoint, node_count, nodes:[{group_id, edge_node_id, online,
born, devices:[...], metric_aliases_known, seq_gap_count, seq_issues}],
primary_hosts:[{host_id, state}]}.
Example: sparkplug_node_list(timeout_s=15).
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| endpoint | No | ||
| timeout_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it read-only and non-destructive. The description adds valuable context: it details the internal model built from BIRTH/DATA/DEATH/STATE topics, explains what 'online' means, and lists return fields including seq gaps and primary host state. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with summary, parameter doc, return structure, and example. It is slightly verbose (e.g., repeating 'builds the birth/death + seq model'), but every sentence adds value given the complex domain. Could be tightened, but still effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of Sparkplug and lack of output schema, the description thoroughly explains the return dict structure with all nested fields. It covers parameter behavior, default values, and provides an example. No gaps remain for an agent to select and invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, but the description compensates fully with detailed explanations for each parameter (endpoint from config, timeout_s range 1-60, count 1-500) and their purpose. Includes an example invocation, making parameter usage crystal clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the tool discovers edge nodes/devices and online state plus primary-host state, using specific Sparkplug topics. It clearly distinguishes from sibling tools like sparkplug_subscribe_sample or sparkplug_decode_payload by focusing on node listing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains use cases via the example and parameter guidance (e.g., longer timeout for infrequent nodes), but does not explicitly contrast with alternatives among the many Sparkplug-related siblings. The context is clear enough for an agent to infer appropriate use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sparkplug_subscribe_sampleARead-only
[READ][risk=low] Bounded Sparkplug B sample with full decode + birth/death/seq.
Topics are parsed and payloads fully protobuf-decoded; a birth/death + seq
model resolves aliases (from NBIRTH/DBIRTH), applies NDATA/DDATA by alias, and
flags is_historical metrics and seq gaps.
Args:
endpoint: Endpoint name from config.
topic: Topic filter (default 'spBv1.0/#').
count: Max messages (1..500).
timeout_s: Max seconds to wait (1..60).
Returns dict: {endpoint, topic, message_count, historical_metric_count,
seq_gap_count, samples:[{topic, sparkplug:{group_id, message_type,
edge_node_id, device_id}, payload:{metrics:[{name, alias, datatype, value,
is_historical}]}}]}.
Example: sparkplug_subscribe_sample(topic="spBv1.0/Plant1/#", count=20).
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| topic | No | ||
| endpoint | No | ||
| timeout_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only and non-destructive nature. The description adds valuable behavioral context: bounded count/timeout, full protobuf decoding, alias resolution from birth certificates, flagging of historical metrics and sequence gaps. This goes well beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (summary, technical details, args, returns, example). It is moderately concise; every sentence adds information, though the technical paragraph could be slightly more succinct.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description fully details the return dictionary structure, making the tool's output understandable. It covers purpose, inputs, outputs, and an example. Missing usage guidelines and error handling, but otherwise complete for a tool of this complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema coverage, the description carries the full burden. It provides parameter names, brief descriptions, and constraints (count: 1..500, timeout: 1..60) not present in the schema. The example aids understanding. No details on endpoint source or topic format beyond defaults.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as a bounded Sparkplug B sample with full decode and birth/death/seq handling. It specifies the exact resource (Sparkplug B topics) and verb (subscribe and sample), distinguishing it from siblings like sparkplug_decode_payload or mqtt_read_topic.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives. While the description implies it is for sampling a bounded number of messages, it does not mention when not to use it (e.g., for continuous subscription or decoding individual payloads).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
stream_publishA
[READ][risk=low] Publish already-read normalized points to a message bus (NATS).
Egress of data the agent already READ — NOT a control write. Each numeric point becomes a JSON
message on ``<subject_prefix>.tag.<metric>``; non-numeric points are skipped (use a historian
sink for text/state). Needs the extra: pip install iaiops[nats].
Args:
points: Collected point dicts (e.g. from *_read_many): {ref/metric, value, timestamp, ...}.
subject_prefix: NATS subject root (default 'iaiops').
servers: Comma-separated NATS server URLs (default nats://localhost:4222).
token: Optional NATS auth token.
tls: Use TLS to the broker.
publisher: Bus kind (currently 'nats').
Returns dict: {publisher, subject_prefix, received, published, skipped_non_numeric}.
Example: stream_publish(points=[{"ref": "line1.temp", "value": 21.5}], subject_prefix="plant").
| Name | Required | Description | Default |
|---|---|---|---|
| tls | No | ||
| token | No | ||
| points | Yes | ||
| servers | No | nats://localhost:4222 | |
| publisher | No | nats | |
| subject_prefix | No | iaiops |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false and destructiveHint=false, and the description aligns by stating it is a publish (write) operation of already-read data. It adds context: non-numeric points are skipped, and the tool requires an extra pip install. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a summary line, behavioral explanation, Args, Returns, and Example. It is front-loaded with the purpose. While not overly verbose, every sentence adds value and it remains focused.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 6 parameters, no output schema, and no enums, the description comprehensively covers input parameters, return value format, and provides an example. It is complete enough for an agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description fully compensates by explaining each parameter in the Args section (points, subject_prefix, servers, token, tls, publisher) and providing an example. This adds essential meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it publishes already-read normalized points to a NATS message bus, specifying it is for egress of read data and not a control write. It distinguishes from sibling tools like stream_publish_event, historian_push, and mqtt_publish by focusing on NATS.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains to use this tool for publishing already-read numeric points, notes that non-numeric points are skipped, and suggests using a historian sink for text/state. It also mentions the needed pip install. While it doesn't explicitly list when not to use, it provides clear context for appropriate usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
stream_publish_eventA
[READ][risk=low] Publish one computed event (RCA verdict / alarm) to a message bus (NATS).
Egress of a finding the brain already COMPUTED — e.g. an RCA verdict or an alarm episode — to
``<subject_prefix>.<subject>`` as JSON. NOT a control write. Needs: pip install iaiops[nats].
Args:
subject: Event subject suffix (e.g. 'rca.verdict', 'alarm.flood').
event: The event payload dict (published as JSON).
servers/token/tls/subject_prefix/publisher: bus connection (see stream_publish).
Returns dict: {publisher, subject, published}.
Example: stream_publish_event(subject="rca.verdict", event={"primary_cause": "seal"}).
| Name | Required | Description | Default |
|---|---|---|---|
| tls | No | ||
| event | Yes | ||
| token | No | ||
| servers | No | nats://localhost:4222 | |
| subject | Yes | ||
| publisher | No | nats | |
| subject_prefix | No | iaiops |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=false and destructiveHint=false. The description adds that it publishes to NATS, is not a control write, requires pip install iaiops[nats], and returns a dict with publisher, subject, published. This goes beyond annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a lead line, parameter list, return info, and example. Every sentence adds value. It is front-loaded with the core purpose. No unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 7 parameters, no output schema, and many siblings, the description covers the output format, gives an example, and references stream_publish for connection details. It lacks edge cases or error handling, but overall provides sufficient context for an agent to use the tool effectively.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so description must compensate. It defines subject and event with examples and types. For the 5 connection parameters (servers, token, tls, subject_prefix, publisher), it merely groups them and defers to stream_publish, lacking individual details. This provides basic but incomplete semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool publishes one computed event to a message bus (NATS), with specific verb 'publish' and resource 'event'. It distinguishes from siblings by noting it's for computed findings (RCA verdict/alarm) and explicitly says 'NOT a control write', contrasting with stream_publish.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use: for egress of already computed results, and not for control writes. It references stream_publish for connection details, indicating alternative for raw publishing. An example further clarifies usage. Lacks explicit when-not-to-use scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
subscription_healthARead-only
[READ][risk=low] Health of a sequenced subscription feed (OPC-UA or Sparkplug B).
Detects dropped notifications (sequence gaps), duplicates / out-of-order, a high
republish-rejection rate, and overloaded channels — the classic Kepware
"too many tags on one channel → republish/queue-flush dropouts" fault.
Args:
sequence: Sequence numbers actually received, in arrival order.
republish_requested: How many republish requests were made.
republish_rejected: How many were rejected (server couldn't keep up).
tags_per_channel: {channel/endpoint: tag_count} — flags channels over the max.
max_tags_per_channel: Density above which a channel is flagged (default 5000).
wrap_at: Modulus for rolling counters (e.g. 256 for Sparkplug B seq); omit
for monotonic OPC-UA counters.
Returns dict: {received, missed_count, duplicate_count, out_of_order_count,
republish_requested, republish_rejected, republish_reject_rate,
overloaded_channels:[{channel, tags}], max_tags_per_channel,
verdict ('ok'|'reordered'|'lossy'|'overloaded'), recommendation}.
Example: subscription_health(sequence=[1,2,4,5], tags_per_channel={"ch1":7000}).
| Name | Required | Description | Default |
|---|---|---|---|
| wrap_at | No | ||
| sequence | Yes | ||
| tags_per_channel | No | ||
| republish_rejected | No | ||
| republish_requested | No | ||
| max_tags_per_channel | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description adds behavioral details such as being a read operation with low risk, and explains the algorithmic detection of issues. This goes beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (purpose, args, returns, example) and front-loaded with the key purpose. However, it is somewhat lengthy, but every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (6 params, no output schema), the description is complete: it explains all inputs, details the return dict structure, and provides an example. This fully equips an agent to use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 0% schema coverage, the description provides thorough explanations for all 6 parameters, including type hints, defaults, and an example. This fully compensates for the lack of schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: analyzing the health of a sequenced subscription feed (OPC-UA or Sparkplug B). It specifies what it detects (sequence gaps, duplicates, etc.), making it distinct from sibling tools like 'opcua_health_summary' or 'sparkplug_subscribe_sample'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when monitoring subscription feeds and suspecting sequence issues or overloaded channels. It provides context but does not explicitly state when not to use it or suggest alternative tools for different scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tag_healthARead-only
[READ][risk=low] Rank tag offenders by bad-quality / flatline / range / anomaly.
Args:
tags: Per-tag dicts — {ref, label?, samples:[scalars or {value, good|quality}],
warn_high?, alarm_high?, warn_low?, alarm_low?}.
thresholds: Optional {ref: {warn_high, alarm_high, warn_low, alarm_low}} override.
Returns dict: {evaluated, overall ('ok'|'warn'|'alarm'), offender_count,
offenders:[{ref, label, samples, latest, flags:[...], anomaly_count,
severity (0..3)}], results:[...]}. Flags include bad_quality, flatline,
out_of_range_warn/alarm, statistical_anomaly.
Example: tag_health(tags=[{"ref":"ns=2;i=5","samples":[70,71,70,99]}]).
| Name | Required | Description | Default |
|---|---|---|---|
| tags | Yes | ||
| thresholds | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds detail on the output structure, flags, and severity levels, going beyond the annotations by explaining the behavioral aspects of the ranking and return format.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a summary line and then organized into Args and Returns. It is slightly lengthy but necessary due to the tool's complexity; could be trimmed without losing essential information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description comprehensively explains the return values (dict with overall, offenders, flags) since no output schema exists. It covers the main use case but lacks mention of error handling or edge cases, which is acceptable for a read-only tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by detailing the structure of 'tags' (e.g., per-tag dicts with optional fields) and 'thresholds' (optional override). This adds significant meaning beyond the minimal schema definition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'Rank tag offenders by bad-quality / flatline / range / anomaly', which clearly specifies the verb 'rank' and the resource 'tag offenders'. It is distinct from sibling tools like alarm_bad_actors or anomaly_scan, but does not explicitly differentiate them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives such as data_quality_scorecard or health_summary. The description only explains what the tool does without usage context or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
uns_browseARead-only
[READ][risk=low] Browse the live topic tree (UNS) under a filter (bounded).
Args:
endpoint: Endpoint name from config.
topic: Topic filter to browse under (default '#').
timeout_s: Observation window in seconds (1..60).
count: Max messages to inspect (1..500).
Returns dict: {endpoint, filter, topic_count, topics:[...], tree:{nested segments}}.
Example: uns_browse(topic="factory/#", timeout_s=8).
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| topic | No | # | |
| endpoint | No | ||
| timeout_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds behavioral details beyond annotations, such as risk level ('risk=low'), bounded observation window, and max message count. It does not contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded with purpose. It lists arguments, return format, and an example in a clear, structured manner. Every sentence adds value with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the return format (endpoint, filter, topic_count, topics, tree) despite the lack of an output schema. However, it could be more explicit about edge cases or the exact structure of the tree.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite schema coverage being 0%, the description thoroughly explains each parameter: endpoint, topic, timeout_s, count, including defaults, ranges, and example usage. This adds significant meaning beyond the raw schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it is a read-only operation to browse the live UNS topic tree under a bounded filter. The verb 'browse' and resource 'topic tree (UNS)' are specific and distinguish it from sibling tools like uns_topic_audit or uns_live_audit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives. The description lacks any 'when to use' or 'when not to' statements, leaving the agent to infer context from the name and parameters alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
uns_live_auditARead-only
[READ][risk=low] Capture the LIVE UNS topic tree (bounded) then audit it.
Closes the governance loop: subscribes to a live broker, collects up to
``max_msgs`` messages or until ``duration_s`` (whichever first), then runs the
naming-conformance + topic-sprawl audit over the observed topics. Never an
open-ended loop.
Args:
endpoint: Endpoint name from config (protocol must be 'mqtt').
topic: Topic filter to capture under (default '#').
duration_s: Capture window in seconds (1..60, capped server-side).
max_msgs: Max messages to capture (1..500, capped server-side).
allowed_roots: Permitted top-level segments; others are flagged (optional).
min_segments: Minimum namespace depth a well-formed topic must have.
max_leaf_parents: A leaf under more than this many parents is scattered.
Returns dict: the uns_topic_audit result (topic_count, depth, verdict, findings)
plus capture:{endpoint, topic, observed_messages, unique_topics, topics[]}.
Example: uns_live_audit(topic="factory/#", duration_s=8, allowed_roots=["factory"]).
| Name | Required | Description | Default |
|---|---|---|---|
| topic | No | # | |
| endpoint | No | ||
| max_msgs | No | ||
| duration_s | No | ||
| min_segments | No | ||
| allowed_roots | No | ||
| max_leaf_parents | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds behavioral context: subscribes to a live broker, collects up to max_msgs or duration_s (bounded), and runs naming-conformance + topic-sprawl audit. It does not contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: a header line, a paragraph on governance loop, an Args list, Returns, and an Example. It is somewhat lengthy but every sentence adds value. Could be slightly more concise, but overall effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers all aspects: behavior, parameters, return format (including nested dict shape), and provides an example. Since there is no output schema, the description's explanation of the return dict is essential and well-provided.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema description coverage at 0%, the description fully compensates by explaining each parameter in the Args section, including bounds (e.g., duration_s: 1..60 capped, max_msgs: 1..500 capped), their purpose (e.g., allowed_roots: 'Permitted top-level segments; others are flagged'), and a usage example.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Capture the LIVE UNS topic tree (bounded) then audit it', specifying the action (capture + audit), the resource (LIVE UNS topic tree), and the bounded nature. It distinguishes from sibling tools like uns_topic_audit (offline audit) by emphasizing live capture.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains the tool's role: 'Closes the governance loop' and describes the capture-then-audit process. It clarifies the tool is not an open-ended loop. However, it does not explicitly mention when to avoid this tool or suggest alternatives (e.g., uns_topic_audit for offline audits).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
uns_live_driftARead-only
[READ][risk=low] Capture the LIVE Sparkplug schema (bounded) and diff vs baseline.
Captures current node/metric definitions from live BIRTHs, then runs schema drift
against ``baseline`` — added / removed / type-changed metrics per node with a
none/additive/breaking verdict.
Args:
baseline: Prior schema {node:{metric:datatype}} (e.g. from sparkplug_live_schema).
endpoint: Endpoint name from config.
topic: Topic filter (default 'spBv1.0/#').
duration_s: Capture window in seconds (1..60).
max_msgs: Max messages to capture (1..500).
Returns dict: the uns_schema_drift result (changed_nodes, verdict, node_changes)
plus capture:{endpoint, topic, message_count, birth_count, node_count}.
Example: uns_live_drift(baseline={"Plant1/Edge1":{"Temperature":"Double"}}).
| Name | Required | Description | Default |
|---|---|---|---|
| topic | No | spBv1.0/# | |
| baseline | Yes | ||
| endpoint | No | ||
| max_msgs | No | ||
| duration_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds significant transparency: it explains the bounded capture via duration_s and max_msgs, the live BIRTHs as data source, and the structure of the return value (changed_nodes, verdict, node_changes plus capture metadata). This goes beyond annotations to fully disclose behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact yet complete: a one-liner summary, a brief explanation, then structured sections for Args, Returns, and a concrete Example. Every sentence is informative, with no redundancy. It is front-loaded with the core purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description fully explains the return value (drift result plus capture info). Constraints (duration_s 1..60, max_msgs 1..500) are included. The tool's complexity is low (read-only drift), and the description covers all needed aspects for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 0% coverage (no descriptions in schema properties), but the description compensates with an explicit Args section covering all five parameters: baseline, endpoint, topic, duration_s, max_msgs. Each has type, default, and purpose. Baseline is described as a structured object. The example also demonstrates parameter usage. This provides full semantic meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a clear verb-resource pair: 'Capture the LIVE Sparkplug schema (bounded) and diff vs baseline.' It specifies the tool's action (capture and diff) and the resource (Sparkplug schema). It distinguishes itself by mentioning the baseline from sparkplug_live_schema and the output type uns_schema_drift, setting it apart from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool: to capture live schema and compare against a baseline. It references the baseline source (e.g., from sparkplug_live_schema), guiding the user on how to prepare input. The return structure and example further clarify usage. No explicit exclusions are needed given the straightforward use case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
uns_publishA
[READ][risk=low] Publish already-read normalized points to an MQTT broker / UNS.
Egress of data the agent already READ — NOT a control write. Each numeric point becomes a JSON
message on ``<topic_prefix>/<metric>``, with a dotted metric nested into topic levels
(``line1.temp`` -> ``plant/line1/temp``) so a Unified Namespace stays browsable. Non-numeric
points are skipped (use a historian sink for text/state). The topic is always derived from
``topic_prefix`` — it is never taken verbatim, so this cannot address a command topic. Needs the
extra: pip install iaiops[mqtt].
Args:
points: Collected point dicts (e.g. from *_read_many): {ref/metric, value, timestamp, ...}.
topic_prefix: Root of the topic tree (default 'iaiops'); wildcards are stripped.
host: Broker hostname or IP (default localhost).
port: Broker port; 0 picks 8883 with TLS else 1883.
username: Optional broker username.
password: Optional broker password.
use_tls: Use TLS to the broker.
qos: MQTT QoS 0/1/2 (default 0, fire-and-forget); values outside 0-2 are clamped.
retain: Ask the broker to retain the last value per topic (useful for a UNS).
Returns dict: {publisher, topic_prefix, broker, received, published, skipped_non_numeric}.
Example: uns_publish(points=[{"ref": "line1.temp", "value": 21.5}], topic_prefix="plant",
host="10.0.0.5").
| Name | Required | Description | Default |
|---|---|---|---|
| qos | No | ||
| host | No | localhost | |
| port | No | ||
| points | Yes | ||
| retain | No | ||
| use_tls | No | ||
| password | No | ||
| username | No | ||
| topic_prefix | No | iaiops |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses rich behavioral detail beyond the annotations: dotted-metric topic nesting, non-numeric point skipping, derived topic prefix with wildcard stripping, QoS clamping, port/TLS auto-selection, and the exact return dictionary. Annotations are minimal and safe (destructiveHint false), so the description carries and fully satisfies the burden. There is no contradiction with readOnlyHint=false because the publication is a side-effect write, while '[READ]' refers to source data already read.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every section earns its place: a purpose statement, safety clarification, behavioral details, a structured parameter list, return type, and a concrete example. It is front-loaded with the core purpose and risk tag before diving into details, and the formatting makes it easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 9 parameters, no output schema, and no parameter descriptions in the schema, the description is remarkably complete. It defines the return dict, covers edge cases (non-numeric skip, wildcard stripping, QoS clamping), mentions the installation prerequisite, provides an example, and clarifies the safety profile. Nothing an agent needs to call this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must fully explain each of the 9 parameters. It does: points, topic_prefix, host, port, username, password, use_tls, qos, and retain, each with defaults, meaning, and behavioral notes (e.g., 'wildcards are stripped', 'values outside 0-2 are clamped'). This comprehensively compensates for the schema gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action: 'Publish already-read normalized points to an MQTT broker / UNS.' It clearly defines the resource (numeric points) and differentiates from control-write tools by noting 'NOT a control write' and from historian sinks for non-numeric data. This makes its purpose unambiguous and distinguishable from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says when to use: to egress data the agent has already read. It gives when-not guidance: 'Non-numeric points are skipped (use a historian sink for text/state)' and 'cannot address a command topic.' It also mentions the prerequisite pip install, leaving no ambiguity about invocation context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
uns_schema_driftARead-only
[READ][risk=low] Detect Sparkplug/UNS schema drift between two snapshots.
Compares baseline vs current node/metric definitions (e.g. two NBIRTH snapshots)
and reports added / removed / type-changed metrics per node, with a verdict.
Args:
baseline: {node: {metric: datatype}} or [{node|topic, metrics:[{name, datatype}]}].
current: Same shape — the newer snapshot to compare against the baseline.
Returns dict: {baseline_nodes, current_nodes, changed_nodes,
verdict ('none'|'additive'|'breaking'), node_changes:[{node, node_status,
added[], removed[], type_changed:[{metric, from, to}]}]}.
Example: uns_schema_drift(baseline={"N1":{"temp":"Float"}},
current={"N1":{"temp":"Int32","rpm":"Float"}}).
| Name | Required | Description | Default |
|---|---|---|---|
| current | Yes | ||
| baseline | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description tags the tool as [READ][risk=low], aligning with annotations (readOnlyHint=true, destructiveHint=false). It discloses the output structure and the type of changes detected (added, removed, type-changed), going beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: a one-line title, explanation of purpose, argument format, return type, and a concrete example. Every sentence adds value without fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers input format, output structure with all keys, and a usage example. With no output schema, this provides sufficient context for an agent to understand what the tool returns and how to use it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 0% schema description coverage, the description thoroughly explains the expected shape and format of both parameters (baseline and current) including an example. This fully compensates for the lack of schema-level description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool detects schema drift between two snapshots for Sparkplug/UNS, specifying the verb 'detect' and resource 'schema drift'. It distinguishes itself from siblings like uns_browse or uns_topic_audit by focusing on comparison of snapshots.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains what the tool does (compare baseline vs current) and provides an example, but does not explicitly contrast with sibling tools like uns_live_drift or baseline_check. The usage context is clear enough for an agent familiar with the domain.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
uns_topic_auditARead-only
[READ][risk=low] Govern a UNS topic tree: naming conformance + topic sprawl.
Pure analysis over a provided list of UNS topic strings (no live broker). Flags
non-conforming roots, too-shallow topics, casing collisions of the same logical
name, leaf metrics scattered under many parents, depth outliers, and duplicates.
Args:
topics: UNS topic strings, e.g. ["Enterprise/Site/Area/Line1/temperature", ...].
allowed_roots: Permitted top-level segments; others are flagged (optional).
min_segments: Minimum namespace depth a well-formed topic must have.
max_leaf_parents: A leaf appearing under more than this many parents is scattered.
Returns dict: {topic_count, unique_topics, root_count, roots[], depth{min,max,mean},
verdict ('clean'|'minor'|'sprawling'), sprawl_findings, findings{
non_conforming_root[], too_shallow[], casing_collisions[], scattered_leaves[],
depth_outliers[], duplicate_topics[]}}.
Example: uns_topic_audit(topics=["Ent/Site/Line1/temp","Ent/site/Line1/Temp"],
allowed_roots=["Ent"], min_segments=3).
| Name | Required | Description | Default |
|---|---|---|---|
| topics | Yes | ||
| min_segments | No | ||
| allowed_roots | No | ||
| max_leaf_parents | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The descriptions adds significant behavioral context beyond annotations. It declares the tool as read-only and low risk, consistent with readOnlyHint=true, and details the exact types of analysis performed (e.g., flagging non-conforming roots, casing collisions, scattered leaves). No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a header, a concise explanation, and clear Args/Returns sections. It front-loads the core purpose and risk level. While detailed, every sentence contributes value, though the Returns block could be slightly more compact. Overall, it strikes a good balance between completeness and brevity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description provides a comprehensive dict structure for return values. It covers all parameter explanations, analysis logic, and expected outputs. The annotations already handle safety, and the description fills in all behavioral and usage gaps, making the tool well-understood by an AI agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 0% description coverage, so the description carries the full burden. It provides clear semantic explanations for all 4 parameters: topics (UNS topic strings), allowed_roots (permitted top-level segments), min_segments (minimum depth), and max_leaf_parents (scatter threshold). This adds essential meaning beyond the schema's type-only definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: to govern a UNS topic tree by performing naming conformance and topic sprawl analysis. It explicitly specifies that it works on a provided list of topic strings (no live broker), distinguishing it from sibling tools like uns_live_audit and uns_browse that operate on live data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for static topic analysis by stating 'no live broker', but it does not explicitly list when to use this tool versus alternatives (e.g., uns_live_audit for live monitoring). There is no direct mention of when not to use it or explicit sibling comparisons, leaving room for ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
verify_determinismARead-only
[READ][risk=low] Prove this engine's analysis is reproducible without a model.
Runs a named suite of analyses (availability, production counts, the Six Big
Losses, ISA-18.2 alarm load, control charts, the conservative baseline, the
RCA copilot) over a pinned reference dataset, canonically encodes each result
and digests it — twice in this process and, with ``subprocesses``, once more
in each of two fresh interpreters started at different PYTHONHASHSEED values.
That last arm is the one that catches a set or dict iteration order reaching a
result; a single run never can. The socket API raises throughout, so a
computation that reached for a device or a hostname fails here rather than
quietly succeeding on a machine that happens to be online. ``sys.modules`` is
checked afterwards for any model library — empty is the guarantee.
Use it to answer "how do I know your AI didn't make this number up": the
answer is that no model is in the path, and here is the SHA-256 that says so,
reproducible on the customer's own box. Read-only; nothing is written unless
the CLI (`iaiops verify determinism --out record.json`) is used to save the
signable record for a validation file.
Args:
subprocesses: Also re-run in two fresh interpreters at fixed, different
hash seeds (default True; adds roughly a second).
Returns dict: {check, result:{verdict ('reproducible'|'not_reproducible'),
suite_digest, dataset:{name, revision, digest}, checks:[{name, covers,
digest}], arms:[{arm, suite_digest, matches_first_arm}], arms_disagreeing,
model_modules_loaded, network}, context:{iaiops_version, python, platform,
generated_at, ...}, note}. ``result`` is identical between runs; ``context``
is not — it records when and where this run happened.
Example: verify_determinism().
| Name | Required | Description | Default |
|---|---|---|---|
| subprocesses | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, it discloses subprocess execution, fixed differing PYTHONHASHSEED runs, socket API failures, the sys.modules model-libery check, and the fact that result is stable across runs while context is not. It also states the read-only caveat with the CLI --out path. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose and risk, and each paragraph adds relevant behavior, parameters, or output shape. It is slightly verbose for a one-parameter tool, with the Returns dict and user-story framing adding length, but nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read-only verification tool, the description covers purpose, when to use it, execution model, side-effect caveat, return structure, and how to interpret reproducibility. Even with an output schema present, the inline Returns dict adds useful detail without leaving any gap needed to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the Args section fully compensates by explaining that subprocesses re-runs in two fresh interpreters at fixed different hash seeds, defaults to true, and adds about a second. This is exactly the behavioral meaning the schema alone does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening line states a specific verb and object: prove the engine's analysis is reproducible without a model. The next sentence enumerates the exact suite of analyses and the pinned reference dataset, and the socket/sys.modules constraints make it unmistakable among the many sibling health/read tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit use case: answer 'how do I know your AI didn't make this number up', and clarifies the tool is read-only unless the CLI flag is added. It does not name alternatives or when-not-to-use conditions, so it misses the full when/when-not/alternatives bar.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
5 tool updates
v0.27.0- Added
alarm_event_clusters - Added
baseline_check_in_context - Added
baseline_learn_contextual - Added
device_advisory_check - Added
downtime_attribution
4 tool updates
v0.26.0- Added
plc_program_drift - Added
plc_program_history - Added
plc_program_snapshot - Added
verify_determinism
9 tool updates
v0.25.0- Added
investigation_list - Added
investigation_open - Added
investigation_readiness - Added
investigation_show - Added
line_relation_declare - Added
line_relations_list - Added
mechanism_library_check - Added
mechanism_library_list - Added
site_readiness
1 tool update
v0.23.0- Added
uns_publish
134 tool updates
v0.1.0- First observed
adopt_alias_map - First observed
alarm_bad_actors - First observed
alarm_cascade - First observed
alarm_flood_analysis - First observed
alarm_rationalization_worksheet - First observed
anomaly_scan - First observed
asset_inventory - First observed
baseline_check - First observed
baseline_learn - First observed
baseline_record_change - First observed
baseline_status - First observed
changeover_analysis - First observed
compliance_dengbao_levels - First observed
compliance_evidence_bundle - First observed
compliance_frameworks - First observed
compliance_mapping - First observed
compliance_report - First observed
cross_protocol_asset_model - First observed
data_quality_fleet_rollup - First observed
data_quality_scorecard - First observed
diagnose_dataflow - First observed
diff_alias_map - First observed
downtime_events - First observed
downtime_root_cause - First observed
downtime_root_cause_live - First observed
downtime_triage - First observed
eip_controller_info - First observed
eip_list_tags - First observed
eip_read_many - First observed
eip_read_tag - First observed
eip_write_tag - First observed
ethercat_master_state - First observed
ethercat_read_pdo - First observed
ethercat_read_sdo - First observed
ethercat_set_state - First observed
ethercat_slave_info - First observed
ethercat_slaves - First observed
ethercat_write_sdo - First observed
export_data - First observed
fins_cpu_info - First observed
fins_cpu_status - First observed
fins_read_bits - First observed
fins_read_many - First observed
fins_read_words - First observed
fins_write_words - First observed
fleet_incidents - First observed
fleet_status - First observed
health_summary - First observed
heartbeat_health - First observed
historian_coverage - First observed
historian_health - First observed
historian_push - First observed
historian_query - First observed
ignition_alarm_status - First observed
ignition_gateway_status - First observed
ignition_tag_browse - First observed
ignition_tag_history - First observed
ignition_tag_read - First observed
iolink_device_info - First observed
iolink_master_info - First observed
iolink_ports - First observed
iolink_read_isdu - First observed
iolink_read_pdin - First observed
iolink_scan - First observed
learn_cause_weights - First observed
mc_cclink_link_read - First observed
mc_cclink_network_health - First observed
mc_cclink_templates - First observed
mc_cpu_status - First observed
mc_read_bits - First observed
mc_read_many - First observed
mc_read_words - First observed
mc_write_words - First observed
modbus_apply_template - First observed
modbus_detect_byte_order - First observed
modbus_health_summary - First observed
modbus_list_templates - First observed
modbus_read_coils - First observed
modbus_read_discrete - First observed
modbus_read_holding - First observed
modbus_read_input - First observed
monitor_changes - First observed
mqtt_publish - First observed
mqtt_read_topic - First observed
mtconnect_assets - First observed
mtconnect_current - First observed
mtconnect_oee_snapshot - First observed
mtconnect_probe - First observed
mtconnect_sample - First observed
oee_compute - First observed
oee_multidim - First observed
opcua_alarm_events - First observed
opcua_anomaly_scan - First observed
opcua_browse - First observed
opcua_diagnose_connection - First observed
opcua_discover_tags - First observed
opcua_health_summary - First observed
opcua_read_alarms - First observed
opcua_read_history - First observed
opcua_read_many - First observed
opcua_read_node - First observed
opcua_server_info - First observed
opcua_subscribe_sample - First observed
pdm_forecast - First observed
plc_program_outline - First observed
plc_program_section - First observed
plc_program_visibility - First observed
plc_program_xref - First observed
profinet_asset_inventory - First observed
profinet_dcp_set - First observed
profinet_discover - First observed
profinet_identify_station - First observed
profinet_station_params - First observed
protocols_supported - First observed
rca_corpus_from_maintenance - First observed
rca_narrate - First observed
s7_cpu_info - First observed
s7_read_area - First observed
s7_read_db - First observed
s7_read_many - First observed
s7_write_db - First observed
sparkplug_decode_payload - First observed
sparkplug_live_schema - First observed
sparkplug_node_list - First observed
sparkplug_subscribe_sample - First observed
stream_publish - First observed
stream_publish_event - First observed
subscription_health - First observed
tag_health - First observed
uns_browse - First observed
uns_live_audit - First observed
uns_live_drift - First observed
uns_schema_drift - First observed
uns_topic_audit
TDQS
Tools are mostly distinct due to protocol prefixes (opcua_, s7_, eip_) and specific functionality (e.g., data_quality_scorecard vs. alarm_flood_analysis). However, there is overlap among alarm analysis tools (alarm_flood_analysis, alarm_bad_actors, alarm_cascade) and downtime tools (downtime_root_cause, downtime_triage, downtime_events), which could cause confusion. Descriptions help differentiate, but the large number of similar-sounding tools makes misselection possible.
Tool names follow a mix of conventions: some use protocol prefix (opcua_read_node), some use verb_noun (read_many), and some use noun_verb (cpu_info). While consistent within protocol groups, the overall pattern is inconsistent across the server. The naming is still readable, but the lack of a unified pattern reduces predictability.
With 134 tools, the set is excessively large for an agent to manage effectively. While the broad scope covering many OT protocols and analytics justifies a high count, the number is overwhelming. Many tools have similar purposes (e.g., multiple alarm analyses), and the agent may struggle to select the right tool quickly. This exceeds typical coherence thresholds.
The tool set is exceptionally comprehensive, covering major OT protocols (OPC-UA, Modbus, S7, Mitsubishi MC, EtherNet/IP, PROFINET, EtherCAT, IO-Link, etc.), advanced analytics (downtime root cause, OEE, alarm management, data quality, historian, compliance), and even PLC program analysis. Read and write tools (with safety guards) are included, along with diagnostics and asset management. There are no significant gaps for its stated purpose.
Maintenance
Related MCP Connectors
Cross-OEM industrial machine intelligence: identity, normalization, automation, attestation.
Protocol-native energy infrastructure orchestration for AI data centers. Provides 46 MCP tools across 8 grid protocols (IEC-61850, DNP3, Modbus, OCPP, OpenADR, IEEE 2030.5, IEC 60870-5-104, ICCP) with 5 core API primitives: connect, dispatch, settle, comply, and intel. Enables AI agents to programmatically interact with substations, grid interfaces, and energy assets for real-time workload-grid coordination.
Query Allen-Bradley and Siemens PLC projects, live tag values, and analyses in plain English.
- MaplithOAuthcom.maplith
Data-ontology maps of your business systems, served to AI agents over MCP.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceConnects AI agents to OPC UA-enabled industrial systems for real-time monitoring and control of operational data. It enables users to read, write, and browse industrial device nodes through natural language interactions.MIT

@inscada/mcp-serverofficial
AlicenseAqualityDmaintenanceEnables AI assistants to interact with inSCADA systems via the Model Context Protocol, providing 39 tools for live data, alarms, scripts, historical analysis, charts, and more.3966MIT- AlicenseAqualityCmaintenanceEnables LLMs to connect to factory PLC sensors, read register data, analyze predictive maintenance, and monitor energy consumption in industrial environments.3MIT
- AlicenseBqualityAmaintenanceExposes a deterministic IoT edge runtime — Modbus/CAN/J1939 acquisition, local rules, alarms, and history — to AI assistants as typed, governed MCP tools. Reads are safe by default; device control stays deny-by-default, explicitly confirmed, and audited.233Apache 2.0
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/industrial-aiops/industrial-aiops'
If you have feedback or need assistance with the MCP directory API, please join our Discord server