Skip to main content
Glama
industrial-aiops

OT-AIops Energy

industrial-aiops-energy — Energy Edition (Substation / Utility)

English · 中文

The energy edition of Industrial-AIOps, split out into its own repo: read-only OT connectors for substation / utility telecontrol protocols, built on top of iaiops.core.

  • IEC 60870-5-104 (c104) — RTU / substation telemetry

  • DNP3 / IEEE 1815 (pydnp3) — outstation monitoring

  • IEC 61850 MMS (pyiec61850, linux-only wheel) — substation IED reads

It reuses the base package's shared governance (audit / budget / risk-tier / undo), cross-protocol brain (data-flow / alarm / OEE / downtime RCA on the normalized ISA-95/18.2 model), and MCP server infrastructure — this repo only adds the three energy connectors + their session builders + MCP tools. Read-first: no control-direction writes are exposed.

Current release: 0.1.11 (requires iaiops>=0.20.3,<1.0). New in 0.1.11 — all three monitor paths are CI-gated for the first time, and a skipped live test now fails the build instead of passing it. DNP3 was the holdout: pip install pydnp3 fails on any current Linux, so this repo inherited the ecosystem's "unbuildable on hosted runners" and tests/test_dnp3_live.py skipped on every build. It is not unbuildable — opendnp3 compiles clean, and the 2019 binding layer needed three mechanical fixes, now scripted in scripts/build_pydnp3.sh and running on real GitHub runners. Also inherits two governance fixes from iaiops 0.20.3 (pin raised): a call that failed is no longer audited as a success (which also mis-informed the pattern circuit breaker on every failure), and the runaway guard can now see a caller retrying a denial forever. Previously in 0.1.10 — a security fix inherited from the base package: three egress tools this edition mirrors (stream_publish, stream_publish_event, historian_push) wrote their credential — a NATS auth token, a TSDB password — into the audit log in the clear, and audit_forward shipped that row to the configured SIEM. They are defined in iaiops, so this edition could not fix it alone; the pin moves to iaiops>=0.20.2, and a contract test now fails the build if the whole registered surface ever again carries an undeclared credential parameter. If you have passed a token or historian password to these tools, rotate it and check existing audit rows. The energy connectors themselves take no credential parameters. Previously in 0.1.9 — every tool ships the MCP ToolAnnotations hints (readOnlyHint / destructiveHint / openWorldHint), derived from the @governed_tool harness rather than hand-written, so a client can tell a monitor read from a tool that acts without parsing the [READ]/[WRITE] docstring tag. On the wire that is 59 tools, 55 read-only and 0 destructive — this edition exposes no control direction, and that is now enforced by a test rather than only documented. They are hints, not a gate: the MCP spec forbids relying on annotations for security decisions, and enforcement stays in @governed_tool. The base pin moved to iaiops>=0.20.1 so the hint derivation is imported from mcp_server.hints instead of duplicated here.

Previously in 0.1.8 — the base IAIOPS_READ_ONLY gate was removed in iaiops 0.19.0 (read/write authorisation is the caller's decision — agent judgement / account management — not the tap's; every tool is governed and audited via the base @governed_tool harness), so this edition drops it too. It keeps the IAIOPS_NO_EGRESS=1 gate — a data-exfiltration / airgap axis that withholds data-shipping tools from list_tools() at registration time. This edition runs its own FastMCP instance, so the gate is wired into its own main(); without it IAIOPS_NO_EGRESS=1 would still expose historian_push, rca_narrate and the stream_publish* pair mirrored in from the base brain. The energy connectors themselves are monitor-only and survive the gate intact. See CHANGELOG.md.

Previously in 0.1.6 — an audit-hardening pass over the three read-only connectors: DNP3 no longer reports an offline outstation as online or returns a partial integrity-poll database; IEC-61850 gained a bounded connect/request timeout and stopped fabricating 0.0/empty-success on failure; the substation analyzer no longer calls a lone breaker-open a "selective trip"; tests isolate IAIOPS_HOME; and the base pin was raised to iaiops>=0.14 so the governance endpoint-scoping fix applies. See CHANGELOG.md §0.1.6. (0.1.5 verified the IEC-104 monitor path — a real c104 client↔server round-trip in a Linux container, tests/test_iec104_live.py.) Physical RTU / IED remains unverified. Since 0.1.3 the server has its own MCP identityiaiops-energy-mcp runs a dedicated FastMCP("iaiops-energy") instance with energy-specific instructions (IEC-104 / DNP3 / IEC-61850, read-first, no control/operate), with the base cross-protocol brain tools mirrored onto it — plus an edition skill (skills/iaiops-energy/SKILL.md, anti-drift-tested against the registered tool surface) and protocol-consistency contract tests (every tool must carry the governance marker, a [READ]-style risk tag, an Args: section, and the canonical {error, hint} error shape; the server refuses to start if any registered tool lacks the governance marker).

