Skip to content

ovos-workshop Documentation

Maturity: Mature ⬤⬤⬤⬤⬤

This package is long-lived, tested in production, and actively maintained. You can depend on it freely. It is rated by repository health, not by version number.

In a nutshell

A "skill" is an add-on that teaches OVOS to do one thing. It can tell the weather, set a timer, or play music. ovos-workshop is the starter kit that gives skill makers the building blocks, so they do not have to start from scratch. This page is for people who want to build their own skills. If you just use OVOS, you can skip it. See Skill Design Best Practices and the Glossary.

ovos-workshop provides all base classes, decorators, and helpers needed to write skills and applications for OpenVoiceOS.

Package: ovos-workshop Source: ovos_workshop/ Entry point group: opm.skill


Quick-Start: Minimal Skill in 20 Lines

from ovos_workshop.skills.ovos import OVOSSkill
from ovos_workshop.decorators import intent_handler


class HelloWorldSkill(OVOSSkill):
    """A minimal OVOS skill."""

    @intent_handler("hello.intent")
    def handle_hello(self, message):
        """Respond to a greeting."""
        self.speak_dialog("hello.response")


def create_skill():
    return HelloWorldSkill()

pyproject.toml entry point:

[project.entry-points."opm.skill"]
hello-world-skill = "hello_world_skill:HelloWorldSkill"

Full Class Hierarchy

OVOSSkill                             ovos_workshop/skills/ovos.py
├── ConversationalSkill               ovos_workshop/skills/converse.py
│   └── ActiveSkill                   ovos_workshop/skills/active.py
│       └── PassiveSkill              ovos_workshop/skills/passive.py
├── FallbackSkill                     ovos_workshop/skills/fallback.py
├── IdleDisplaySkill                  ovos_workshop/skills/idle_display_skill.py
├── OVOSCommonPlaybackSkill           ovos_workshop/skills/common_play.py
│   └── OVOSGameSkill                 ovos_workshop/skills/game_skill.py
│       └── ConversationalGameSkill   ovos_workshop/skills/game_skill.py
├── UniversalSkill                    ovos_workshop/skills/auto_translatable.py
│   └── UniversalFallback             ovos_workshop/skills/auto_translatable.py
└── OVOSAbstractApplication           ovos_workshop/app.py
    (not loaded by ovos-core itself - used by things that run alongside it,
     e.g. ovos-persona's PersonaService and the OCP media player)

# CommonQuery skills are plain OVOSSkills using the @common_query decorator

Document Key Classes Description
skill-classes.md OVOSSkill, FallbackSkill, OVOSCommonPlaybackSkill, ActiveSkill, OVOSGameSkill, ConversationalGameSkill, UniversalSkill, UniversalFallback Full class reference and when to use each
ovos-skill.md OVOSSkill Base class: intent registration, settings, resources, GUI, lifecycle
decorators.md intent_handler, killable_intent, ocp_search, layer_intent, skill_api_method All intent and utility decorators with source citations
skill-classes-reference.md#ovosabstractapplication OVOSAbstractApplication Skill-like app that runs without the intent service
skill-classes-reference.md#ovosgameskill OVOSGameSkill, ConversationalGameSkill OCP-integrated game loop with converse and auto-save
skill-classes-reference.md#universalskill UniversalSkill, UniversalFallback Auto-translate input/output for any language
skill-api.md SkillApi, skill_api_method Inter-skill RPC over the messagebus
skill-filesystem.md FileSystemAccess Sandboxed, XDG-compliant file storage for skills
resource-files.md SkillResources Locale, dialog, vocab, regex, and other resource files
skill-settings.md JsonStorage, PrivateSettings Skill settings: persistence, change callbacks, file watching
layers.md IntentLayers Enable/disable intent sets at runtime
skill-classes-reference.md#skill-launcher SkillLoader, PluginSkillLoader Loading skills as plugins or in standalone mode

Key Concepts

messagebus

OVOS uses a WebSocket publish/subscribe bus. Every message has three fields:

Message(
    msg_type="my.event.type",   # str — event name
    data={"key": "value"},      # dict — payload
    context={"session_id": ...} # dict — metadata
)

Skills interact with the bus through self.bus. Use self.add_event() to subscribe and self.bus.emit() to publish.

Settings

Skills store persistent configuration in $XDG_CONFIG_HOME/<base_folder>/skills/<skill_id>/settings.json (<base_folder> defaults to mycroft, see Skill Settings). Access via self.settings:

volume = self.settings.get("volume", 50)
self.settings["volume"] = 80

Settings changes are automatically persisted. OVOSAbstractApplication uses apps/ instead of skills/. See settings.md for change callbacks and file watching.

Resources

Resource files live in the skill's locale/ directory, organized by language tag:

locale/
  en-us/
    dialog/   # .dialog files - spoken responses
    vocab/    # .voc files - keyword lists for Adapt
    intent/   # .intent files - Padatious training phrases
    regex/    # .rx files - named-entity patterns

Access via self.speak_dialog("my.response"), self.get_response(), etc. See resource-files.md.

Nested or flat, both work

Resource lookup walks the whole language directory recursively (find_resource's os.walk). Both the nested-by-type layout shown above (locale/en-us/dialog/x.dialog) and a flat layout (locale/en-us/x.dialog) resolve correctly. Pick whichever layout keeps your skill's locale/ folder easier to navigate.

Intents

Two intent-matching pipeline plugins are supported:

  • Adapt: keyword-based, uses IntentBuilder and .voc files.

  • Padatious: ML phrase-matching, uses .intent files.

Register intents with @intent_handler or self.register_intent(). See decorators.md and ovos-skill.md.

Decorators

Decorators are the primary way to register skill behavior:

from ovos_workshop.decorators import intent_handler, fallback_handler, skill_api_method
from ovos_workshop.decorators.killable import killable_intent
from ovos_workshop.decorators.layers import enables_layer, layer_intent
from ovos_workshop.decorators.ocp import ocp_search, ocp_featured_media

See decorators.md for a complete reference with source citations.

Plugin Discovery

Skills are discovered via Python entry points in pyproject.toml:

[project.entry-points."opm.skill"]
my-skill-id = "my_skill.skill:MySkill"

ovos-plugin-manager scans the opm.skill group at runtime (via find_skill_plugins()) and loads the matching classes. It still accepts the older ovos.plugin.skill group name as a deprecated alias.


Source code: OpenVoiceOS/ovos-workshop.


Read next: OVOSSkill Related: Skill Metadata File · Skill Classes · Decorators · Skill Structure