---
sidebar_position: 2
---

# Home Automation

In this example we demonstrate how BondAI is able to use the *ShellTool* and *PythonREPLTool* to turn off a Kasa lamp with only a very simple prompt and no direction on how to solve the problem. Note that in this example BondAI is given no information and no additional prompting on how to go about turning off the Kasa lamp. It tries several different strategies including using the `python-kasa` library, the kasa CLI and ultimate ends up using the `pyHS100` library which was successful.

This implementation is obviously an inefficient home automation solution but it demonstrates BondAI's ability to attempt multiple strategies, resilience to error conditions and adaptibility. While it struggles with several of it's initial attempts, likely due to outdated knowledge of the library APIs, it keeps trying solutions until it finds a successful path and eventually turns the light off.

**Note** that a much more efficient solution could be built quite easily by implementing a KasaTool with this functionality implemented and exposed to BondAI as functions it can call.

First we will configure the environment variable for OpenAI.

```bash
export OPENAI_API_KEY=sk-XXXXXXXXXX
```

Next we will create an Agent with 2 tools. Note that these tools are considered **dangerous** as running arbitrary code and shell commands generated by an LLM can damage the host machine. It is highly recommended that these are only used from within a Docker environment.
- **PythonREPLTool** - Allows the Agent run Python scripts.
- **ShellTool** - Allows the Agent access to the shell. This is useful for installing libraries.

```python
from bondai import Agent
from bondai.tools import PythonREPLTool, ShellTool

task = (
  "I want you to turn off my Bedroom Lamp. "
  "It's a Kasa smart plug btw on the same network."
)

Agent(tools=[
  PythonREPLTool(), 
  ShellTool()
]).run(task)
```

## Example Output