🧪 Beta testing & co-creation

Live substation RTU / IED / IEC-104 field testing is what this package needs most. The IEC-104, DNP3 and IEC-61850 monitor paths are library-loopback-verified, and all three now run on every CI build — a skip fails the build rather than passing it. (Since 2026-08-01: DNP3's evidence used to be a single manual run on 2026-07-02, because pydnp3 was believed unbuildable on hosted runners. That belief was wrong — see scripts/build_pydnp3.sh.) Real RTU / IED hardware remains unverified. If you can run iaiops doctor against real substation gear in an authorised test environment, we would very much like to hear the result — verified devices are credited by name in the support matrix. Report results (protocol + device model + iaiops doctor output) via the base repo's pinned issue: 👉 industrial-aiops#28 — Call for field-testing partners (v0.10.0)

Related MCP server: OT-AIops

Why a separate repo

Energy targets a distinct buyer (utilities / substations), has heavier platform-specific deps (pyiec61850 is a linux-only SWIG wheel; pydnp3 builds a native ext), and its own compliance surface (China's Security Protection of Power Monitoring Systems regime). Splitting keeps the base install light. See the base repo's docs/ENERGY-SPINOUT.md for the plan.

Install

pip install iaiops-energy[energy]      # all three energy protocols
pip install iaiops-energy[iec104]      # just IEC-104

iaiops-energy pulls in iaiops (the shared core) automatically.

Use (MCP)

iaiops-energy-mcp                       # brain + energy tools over stdio

Point a target at your substation gear in ~/.iaiops/config.yaml (protocol: iec104|dnp3|iec61850, host, port, common_address / unit_id).

Edge deployment & ecosystem (edge-native / Margo)

Like the base package, the energy edition rides on a hardened, centrally-managed edge host as a portable, governed edge application — mapping onto the Margo edge-interoperability roles (immutable host · compliant orchestrator · iaiops-energy = the OT-domain app), deployable as an OCI Managed Container (outbound-only to substation RTUs/IEDs, no inbound). A container + margo.org/v1-alpha1 application-description skeleton is in deploy/margo/; the full alignment + honest gap analysis lives in the base repo's docs/MARGO-ALIGNMENT.md. The descriptor is validated against Margo's published margo.org/v1-alpha1 LinkML schema on every PR (CI job margo-descriptor) and passes clean — structural validity only, see deploy/margo/schema/PROVENANCE.md.

Honest status: a natural Margo edge application, but NOT Margo-compliant yet — image build, hosted+signed package, and a published conformance result are roadmap . No claim of compliance until that result exists, and the schema pass above is not a step toward it: the compliance test suite cannot be run today because it does not exist yet (no conformance repo in the margo org; a first PR1 vertical slice was still being scoped as of 2026-01-15).

Validation status (honest)

The same honesty ladder as the base repo. Driver codec / API surface is verified against the real libraries; the mock/monkeypatched unit tests run in CI without hardware. See the base repo's docs/PREVIEW-VERIFICATION.md runbook for how a protocol is promoted.

Protocol

Status

CI coverage

Evidence

DNP3 / IEEE 1815

verified (monitor path)

✅ runs every push ¹

Real master↔outstation round-trip against a live opendnp3 outstation (pydnp3): is_online() reflects the real channel OnStateChange, and integrity_poll() (Class 0/1/2/3) returns the seeded binary/analog/counter database grouped by type. See tests/test_dnp3_live.py (@pytest.mark.integration). No physical RTU.

IEC 60870-5-104

verified (monitor path)

✅ runs every push

Real client↔server round-trip against an in-process c104 server (tests/test_iec104_live.py + tests/iec104_server_harness.py, @pytest.mark.integration, passes in a Linux container): iec104_connection_info discovers the seeded station, iec104_interrogate (general interrogation / C_IC) returns the seeded M_ME_NC_1 + M_SP_NA_1 points with quality, iec104_read_point reads the measurand, a bad IOA yields found=False with no fabricated value, and server-side ASDU capture proves no control ASDU (C_SC / C_DC / C_SE) is ever issued. c104 ships no macOS wheel so the test skips on macOS (runs in CI / Linux). No physical RTU. Monitor/read only.

IEC 61850 (MMS)

verified (monitor path)

✅ runs every push

Real client↔server MMS round-trip against an in-process libiec61850 MMS server built with pyiec61850's server API: iec61850_device_directory lists the logical device (and browses its logical nodes / data objects), and iec61850_read returns a seeded measurand (TotW.mag.f, FC MX) over real ISO-on-TCP; a bad reference surfaces an MMS data-access error instead of a fabricated value. See tests/test_iec61850_live.py (@pytest.mark.integration, skips when pyiec61850 / its server API is absent). No physical IED. Read/monitor only — control / GOOSE / SV out of scope.

¹ All three monitor paths are now CI-gated, and a skip fails the build rather than passing it (no live protocol test may skip). This used to read: "only IEC-104 is CI-gated; DNP3 and IEC-61850 rest on out-of-CI runs, not on the green badge." That was true and is no longer.

DNP3 was the last one, and the reason is worth recording because the old note here — and the CI job, and this README — all repeated the same wrong conclusion for months: pip install pydnp3 fails on any current Linux, so it was taken as unbuildable on hosted runners. It is not. opendnp3 itself compiles clean; what had rotted was the 2019 binding layer. Three mechanical fixes, no patches to opendnp3:

  1. Python headers must be present (python3-dev) — without them the build dies at Python.h: No such file or directory, which is what "unbuildable" looked like;

  2. 214 vendored headers #include <python2.7/Python.h>, rewritten to <Python.h>;

  3. the vendored pybind11 predates CPython 3.11 (it reads PyFrameObject internals that 3.11 made opaque) and GCC 13 (std::uint16_t without <cstdint>) — replaced with pybind11 v2.13.6.

scripts/build_pydnp3.sh applies all three and verifies the import. ~3 min cold on two cores. The lesson generalises: "the ecosystem says it cannot be built" is a claim to test, not to inherit.

DNP3 notes: read-only / monitor direction only (no control). Its DNP3Manager.Shutdown() can block in a long-lived interpreter, so the connector bounds teardown (_Pydnp3MasterAdapter.shutdown) and the test drives the round-trip in a short-lived child process.

License

MIT — © wei. Part of the vendor-neutral, governed Industrial-AIOps line.

Available Tools

59 tools
adopt_alias_mapA
Read-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").
ParametersJSON Schema
NameRequiredDescriptionDefault
siteNo
feedsYes

TDQS

A4/5.0
Behavior1/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_actorsA
Read-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"}, ...]).
ParametersJSON Schema
NameRequiredDescriptionDefault
top_nNo
eventsYes
standing_sNo
window_minutesNo
chatter_window_sNo

TDQS

A4.6/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_cascadeA
Read-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"}, ...]).
ParametersJSON Schema
NameRequiredDescriptionDefault
eventsNo
endpointNo
window_sNo
duration_sNo
min_cascadeNo

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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_flood_analysisA
Read-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"}, ...]).
ParametersJSON Schema
NameRequiredDescriptionDefault
eventsNo
endpointNo
max_rowsNo
window_sNo
thresholdNo
duration_sNo
max_episodesNo
load_bucket_sNo
stale_after_sNo

TDQS

A5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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_worksheetA
Read-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").
ParametersJSON Schema
NameRequiredDescriptionDefault
eventsNo
endpointNo
out_pathNo
window_sNo
thresholdNo
duration_sNo

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_scanA
Read-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.
ParametersJSON Schema
NameRequiredDescriptionDefault
sigmaNo
node_idYes
samplesNo
endpointNo
interval_msNo

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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_inventoryA
Read-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"]).
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointsNo

TDQS

A5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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_checkA
Read-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).
ParametersJSON Schema
NameRequiredDescriptionDefault
tagYes
endpointNo
window_sNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_learnA
Read-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").
ParametersJSON Schema
NameRequiredDescriptionDefault
tagYes
sinceNo
endpointNo

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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_record_changeA
Read-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").
ParametersJSON Schema
NameRequiredDescriptionDefault
tagYes
noteYes

TDQS

A3.8/5.0
Behavior1/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_statusA
Read-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").
ParametersJSON Schema
NameRequiredDescriptionDefault
tagNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

compliance_dengbao_levelsA
Read-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="三级").
ParametersJSON Schema
NameRequiredDescriptionDefault
levelNo

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_bundleA
Read-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").
ParametersJSON Schema
NameRequiredDescriptionDefault
sinceNo
untilNo
out_pathYes

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_frameworksA
Read-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().
ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.8/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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_mappingA
Read-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().
ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_reportA
Read-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").
ParametersJSON Schema
NameRequiredDescriptionDefault
siteNo
levelNo
out_pathNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_modelA
Read-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").
ParametersJSON Schema
NameRequiredDescriptionDefault
siteNo
feedsYes

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_rollupA
Read-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}]}]}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
nowNo
feedsYes
top_nNo
default_staleness_sNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_scorecardA
Read-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]}]}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
nowNo
feedsYes
default_staleness_sNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

