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 "Deploy 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: IndustrialOps Industry 4.0 PLC Monitor 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?
The description states 'PERSIST' and 'Writes a local owner-only advisory JSON file,' which directly contradicts the readOnlyHint=true annotation. This is a critical inconsistency that misleads the agent about whether the tool modifies state.
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 (Args, Returns, Example) and every sentence provides essential information. It is dense but not verbose, and the example aids understanding.
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 explains the return dict, overwrite behavior, ownership, and safety profile, plus gives an example. This makes the tool's behavior and usage fully 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?
With 0% schema description coverage, the description fully compensates: it defines the feeds argument's shape, the site argument's format and default, and provides a concrete example. This adds substantial 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 opens with a specific verb and resource: 'Adopt + persist the canonical alias map for a site.' It clearly distinguishes this from siblings like diff_alias_map by focusing on adoption and persistence, and it explains the map's structure 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 implies when to use the tool (to adopt and persist a canonical alias map) and provides context about it being advisory and non-OT-device-write. However, it does not explicitly mention when not to use it or name a direct alternative.
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?
Annotations already indicate read-only, non-destructive behavior, and the description adds meaningful context: it explains that window_minutes is inferred if omitted, defines chatter_window_s and standing_s, and details the return structure. This goes beyond simply echoing 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 terse purpose line, labeled Args and Returns sections, and a concrete example. Every sentence adds value without redundancy, and the front-loaded purpose makes it immediately scannable.
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 takes on the burden of explaining the return dict in detail, listing all keys and example values. For a tool with 5 parameters and a complex result set, this is remarkably complete, even including a usage 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?
The schema has 0% description coverage, but the description's Args section fully explains each parameter's meaning and default behavior (e.g., 'chatter_window_s: A source with >=3 transitions inside this window chatters'). It completely compensates for the schema's lack of 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 'ISA-18.2 alarm-flood analysis over a list of alarm events' and elaborates with specific outputs like 'top offenders', 'chattering', and 'standing'. This distinguishes it from siblings such as alarm_flood_analysis or alarm_cascade by focusing on 'bad actors' (source-level 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 provides clear context on what the tool does and its inputs, making its intended use apparent. However, it does not explicitly mention when not to use it or reference alternative sibling tools, so it lacks explicit exclusions.
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, but the description adds valuable behavioral context beyond that: it reveals the first-out heuristic is 'transparent' and 'cited by timestamp — NOT causal,' notes the tool is 'bounded,' and explains it collects live via the 'OPC-UA active-condition scan.' This enriches the agent's understanding beyond the structured 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 Args, Returns, and Example, and the opening line is an immediate purpose statement. It is longer than some descriptions, but every sentence adds necessary detail for correct usage. Slightly verbose but not wasteful, 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 the complexity (5 parameters, no schema descriptions, no output schema), the description is comprehensively complete. It covers the return dict structure with all nested fields, explains the cascade logic, clarifies the heuristic nature, and provides a concrete example. This gives the agent everything 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%, so the description carries full responsibility for parameter meanings. It does this excellently by explaining each parameter: 'endpoint', 'duration_s' (with range 1..300), 'window_s' (quiet gap), 'min_cascade', and 'events' (with format {source, timestamp, state?}). It also provides an example call, making usage 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's function: 'Collapse an alarm flood into cascades + each cascade's first-out root.' This uses a specific verb ('collapse') and resource ('alarm flood'), and it precisely answers the question 'which alarm to look at first.' It also distinguishes itself from sibling tools like 'downtime_root_cause' by explicitly stating it is a heuristic, 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 gives explicit usage context: 'when 100+ alarms hit in minutes' and explains the tool answers 'which alarm to look at first.' It clearly differentiates from alternatives by stating 'NOT causal (use downtime_root_cause for causality)' and clarifies when to use live collection vs. pure analysis with 'Pass 'events' for pure analysis, or an endpoint to collect live.'
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?
Even with annotations indicating readOnly/openWorld/non-destructive, the description adds substantial behavioral depth: it never applies suppression/shelving/deadband/delay changes, output is bounded with truncation flags, and live collection is limited to the OPC-UA active-condition scan. This goes far beyond the annotations and explains non-obvious side effects and limitations.
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 long, the description is efficiently structured: a one-line summary, a detailed paragraph, then Args/Returns/Example sections. Every sentence adds information; there is no filler or tautology. The density is warranted for a tool with 9 parameters and a rich output shape.
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?
There is no output schema, so the description's detailed 'Returns dict' fills the gap with field names and nested structures. It also covers collection methods, advisory semantics, truncation behavior, and supplies a concrete example. For a complex analytical tool, this is a complete and self-sufficient specification.
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 Args section fully compensates by explaining all 9 parameters with meanings, defaults, and relationships (e.g., 'endpoint used only when events is omitted', 'events skips live collection entirely', 'stale_after_s: Continuously-active age that marks a standing alarm'). This adds critical semantics 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 opens with a specific verb and resource ('ISA-18.2 deep alarm-flood analysis') and lists concrete outputs (episodes, chattering, stale, advice). It explicitly differentiates from the sibling tool alarm_bad_actors by stating 'Deepens alarm_bad_actors', making the tool's unique scope 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?
Provides clear situational guidance: 'Pass events for pure analysis, or an endpoint to collect live' and warns that 'other protocols contribute no alarms' (an explicit exclusion). The advisory-only caveat tells the agent this tool is not for applying changes, effectively distinguishing it from mutation-oriented siblings.
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?
The description opens with [READ][risk=low] and adds rich behavioral context beyond the readOnly/destructive annotations: it discloses live OPC-UA collection, CSV file writing when out_path is set, bounded inline rows with truncation noted, and that endpoint is used only when events are omitted. This exceeds what annotations alone convey and does not contradict 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 summary, Args, Returns, and Example, and it front-loads safety tags. It is somewhat lengthy but necessary given the lack of schema descriptions; there is minimal 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 6-parameter tool with no output schema, the description is complete: it explains input modes, output dict shape, CSV side-effect, truncation behavior, defaults, and provides an example. An agent has everything 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?
The input schema has 0% property description coverage, so the description must carry the burden, and it does thoroughly. The Args section explains all six parameters with purpose, defaults, constraints (e.g., duration_s 1..300, default 60; window_s default 600; threshold default 10), and the expected structure of events. This is exemplary compensation for schema gaps.
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 produces an ISA-18.2 alarm-rationalization worksheet (CSV or inline rows), with specific columns and count-descending ordering. It distinguishes itself from sibling alarm tools by framing itself as the starting document for rationalization review and explaining both event-based and live-endpoint modes.
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 context: pass 'events' for pure analysis or provide an endpoint to collect live via the OPC-UA scan, and use 'out_path' to write CSV versus inline rows. However, it does not explicitly name sibling alternatives or state when not to use this tool, so it stops 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.
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?
Beyond the readOnlyHint and destructiveHint annotations, the description discloses that it samples over a bounded window, computes mean/stddev/min/max, flags outliers using sigma, and does not persist models. It also notes server-side capping of samples, adding 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 compact and well-structured: a deprecation notice, a clear one-line summary, a brief algorithm explanation, and a concise args list. Every sentence adds value 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?
The description covers the tool's purpose, algorithm, limitations, and all parameters. Although there is no output schema and the return format isn't explicitly described, the tool's behavior is sufficiently clear for a read-only statistical scan. The deprecation notice makes completeness slightly less critical.
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 provides no descriptions for its 5 parameters, but the description compensates fully with an Args section explaining each parameter's purpose (node_id, endpoint, samples, interval_ms, sigma). This provides complete 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 description explicitly states it performs a statistical outlier scan on an OPC-UA node, with a specific verb and resource. It also clearly marks itself as deprecated in favor of opcua_anomaly_scan, distinguishing it from that alternative.
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 notice explicitly directs users to opcua_anomaly_scan instead of this tool, providing a clear alternative. It also clarifies the tool's scope ('Simple statistics only — no ML, no persisted model'), implying when it is appropriate.
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 mark readOnlyHint=true and destructiveHint=false, but the description adds meaningful context: the tool connects to endpoints via its own protocol client and reads identity calls. It also warns about reachability constraints and labels risk as low, going beyond the structured 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?
Information is front-loaded with [READ][risk=low], followed by a concise explanation, an honest scope note, parameter guidance, return structure, and example. Every sentence adds value and the format is easily scannable.
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 fully specifies the return dict including all fields such as asset_count, reachable_count, method, and asset details. It covers scope, parameters, example, and edge cases (unreachable endpoints), making it complete 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?
Although schema description coverage is 0%, the text fully explains the only parameter: 'endpoints: Endpoint names to fingerprint; omit to fingerprint ALL configured endpoints.' 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?
Description opens with a specific verb+resource: 'Actively fingerprint endpoints into an asset register.' It then lists concrete protocol identity calls and explicitly distinguishes active fingerprinting from passive SPAN/tap discovery, clearly separating it from 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?
Provides explicit scope boundaries: 'ACTIVE fingerprinting (we connect to each device), NOT passive SPAN/tap discovery' and 'Only finds devices we are configured to reach.' It also explains the optional endpoints parameter, giving the agent clear guidance on when to omit it.
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?
Beyond the annotations (readOnlyHint true, destructiveHint false), the description discloses critical behavior: it reads from a local database with no device I/O, reports violations only under specific conservative conditions (3×MAD and sustained for 3+ samples), handles missing baselines with an explicit 'no_baseline' response, and bounds output size. This is exemplary 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 and front-loaded with the core purpose, followed by behavioral details, parameter definitions, return format, and an example. Every sentence adds value, and the length is appropriate for the tool's 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 explicitly lists the return dict structure and fields. It covers parameters, behavior, edge cases, and output bounds, making it fully self-contained for an AI agent to select 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 each parameter: tag (with example), endpoint (label filter), and window_s (range and default). It also provides a concrete usage example, making the parameters unambiguous.
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: 'Check recent local samples against the learned baseline.' It uses a specific verb ('check') and resource ('samples against baseline'), and differentiates itself from sibling tools like baseline_learn and baseline_status by focusing on anomaly detection against a stored baseline.
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 on when to use the tool (checking recent samples for baseline violations) and explains its conservative detection policy. It does not explicitly name alternative tools or exclusions, but the context strongly implies this is the go-to for anomaly checking, especially with siblings like baseline_status for status inquiries.
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?
Despite readOnlyHint=true, the description honestly discloses that successful calls persist the band to ~/.iaiops/baselines.json, adding important context about a local write side effect. It also details algorithm behavior (percentiles, no ML), refusal conditions, and the guarantee that it 'never invents a band from thin data', going 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: intro, source, algorithm, refusal, persistence, args, returns, and example. Every sentence adds value, and the length is justified by the tool's complexity. The upfront '[READ][risk=low]' provides an immediate safety signal.
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 fully specifies the return dict fields, including status, band components, n_samples, window, segment, and optional missing list. It covers all necessary invocation context (source, algorithm, refusal, side effects, parameters, example), making it complete for an AI agent to select and call 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 schema has zero descriptions, so the Args section compensates by explaining each parameter: tag with example, endpoint as a label filter, and since as an ISO-8601 time filter. The example call further disambiguates usage, though the descriptions are brief and do not specify all edge-case behaviors (e.g., null for endpoint).
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 'Learn a conservative per-tag normal band from local history' uses a specific verb and resource, precisely stating what the tool does. It further distinguishes itself from live device reads and references related tools like baseline_record_change and historian_push, 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 the data source is '~/.iaiops/data.db' written by historian_push and stresses 'NOT a live device read', clearly indicating when not to use it. It also gives concrete refusal thresholds (100 samples or 24h span), telling the agent exactly when the tool will reject insufficient data, and mentions the dependency on baseline_record_change for segmentation.
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?
Annotation Contradiction: the description explicitly says 'Writes ONLY local metadata' and 'Record an operator change-log entry', which is a side-effecting write, while annotations set readOnlyHint=true. Although the description is otherwise transparent about file path, owner-only access, and no OT device write, the contradiction requires a score of 1.
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 line, safety note, behavioral explanation, args, return, and example. It is relatively long, but each section provides necessary domain context and the [READ][risk=low] prefix front-loads 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 is highly complete: it names the local metadata file, explains why no OT device write occurs, describes the return dict, gives an example, and explains the impact on baseline_learn. Since there is no output schema, explicitly documenting the return format is especially valuable.
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 burden. The Args section clarifies 'tag' as the process tag and 'note' as what changed, with concrete examples ('line1.temp', 'setpoint 60→70C'), adding meaningful semantics beyond the bare schema 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 'Record an operator change-log entry for a tag (local only)' — a specific verb and resource. It distinguishes itself from siblings like baseline_learn by explaining that a recorded change marks a regime boundary and that baseline_learn uses only samples after the latest change.
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 (after an operator change such as a setpoint move or valve replacement) and explicitly contrasts it with baseline_learn. It lacks an explicit 'do not use when...' list, but the intended 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.
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?
The description goes well beyond the annotations by explaining the exact status values ('no_baseline', 'learning', 'ok', 'violation'), that it never guesses, reads only from local store, and lists are bounded to 100 entries. It also describes the return shapes for both one-tag and all-tag cases. No contradiction with 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 clear header, a concise explanation of behavior, an Args section, a Returns section, and an example. Every sentence contributes useful information without 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 single optional parameter and no output schema, the description is fully complete. It covers input, output shape, status meanings, listing behavior, bounded entries, and provides an example invocation. No important information is missing 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?
The input schema provides only the parameter name 'tag' with a default of null, but no description. The description explains that the tag is optional and omitting it lists all tracked tags. It also clarifies how the parameter affects the return value, 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 that this tool returns baseline status for one tag or a bounded listing of all tags. It uses a specific verb ('status') and resource ('baseline'), and distinguishes itself from sibling tools by emphasizing read-only local store access and no device I/O.
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 that this is a read-only status query operating only on the local store with no history scan or device I/O. It does not explicitly mention alternatives or when-not-to-use, but the context is sufficient to know when it is appropriate.
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 declare readOnlyHint=true and destructiveHint=false. The description adds behavioral context by stating it offers an 'honest iaiops posture' with per-control status/gap, and emphasizes it is not a certification. This goes beyond the annotations and provides insight into the tool's output reliability and scope.
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, starting with a clear summary line before diving into details. The Args and Returns sections are clearly labeled and the example is useful. Every sentence adds value, though a bit of density could be trimmed without loss.
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?
There is no output schema, so the description carries the full burden of explaining returns. It does so by explicitly listing the keys of the returned dict (framework, levels, selected_level, pillar_count, deltas, note) and describing the delta structure. Coupled with parameter details and an example, the tool is fully specified 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 schema only defines 'level' as a string/null with no values, giving 0% coverage. The description fully compensates by listing accepted values ('l2'/'l3', '二级'/'三级', or '2'/'3') and explaining the default behavior when omitted (both levels). 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 tool's function: comparing 等保 2.0 二级 vs 三级 per-pillar deltas and iaiops posture. It explicitly says it is an onboarding/self-assessment aid, not a certification, which distinguishes it from sibling compliance tools like compliance_mapping or compliance_report. The verb and resource 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 gives clear context for when to use the tool: as an onboarding/self-assessment aid, and clarifies what it is not for (certification). It also explains how to pass the level argument with accepted values. However, it does not explicitly name alternative tools or provide when-not-to-use guidance beyond the certification disclaimer.
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?
Beyond the readOnlyHint=true annotation, the description discloses deterministic packaging, upstream secret redaction, path traversal validation with '..' rejection, parent directory creation with 0700 permissions, and a complete return dictionary. These are nontrivial behavioral traits that meaningfully inform an agent about 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, file list, argument definitions, return value, and example. Every sentence contributes functional knowledge without fluff, and the front-loaded [READ][risk=low] tag aids quick classification.
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 defines the exact return dict structure, all parameters, validation behavior, and a usage example. It is sufficiently complete for an agent to invoke the tool correctly and interpret its result.
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 provides no descriptions and has 0% coverage, so the description carries the full burden. It explains out_path must end in .zip, defines since/until as ISO-8601 inclusive bounds, and provides a concrete usage example. This fully compensates for the empty 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 a specific verb-resource pair ('Export the audit-evidence bundle (zip) for an auditor') and details the deterministic zip contents, clearly differentiating it from generic export or compliance reporting tools. It names the exact output artifact and 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 phrase 'for an auditor' gives clear context on when to use the tool, and the detailed contents imply it is for governance/audit evidence packaging rather than general data export. It does not explicitly name alternatives or exclusions, but the context is strong enough to guide selection.
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 declare readOnlyHint=true and destructiveHint=false, and the description adds a redundant '[READ][risk=low]' tag without new safety info. However, it does add context about the output containing 'current iaiops status' and positions the tool as a companion to compliance_mapping with a different perspective, which is useful 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 well-structured: a concise summary, detailed mapping explanation, return schema, and example. Every sentence contributes meaning without fluff, and the length is appropriate for the complexity of 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?
For a read-only, zero-parameter tool, the description is complete. It explains the purpose, return format, example invocation, and relationship to the sibling compliance_mapping. The lack of an output schema is compensated by the detailed dict structure provided in the 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?
With zero parameters and an empty schema, the description adds value by showing an example call `compliance_frameworks()` and detailing the return dict structure. This clarifies that no arguments are needed and what the response will contain, fully compensating for the lack of schema detail.
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: cross-framework mapping between 防护指南, 等保 2.0, and IEC 62443. It explicitly distinguishes itself from compliance_mapping by noting it provides a high-level crosswalk for answering which clause satisfies what, making it a distinct sibling 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 provides explicit usage guidance: 'use this to answer which 等保 / 62443 clause does this satisfy'. It also names compliance_mapping as the alternative for per-control gaps, offering clear when-to-use versus when-not-to-use direction.
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 declare readOnlyHint=true and low risk, and the description echoes '[READ][risk=low]' consistent with annotations. It adds behavioral context by detailing the return dict structure and honest status values, which helps the agent understand the output shape. It does not disclose any side effects or prerequisites, but with annotations covering safety, this is acceptable.
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: it opens with the mapping scope, lists pillars, describes the return format, and closes with an example. Each sentence contributes useful information, though a slightly terser phrasing could improve conciseness without losing substance.
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 parameters and no output schema, the description compensates by fully spelling out the return dict structure and providing an example. It also cross-references compliance_frameworks for further context. The main gap is a lack of explicit error handling or when-to-use guidance, but given the tool's simplicity, this is largely 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 zero parameters, so the baseline is 4 per the rubric. The description adds meaning by showing the exact invocation example `compliance_mapping()` and clarifying that the tool takes no arguments, which is helpful 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 maps a specific standard (《工控系统网络安全防护指南》) to iaiops governance, with specific pillars and status taxonomy. It distinguishes itself from the sibling compliance_frameworks by focusing on this one framework, making the 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 provides an explicit alternative reference: 'See compliance_frameworks for the full cross-framework 对照,' which guides users needing broader coverage. However, it does not explicitly state when to prefer this tool over other compliance siblings, so 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.
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?
Beyond the annotations (readOnlyHint, openWorldHint, destructiveHint), the description adds substantial behavioral details: the '[READ][risk=low]' prefix, the full report contents, truncation behavior with a hint to pass `out_path`, and the exact return dict structure. It also clarifies the tool is not a certification, enriching the agent's understanding of side effects and limitations.
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, Args, Returns, Example). Every sentence adds value—no fluff or tautology. The length is justified by the tool's complexity and the need to convey truncation behavior, return format, and parameter semantics.
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 no enum constraints, the description covers all essential context: what the report contains, return dict fields, truncation behavior, and a concrete example. The agent can confidently select and invoke this tool without additional documentation.
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: `level` with accepted values ('l2'/'l3', '二级'/'三级', '2'/'3', omit for both), `site` as the name stamped on the title page, and `out_path` as a required file path when the report exceeds the inline bound. It even provides an example call, making parameter usage unmistakable.
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: 'Render the 等保 2.0 / IEC 62443 compliance report (Markdown)'—clearly stating the tool's purpose. It distinguishes itself from sibling compliance tools by emphasizing it produces a deliverable document for a CISO and explicitly notes it is 'NOT a certification', setting it apart from raw mapping or evidence 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 clear usage context: it is an 'onboarding/self-assessment aid' and includes an explicit exclusion ('NOT a certification'). It also gives actionable guidance on when `out_path` is required (when report exceeds ~400 lines). However, it does not explicitly name alternative tools from the sibling list, so it stops short of full 5-level guidance on when to use alternatives.
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 and destructiveHint=false, but the description adds substantial behavioral depth: the 'OT-dangerous' warning that aliases are never server-side renames, the re-classification using the same semantic classifier as OPC-UA, and the grouping behavior across protocols. The explicit 'Advisory only' caveat is exactly the kind of contextual disclosure beyond annotations that helps an agent trust the tool's side effects.
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 effectively structured with a bolded purpose statement, safety advisory, then structured Args/Returns/Example sections. Every sentence contributes either operational semantics, parameter details, or output format. The front-loaded '[READ][risk=low]' tag and clear examples make it easy to scan. No filler or 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?
Given the tool's complexity and lack of an output schema, the description is remarkably complete. It specifies the return dictionary's structure including all keys and nested fields, provides an example call, and mentions the two upstream tools that produce valid 'feeds'. The advisory nature and site prefix behavior are also covered, leaving little ambiguity for an agent deciding whether and how to call 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?
With 0% schema_description_coverage, the description fully compensates. It explains the 'feeds' parameter in detail: each element has {protocol, source, asset?, tags:[...]}, clarifies the possible tag sources (OPC-UA descriptors, Modbus template tags, or normalized tags), and describes how a feed-level 'asset' applies to tags. It also documents the 'site' parameter with a default value. This goes far beyond the minimal schema and enables correct invocation.
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 phrase 'Fuse per-protocol tag feeds into ONE unified asset model.' This specifies exactly what the tool does (fusion/unification) and the resource (per-protocol tag feeds). It also distinguishes itself from per-protocol tools by name (OPC-UA, Modbus) and mentions upstream tools like opcua_discover_tags and modbus_apply_template, establishing a unique role 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 clearly frames when to use this tool: when unifying per-protocol tag feeds into a cross-protocol model. It also gives essential context by stating 'Advisory only' and that aliases are suggestions, not server-side renames, which informs appropriate use. However, it does not explicitly list alternative tools or say 'use X instead when...', so it stops short of full exclusion guidance.
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?
Despite annotations already declaring readOnlyHint=true and destructiveHint=false, the description adds substantial behavioral context: it states 'Pure analysis,' details the exact return dict structure, explains deterministic 'now' for reproducibility, and clarifies that staleness budgets are per-tag/per-feed. This goes well beyond the annotations and provides valuable operational detail.
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: a one-paragraph summary of the tool's purpose and behavior, followed by a structured Args list, Returns dict, and a concrete example. Every sentence adds value, and the length is appropriate for the tool's complexity. 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 the tool's complexity and lack of output schema, the description is remarkably complete: it covers input structure, return fields, examples, and configuration nuances (slow vs. fast feeds). It also mentions deterministic 'now' for reproducibility, which is helpful for testing. No significant 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?
With 0% schema description coverage, the description fully compensates by providing an in-depth Args section that explains each parameter, including nested structure for 'feeds' with optional fields, the fallback behavior of 'default_staleness_s', the purpose of 'now', and the default for 'top_n'. An example usage further clarifies 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's function: 'Cross-endpoint fleet rollup of data-TRUST: worst tags + bad quality.' It specifies a concrete verb ('rollup') and resource ('data-TRUST'), distinguishes itself from siblings like data_quality_scorecard by emphasizing a fleet-wide view, and lists distinct outputs (endpoint ranking, bad-quality rollup, liveness rollup).
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 contextual guidance: 'Builds on data_quality_scorecard to give a fleet-wide view' and explains that staleness/gap budgets are configurable per tag to handle different feed types. However, it does not explicitly state when NOT to use this tool or name alternative tools for single-endpoint analysis, 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.
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 declare readOnlyHint=true and destructiveHint=false, and the description adds substantial behavioral detail: scoring criteria (staleness, dead heartbeat, quality, flatline, gaps, anomaly), deterministic 'now' handling, and the explicit limitation that it does not evaluate whether values are alarming. These details go well beyond what annotations 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 long enough to cover a complex tool but every sentence serves a purpose: summary, exclusion, parameter details, return structure, and example. It is well-structured with labels and a clear example, keeping all information directly usable.
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 sparse input schema, absence of output schema, and presence of closely related sibling tools, the description is remarkably complete. It documents the expected feeds structure, parameter defaults, return dict contents, and a usage example, leaving no significant gaps 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?
Schema description coverage is 0%, so the description carries the full burden, and it succeeds by fully specifying the structure of 'feeds', explaining defaults for 'default_staleness_s' and 'now', and providing a concrete example call. The parameter semantics are thoroughly compensated.
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 a specific verb ('Scores') and resource ('data-TRUST scorecard across endpoints' tag feeds'), and explicitly distinguishes itself from process health by noting it assesses trustworthiness, not alarming values. This effectively differentiates it from sibling tools like health_summary and 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 provides a clear when-not-to-use exclusion ('NOT process health') and states it is 'Pure analysis over provided feeds.' However, it does not explicitly name alternative tools or state 'use this when X' beyond the inherent purpose, so it stops 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.
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 already declare readOnlyHint=true, destructiveHint=false, and the description reinforces with '[READ][risk=low]'. It goes far beyond annotations by detailing the probe sequence (connect → read(ref) → freshness → variance) and disclosing that it returns per-hop detail and a recommended action. This gives the agent a clear mental model of what happens during invocation.
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?
Although the description is longer than typical, it is tightly structured with a clear READ/risk header, a concise behavioral summary, a bulleted Args list, a Returns dict format, and an example. Every sentence adds information—there is no filler or redundancy. The front-loading of the core purpose and verdict taxonomy makes it scannable.
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, so the description must explain the return contract—and it does, listing the exact verdict strings and the structure of hops. It also covers edge cases (omitting ref, injecting series for flatline analysis) and provides a concrete example. For a moderately complex diagnostic tool, this 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%, so the description fully carries the parameter documentation load. Each of the five parameters is explained with type, purpose, and default behavior (e.g., 'ref: Tag/node/address/device to read... Omit to test connectivity only', 'freshness_threshold_s: Max value-age (seconds) before stale'). This is exemplary compensation for the empty 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 a specific verb and resource: 'Localize a 'no data' break across an endpoint's reachable hops.' It clearly distinguishes this tool from siblings by naming it the '#1 OT triage' and enumerating distinct failure-mode verdicts (cannot_connect, comms_ok_value_stale, comms_ok_flatline), which differentiates it from generic health or anomaly 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 context: use when there is a 'no data' break, and explains that it distinguishes network/PLC down, stale values, and flatline. It also provides an actionable usage hint ('Omit ref to test connectivity only'). It does not explicitly name alternative tools or state when not to use it, 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.
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?
While annotations already declare readOnlyHint=true and destructiveHint=false, the description adds behavioral context by explaining that the tool 're-runs the cross-protocol asset model over feeds' and reports how the address space moved. It also discloses the return structure with counts and lists, which is valuable beyond the annotations. 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 well-structured and front-loaded: it opens with a concise one-line summary, then explains the process, defines arguments, describes the return dict, and provides a concrete example. Every sentence adds useful information 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?
Given that there is no output schema, the description includes the full return dict structure with counts and lists, which is important for the agent. It also gives a full example invocation. The main gaps are the site default inconsistency and the fact that 'feeds' format is only described by reference to 'adopt_alias_map,' which might require the agent to look up that tool's schema. Overall, the description is robust.
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 zero description coverage, so the description must compensate for parameter meaning. It explains 'feeds' as fresh per-protocol tag feeds of the same shape as adopt_alias_map, and 'site' as the site label whose baseline to diff against, defaulting to 'site.' This adds meaning not present in the schema, but the description relies on referencing another tool's shape for 'feeds' and there is a minor discrepancy: the schema default for 'site' is null, while the description says default is 'site.'
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] Diff a fresh discovery run against the adopted baseline,' which clearly states the tool's function with a specific verb (diff) and resource (alias map). It distinguishes itself from the sibling tool 'adopt_alias_map' by explaining it diffs against an adopted baseline, making the 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 provides explicit usage context by stating 'Adopt a baseline first with adopt_alias_map,' which is a clear prerequisite. It also describes the categories of output (added, removed, renamed, reclassified) and the stable|changed verdict, implying when this tool is appropriate. It does not explicitly mention alternatives, but the prerequisite and operational detail offer solid guidance.
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?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the read-only nature is covered. The description adds substantial behavioral detail: the keyword heuristic categorization logic, the effect of min_duration_s as a filter, and the exact structure of returned events. The [READ][risk=low] tag further reinforces safety expectations. 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-organized into Summary, Args, Returns, and Example sections. Each sentence provides essential information, and the core purpose is front-loaded. Despite being longer than typical descriptions, it justifies its length given the tool's complexity and the absence of an 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?
For a 3-parameter tool with no output schema, the description is fully complete. It defines all inputs, the output structure (including nested by_category and events), the category mapping behavior, and gives a concrete example. An agent has all necessary information to invoke the tool correctly without additional assumptions.
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 thoroughly explains each parameter: series format (ISO-8601 timestamps, state types including string/bool/number), category_map as an optional override with default heuristic behavior, and min_duration_s as a filter. This goes well beyond the schema's bare names 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 opens with a specific verb+resource: 'Detect running→stopped transitions and categorize stoppages.' This clearly states the tool's function and distinguishes it from sibling tools like downtime_root_cause or oee_compute. The additional example and return structure 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?
The description clearly implies when to use the tool: when you need to identify and categorize downtime events from timestamped state data. However, it does not explicitly name alternatives or exclusions. The precise input/output specification gives enough context for an agent to infer appropriateness, but lacks explicit comparison to other downtime-focused tools.
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 mark it read-only, but the description goes further: 'executes nothing', 'proposes a human-approved, undoable (MOC-gated) action', and 'only signals present in the input are cited'. It also discloses anti-hallucination downgrade and lead-window weighting behavior, adding meaningful 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 long but well-structured with [READ], an overview, Args, behavior notes, return dict, and a concrete example. Each section adds necessary detail for a complex 8-parameter tool with no output schema; nothing feels redundant.
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 fully defines the return dict, including hypotheses/evidence fields and optional graph. It also covers optional historian trend evidence and config-dependent behavior, making the tool safe to invoke in varied 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?
Schema coverage is 0%, but the description compensates with a detailed Args section. It explains window semantics including end-omission bound by state_series, per-argument shapes, cause_weights override/rejection/clamping, and include_graph's output behavior. This provides far more meaning than 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?
Description opens with '[READ][risk=low] AI downtime root-cause copilot' and explicitly states it 'correlates' evidence, 'ranks candidate root causes', and 'cites the REAL signals'. This clearly identifies a specific analytical read-only tool and differentiates it from live/other siblings via its advisory, evidence-cited 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?
It says to supply evidence around a downtime/incident window (alarms, tags, dataflow, state series) and clarifies when it should be used as a read-only analysis. It also explains how insufficient evidence is handled, but does not name explicit alternatives or when-not-to-use conditions, so 4 rather than 5.
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?
Beyond readOnlyHint=true and destructiveHint=false, the description discloses live evidence gathering, sampling caps (refs capped at 20), load controls (sample_count, interval_ms), graph as 'pure re-shape', and 'no hidden inputs'. It also confirms non-destructive and nothing executed, enriching the annotation profile.
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 lengthy but well-structured with distinct sections: purpose, Args, return shape, and example. Every sentence carries information, but the length is justified given the 8 parameters and behavioral nuance. Could be slightly trimmed without loss.
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 output schema, the description fully covers inputs, behavior, return shape (referencing downtime_root_cause plus 'collected_evidence'), and provides a concrete example. It also notes the graph block's structure. No significant 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?
With 0% schema coverage, the description compensates fully by explaining every parameter's meaning, type, constraints, defaults, and relationships (e.g., 'first is also the diagnose_dataflow target', 'OPC-UA only'). This far exceeds the bare schema and gives precise operational guidance.
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 tool is an 'AI downtime RCA copilot that GATHERS its own live evidence' with a specific verb (gathers) and resource (live evidence). It explicitly distinguishes from sibling downtime_root_cause: 'instead of hand-injecting evidence you give an endpoint + incident window and it pulls the evidence itself'.
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 differentiates when to use this tool vs downtime_root_cause by explaining the difference in evidence handling (auto-gathered vs hand-injected). It also notes 'Light read load; non-destructive; nothing executed', which signals safe contexts, but does not explicitly list 'when not to use' exclusions.
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?
The description goes far beyond the readOnlyHint/openWorldHint/destructiveHint annotations by explicitly stating 'READ' and 'risk=low', 'proposes but executes nothing', and 'Thin evidence downgrades honestly rather than guessing'. This provides clear behavioral context about safety, advisory nature, and handling of uncertain evidence, with 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?
Though lengthy, the description is well-structured with clear sections (summary, Args, Returns, Example) and every sentence adds substantive detail. The front-loaded summary conveys the core purpose immediately, and the parameter explanations are essential for the complex tool. No fluff or 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?
With 11 parameters, no output schema, and complex composite behavior, the description is exceptionally complete. It details the expected input structures, the composition of sub-reports, the return dictionary with all fields, and includes a concrete example. It fully equips an agent 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%, so the description fully compensates by explaining every parameter in the Args section. It provides meaningful semantics for window, alarms, tags, dataflow, state_series, precursors, cascade_window_s, lead_window_s, cause_weights, imminent_within_s, and include_graph, including defaults and behavior.
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 'One-call downtime triage' that composes alarm cascade, RCA, and precursor forecasts into a single tool answering three explicit questions about a stopped line. This unambiguously distinguishes it from sibling tools like alarm_cascade, downtime_root_cause, and pdm_forecast, which are listed as components.
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 specifies the primary use case ('on a stopped line') and notes the tool is read-first and advisory. However, it does not explicitly state when NOT to use it or name alternative tools for simpler cases (e.g., if only one question is needed). The composition context implies the usage but lacks explicit exclusions.
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 adds significant behavioral context beyond the annotations: it identifies the source as ~/.iaiops/data.db, warns the output preview is bounded to 200 rows to avoid flooding, and notes the parquet format requires pip install 'iaiops[export].' These details are valuable and not present in the annotations. No contradictions with the 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 organized with a clear one-line summary, followed by source context, arg breakdown, return structure, and an example. Every sentence carries essential information—no filler or repetition. Despite its length, it earns its space for a 7-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?
The description is complete: it covers the source, format options, required dependency, all parameters, output schema (since no output schema is provided), and a concrete example. Given the tool's complexity (7 params, no output schema), this description covers all bases needed 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 explaining every parameter: fmt values, since/until as ISO-8601 inclusive bounds, endpoint and tag as filters, limit with range and default, and out_path with default pattern. This goes far 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 opens with a specific verb+resource: 'Export collected samples from the LOCAL SQLite sink to a file.' It clearly distinguishes from siblings by noting the source is the local SQLite store, not a live device read, which differentiates it from historian_query and live-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 clear context on when to use the tool: data comes from the local SQLite sink written by historian_push(sink="sqlite"), and explicitly states 'NOT a live device read.' It also gives format selection guidance (csv, sqlite, parquet) and mentions the optional dependency for parquet. However, it never explicitly names alternative tools (e.g., historian_query) or states 'when not to use,' so it stops short of a full usage guide.
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?
Beyond the annotations (readOnlyHint=true, destructiveHint=false), the description adds 'Read-only; no device I/O' and a [risk=low] tag, clarifying that this tool does not interact with devices. This is useful behavioral context that goes beyond the structured hints, though it omits details like rate limits or auth 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 well-structured with a front-loaded summary line, labeled Args/Returns sections, and an example. It is somewhat verbose, repeating the read-only nature already in annotations, but each part serves a purpose and the format 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?
The description thoroughly explains the single input parameter and the return dict structure, which is critical given there is no output schema. It also clarifies the fleet-wide aggregation scope. However, it does not cover edge cases (e.g., empty sites list, missing causes) or aggregation semantics (e.g., how top_causes are ranked), leaving 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?
The input schema for 'sites' is a bare array of objects with no property descriptions (0% schema description coverage). The description fully compensates by detailing the expected structure: 'Per-site reports carrying incidents: [{site, incidents:[{cause|primary_cause, confidence?}]}],' and provides an exact example. This is essential for correct invocation.
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: 'Roll up active RCA incidents across sites → fleet-wide top causes.' It specifies the verb ('roll up'), the resource ('active RCA incidents'), and the scope ('fleet-wide'), distinguishing it from site-level tools like downtime_root_cause and aligning with the sibling set's fleet-analytics theme.
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: it aggregates per-site incident reports into a fleet picture, implying use when a fleet-wide root-cause overview is needed. However, it does not explicitly name alternatives 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.
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 mark it as read-only and non-destructive, and the description goes further by adding 'Read-only, pure; no device I/O,' explaining the offline logic based on stale_after_s, and clarifying that fleet_status is the worst site status present. This adds valuable behavioral context beyond the structured 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 Args, Returns, and Example sections. Every sentence adds value—no filler—and the length is justified given the need to document three parameters and return semantics in the absence of schema descriptions.
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 lists the return dict keys and explains the input behavior and output structure. It also provides an example, making the tool self-contained and fully understandable 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?
The schema provides no parameter descriptions (0% coverage), but the description fully compensates. It details the sites argument structure including optional fields and status values, defines stale_after_s with its default, explains now as an optional ISO-8601 timestamp for deterministic staleness, and even includes 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 function: 'Roll up per-site status reports into one fleet health view.' It also differentiates itself from sibling data_quality_fleet_rollup by noting it aggregates across edge SITES rather than per-endpoint within one site, 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 explicitly positions this tool as 'the tier above data_quality_fleet_rollup' for central management across sites, giving clear context for when to use it. However, it does not explicitly state when not to use it or mention alternatives beyond that one sibling, so it stops short of full exclusionary guidance.
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, so the safety profile is covered. The description adds valuable behavioral context: the tool is deprecated and redirected to opcua_health_summary, thresholds come from config or per-ref overrides, and the return includes ok/warn/alarm/unknown counts plus offending tags. 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 compact and front-loaded with the deprecation warning and READ status. The two-sentence summary plus a concise Args block provides necessary information without waste. Every sentence serves a purpose: deprecation, safety, behavior, and parameter meaning.
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 adequately explains the return value (counts and offending tags). It also covers default behavior (configured tags), override mechanism (thresholds), and deprecation. For a 3-parameter read-only tool, this is sufficient 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?
The input schema only provides types and defaults with no descriptions, so the description carries full weight. The Args section clearly explains each parameter: endpoint as a config name, node_ids as tag node IDs with an omit-to-use-configured-tags behavior, and thresholds as an optional dict of per-ref overrides. This adds essential 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 states a specific verb ('Classify') and resource ('OPC-UA tags') with clear scope: 'Classifies tag node-ids against warn/alarm thresholds.' It distinguishes itself from generic health tools by specifying the OPC-UA context, threshold-based classification, and return contents (counts plus offending 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 provides clear context on how to use the tool: it explains that node_ids can be omitted to use configured tags, and that thresholds can be overridden. It does not explicitly state when to use this vs. sibling tools like tag_health or subscription_health, but the OPC-UA and threshold-specific language implies the intended scope.
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 declare readOnlyHint=true and destructiveHint=false; the description aligns with '[READ][risk=low]' and adds significant behavioral context: the liveness logic based on changes, longest-stall detection, and the nuanced point that comms/quality can look fine while the upstream is dead. It also lists the return dict fields, adding 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?
The description is multi-sectional (overview, Args, Returns, Example) and front-loaded with the core purpose. Every sentence adds value, though the Args section partially repeats schema property names. It is appropriately concise given the amount of useful detail, with no 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?
For a simple 2-parameter tool with no output schema, the description is complete: it explains the concept, input formats, return values, and provides an example. It also covers edge-case behavior (max_interval_s) and the reason for flatlining. Nothing essential 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 fully compensates. It explains 'series' as 'heartbeat samples — scalars or {value, timestamp?} (a counter/toggle)' and 'max_interval_s' as 'max allowed gap between changes; exceeding it = not alive.' The example further clarifies usage, 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 a specific verb+resource: 'Is a heartbeat/watchdog tag still alive? (liveness check).' It defines the tool's unique scope (heartbeat/watchdog vs. siblings like tag_health or historian_health) and the core concept of change detection. This distinguishes it from other health 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 useful context: a heartbeat must keep changing, and a flatlined one signals death even when other signals look fine. It implies when to use (for liveness of heartbeat series) but does not explicitly name alternatives or state when not to use. This is implied usage guidance rather than explicit 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?
The description discloses key behaviors beyond annotations: 'Read-only, bounded (tag list is capped with a truncation flag); no device I/O' and 'TSDB readers need their extra: pip install iaiops[tdengine|iotdb]'. It also explains fallback behavior for the reader parameter. These details add significant context that the annotations (readOnlyHint, destructiveHint) only partially 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 clear sections: a lead summary, Args, Returns, and Example. It is detailed yet concise, with every sentence contributing useful information. The use of headers and inline code 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?
Despite having no output schema, the description fully specifies the return structure: '{reader, source, tag_count, tags:[{tag, rows, first_ts, last_ts}], truncated}' plus the standard envelope. It also provides an example call and covers optional dependencies, making it complete for 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?
With 0% schema description coverage, the description fully compensates by explaining both parameters: reader accepts 'sqlite' | 'tdengine' | 'iotdb', with default behavior (config or local sqlite) and pip install prerequisites; limit is 'Max tags returned (1..2000; default 500)'. This is thorough and adds 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 the tool's purpose: 'Per-tag history coverage — what history do we actually have.' It specifies the exact resource (history store) and the output (rows, first_ts, last_ts per tag). This distinguishes it from sibling tools like historian_query and historian_push by focusing on coverage metadata rather than data retrieval or writing.
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 context for when to use the tool: 'Answers the question every RCA starts with' and explicitly notes it queries the same store historian_push writes. However, it does not explicitly name alternatives or describe when not to use it (e.g., 'for actual data values use historian_query'), 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.
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?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description reinforces this with '[READ][risk=low]' and 'Pure analysis.' It goes beyond annotations by detailing the return dict structure and verdict values, giving the agent a more complete picture of 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?
The description is compact with labeled Args and Returns sections, front-loaded safety/risk info, and a practical example. Every sentence contributes useful 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?
There is no output schema, but the description specifies the complete return dict including all keys and the verdict string. The example further clarifies the expected input format, making the tool self-contained for an agent to call and interpret.
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, and it does. It defines the series format, gap_threshold_s as 'time gap ... counts as a data gap (default 60),' and flatline_eps as 'spread at/below which the series counts as flatline.' This fully documents all three 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?
The description opens with a specific verb and resource: 'Bad-tag / flatline / gap detection over a provided series.' It clearly distinguishes itself from sibling tools like historian_query by emphasizing 'pure analysis over an injected sample series — no live historian needed.'
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 states the use case: analysis over an injected series, with the important caveat that no live historian is needed. It does not explicitly name alternative tools or provide when-not-to-use guidance, but the context is clear enough for an agent to select it appropriately.
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 only indicate readOnlyHint=false and destructiveHint=false, but the description adds meaningful safety context: 'risk=low', 'Data egress to the operator's OWN database,' and 'Non-numeric points are skipped.' It also discloses the return dict shape, going well beyond the structured 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 concise header, intro, Args list, Returns line, and example. It is front-loaded with the core purpose. It is slightly verbose (repeats 'write' concept), but every section adds value; the example is helpful. A touch more brevity would make it perfect.
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 7-parameter tool with no output schema, the description covers input format, defaults, target systems, return values, and a complete example. It also adds domain context (national TSDB, 信创) and safety disambiguation. No critical 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 coverage is 0%, so the description must compensate. It does: it explains each parameter group (points, sink, host/port/user/password, database), provides value domains for sink ('tdengine' or 'iotdb'), notes sensible defaults, and gives an example mapping for points. 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 opens with a specific verb+resource: 'Push collected telemetry to a national TSDB.' It clearly distinguishes from siblings by specifying the target (TDengine/IoTDB) and explicitly saying 'instead of binding InfluxDB' and 'NOT a control-system write,' differentiating it from read/query tools and other write 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 states when to use it: 'Writes already-collected points' and lists example input sources (output of interrogate / integrity_poll / read_points / monitor). It also gives a when-not: 'NOT a control-system write,' and an alternative: 'instead of binding InfluxDB.' This provides explicit usage context and exclusions.
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 mark readOnlyHint=true and destructiveHint=false, but the description adds bounded rows ('rows are capped and a truncation flag is set when more history exists') and a crucial semantic: 'an empty samples with is_truncated=false means the history really is empty, NOT that the result was cut short.' Also discloses no device I/O.
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 summary line, context, args, return dict, and example. Each sentence adds necessary behavioral or parameter detail; no 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?
No output schema exists, so the description specifies the return dict fields and the `is_truncated` trust semantics. It also covers the reader fallback path and example invocation, making it self-contained 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?
Schema coverage is 0% and the Args section fully compensates: each parameter is explained with types, defaults, constraints (e.g., limit 1..10000 default 1000), and reader-specific behavior ('endpoint ... sqlite reader only — the TSDB layout stores no endpoint label').
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 opens with '[READ][risk=low] Query a tag's historical samples from a historian.' The verb 'Query' and resource 'tag's historical samples' are specific, and it contrasts with sibling historian_push and live-sample 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?
Description says 'so the RCA copilot / an agent can see real pre-incident windows instead of only short live samples,' giving clear context for historical analysis. It does not explicitly name an alternative tool for exclusion, so a 4 rather than 5.
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?
Beyond the readOnly and non-destructive annotations, the description discloses important behavioral traits: it is 'pure + explainable', uses Laplace smoothing and a per-cause min-sample guard to prevent overfitting, falls back to defaults for thin corpora, and only tunes ranking without executing anything. This adds significant context not available 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: a concise opening summary, detailed behavioral explanation, parameter descriptions, return format, and a concrete example. Every sentence adds value, with no filler or redundancy, despite the length needed for the tool's 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?
For a tool with 3 parameters, no output schema, and no nested objects, the description is remarkably complete. It explains the input format, the output dictionary with all fields, the algorithm's safeguards, and provides an example. There are no significant gaps in understanding how to invoke and interpret 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?
Even though the schema provides no parameter descriptions, the tool description thoroughly explains each parameter: history (with taxonomy enum values), min_samples (with default and behavioral consequence), and smoothing (with interpretation as a pseudo-count). This fully compensates 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 the tool's function: 'Learn a per-site RCA {cause: weight} profile from history.' It specifies the resource (per-site cause-weight profile) and verb (learn), and distinguishes it from related tools by explaining how it feeds into 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 explains when to use the tool: to adapt downtime_root_cause to this site's evidence, based on confirmed past incidents. It also states it is advisory and never executes anything. However, it does not explicitly mention when not to use it or list alternatives.
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 already declare read-only and non-destructive, but the description adds significant behavioral detail: hard caps on duration and max_changes (preventing infinite loops), polling interval semantics, deadband threshold meaning, and the exact return shape with timestamps. This goes well beyond the annotations and helps the agent anticipate real-world 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 structured logically: summary, behavioral note, argument list, return spec, and an example. Every sentence adds value, and the formatting makes it easy to scan. Length is justified by the tool's complexity and the lack of schema documentation.
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 supplies a full return dict. It covers all six parameters, constraints, protocol support, and even gives a concrete example. In the context of many sibling monitoring tools, this description uniquely clarifies the change-only, bounded-window behavior, making it complete for an AI 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 coverage is 0%, so the description fully carries parameter meaning. It explains each argument (ref, endpoint, duration_s, interval_ms, deadband, max_changes) with types, constraints, defaults, and protocol-specific context. The return dict is also detailed, making the tool self-contained despite 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 description opens with a specific, actionable statement: "Capture only the value CHANGES of a point over a bounded window." It clearly identifies the resource (value changes of a point) and the action (capture) while explicitly contrasting with every-sample polling. The deadband-report pattern mention further distinguishes it from sibling historian 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 provides clear context on when to use the tool: when only changes matter, via the deadband-report pattern, and lists supported protocols. It doesn't explicitly state when not to use it or name alternative tools, but the bounded-window and change-only behavior implicitly set it apart from continuous or full-history query tools.
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?
Annotations already mark the tool as read-only and non-destructive, and the description reinforces this with [READ][risk=low]. It adds substantial behavior detail: optional parameters split loss categories, energy block activates only when actual_kwh is provided, and emission factor default is a flagged placeholder. 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 formula, Args block, Returns block, and Example. It is longer than average, but each parameter definition and return detail earns its place given the tool's 13 parameters. The information is front-loaded and 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?
With no output schema and a complex computation, the description is comprehensive: it covers all inputs, output keys, loss breakdown, energy/carbon behavior, and provides a representative example. It leaves little ambiguity for an agent selecting and invoking 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?
The input schema has 0% description coverage, so the description carries full responsibility. It defines every parameter with units and semantics, explains how optional parameters split losses, and includes a worked example. This fully compensates for the schema's lack of detail.
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 computes OEE using the formula Availability × Performance × Quality and describes the returned dictionary. However, it does not distinguish this from the sibling tool oee_multidim, so it lacks sibling 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?
There is no explicit guidance on when to use this tool versus alternatives. The description reads like a function specification with parameters and returns, but it does not mention oee_multidim or any conditions for choosing 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.
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?
The description adds behavioral details beyond annotations: it explains that energy data triggers an energy_baseline block with anomaly flagging, notes the emission factor placeholder requires user action, and describes the return dict contents. Given annotations already declare safety, this is rich 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 well-structured with purpose, args, returns, and example. Front-loaded core action, uses bullets for readability, and 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?
For a tool with no output schema, the description thoroughly explains the return format, including conditional energy_baseline, and provides an illustrative example. Combined with parameter details, an agent has sufficient information 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?
Schema coverage is 0%, so the description fully documents all four parameters with meanings, defaults, and expectations. It even specifies the record structure including required fields and optional energy fields.
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 'Aggregate OEE (+ optional energy) across dimensions', a specific verb-resource pair. It explains return structure and gives an example, distinguishing it from single-point OEE tools like oee_compute (which appears in 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 clearly specifies that dimensions can be passed, with a default of ['machine','part','shift'], and explicitly suggests using ['shift'] for by-shift energy comparison, giving use-case context. However, it doesn't explicitly name alternative tools or 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.
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?
Annotations declare readOnlyHint=true and destructiveHint=false, and the description reinforces this with '[READ][risk=low]', 'read-only', 'pure over the provided series', and 'no device I/O'. It also discloses behavioral details beyond annotations: robust Theil-Sen fitting, refusal of thin history, timestamp-dependent ETA units, and structured uncertainty reporting. No contradictions 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 and front-loaded with a one-sentence summary and risk/read indicator, followed by a contextual paragraph, Args, Returns, and an Example. The length is justified by the tool's complexity (7 parameters, multiple output blocks, edge cases), and every section adds distinct 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?
This is a complex forecasting tool with no output schema, so the description must compensate by explaining input requirements, behavioral constraints, and return structure. It does so comprehensively: return dict fields, degradation/rule/waveform sub-blocks, example call, and edge cases like thin history. The description is fully self-sufficient for correct invocation and interpretation.
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 zero description coverage (0%), so the description bears full responsibility for explaining parameters. It does so thoroughly: series format and minimum length, limit directionality, imminent_within_s default, and include_waveform semantics. Each parameter is given meaningful context that the schema alone cannot 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 description states a specific action: forecasting a value's trend and time until it crosses a warn/alarm limit. It explicitly distinguishes itself from sibling baseline_check by positioning itself as the predictive step above that violation-flagging tool. The scope (trend extrapolation, ETA estimation) is concrete 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 clearly states when to use this tool (predictive early warning before a limit is crossed) versus baseline_check (which flags violations that already happened). It also provides practical usage conditions: requires >=30 samples, refuses thin history, and notes when to disable waveform features (slow trend-only signals). This is explicit, actionable guidance.
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 declare readOnlyHint=true and destructiveHint=false, but the description adds substantial behavioral context: file size limit (≤5 MB), format support with content sniffing, graceful degradation to parse_errors, citation requirements, and truncation limits for variables (≤100) and blocks (≤50). This goes well beyond the annotations and helps the agent understand side effects and limitations.
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 leading summary, then parameter details, return value breakdown, and example. It is longer than average but every sentence adds value, explaining formats, error handling, and citations. The only minor issue is slight redundancy in restating the file size (≤5 MB) multiple times, but this is not a serious flaw.
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 provides a detailed return structure including stats, blocks, call graph, parse_errors, and citation_note. It also covers edge cases (malformed sections, truncation) and practical usage guidance (quote citations). Given the tool's complexity, the description is complete enough for an agent to select and invoke it correctly without needing external documentation.
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 only defines a single string parameter 'path' with 0% coverage. The description fully compensates by specifying allowed extensions (.st/.scl/.awl/.l5x/.txt), existence requirement, size limit (≤5 MB), and a concrete example. This provides semantic meaning far 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's purpose: it parses an exported PLC program file and returns a structural outline, including blocks, branches, timers/counters, and call graph. It specifies the verb 'Parses' and the resource 'exported PLC program file', and distinguishes from siblings like plc_program_visibility (live) by emphasizing 'Never uploads from a live PLC'.
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: for analyzing exported text files, not live PLCs. It states 'Never uploads from a live PLC' and 'reads exactly the named file', which implies when not to use it. It does not explicitly name alternative sibling tools, but the context is strong enough for an agent to infer appropriate usage.
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?
Beyond the readOnlyHint and destructiveHint annotations, the description discloses specific behavior: 200-line cap with a truncated flag, case-insensitive block names, list of available blocks on failure, and the exact return dictionary keys. This adds substantial 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, args, returns, and an example. Every sentence adds value and is concise, making it easy for an agent to parse quickly.
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 complete: it covers input constraints, output structure (including all return keys), failure behavior, and a practical example. Even without an output schema, the agent knows exactly what to expect.
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 the schema provides no parameter descriptions, the description fully compensates by detailing path (file extensions, existence, ≤5 MB) and block (case-insensitive, quotes optional). This is essential for correct invocation.
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: returning the exact source text of a single named block from an exported program. It distinguishes itself from sibling tools like plc_program_outline (outline) and plc_program_xref (cross-reference) by focusing on raw source retrieval.
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: it is for reading exactly the section the agent is explaining, capping at 200 lines, and failing unknown blocks with a list. However, it does not explicitly state when to use this tool instead of alternative siblings (e.g., outline for overview), so it stops 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.
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 the readOnlyHint and non-destructive annotations, the description discloses concrete behavioral traits: reads only the named file (≤5 MB), never performs live PLC uploads, every finding cites source_file+line, the risk score is transparent with cited reasons, and parse errors are reported. These details significantly aid the agent in predicting side effects and limitations.
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 bracketed [READ][risk=low] tag and a concise summary sentence, then expands into structured Args/Returns/Example sections. It is longer than average, but the detailed return dict is justified given the absence of an output schema. A slight trim could improve clarity, but every section 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?
This is a complex analysis tool with one parameter and no output schema. The description provides a comprehensive return structure with nested fields, explains input constraints and behavioral limitations, and gives an example. It fully equips the agent to understand what the tool does, what it takes, and what it returns.
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 lists only a bare 'path' string with no description, so the description carries the full burden. It adds critical semantics: acceptable file extensions (.st/.scl/.awl/.l5x/.txt), existence requirement, and the ≤5 MB size limit, plus an example. This fully compensates for the 0% schema 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 the tool's purpose: producing a maintainability/operational-risk profile for an exported PLC program, with specific outputs like documentation coverage, unreferenced blocks, complexity hotspots, and risky constructs. This goes beyond a generic verb+resource and distinguishes it from sibling tools like plc_program_outline or 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 strong contextual cues: it is the 'what am I inheriting?' view for reviewing legacy code, works on exported files only, and explicitly excludes semantic understanding and live PLC uploads. It implies when to use (risk assessment of static files) and when not (live data or semantic analysis), though it does not name specific alternative tools.
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?
Annotations already declare readOnlyHint=true and destructiveHint=false; the description reinforces this with '[READ][risk=low]' and adds substantial extra context: the access classification is heuristic (op/regex, not data-flow analysis), specific classification rules for SCL/AWL/L5X are given, hits are truncated at 200, and the file must exist and be ≤5 MB. This goes well beyond the annotations and fully discloses limitations such as the verbatim source quoting and L5X line-as-rung 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 dense but well-organized: it opens with a one-line summary, then details search scope, access classification, arguments, return structure, and an example. Every sentence provides necessary information—no filler or redundant repetition of schema fields. The layout makes it easy to scan and quickly extract key constraints and behavioral nuances.
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 params, no output schema, and moderate algorithmic complexity, the description is remarkably complete. It explains what the tool returns (dict with source_file, format, symbol, hit_count, hits, hits_truncated, by_access), lists the classification rules, specifies file size and word-boundary matching, and even includes a usage example. This is more than sufficient for an agent to select and invoke the tool correctly without additional documentation.
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 only 'path' and 'symbol' with no descriptions (0% schema coverage). The description compensates fully: 'path' is defined as an exported program file with accepted extensions, existence requirement, and size limit; 'symbol' is described as a symbol/tag/absolute address with word-bounded match semantics. This adds essential meaning that the schema completely 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 opens with 'Cross-reference one symbol in an exported PLC program,' which uses a specific verb ('cross-reference') and resource ('symbol in exported PLC program'). It further distinguishes itself from siblings by detailing exactly what it finds (read/write/call/declare sites) and providing concrete symbol examples. This is unmistakably distinct from tools like plc_program_outline or plc_program_section.
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 implies when to use the tool: whenever an agent needs to trace all references to a given symbol or address in an exported PLC file. It does not explicitly mention alternatives or exclusions, but the specificity of the purpose ('finds every... site') and the file format constraints make the intended context very clear. No explicit when-not guidance is provided, so slightly below a 5.
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?
Beyond the annotations (readOnlyHint, openWorldHint, destructiveHint:false), the description adds a risk level ('[READ][risk=low]'), clarifies that read/write authorization is the caller's decision, and discloses that every call is audited. It also explains the no-egress gate reporting behavior, adding significant context not present in 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 compact tag, a one-line summary, an explicit usage directive, a detailed list of contents, an essential server-posture note, and a return-dict sketch. Every sentence serves a purpose, and the front-loading ensures the core intent is immediately 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 absence of an output schema, the description provides a detailed return key structure. It also covers the no-egress gate and audit behavior, which are critical for an agent deciding whether to proceed. This is complete for a zero-parameter 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?
With zero parameters, the schema provides full coverage. The description includes an example call ('protocols_supported()') to reinforce the no-argument usage. This meets the baseline for a parameterless tool.
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 identifies the tool as a 'capability map' with the specific verb 'discover', listing protocols, status, tools, and connection params. It clearly distinguishes itself from sibling tools by framing itself as the pre-choice discovery step ('Call this to discover what iaiops can do before choosing a protocol/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 provides explicit when-to-use context: 'before choosing a protocol/tool'. It also explains a specific benefit (learning about the no-egress gate) but does not explicitly state when-not-to-use or name alternative tools. This is clear context without formal exclusions.
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?
Beyond the readOnly/destructive annotations, the description discloses the full decision pipeline (explicit taxonomy > synonym table > unambiguous keyword inference), states that unmapped rows are returned with reasons rather than silently guessed, and notes that signals may be empty with no fabricated evidence. It also explains the 'advisory' nature and behavior when learn=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 summary line, behavioral explanation, args list, return format, and example. Every element adds information without filler; the length is appropriate for the tool's 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?
No output schema exists, but the description explicitly lists the return dict structure and provides an example. It covers purpose, fallback logic, parameter semantics, and output format, making it comprehensive for a tool with this complexity and sibling 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?
With 0% schema description coverage, the description fully compensates by detailing recognized cause and free-text columns for rows, providing a concrete synonym example, and explaining learn, min_samples, and smoothing as parameters passed to learn_cause_weights. This gives far more meaning than the bare schema types/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 opens with a specific verb+resource statement: 'Turn a CMMS/work-order export into the RCA incident corpus.' It further explains it auto-builds the labeled history needed by learn_cause_weights, distinguishing it from sibling tools like learn_cause_weights or 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 tool's context is clear: use it to build an RCA corpus from closed maintenance records, optionally feeding learn_cause_weights. It references learn_cause_weights as a downstream consumer but does not explicitly list when-not-to-use alternatives or exclusions, 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.
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 is rich in behavioral detail (air-gapped, local model, only rephrases, never adds cause/number/citation, no device I/O), but it directly contradicts the annotation readOnlyHint: false. Since the description claims 'Read-only' while annotations indicate the opposite, this is a clear annotation contradiction, warranting the minimum score.
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 functional summary, behavioral notes, Args, Returns, and an example. It is somewhat verbose but every sentence adds context (prerequisites, strict prompt, return shape). It is front-loaded with the primary purpose, making 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 that this tool invokes a local LLM and there is no output schema, the description covers prerequisites (pip install, running model), behavioral constraints (no additions), input source (RCA verdict), parameters, return format, and an example. It also points to docs for the strict prompt, 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?
Schema description coverage is 0%, but the description fully compensates with a detailed Args section. It explains that 'verdict' is the output of downtime_root_cause, defines base_url as the Ollama server URL, lists model defaults, and notes provider currently only supports 'ollama'. This goes beyond the schema's property names and defaults, providing actionable 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 states a specific verb and resource: 'Narrate a cited RCA verdict in plain language via an on-box LLM.' This clearly distinguishes it from siblings like downtime_root_cause (which computes the verdict) by emphasizing the narration step. The READ tag and air-gapped note further clarify its unique role.
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 example explicitly links to downtime_root_cause output, and the phrase 'hands the already-computed, already-cited verdict' implies it should be used after a verdict exists. However, it does not explicitly state when NOT to use it or name alternative narration tools, so it stops short of full usage boundaries.
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?
Beyond the annotations, the description discloses important behaviors: it skips non-numeric points, requires an extra install ('pip install iaiops[nats]'), formats subjects as '<subject_prefix>.tag.<metric>', and returns a dict with counters. It also explicitly frames the side effect as safe egress of already-read data, adding value beyond readOnlyHint=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 front-loaded with a one-line summary, then details, args, return, and example. Each section earns its place; the example clarifies usage and the install note is essential. It is concise for the amount of information covered, with 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?
With no output schema, the description compensates fully by stating the return dict structure. It covers prerequisites, alternative tools, behavior on non-numeric data, parameters, and an example—making it complete for a 6-parameter tool with only 1 required parameter.
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. It provides meaningful explanations for all six parameters (points, subject_prefix, servers, token, tls, publisher), including defaults and the expected shape of 'points', which goes well beyond the bare schema 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 'Publish already-read normalized points to a message bus (NATS)', specifying a concrete verb, resource, and scope. It differentiates itself from siblings like stream_publish_event and historian_push by emphasizing egress of already-read numeric data and pointing to a historian sink for text/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?
It explicitly tells when to use: after '*_read_many' collection, for numeric points. It names an alternative for non-numeric points ('use a historian sink for text/state') and clarifies this is not a control write. This gives strong usage context beyond what annotations convey.
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?
The description begins with '[READ]', which contradicts the annotation readOnlyHint=false, indicating the tool performs writes. This is a serious inconsistency. Although the description adds context like 'NOT a control write' and the return dict, the contradiction warrants a score of 1.
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 and concise: a summary, behavioral clarification, dependency notice, argument descriptions, return type, and an example. Every sentence contributes meaning 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?
The description covers purpose, behavior, parameters, returns, and an example. It does not mention failure modes or detailed connection prerequisites beyond pip install, but for a publish tool it provides sufficient context, especially since an output schema is absent but the return dict 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?
With 0% schema description coverage, the description explains the required parameters subject and event, and groups connection parameters (servers/token/tls/subject_prefix/publisher) referencing stream_publish. It does not detail each connection parameter individually, leaving some semantics to be inferred or looked up elsewhere.
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 and specifically states the tool publishes one computed event (RCA verdict/alarm) to a NATS message bus. It distinguishes itself from control writes and sibling tools by emphasizing that this is egress of already-computed findings, not a control 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 indicates when to use this tool (for computed findings) and explicitly states what it is NOT (a control write). It also points to stream_publish for bus connection details, but it does not explicitly exclude alternative tools or provide a full when-not-to-use list.
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?
Beyond the readOnlyHint, the description discloses detailed behavior: detection categories, meaning of parameters (e.g., 'server couldn't keep up' for republish_rejected), the return dict structure, and a concrete example. This goes well beyond the annotation basics.
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: starts with a READ/risk tag, then a terse summary, followed by detection targets, Args, Returns, and an Example. Every sentence contributes information, 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?
With no output schema, the description fully specifies the return dictionary and verdict values. All 6 parameters are documented, an example is given, and the classic failure scenario is described. This is sufficient for an agent to select 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?
Schema coverage is 0%, but the description's Args section explains every parameter's meaning, types, defaults, and usage (e.g., 'wrap_at: Modulus for rolling counters... omit for monotonic OPC-UA counters'). This adds essential semantics 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 the tool's purpose: 'Health of a sequenced subscription feed' and explicitly lists what it detects (dropped notifications, duplicates, out-of-order, republish rejections, overloaded channels). This specific verb+resource combination distinguishes it from sibling health tools like tag_health or heartbeat_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?
It provides clear context on when to use: for diagnosing subscription feed health issues, with a concrete 'classic Kepware' failure scenario. However, it doesn't explicitly name alternative tools or state when *not* to use it, so it falls short of full 5.
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, and the description adds a '[READ][risk=low]' preface consistent with that. It also discloses the exact output structure, severity levels, and flag types, providing meaningful behavioral detail 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: a compact summary line, clear Args/Returns sections, and a short example. Every sentence adds valuable detail without 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?
Despite having no output schema, the description fully explains the return dictionary, flags, severity range, and includes a realistic example. The complexity is moderate and the description covers parameters, behavior, and results completely.
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 documenting the 'tags' structure (fields like ref, label, samples, thresholds) and explaining the optional 'thresholds' override. It also provides an example call, making parameter usage unambiguous.
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: 'Rank tag offenders by bad-quality / flatline / range / anomaly.' This clearly states what the tool does and distinguishes it from generic health or scan tools by focusing on per-tag offender ranking with concrete detection categories.
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 context by defining the tool's role as ranking tag offenders, but it does not explicitly state when to prefer this tool over siblings like anomaly_scan or health_summary. No when-not-to-use conditions or alternatives are mentioned.
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.
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
Scored across 153 tools
The protocol-prefixed read/write tools are well separated, but the analytics layer has serious overlap: three RCA tools (downtime_root_cause, downtime_root_cause_live, downtime_triage), five alarm-analysis tools (alarm_bad_actors, alarm_flood_analysis, alarm_cascade, alarm_rationalization_worksheet, alarm_event_clusters), and redundant pairs like s7_read_area/s7_read_db and data_quality_scorecard/data_quality_fleet_rollup. Excellent descriptions mitigate but do not remove the misselection risk across 153 tools.
Snake_case with protocol prefixes (opcua_, modbus_, s7_, eip_, mc_, fins_) provides a coherent frame, and read/read_many/write patterns are mostly regular. But conventions mix verb_noun with noun-phrase names, per-protocol identity tools are inconsistently named (s7_cpu_info vs mc_cpu_status vs eip_controller_info vs ethercat_master_state), and two deprecated unprefixed names (health_summary, anomaly_scan) remain alongside their replacements.
153 tools is over three times the calibration threshold for 'extreme mismatch' (50+). Even a multi-protocol OT platform with this genuine breadth would be far more usable split into per-protocol or per-domain servers; one flat namespace of 153 tools is not something an agent can effectively navigate or select from.
Domain coverage is exceptionally deep: a dozen protocols with read/browse/discovery, OEE/downtime/ISA-18.2 analytics, evidence-cited RCA with site learning, baselines/SPC, compliance crosswalks, PLC program analysis, and data egress. Real gaps exist — no Modbus or OPC-UA write tools while six other protocols have gated writes, and the investigation lifecycle is read-only (open/show/list, no close/delete) — but they are minor relative to the enormous covered surface.
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.
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
- 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
- AlicenseAqualityAmaintenanceGoverned, read-only OT data tap for substation and utility telecontrol — IEC 60870-5-104, DNP3/IEEE 1815, and IEC 61850 MMS connectors with cross-protocol asset discovery, alarm and downtime RCA, unbypassable audit logging (MCP + CLI), budget/runaway guards, and an airgap no-egress mode. Energy edition of Industrial-AIOps, built on iaiops.core.5949 PyPI1MIT