Writing a tool

Integrate a new external system as a tool: scaffold it, implement it, and pass the conformance kit.

A tool integrates one external system. It reports facts, answers a health probe and, optionally, runs jobs on the system. Tools are released independently, one version per tool; see Versioning.

Scaffold#

nistor tool new my_system

The command writes, under <--dest>/packages/integrations/my_system, a complete, conforming package from the same template as the shipped example (examples/providers/hello_world). It names the distribution nistor-tool-my-system and the module nistor_tool_my_system. See CLI for the command's rules and options.

What is in the package#

  • pyproject.toml: the distribution, a range on nistor-core, and the entry-point rows. nistor.tools points at the manifest; further rows declare an executor, a connection type or settings.
  • manifest.py: MANIFEST: the tool id, version, the facts it produces, its facets, connection type and settings.
  • config.py: the tool's settings model (the manifest's settings_model).
  • health.py: check(connection) returns a health fact and never raises; testing a connection runs it.
  • connection_spec.py: the connection's configuration schema and its secret fields.
  • client.py: the vendor client. Replace it with yours.
  • executors/: the executor facet, if your tool launches work: launch, find an existing run, report status.
  • tests/: unit tests, and the conformance test.

Test with the conformance kit#

The kit (nistor-testing) checks the installed manifest and replays what the vendor answered, with no network. The manifest checks are two lines:

from nistor_testing.tool_kit import ToolConformance


class TestConformance(ToolConformance):
    tool_id = "my_system"

Record the vendor's real answers once, under tests/conformance/: facts/ (what your tool reports), health/ (probe replies) and executor/ (recorded fake job systems). The kit then checks that facts validate against the core shapes, that the probe never raises and answers within budget, that dispatch is idempotent and that every vendor state maps to a status.

Those runtime checks need two replay adapters that only your tool can write, because only it knows how its vendor is reached: health_replay (make the probe see a recorded reply) and, for a tool with the executor facet, executor_replay (stand a recorded job service up). The scaffold generates both; see examples/providers/hello_world/tests/test_conformance.py.

pip install -e packages/core -e packages/testing
pip install --no-deps -e packages/integrations/my_system
cd packages/integrations/my_system && pytest tests

Rules a tool follows#

  • Import nistor_core contracts only; never another tool or a plugin.
  • Keep secrets in the connection's secret fields; never in the configuration or in logs.
  • Declare requires_core_api in the manifest (a version specifier on the core API version, for example >=1.0,<2) and the nistor-core range you support. A tool built against core 1.x keeps working on every later 1.x; see Versioning.

Submit it#

Open a merge request (CONTRIBUTING.md). A tool that lives in your own repository needs no merge request at all: publish it as a package and install it beside Nistor.

Edit this page on GitLab

↑ ↓ to moveEnter to openEsc to close