diagnose_dataflowA
Read-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).
ParametersJSON Schema
NameRequiredDescriptionDefault
refNo
seriesNo
endpointNo
flatline_epsNo
freshness_threshold_sNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_mapA
Read-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").
ParametersJSON Schema
NameRequiredDescriptionDefault
siteNo
feedsYes

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

dnp3_integrity_pollA
Read-only

[READ][risk=low] Class 0/1/2/3 integrity poll → the outstation's database.

Returns all static points grouped by measurement type (binary_input,
analog_input, counter, …).

Args:
    endpoint: Endpoint name from config (protocol 'dnp3').

Returns dict: {endpoint, outstation_address, point_count, by_type{},
    points:[{type, group, index, value, quality, timestamp}]}.

Example: dnp3_integrity_poll(endpoint="rtu2").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool as read-only and non-destructive. The description adds that it is low risk and details the return dictionary structure, providing context beyond the annotation's safety profile.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded with the core action, followed by the return structure, parameters, and an 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.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with one parameter and no output schema, the description is complete: it covers the operation, parameter semantics, return format, and an example, leaving no significant gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has only one optional parameter with no description, but the description provides an Args section explaining 'endpoint' as the endpoint name from config and includes a usage 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.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool performs a Class 0/1/2/3 integrity poll that returns all static points grouped by measurement type. It names the specific DNP3 operation and distinguishes it from siblings like dnp3_link_status or iec104_interrogate.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool should be used when a complete read of DNP3 static data is needed, but it does not explicitly contrast with alternatives or state when not to use it. This is clear context without exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

