Skip to main content

Smart-home sandbox for AI agents. Bundles Home Assistant + MQTT + a fully simulated home + MCP server + a built-in CLI agent. Runs on a laptop or a Raspberry Pi.

Project description

sandcastle-sim

build pypi license python

Sandcastle Sim is a sandbox for smart-home AI agents. Real Home Assistant (HA) and Mosquitto run in Docker; the devices are simulated and publish via standard MQTT discovery. From HA's perspective there's no difference between a simulated bulb and a real one, so an agent that works here works against a real home unchanged.

For developers building smart-home agents. One command brings up the full stack. A built-in CLI agent gets you to a working demo in minutes, then drop in your own when you're ready to iterate on prompts, UX, and edge cases.

architecture

Contents

Install

Prerequisites

  • Docker with Compose v2
  • Python >= 3.10
  • Ollama for the built-in CLI agent. Optional if you're connecting your own MCP agent.
  • Tested on Mac (Apple Silicon), Linux, and Raspberry Pi 4/5. Windows not yet tested.

Setup

Create and activate a virtual environment so the install stays isolated from your system Python:

python -m venv .venv
source .venv/bin/activate

Then install:

pip install sandcastle-sim

Planning to make code changes? Install editable from a checkout instead (pip install -e .). See CONTRIBUTING.md for the full dev setup.

Quickstart

Start the stack

sandcastle-sim start

When the castle banner prints in the terminal, the stack is up. Open http://localhost:8766 and you should see the floor plan with every device laid out across six rooms. Click any device to flip it on or off, dim a light, or open a blind. That's the simulated home.

Drive it with natural language

In a separate terminal, pull the model and start Ollama:

ollama pull gemma4:e4b
ollama serve

Then back in your first terminal:

sandcastle-sim chat

A chat panel shows up listing the model and the available tools. Try prompts like:

turn off the kitchen counter light
set up movie night
what just happened in the home?

Each response prints the tool calls the agent fired. The floor plan reflects every change in real time, so you can watch the kitchen light go dark or the bedroom lamp shift colour as the prompts run.

Run sandcastle-sim --help for the full command list.

Using an AI coding agent (Claude Code, Codex, Copilot)? Read AGENTS.md first.

Eval suite

AI agents aren't deterministic. The same prompt can produce different outputs as you change the model, the system prompt, or the tool config. Small changes break things in non-obvious ways. The eval suite is how you catch that.

Save a snapshot of how the agent behaves right now:

sandcastle-sim eval --save-baseline

Make any change to your agent, then check what shifted:

sandcastle-sim eval --diff

The report leads with cases that used to pass and now fail. Cases that got noticeably slower show up too. Exit code is non-zero if anything regressed, so a coding agent running this in a loop can tell when its own changes broke something.

To see the diff workflow in action without writing any code, toggle off the agent's tool-routing optimisation for one run:

sandcastle-sim eval --no-routing --diff

Every case lands a bit slower (no failures), and the diff surfaces clean latency regressions. The flag scopes to that one command; the next eval reverts to defaults automatically.

evals/quick.yaml is the starter suite. Write your own to match your agent's acceptance bar.

Connect your agent

Point any MCP client at http://localhost:8765/mcp/:

from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

async with streamablehttp_client("http://localhost:8765/mcp/") as (r, w, _):
    async with ClientSession(r, w) as session:
        await session.initialize()
        tools = await session.list_tools()

docs/integrating-your-agent.md covers the Anthropic SDK, OpenAI SDK, and raw streamable-HTTP samples.

Customize

The kit is set up to be forkable. Topology defines what's in the home, the simulator brings devices to life, the MCP server exposes the contract your agent calls. Here's where each one lives.

  • src/sandcastle_sim/simulator/topology.py : the home's device list, areas, friendly names
  • src/sandcastle_sim/simulator/ : one module per device type (lights, locks, climate, sensors, vacuum, covers)
  • src/sandcastle_sim/mcp_server/server.py : MCP tool surface and HA integration
  • src/sandcastle_sim/agent/ : built-in Ollama + MCP agent (one-shot and chat REPL)
  • src/sandcastle_sim/data/gui/index.html : floor-plan GUI
  • evals/quick.yaml : starter eval suite for the regression net
  • pyproject.toml : runtime and dev deps; optional extras .[dev]

docs/extending-the-simulator.md for the deep dive.

Read more


Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sandcastle_sim-0.1.0.tar.gz (109.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sandcastle_sim-0.1.0-py3-none-any.whl (113.5 kB view details)

Uploaded Python 3

File details

Details for the file sandcastle_sim-0.1.0.tar.gz.

File metadata

  • Download URL: sandcastle_sim-0.1.0.tar.gz
  • Upload date:
  • Size: 109.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for sandcastle_sim-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a7b7fec3de196a5aeed12fbfd5834eba6f640ca23b285bbf33e71e69ccc489c8
MD5 09eb304410801fb1c74e6a439d8e8b49
BLAKE2b-256 08920bfa5d4e88ecaf3eb97cb5898e4cf2504c27a0b24f2d7421aab243953f12

See more details on using hashes here.

File details

Details for the file sandcastle_sim-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: sandcastle_sim-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 113.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for sandcastle_sim-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 751564a07416eca9ef575695ada36b31165280105a1a7cf975e198a6f1c6bc2e
MD5 21edf419c83718a46ee46ee5fb862709
BLAKE2b-256 66973ffab1faa7820e842859170a93ed7203e68727e51cca3c99576cd3c2ea6f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page