```
Using the shell_tool tool
Thought: I'm installing the python-kasa library which will allow us to interact with the Kasa smart plug.
Arguments
command: pip install python-kasa
Output: Output: Requirement already satisfied: python-kasa in ./venv/lib/python3.11/site-packages (0.5.3)...


Using the python_repl tool
Thought: I'm executing the Python code to discover the Kasa smart plug and turn it off.
Arguments
code: from kasa import Discover import asyncio  async def turn_off_plug():     devices = await Discover...
An Error occured: There is no current event loop in thread 'Thread-2 (target)'.


Using the python_repl tool
Thought: I'm creating a new event loop, setting it as the current event loop, and then running the coroutine to turn off the Kasa smart plug.
Arguments
code: import asyncio from kasa import Discover  async def turn_off_plug():     devices = await Discover...
An Error occured: name 'Discover' is not defined


Using the python_repl tool
Thought: I'm trying to import the 'kasa' package to check if it's installed correctly.
Arguments
code: import kasa
result: {'kasa': <module 'kasa' from '/Users/kevin/Desktop/bondai/venv/lib/python3.11/site-packages/kasa/__init__.py'>}
stdout: 
stderr: 
Output: Result Variables: kasa: <module 'kasa' from '/Users/kevin/Desktop/bondai/venv/lib/python3.11/site...


Using the python_repl tool
Thought: I'm trying to import the 'Discover' module from the 'kasa' package to check if it's accessible.
Arguments
code: from kasa import Discover
result: {'Discover': <class 'kasa.discover.Discover'>}
stdout: 
stderr: 
Output: Result Variables: Discover: <class 'kasa.discover.Discover'> 


Using the python_repl tool
Thought: I'm discovering all the devices on the network and printing their aliases and IP addresses. This will help us identify the IP address of the 'Bedroom Lamp'.
Arguments
code: import asyncio from kasa import Discover, SmartPlug  async def discover_devices():     devices = ...
An Error occured: name 'Discover' is not defined


Using the python_repl tool
Thought: I'm trying to create an instance of the 'SmartPlug' class using a dummy IP address to check if the 'kasa' package is working correctly.
Arguments
code: from kasa import SmartPlug  plug = SmartPlug("192.168.1.1") plug
result: {'SmartPlug': <class 'kasa.smartplug.SmartPlug'>, 'plug': <DeviceType.Plug at 192.168.1.1 - update() needed>}
stdout: 
stderr: 
Output: Result Variables: SmartPlug: <class 'kasa.smartplug.SmartPlug'> plug: <DeviceType.Plug at 192.168...


Using the shell_tool tool
Thought: I'm using the 'kasa discover' command to list all Kasa devices on the network and their IP addresses. This will help us identify the IP address of the 'Bedroom Lamp' plug.
Arguments
command: kasa discover
Output: Output: Discovering devices on 255.255.255.255 for 3 seconds == Stairway Christmas Lights - HS103...


Using the python_repl tool
Thought: I'm executing the Python code to turn off the 'Bedroom Lamp' using the 'SmartPlug' class from the 'kasa' package.
Arguments
code: import asyncio from kasa import SmartPlug  async def turn_off_lamp():     plug = SmartPlug("192.1...
An Error occured: name 'SmartPlug' is not defined


Using the python_repl tool
Thought: I'm trying to import the 'SmartPlug' class from the 'kasa' package to check if it's accessible. If it's not accessible, we might need to reinstall the 'kasa' package or check the Python environment for issues.
Arguments
code: from kasa import SmartPlug SmartPlug
result: {'SmartPlug': <class 'kasa.smartplug.SmartPlug'>}
stdout: 
stderr: 
Output: Result Variables: SmartPlug: <class 'kasa.smartplug.SmartPlug'> 


Using the python_repl tool
Thought: I'm creating an instance of the 'SmartPlug' class using the IP address of the 'Bedroom Lamp' and calling its 'turn_off' method to turn off the lamp. I'm then returning the 'plug' object to check its state.
Arguments
code: from kasa import SmartPlug  plug = SmartPlug("192.168.4.29") plug.turn_off() plug
result: {'SmartPlug': <class 'kasa.smartplug.SmartPlug'>, 'plug': <DeviceType.Plug at 192.168.4.29 - update() needed>}
stdout: 
stderr: <string>:4: RuntimeWarning: coroutine 'SmartPlug.turn_off' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

Output: Errors: <string>:4: RuntimeWarning: coroutine 'SmartPlug.turn_off' was never awaited RuntimeWarni...


Using the python_repl tool
Thought: I'm executing the Python code to turn off the 'Bedroom Lamp' using the 'SmartPlug' class from the 'kasa' package. I'm creating a new event loop, setting it as the current event loop, and then running the coroutine to turn off the lamp.
Arguments
code: import asyncio from kasa import SmartPlug  async def turn_off_lamp():     plug = SmartPlug("192.1...
An Error occured: name 'SmartPlug' is not defined


Using the shell_tool tool
Thought: I'm uninstalling and then reinstalling the 'kasa' package to try to fix the issues with the 'SmartPlug' and 'Discover' classes.
Arguments
command: pip uninstall -y python-kasa && pip install python-kasa
Output: Errors: ERROR: Invalid requirement: '&&'  


Using the shell_tool tool
Thought: I'm uninstalling the 'kasa' package to try to fix the issues with the 'SmartPlug' and 'Discover' classes.
Arguments
command: pip uninstall -y python-kasa
Output: Output: Found existing installation: python-kasa 0.5.3 Uninstalling python-kasa-0.5.3:   Successf...


Using the shell_tool tool
Thought: I'm reinstalling the 'python-kasa' package to try to fix the issues with the 'SmartPlug' and 'Discover' classes.
Arguments
command: pip install python-kasa
Output: Output: Collecting python-kasa   Obtaining dependency information for python-kasa from https://fi...


Using the python_repl tool
Thought: I'm trying to import the 'SmartPlug' class from the 'kasa' package to check if it's accessible. If it's not accessible, we might need to check the Python environment for issues or consider using a different approach to turn off the 'Bedroom Lamp'.
Arguments
code: from kasa import SmartPlug SmartPlug
result: {'SmartPlug': <class 'kasa.smartplug.SmartPlug'>}
stdout: 
stderr: 
Output: Result Variables: SmartPlug: <class 'kasa.smartplug.SmartPlug'> 


Using the python_repl tool
Thought: I'm executing the Python code to turn off the 'Bedroom Lamp' using the 'SmartPlug' class from the 'kasa' package. I'm running the 'turn_off_lamp' coroutine in the default event loop to avoid the issues with the 'SmartPlug' class not being defined in a new event loop.
Arguments
code: import asyncio from kasa import SmartPlug  async def turn_off_lamp():     plug = SmartPlug("192.1...
An Error occured: name 'SmartPlug' is not defined


Using the shell_tool tool
Thought: I'm using the 'kasa' CLI command to turn off the 'Bedroom Lamp'. The '--plug' option specifies that we're interacting with a plug, the '--host' option specifies the IP address of the plug, and 'off' is the command to turn off the plug.
Arguments
command: kasa --plug --host 192.168.4.29 off
Output: Errors: Usage: kasa [OPTIONS] COMMAND [ARGS]... Try 'kasa --help' for help.  Error: No such optio...


Using the shell_tool tool
Thought: I'm installing the 'pyHS100' package which will allow us to interact with the Kasa smart plug.
Arguments
command: pip install pyHS100
Output: Output: Collecting pyHS100   Using cached pyHS100-0.3.5.2-py3-none-any.whl (31 kB) Requirement al...


Using the python_repl tool
Thought: I'm creating an instance of the 'SmartPlug' class from the 'pyHS100' package using the IP address of the 'Bedroom Lamp' and calling its 'turn_off' method to turn off the lamp. I'm then returning the 'plug' object to check its state.
Arguments
code: from pyHS100 import SmartPlug  plug = SmartPlug("192.168.4.29") plug.turn_off() plug
result: {'SmartPlug': <class 'pyHS100.smartplug.SmartPlug'>, 'plug': <SmartPlug at 192.168.4.29 (Bedroom Lamp), is_on: False - dev specific: {'LED state': True, 'On since': datetime.datetime(2023, 10, 1, 16, 44, 51, 838776)}>}
stdout: 
stderr: 
Output: Result Variables: SmartPlug: <class 'pyHS100.smartplug.SmartPlug'> plug: <SmartPlug at 192.168.4....


Using the final_answer tool
Arguments
input: The Bedroom Lamp has been successfully turned off.
Output: The Bedroom Lamp has been successfully turned off.
```