downtime_eventsA
Read-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"}, ...]).
ParametersJSON Schema
NameRequiredDescriptionDefault
seriesYes
category_mapNo
min_duration_sNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_causeA
Read-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"}).
ParametersJSON Schema
NameRequiredDescriptionDefault
tagsNo
alarmsNo
windowYes
dataflowNo
state_seriesNo
cause_weightsNo
include_graphNo
lead_window_sNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_liveA
Read-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"]).
ParametersJSON Schema
NameRequiredDescriptionDefault
refsNo
windowNo
endpointNo
interval_msNo
sample_countNo
include_graphNo
lead_window_sNo
include_alarmsNo

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_triageA
Read-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}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
tagsNo
alarmsNo
windowYes
dataflowNo
precursorsNo
state_seriesNo
cause_weightsNo
include_graphNo
lead_window_sNo
cascade_window_sNo
imminent_within_sNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

export_dataA
Read-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").
ParametersJSON Schema
NameRequiredDescriptionDefault
fmtYes
tagNo
limitNo
sinceNo
untilNo
endpointNo
out_pathNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

fleet_incidentsA
Read-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"}]}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
sitesYes

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_statusA
Read-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"}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
nowNo
sitesYes
stale_after_sNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_summaryA
Read-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}}.
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo
node_idsNo
thresholdsNo

TDQS

A4.6/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_healthA
Read-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).
ParametersJSON Schema
NameRequiredDescriptionDefault
seriesYes
max_interval_sNo

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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_coverageA
Read-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().
ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
readerNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_healthA
Read-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"}, ...]).
ParametersJSON Schema
NameRequiredDescriptionDefault
seriesYes
flatline_epsNo
gap_threshold_sNo

TDQS

