Capabilities
The Capability Model¶
Every app accesses the world through capabilities, never direct tools. A capability is a human verb — with a chain of providers that try in order until one succeeds.
Human is always the final fallback. If every tool is offline, the system asks you.
16 Capabilities¶
| Capability | Purpose | Providers |
|---|---|---|
| think | Generate text responses. | ollama, openai, claude-cli, human |
| read | Read content from a path. | filesystem, markitdown, human |
| write | Write content to a path. | filesystem, human |
| search | Search for content. | grep, human |
| speak | Generate speech from text. | edge-tts → openai-tts → kokoro → xtts |
| listen | Transcribe audio to text. | openai-whisper → whisper (local) |
| draw | Generate images from text. | comfyui |
| animate | Generate a video clip from a prompt + optional reference image. | comfyui-ltx |
| model | Generate an articulated 3D model from a prompt. | robot-modeller (cadquery) |
| artifact | Generate a single-file HTML artifact from a prompt. | viz (standalone HTML) |
| see | Capture an image from a camera. | webcam → human |
| pronounce | Score a learner's pronunciation against a reference text. | wav2vec2 (local) |
| send | Deliver an outbound message to an external recipient. | email-smtp → human |
| browse | Drive a headless browser. | playwright (headless Chromium) |
| footage | Fetch a royalty-free stock video clip matching a search term. | pexels → pixabay → human |
| translate | Translate strings from a source language into a target language. | nllb-200 (local) → llm-translate |
Provider Chains¶
Providers are tried in priority order. Plugins inject high-priority providers at startup (enhancer pattern).
think: ollama → openai → claude-cli → human
read: filesystem → human
write: filesystem → human
search: grep → human
speak: voice-api (kokoro → edge-tts → xtts)
listen: voice-api (whisper)
draw: comfyui
If a plugin is absent, its provider simply isn't in the chain. Apps never know which provider answered — they just call self.think() or self.search().
Domain Routing¶
The think capability supports domain-specific routing. Different domains can use different models:
# Uses the domain-specific provider chain for 'code'
result = await self.think("Analyze this", domain="code")
# Default chain
result = await self.think("Summarize this article")
Domains are configured in emptyos.toml under [capabilities.think.domains].