Skills¶
Skills are Kenzy's abilities — checking the weather, reading the news, controlling your smart home, announcing to other rooms. A good set ships built in and works out of the box; the dashboard's Skills tab shows what's loaded and lets you switch any of them on or off with a click. If you can write a little Python, adding your own is a single small file.
Technically, each skill is an async Python function decorated with @skill. The language model calls skills as tools, deciding when to use each one from its docstring and type signature.
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 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:
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.