A4.6/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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").
ParametersJSON Schema
NameRequiredDescriptionDefault
hostNolocalhost
portNo
sinkYes
userNo
pointsYes
databaseNo
passwordNo

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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_queryA
Read-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").
ParametersJSON Schema
NameRequiredDescriptionDefault
tagYes
limitNo
sinceNo
untilNo
readerNo
endpointNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

iec104_connection_infoA
Read-only

[READ][risk=low] Connect and report IEC-104 link status + discovered stations.

Args:
    endpoint: Endpoint name from config (protocol 'iec104'); omit for default.

Returns dict: {endpoint, host, port, connected, configured_common_address,
    station_count, common_addresses[]}.

Example: iec104_connection_info(endpoint="rtu1").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate a safe read-only operation. The description adds behavioral context by mentioning that the tool 'connects' and reports status, and it discloses the structure of the returned dictionary. 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and well-structured: purpose, args, returns, and example. Every sentence earns its place, and the front-loaded title bracket gives an immediate safety/risk hint.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter, read-only tool with no output schema, the description fully covers the tool's behavior, parameters, and return value. It provides enough information for an agent to invoke and interpret the result without ambiguity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides only the param name and type, with 0% description coverage. The description compensates by explaining that 'endpoint' is a config name for protocol 'iec104', is optional, and provides a concrete example. This adds meaningful semantic information beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Connect and report') and resource ('IEC-104 link status + discovered stations'), clearly distinguishing it from sibling tools like iec104_interrogate or iec104_read_point, which focus on data operations rather than connection status.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides usage context (endpoint from config, optional default) and an example, but does not explicitly state when to use this tool versus alternatives. The guidance is implied by its purpose, but no direct exclusions or comparisons to siblings are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

iec104_interrogateA
Read-only

[READ][risk=low] General interrogation: all monitored points of a station (ASDU CA).

Args:
    common_address: ASDU common address; omit for the configured/first station.
    endpoint: Endpoint name from config (protocol 'iec104').

Returns dict: {endpoint, common_address, point_count, points:[{io_address, type,
    value, quality, recorded_at}]}.

Example: iec104_interrogate(common_address=1, endpoint="rtu1").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo
common_addressNo

TDQS

A4.5/5.0
Behavior4/5

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 details return structure including point fields. 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and well-structured: a header tag, one-line purpose, then Args/Returns/Example sections. 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.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only interrogation tool, the description covers parameters, return format, and example. It does not mention pagination or potential large responses, but given the annotations and simplicity, it is sufficiently complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 0% description coverage, so the description fully compensates by explaining both params: common_address as ASDU common address with omit behavior, and endpoint as endpoint name. The example further clarifies usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'General interrogation: all monitored points of a station (ASDU CA)', a specific verb and resource. It distinguishes from sibling iec104_read_point by indicating it covers all points rather than a single point.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies use when needing all monitored points, and provides endpoint and common_address context. It does not explicitly name alternatives or exclusions, but the scope is clear from 'all monitored points'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

iec104_read_pointA
Read-only

[READ][risk=low] Read one monitored point by information-object address (IOA).

Args:
    io_address: The point's information-object address (IOA).
    common_address: ASDU common address; omit for the configured/first station.
    endpoint: Endpoint name from config (protocol 'iec104').

Returns dict: {endpoint, common_address, found, io_address, type, value, quality,
    recorded_at}.

Example: iec104_read_point(io_address=1001, common_address=1, endpoint="rtu1").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo
io_addressYes
common_addressNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true, and the description adds the return dict structure including 'found' and 'quality', plus guidance to omit common_address for the first station. It does not describe error handling for missing points, but the 'found' key partially addresses this.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, front-loaded with a clear one-line summary, followed by args, return dict, and example. No wasted words; every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity, the description is complete: it explains how to invoke, what each parameter does, what the return looks like, and provides a concrete example. No output schema exists, but the return dict is documented sufficiently.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description explains all three parameters (io_address, common_address, endpoint) with semantics beyond the schema, including default behavior for common_address and endpoint resolution from config. Since schema description coverage is 0%, this fully compensates.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Read') and resource ('one monitored point by information-object address'), which clearly distinguishes it from sibling tools like iec104_interrogate. It is unambiguous about what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for reading a single point but does not explicitly state when to use it vs alternatives such as iec104_interrogate or iec61850_read. No exclusions or alternative recommendations are provided, leaving the agent to infer based on the tool name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

