Skills¶
Skills are the mechanism by which Kenzy takes actions in the world — fetching weather, reading news, controlling smart home devices, and more. Each skill is an async Python function decorated with @skill. The LLM calls skills as tools based on their docstrings and type signatures.
How skills work¶
Skills load from two places at LLM-service startup:
- Built-in skills ship inside the package (
kenzy/llm/builtin_skills/) and always load first. - Your overlay — the directory named by
skills.dirinllm.yaml(defaultskills/under your config home:~/.config/kenzy/skills, or the repo root in a dev checkout). Loaded second, so a file here that defines a skill of the same name overrides the built-in one.
Every .py file is imported and all @skill-decorated functions are registered. The decorator introspects each function's signature, type annotations, and docstring to generate the JSON Schema tool definition that LiteLLM passes to the model — no separate configuration or registration step. Disable any skill (built-in or custom) by its function name under skills.disabled in llm.yaml.
kenzy/llm/builtin_skills/ ← bundled: weather, news, home_assistant, stocks, …
~/.config/kenzy/skills/
my_skill.py ← your custom skill (overrides a built-in of the same name)
The LLM decides which skills to call and with what arguments based entirely on the docstrings. Well-written docstrings that describe when to use a skill are as important as the skill's implementation.
Two resolution tiers¶
Kenzy resolves a request in two stages, fastest first:
- Fast path (deterministic). Before the LLM is consulted, the request is run through any registered fast intents —
@fast_intentmatchers that recognise common, high-frequency commands locally and answer instantly with no remote model call. Time/date queries and the bulk of Home Assistant control ("turn on the kitchen lights") are handled here. - LLM fallback. Anything a fast intent doesn't confidently match falls through to the tool-calling LLM exactly as before. The fast layer is deliberately high-precision: when it isn't sure, it defers.
A skill can expose both — a deterministic @fast_intent front-end for the easy cases and an @skill tool definition for the LLM to fall back on. See Writing Skills for the fast-intent API.
Skill configuration¶
Per-skill settings live under skills.<skill_name> in llm.yaml:
skills:
home_assistant:
url: "http://homeassistant.local:8123"
news:
max_headlines: 5
Skills read these values at runtime via get_config(section, key, default):
from kenzy.llm.skills import get_config
url = get_config("home_assistant", "url", "http://homeassistant.local:8123")
Disabling skills¶
List skill function names under skills.disabled in llm.yaml to disable them without deleting the file:
skills:
disabled:
- get_stock_info
- yes_no_maybe
Secrets¶
Skills read API keys from environment variables (.env). Never hardcode secrets in skill files.
Included skills¶
See Built-in Skills for documentation on all skills that ship with Kenzy.
Writing a skill¶
See Writing Skills for a step-by-step guide.