ovos-spec-tools¶
Maturity: Beta ⬤⬤⬤◯◯
In real use but still settling. Watch releases for the occasional breaking change. Rated by repository health, not version.
In a nutshell
ovos-spec-tools is the one conformant implementation of the low-level primitives the Formal Specifications describe: template expansion, locale loading, dialog rendering, language matching, the message envelope, session handling, and the keyword-intent builder. Depend on it instead of hand-rolling these pieces again.
Formal specification
This library serves the OpenVoiceOS/architecture specs. See the spec index.
ovos-spec-tools is the single conformant implementation of the low-level primitives the specs describe. OVOS components used to reimplement template expansion, resource loading, and language matching in several places, and the copies drifted. Rather than reimplement (and re-introduce the bugs), depend on this package. It is dependency-light (the core has no dependencies) and tracks the specs clause-for-clause.
Primitives¶
| Primitive | Spec | What it does |
|---|---|---|
| Sentence-template expander | OVOS-INTENT-1 | Expands (a\|b) / [opt] / {slot} / <vocab> into the sentences it denotes |
| Locale resource loader | OVOS-INTENT-2 | Loads a skill's locale/ .intent / .dialog / .voc / .entity / .blacklist / .prompt files |
| Dialog & prompt renderer | OVOS-INTENT-2 §4 | Renders a spoken .dialog line or a .prompt with slot substitution |
| Language-tag matching | OVOS-INTENT-2 §2.2 (non-normative) | Picks the closest available BCP-47 language for a request |
| Message envelope | OVOS-MSG-1 | The {type, data, context} Message and its forward/reply/response derivations |
Session / SessionManager |
OVOS-SESSION-1 | The registered session-carrier field set with omission-not-null (de)serialization, plus a process-wide one-object-per-session_id registry that folds each incoming snapshot onto the live object and re-stamps forward/reply/response derivations with it |
| Context gating & decay | OVOS-CONTEXT-1 | Stateless helpers over the flat session.intent_context map: gate_satisfied/is_live/decrement/prune/enforce_cap for requires_context/excludes_context gating and decay, plus context_supplied_slots/context_slot_candidates for context-sourced slot fill |
IntentBuilder / Intent |
OVOS-INTENT-4 §5 | Adapt-free, plugin-agnostic keyword-intent definition (require/optionally/one_of/exclude/build()), mapping to the ovos.intent.register.keyword payload. voc_match matches an utterance against a .voc file. Source-compatible with the ovos-workshop classes it replaces |
SpecMessage |
multiple (PIPELINE-1, INTENT-4, STOP-1, PERSONA-1, FALLBACK-1, …) | An enum of every canonical ovos.* spec bus topic, plus MIGRATION_MAP/NamespaceTranslator: the legacy-to-ovos.* rename table the namespace bridge applies |
ovos-spec-lint |
OVOS-INTENT-1 / -2 | A linter that validates a locale/ folder against the resource-format specs, including .blacklist/.entity naming and slot-free constraints |
pip install --pre ovos-spec-tools # core — no dependencies (Python 3.10+)
pip install --pre ovos-spec-tools[langcodes] # adds smart language fallback
from ovos_spec_tools import expand, LocaleResources, render, render_prompt, closest_lang, Message
expand("(turn|switch) [the] light") # every sentence the template denotes
res = LocaleResources("my-skill/locale")
render(res.load_dialog("weather", "en-US"), # a spoken response
slots={"temperature": 21})
render_prompt("Summarize: {{text}}", # a .prompt string — whole text is
slots={"text": "..."}) # the prompt, {{name}} slots filled
# (PromptRenderer is the stateful form)
closest_lang("en-AU", ["pt-BR", "en-US"]) # -> 'en-US'
m = Message("ovos.intent.list", {}, {"source": "skill.id"})
m.response({"intents": ["..."]}).serialize() # -> the 'ovos.intent.list.response' JSON
ovos-spec-lint¶
Lint a skill's locale folder against the grammar and format specs:
ovos-spec-lint also takes a --spec-version flag, for linting a skill that targets an older
runtime. It answers "would a runtime at spec version N ignore any of these files?". Accepted
values are 0 to 3, and the default is 3.
The gate only ever emits a warning, never an error, and it fires when a resource role is newer than the version you name. Each role has the version it arrived in:
| Role | Requires |
|---|---|
.blacklist |
1 |
<name> (inline vocabulary reference) |
2 |
.prompt |
3 |
So --spec-version 0 warns about a .blacklist, and any value from 1 up says nothing about
it. Use the flag to check what an older deployment would silently drop, not to grade a
migration.
Session, intents, and the topic vocabulary¶
The session carrier, the keyword-intent builder, and the canonical topic vocabulary follow the same pattern: plain data plus stdlib-only helpers.
from ovos_spec_tools import IntentBuilder, Session, SpecMessage
# OVOS-SESSION-1 wire-shape carrier; SessionManager (in ovos_spec_tools.session)
# is the optional one-object-per-session_id registry built on top of it
session = Session(session_id="default", lang="en-US")
# OVOS-INTENT-4 §5 keyword-intent structure — adapt-free, source-compatible
# with the ovos-workshop IntentBuilder skills already import
intent = IntentBuilder("HelloIntent").require("Hello").build()
SpecMessage.SPEAK.value # -> 'ovos.utterance.speak', the spec-canonical topic name
ovos-spec-tools also owns the vocabulary of the legacy-to-ovos.* topic
rename: SpecMessage and MIGRATION_MAP, listed in the primitive table above.
The runtime bridge that applies that mapping on the wire lives in
ovos-bus-client. See Bus namespace migration
for that mechanism.
When to reach for it
Building an intent-matching pipeline plugin, a skill loader, a satellite, or any third-party
tool that touches OVOS templates, locale files, language selection, or the
bus envelope? Depend on ovos-spec-tools instead of hand-rolling. That is
exactly the drift the package exists to prevent. See also
Resource Files and Language Selection.
Read next: Specification Tooling · ovos-test-harness Related: Formal Specifications · Bus namespace migration · MessageBus Service