iec61850_browseA
Read-only

[READ][risk=low] Browse immediate model children under a reference (LD/LN/DO).

Args:
    reference: Model reference, e.g. 'IED1LD0' or 'IED1LD0/LLN0'.
    endpoint: Endpoint name from config (protocol 'iec61850').

Returns dict: {endpoint, reference, child_count, children[]}.

Example: iec61850_browse(reference="IED1LD0/MMXU1", endpoint="ied1").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo
referenceYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the primary burden is satisfied. The description adds that only immediate children are returned (non-recursive) and specifies the return dict shape, which provides meaningful 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and well-structured: it opens with a purpose tag, then lists args, return format, and an example. Every sentence earns its place without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only browse tool with no output schema, the description covers the essential aspects: purpose, parameter semantics, return structure, and an example. It does not mention error handling or explicitly guide alternative tool selection, but that is a minor gap given the tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description compensates by documenting 'reference' with concrete examples (e.g., 'IED1LD0' or 'IED1LD0/LLN0') and 'endpoint' as a config name. This adds meaning over the bare schema, though the endpoint description is somewhat terse.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool browses immediate model children under an LD/LN/DO reference, using a specific verb and resource. This distinguishes it from sibling tools like iec61850_read and iec61850_device_directory, which likely handle reads or full directory listing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for hierarchical navigation by saying 'browse immediate model children', but it does not explicitly state when to use this tool versus alternatives. It lacks exclusions or guidance about when to prefer a full device directory or point read.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

iec61850_device_directoryA
Read-only

[READ][risk=low] List the IED's logical devices (optionally their children).

Args:
    include_children: Also browse each logical device's immediate model children.
    endpoint: Endpoint name from config (protocol 'iec61850'); omit for default.

Returns dict: {endpoint, logical_device_count, logical_devices:[{logical_device,
    children[]?, child_count?}]}.

Example: iec61850_device_directory(include_children=True, endpoint="ied1").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo
include_childrenNo

TDQS

A4.4/5.0
Behavior3/5

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 behavioral detail about the return dictionary structure and the optional children inclusion, which is helpful. However, it does not disclose potential edge cases like empty results or errors, but given the simple read-only nature, the bar is slightly lower. 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized: a one-line summary, an Args section, a Returns section, and an example. Every sentence adds value—no fluff. It is appropriately sized for a tool with two parameters, and the example reinforces usage.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only listing tool with 2 optional parameters and no output schema, the description provides everything needed: purpose, parameter meanings, return format, and an invocation example. It is complete without over-explaining.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has no parameter descriptions (0% coverage), so the description carries full burden. It explains 'include_children' as 'Also browse each logical device's immediate model children' and 'endpoint' as 'Endpoint name from config (protocol 'iec61850'); omit for default.' Both parameters get clear, non-schema-derived meaning, plus a concrete example.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb 'List' and a clear resource 'the IED's logical devices', immediately conveying the tool's scope. It also mentions optional behavior ('optionally their children') which distinguishes it from sibling browse/read tools. This is a strong, unambiguous purpose statement.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context: it lists logical devices and optionally children, with endpoint from config ('omit for default'). It does not explicitly name alternative tools or when-not-to-use, but the read-only listing nature is self-evident. The instructions are actionable without being misleading.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

iec61850_readA
Read-only

[READ][risk=low] Read one data attribute by object-reference + functional constraint.

Args:
    reference: Data-attribute object reference, e.g. 'IED1MMXU1.TotW.mag.f'.
    fc: Functional constraint — MX (measurands), ST (status), CF (config), …
    endpoint: Endpoint name from config (protocol 'iec61850').

Returns dict: {endpoint, reference, fc, value, error}.

