Skip to content

tools

tools

What may be asked of a device remotely — and nothing else.

Spec §21 forbids a universal tool. That is not a style preference: an assistant that can call remote.execute(action, params) has, in practice, been handed the other device's shell, and every permission check upstream becomes decoration. The prohibition is enforced structurally here —

  • every tool declares its parameters by name, with a type;
  • unknown parameters are refused, never forwarded;
  • no parameter may be named action, command, method, code, script or sql — the shapes a passthrough always takes;
  • a tool with no declared parameters accepts no arguments at all.

A test (test_no_universal_tool) re-checks these on the whole registry, so adding a fourteenth tool cannot quietly reintroduce the thirteenth's escape hatch.

Classes

RemoteToolSpec dataclass

RemoteToolSpec(
    name: str,
    description: str,
    capability: str,
    parameters: Mapping[str, Mapping[str, Any]] = dict(),
    requires_confirmation: bool = False,
    offline_policy: str = "QUEUE_UNTIL_EXPIRATION",
)

One narrow, explicitly-shaped remote capability.

Methods:
validate
validate(arguments: Mapping[str, Any]) -> None

Refuse anything the tool did not explicitly ask for.

Source code in src/diapason/mesh/tools.py
def validate(self, arguments: Mapping[str, Any]) -> None:
    """Refuse anything the tool did not explicitly ask for."""
    from diapason.mesh.commands import CommandRejected

    if not isinstance(arguments, Mapping):
        raise CommandRejected("DENIED", "Les arguments sont illisibles.")

    unknown = set(arguments) - set(self.parameters)
    if unknown:
        raise CommandRejected(
            "DENIED",
            f"Paramètre non reconnu pour « {self.name} » : "
            f"{', '.join(sorted(unknown))}.",
        )

    for key, rule in self.parameters.items():
        if key not in arguments:
            if rule.get("required"):
                raise CommandRejected(
                    "DENIED", f"Le paramètre « {key} » est obligatoire."
                )
            continue
        value = arguments[key]
        expected = rule.get("type", "string")
        if expected == "string":
            if not isinstance(value, str):
                raise CommandRejected(
                    "DENIED", f"Le paramètre « {key} » doit être du texte."
                )
            if len(value) > int(rule.get("max", 500)):
                raise CommandRejected(
                    "DENIED", f"Le paramètre « {key} » est trop long."
                )
        elif expected == "integer" and not isinstance(value, int):
            raise CommandRejected(
                "DENIED", f"Le paramètre « {key} » doit être un nombre."
            )
        elif expected == "boolean" and not isinstance(value, bool):
            raise CommandRejected(
                "DENIED", f"Le paramètre « {key} » doit être vrai ou faux."
            )
        choices = rule.get("enum")
        if choices and value not in choices:
            raise CommandRejected(
                "DENIED",
                f"Valeur non autorisée pour « {key} ».",
            )

Functions:

list_remote_tools

list_remote_tools() -> list[dict[str, Any]]

The catalogue, as the assistant's tool router should advertise it.

Source code in src/diapason/mesh/tools.py
def list_remote_tools() -> list[dict[str, Any]]:
    """The catalogue, as the assistant's tool router should advertise it."""
    return [
        {
            "name": spec.name,
            "description": spec.description,
            "capability": spec.capability,
            "parameters": {
                key: dict(rule) for key, rule in sorted(spec.parameters.items())
            },
            "requiresConfirmation": spec.requires_confirmation,
            "offlinePolicy": spec.offline_policy,
        }
        for spec in sorted(REMOTE_TOOLS.values(), key=lambda s: s.name)
    ]