Metronisys Tools & Skills Template"

You can build your own custom tools and skills and import them into the Metronisys Solution by building against this template.

Home

Building a Custom Dynamic Skill

Follow this guide to develop, register, and deploy .skill files into the Metronisys runtime.

Overview

Dynamic skills are Python logic stored in .skill files within the SKILLS/ folder. The runtime loads them via loader.py, ensuring only files listed in allowed_manifest.json are executed.

1. The Contract (Required)

Every .skill file must define a register() function returning these core fields:

Field Type Purpose
name str Unique tool ID (e.g., my_custom_tool).
description str Short description for the agent and selector.
function callable The actual logic function to be invoked.
def actual_logic_function(**kwargs):
    return {"answer": "Example dynamic skill ran.", "status": "ok"}

def register():
    return {
        "name": "example",
        "description": "Example dynamic skill for testing.",
        "function": actual_logic_function,
        "input_schema": {"query": "string"}
    }

2. Implementing Your Skill

Step 1: Logic

Define your_function(**kwargs) -> dict. Ensure it returns a "status" of "ok" or "error".

Step 2: Register

Set unique name, description, and map the input_schema for parameter validation.

3. Importing into Solution

  • 1
    Add File: Place my_tool.skill in the SKILLS/ directory.
  • 2
    Manifest: Add "my_tool" to allowed_manifest.json.
  • 3
    Policy: Add - my_tool to the allow_tools list in your baseline.yml.

Quick Checklist

  • ✅ Logic function returns answer and status.
  • register() exported with correct metadata.
  • ✅ Filename matches Tool ID exactly.
  • ✅ Security: Use Fernet encryption for production environments.

Home

example.skill

  
{
# Example dynamic skill (plaintext; for dev only).
# In production, encrypt with Fernet and set METRONISYS_SKILLS_ENCRYPTION_KEY.
#
# CONTRACT:
#   - Define register() returning {"name", "description", "function"} (required).
#   - Add skill name to allowed_manifest.json "allowed" list.
#   - Add skill name to policy allowed_tools (e.g. policies/default/baseline.yml).
#
# OPTIONAL register() fields (sub_agent fills missing params before calling your function):
#   - default_params: dict of default kwarg values when task does not infer params.
#   - params_from_current_datetime: {param_name: "current_datetime_result_key"}
#     e.g. {"start_date": "current_date_utc"} — sub_agent calls built-in current_datetime and fills missing params.
#     Valid keys: current_date_utc, current_time_utc, current_datetime_iso, etc.
#   - params_from_default_location: list of param names for location/country. Standard way to get location params.
#     Valid: ["location", "street", "city", "state", "country", "country_id", "country_code"]
#     From prompt: parsed from " for " / " in " → street, city, state, country (name), country_id (code).
#     location = street + city + state (concatenated). If prompt has no location, fallback to env:
#     location = city + state, country = country. Env: METRONISYS_LOCATION_CITY, _STATE, _COUNTRY.
#
# RETURN: Your function should return a dict with at least "answer" or "message"; include "status": "ok" or "error".

def actual_logic_function(**kwargs):

	# your code here #

    return {"answer": "Example dynamic skill ran.", "status": "ok"}


def register():
    return {
        "name": "example",
        "description": "Example dynamic skill for testing the loader. Params: query (optional).",
        "function": actual_logic_function,
        "input_schema": {"query": "string"},
        "tags": ["example", "test"],
        "capabilities": [],
        "keywords": ["example", "test"],
        "purpose": "example skill for loader and registry testing",
        "use_when": "testing skill loading or tool selection",
        "match_phrases": [],
        "avoid_phrases": [],
        "examples": ["run example skill", "test example"],
    }

}
  

Home Back To Tools