Example: iec61850_read(reference="IED1MMXU1.TotW.mag.f", fc="MX", endpoint="ied1").
ParametersJSON Schema
NameRequiredDescriptionDefault
fcNoMX
endpointNo
referenceYes

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, which the description reinforces with '[READ][risk=low]'. It adds context by noting that the return is a dict with an error field, but it does not disclose potential failure modes or endpoint configuration requirements beyond a brief mention. That said, with annotations covering the safety profile, the additional context is modest.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is efficiently structured with a front-loaded tag, clear Args section, Return type, and a working example. Every sentence serves a purpose with no filler, making it easy to scan and absorb.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple single-read tool with no output schema, the description covers purpose, parameters, return shape, and an example. It omits explicit error-handling details but includes an 'error' field in the return dict, which implies failure reporting. The lack of a defined output schema is offset by the return dict description, making it sufficiently complete for the tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 each parameter: reference with an example, fc with sample values, and endpoint with source from config. It also shows defaults (fc defaults to MX, endpoint null). This provides enough semantic meaning for correct usage, though fc's full range is not exhaustively listed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with '[READ][risk=low]' and states 'Read one data attribute by object-reference + functional constraint.' This is a specific verb, resource, and scope, clearly distinguishing it from sibling browse tools like iec61850_browse. The example further clarifies the exact use case.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for reading a single attribute via the phrase 'Read one data attribute' and provides a concrete example, but it does not explicitly mention when to use this tool versus alternatives like iec61850_browse. No exclusions or alternative guidance is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

learn_cause_weightsA
Read-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"]}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
historyYes
smoothingNo
min_samplesNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

monitor_changesA
Read-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).
ParametersJSON Schema
NameRequiredDescriptionDefault
refYes
deadbandNo
endpointNo
duration_sNo
interval_msNo
max_changesNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

oee_computeA
Read-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).
ParametersJSON Schema
NameRequiredDescriptionDefault
actual_kwhNo
good_countYes
run_time_sYes
total_countYes
baseline_kwhNo
setup_time_sNo
planned_time_sYes
breakdown_time_sNo
energy_toleranceNo
minor_stop_time_sNo
ideal_cycle_time_sYes
startup_reject_countNo
emission_factor_kg_per_kwhNo

TDQS

A4.2/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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_multidimA
Read-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"]).
ParametersJSON Schema
NameRequiredDescriptionDefault
recordsYes
dimensionsNo
energy_toleranceNo
emission_factor_kg_per_kwhNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

pdm_forecastA
Read-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).
ParametersJSON Schema
NameRequiredDescriptionDefault
seriesYes
warn_lowNo
alarm_lowNo
warn_highNo
alarm_highNo
include_waveformNo
imminent_within_sNo

TDQS

A5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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_outlineA
Read-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").
ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_sectionA
Read-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").
ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
blockYes

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_visibilityA
Read-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").
ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_xrefA
Read-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").
ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
symbolYes

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

protocols_supportedA
Read-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().
ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_maintenanceA
Read-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"}).
ParametersJSON Schema
NameRequiredDescriptionDefault
rowsYes
learnNo
synonymsNo
smoothingNo
min_samplesNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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").
ParametersJSON Schema
NameRequiredDescriptionDefault
modelNollama3.1
verdictYes
base_urlNohttp://localhost:11434
providerNoollama

TDQS

A3.9/5.0
Behavior1/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

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").
ParametersJSON Schema
NameRequiredDescriptionDefault
tlsNo
tokenNo
pointsYes
serversNonats://localhost:4222
publisherNonats
subject_prefixNoiaiops

TDQS

A5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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"}).
ParametersJSON Schema
NameRequiredDescriptionDefault
tlsNo
eventYes
tokenNo
serversNonats://localhost:4222
subjectYes
publisherNonats
subject_prefixNoiaiops

TDQS

A3.6/5.0
Behavior1/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_healthA
Read-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}).
ParametersJSON Schema
NameRequiredDescriptionDefault
wrap_atNo
sequenceYes
tags_per_channelNo
republish_rejectedNo
republish_requestedNo
max_tags_per_channelNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

substation_event_analysisA
Read-only

[READ][risk=low] Analyse a substation Sequence-of-Events for protection selectivity.

Pure structural analysis over INJECTED events (no live protocol I/O, no
endpoint): given relay pickups/trips, breaker open/close, lockouts and bus
undervoltage with ISO-8601 timestamps, decide what tripped and whether
protection coordinated — a selective trip (one zone contained), a
non-selective backup operation (wider outage), or a breaker failure.
Monitor-only, advisory, cite-first (every claim ties to a timestamped event).

Args:
    events: SOE list of {ref, timestamp (ISO-8601), type, label?}; ``type``
        is one of protection_pickup / protection_trip / breaker_open /
        breaker_close / lockout / bus_undervoltage (a free-text ``label`` is
        keyword-matched when ``type`` is absent or unknown). ``ref`` is the
        point name / IOA.
    breaker_fail_window_s: Breaker-failure timer — the tripped breaker's own
        open must be seen within this many seconds (default 0.25).
    backup_margin_s: Backup coordination margin — a breaker opening later
        than this past the first protection event is treated as backup
        operation (default 0.5).

