How to Run¶
There are several ways to get a S.T.A.R.K. assistant running, from "just call one function" to "build your own IO layer from scratch." This page covers them in order, from least to most control.
1. Defaults: run()¶
import anyio
from stark import run, CommandsManager
from stark.interfaces.vosk import VoskSpeechRecognizer
from stark.interfaces.silero import SileroSpeechSynthesizer
manager = CommandsManager()
# ... register commands ...
async def main():
recognizer = VoskSpeechRecognizer(model_url='...')
synthesizer = SileroSpeechSynthesizer(model_url='...')
await run(manager, recognizer, synthesizer)
anyio.run(main)
This is the one-call path used on the front page: run() builds a CommandsContext, wires up a VoiceAssistant, starts the microphone, and starts listening. For most assistants, this is all you need.
2. Custom Overrides¶
run()'s full signature:
async def run(
manager: CommandsManager,
speech_recognizer: SpeechRecognizer | list[SpeechRecognizer],
speech_synthesizer: SpeechSynthesizer,
processors: list[CommandsContextProcessor] | None = None,
localizer: Localizer | None = None,
):
processors: override the default pattern-matching pipeline. Omit it andrun()picksSearchProcessoralone, orCorrectionsProcessor+SearchProcessorif you pass alocalizer. See Custom Processors to add your own stage (NER, custom corrections, anything that needs to run before or after matching).localizer: enables multilingual parsing and pulls inCorrectionsProcessorby default. See Going Multilingual.speech_recognizeras a list: pass more than one recognizer (e.g. one per language) andrun()automatically wraps them in aSpeechRecognizerRelay, which compares per-word confidence across recognizers and assembles the best transcription. See Voice Assistant & Modes, Multi-Language Voice Setup.
3. Your Own Minimal Assembly Function¶
run() is opinionated: it always wires a VoiceAssistant, always starts a microphone. If you want a different IO source entirely, text in a terminal, no audio at all, skip run() and construct CommandsContext directly:
import sys
import anyio
from stark.core import CommandsContext, CommandsManager, Response
manager = CommandsManager()
@manager.new('hello')
async def hello_command() -> Response:
return Response('Hello, Stark!')
async def main():
async with anyio.create_task_group() as task_group:
context = CommandsContext(task_group=task_group, commands_manager=manager) # 1
context.delegate = TextDelegate() # 2
for line in sys.stdin: # 3
await context.process_string(line.strip())
anyio.run(main)
- No recognizer, no synthesizer, no microphone,
CommandsContextalone is the whole engine. TextDelegatejust needs to satisfyCommandsContextDelegate, a full, runnable implementation (print responses to the terminal) is in Custom IO & Context Delegate, A Minimal Custom Delegate.- Feed it text however you like, reading stdin here, but it could just as easily be a GUI event handler or an incoming HTTP request.
This is the no-audio, IO-less path, same mechanics as the voice version, minus speech entirely. Good for testing, debugging, or text-first interfaces.
4. The Full Default run(), for Reference¶
Want to see exactly what run() does internally, every task it starts, every delegate it wires, so you can replicate and extend it yourself? See Custom Run in Going Deeper; it walks through the real implementation line by line.
IO Options at a Glance¶
| Interface | Status | Where |
|---|---|---|
| VUI (voice) | Built-in | VoiceAssistant, via run(), see above |
| TUI (terminal text) | Built-in pattern | The minimal example above, or STARK_VOICE_CLI=1 on top of VoiceAssistant, see Voice Assistant & Modes |
| GUI | Not yet built | A great first contribution, see Custom IO & Context Delegate for the shape it would take, and Roadmap |
| API | Not yet built | Same as GUI, CommandsContextDelegate is the integration point |
5. Two Levels of Customization¶
Once you're running an assistant, there are two ways to hook into its behavior, depending on how much you need to change:
Simpler, subclass VoiceAssistant. Override a lifecycle method, call super(), add your logic. Good for things like updating a GUI alongside voice, or logging every response. See Voice Assistant & Modes, Customizing VA and Observing Events.
Full control, implement CommandsContextDelegate yourself. This is the protocol VoiceAssistant itself implements. Skip VoiceAssistant entirely and you control the whole IO loop, this is what step 3 above does. See Custom IO & Context Delegate for the protocol and worked example.
Building something with a custom IO layer? Share it in Discussions or contribute it to STARK-PLACE, GUI and API interfaces especially are open ground.