OpenViSTAI · Agents · Blockchain · Crypto
Menu
OPENVIST RECIPES

Compare Tool Interfaces in Two Saved XML Workflows

Python

Read two local XML workflow files and report tool elements whose tag-and-attribute signatures appear in only one file, without executing or modifying either workflow.

Python code excerpt: Compare Tool Interfaces in Two Saved XML Workflows. Version 0.1.0. Read the full recipe for code, sources and recorded test scope.

When reviewing agent-workflow edits, a structural comparison can show which tool-shaped XML elements were added or removed without running the workflows. This recipe compares exact element signatures from two user-supplied XML files; it is a local XML inspection, not a test of any agent, blockchain, or external service.

Before you start

  • Use Python 3.12 as the intended runner; this recipe makes no claim about a tested minimum version.
  • The Python standard library modules argparse, json, sys, pathlib, and xml.etree.ElementTree are sufficient; no installation, credentials, or network access are required.
  • Provide two readable, well-formed XML files. ElementTree is not secure against maliciously constructed XML; use only trusted local fixtures.
  • The tool identifies elements whose exact case-sensitive local tag name is `tool`; namespaced tool tags are matched by local name but reported with their original qualified tag.

Build and check

  1. Save the script as `compare_tools.py`.
  2. Create two small XML fixtures representing the earlier and later workflow structures.
  3. Run `python3.12 compare_tools.py before.xml after.xml` with the fixture paths as positional arguments.
  4. Review the `added` and `removed` JSON arrays; an empty array means no signature differences in that direction.
  5. Change one tool attribute in a fixture and rerun to confirm the old signature is removed and the changed signature is added.

Limits to understand

  • This is a structural XML comparison, not a workflow validator or an execution test; it does not establish that any tool works or that an external service is available.
  • Only elements with the exact local tag name `tool` are considered; other possible tool-node conventions are not inferred.
  • Signatures include all attributes, so changing any attribute produces an added and removed entry. Text, child elements, namespaces beyond the original tag string, and ordering among repeated identical signatures are not compared.
  • Repeated identical tool signatures collapse to one set entry; this tool compares distinct signatures, not occurrence counts.
  • XML parsing reads each document as a whole. Do not use this small recipe for very large documents or untrusted XML.

What this example adds

The comparison is useful for reviewing a workflow revision because it reports added and removed tool signatures, rather than merely listing selected XML elements from one file. It emits deterministic JSON and treats a signature as the exact XML tag plus its sorted attribute pairs. Attribute changes therefore count as removal of the old signature and addition of a new one; child content and element order are deliberately ignored.

Run it

Save the code as compare_tools.py, then run `python3.12 compare_tools.py before.xml after.xml`. It reads both named local files, prints JSON to standard output, and reports file or XML parse errors to standard error with a nonzero exit status. Python 3.12 is the intended runner; no minimum-version claim is made.

Example input

before.xml:
<workflow><tool name="lookup" mode="read"/><step/></workflow>

after.xml:
<workflow><tool name="lookup" mode="read"/><tool name="quote" mode="read"/></workflow>

Expected output

{
  "added": [
    {
      "tag": "tool",
      "attributes": {
        "mode": "read",
        "name": "quote"
      }
    }
  ],
  "removed": []
}
INSPECT THE SCRIPT

Inspect, copy and run the documented checks.

This browser preview builds code locally. It does not contact an API or run the code.

Default example ready.

Python example
# SPDX-License-Identifier: MIT
# Copyright (c) 2026 OpenViST contributors
import argparse
import json
import sys
import xml.etree.ElementTree as ET
from pathlib import Path


def signatures(path):
    try:
        root = ET.parse(path).getroot()
    except (OSError, ET.ParseError) as exc:
        raise ValueError(f"cannot read valid XML from {path}: {exc}") from exc

    found = set()
    for elem in root.iter():
        # A tool element is identified by the exact, case-sensitive local tag name.
        local_tag = elem.tag.rsplit("}", 1)[-1] if isinstance(elem.tag, str) else ""
        if local_tag == "tool":
            found.add((elem.tag, tuple(sorted(elem.attrib.items()))))
    return found


def main():
    parser = argparse.ArgumentParser(
        description="Compare exact tool-element signatures in two saved XML workflows."
    )
    parser.add_argument("before", help="path to the earlier XML workflow")
    parser.add_argument("after", help="path to the later XML workflow")
    args = parser.parse_args()

    try:
        before = signatures(Path(args.before))
        after = signatures(Path(args.after))
    except ValueError as exc:
        print(f"error: {exc}", file=sys.stderr)
        return 2

    def display(signature):
        tag, attrs = signature
        return {"tag": tag, "attributes": dict(attrs)}

    result = {
        "added": [display(item) for item in sorted(after - before)],
        "removed": [display(item) for item in sorted(before - after)],
    }
    print(json.dumps(result, ensure_ascii=False, indent=2))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
What to verify after running
  • Run with identical valid files and confirm both arrays are empty.
  • Run the synthetic before/after example and confirm only the `quote` signature is listed under `added`.
  • Change the `mode` attribute on an existing tool and confirm the former signature appears under `removed` and the changed one under `added`.
  • Try a well-formed XML document with no tool elements and confirm the output contains two empty arrays.
  • Try an empty file or malformed XML and confirm an error is written to standard error with a nonzero exit status.
  • Try a nonexistent input path and confirm the missing-file error is reported without producing a comparison result.

Request or format preview

Illustrative preview. No provider response, price or balance is fetched.

Change a setting to inspect the preview.

Official sources and related profiles

    Code license: MIT. Keep the license notice with your copy.

    Example version 0.1.0 · Documentation reviewed 2026-10-11.

    Executed 5 synthetic local fixture cases in isolated CPython 3.12.15 on GitHub Actions, without network access. Declared exit codes, output assertions and input integrity checks passed. Live services, installed third-party packages and production behavior remain outside scope. Editorial approval is still required.