Returns dict: {events_analyzed, ignored, verdict, first_protection,
    first_breaker_open, breakers_opened, breaker_open_count, affected_refs,
    timeline, coordination{status, detail}, note}. ``verdict`` is one of
    selective_trip / backup_operation / breaker_failure / insufficient.

Example: substation_event_analysis(events=[
    {"ref": "R1", "type": "protection_trip", "timestamp": "2026-07-12T10:00:00Z"},
    {"ref": "BK1", "type": "breaker_open", "timestamp": "2026-07-12T10:00:00.08Z"}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
eventsYes
backup_margin_sNo
breaker_fail_window_sNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and destructiveHint=false, and the description's '[READ][risk=low]' and 'Monitor-only' are consistent. It adds valuable behavioral context: 'Pure structural analysis over INJECTED events', the cite-first requirement, and the keyword-matching fallback for unknown event types, which go beyond annotation data.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured, front-loading the purpose, then Args, Returns, and Example. While detailed, each section adds value and no redundant or filler text is present.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description includes a return dict with all key names and the verdict enumeration. It also provides a concrete example call. Given the tool's moderate complexity, this is fully sufficient 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.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has no descriptions (0% coverage), but the description thoroughly documents all three parameters. It explains the events list with required fields and allowed type values, and gives semantic meaning and defaults for breaker_fail_window_s and backup_margin_s, fully compensating for the schema's silence.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Analyse a substation Sequence-of-Events for protection selectivity', clearly specifying a verb, resource, and outcome. It further contrasts with live protocol tools by noting 'no live protocol I/O, no endpoint', differentiating it from siblings like iec61850_read or historian_query.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description defines the exact use case: analyzing relay/breaker/lockout/bus undervoltage events to classify trips. It notes it is 'Monitor-only, advisory' and involves 'no live protocol I/O', indicating when not to use it, but it doesn't explicitly name alternative tools for those scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tag_healthA
Read-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]}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
tagsYes
thresholdsNo

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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.

TDQS

A3.8/5.0
Disambiguation2/5

Many tools analyze alarm/health data with overlapping inputs (e.g., alarm_bad_actors, alarm_flood_analysis, alarm_cascade, alarm_rationalization_worksheet; health_summary, tag_health, historian_health, data_quality_scorecard). Deprecated tools like health_summary and anomaly_scan redirect to non-existent replacements, increasing ambiguity. While many tools are distinct, the boundaries between several analytics tools are unclear.

Naming Consistency4/5

Tool names are predominantly snake_case with a consistent verb_noun pattern (diagnose_dataflow, monitor_changes, oee_compute, compliance_report). Protocol-specific prefixes (iec61850_, iec104_, dnp3_) and domain prefixes (plc_program_, compliance_) are used consistently. Minor deviations like protocols_supported, health_summary, and rca_corpus_from_maintenance do not break the overall pattern.

Tool Count2/5

59 tools is well above the 25+ threshold for 'too many'. While the domain is broad (multiple industrial protocols, analytics, compliance, PLC analysis), the count is excessive and many tools are deprecated or overlapping. A more focused set of 15-20 tools would be more coherent.

Completeness3/5

The set covers a wide range of operations: protocol reads, diagnostics, analytics, compliance, historian, fleet, PLC program analysis. However, several tools reference missing components (e.g., opcua_discover_tags, modbus_apply_template, opcua_health_summary) and deprecated tools point to non-existent replacements, creating dead ends. Core workflows exist but gaps in referenced helpers prevent full coverage.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Connects AI agents to energy infrastructure with 30+ tools for managing sites, assets, dispatch, settlements, compliance, and carbon tracking.
    34
    47
    1
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Provides AI agents with safe, governed read access to industrial control systems (OPC-UA, Modbus, S7, Mitsubishi, MTConnect, MQTT/Sparkplug) plus cross-protocol diagnostics for troubleshooting data breaks, alarm floods, and unhealthy tags.
    2
    153
    1
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/industrial-aiops/industrial-aiops-energy'

If you have feedback or need assistance with the MCP directory API, please join our Discord server