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: Abuelo
voice: coral
language_code: es
system_prompt: |
Eres un asistente de voz para una persona mayor ciega.
Hablas despacio, con calma. Nunca dices "no puedo".
Frases cortas. Palabras sencillas.
constraints: [never_say_no, echo_short_input, confirm_if_unclear]
skills:
audiobooks: { library: audiobooks }
radio: {}
news: { location: Villavicencio, CO }
search: { safesearch: moderate }
timers: {}
reminders: { timezone: America/Bogota }
telegram: { contacts: { ... } }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.