Compose yours in Python. Personas in YAML, skills as `pip`-installable packages. Real-time audio, self-hosted.
Declare tools. Handle calls. Return a ToolResult — optionally with an AudioStream, a PlaySound, or an InputClaim for full-duplex audio. The framework sequences the rest.
class LightsSkill:
name = "lights"
tools = [ToolDefinition(
name="set_lights",
description="Turn the lights on or off.",
parameters={"on": "boolean"},
)]
async def handle(self, tool, args):
await hue.set(args["on"])
return ToolResult(output='{"ok": true}')
# pyproject.toml
[project.entry-points."huxley.skills"]
lights = "my_package.skill:LightsSkill"The full plan lives in docs/roadmap.md. These four are the next visible moves.
# personas/abuelos/persona.yaml
name: AbuelOS
voice: alloy
language_code: es
system_prompt: |
Eres AbuelOS. Hablas despacio, con calma.
Nunca dices "no puedo". Siempre intentas ayudar.
constraints: [never_say_no, confirm_destructive]
skills:
audiobooks: { library: /media/audiolibros }
radio: {}
news: { location: Madrid, ES }
timers: {}
comms-telegram: { api_id: ..., api_hash: ... }Runs on OpenAI Realtime: roughly $0.06/min listening, $0.24/min speaking. You pay OpenAI directly — Huxley adds no markup. Idle is free.
$ git clone https://github.com/ma-r-s/Huxley.git && cd Huxley $ echo "HUXLEY_OPENAI_API_KEY=sk-..." > server/runtime/.env $ uv sync && cd server/runtime && uv run huxley # terminal 1 $ cd clients/pwa && bun install && bun dev # terminal 2 $ open http://localhost:5174 # hold the button, speak.