Telegram Bot for House Sitter Access: A Smart Alternative to Home Assistant Apps

This trick is the natural evolution of the house sitter access control package I covered in the previous article.

Managing house sitter access through Home Assistant is powerful, but it comes with a real-world friction. Your house sitter needs to install an app, create an account, understand a smart home interface, and maintain access credentials. If your Home Assistant isn’t publicly exposed, they’ll also need VPN configuration on their phone.

For temporary help like house sitters, cleaners, or pet sitters, this overhead often isn’t worth it.

Yes, you can always let them calls/message you when they arrive and you can open the gate for them, but what if you’re not available at that moment?

There’s a better way: give them a Telegram chatbot instead.

Why Telegram Over Home Assistant Apps?

The Home Assistant dashboard approach has some limitations:

  1. App Installation Required: House sitters must download the Home Assistant Companion App and configure it with the account you create for them
  2. Ongoing Maintenance: Even with kiosk mode and restricted permissions, you need to verify UI limitations haven’t changed with updates
  3. Network Complexity: Without public exposure, you need VPN setup on their device—hardly user-friendly for someone who just needs to feed your cat
  4. Learning Curve: Not everyone is comfortable navigating smart home interfaces, even simplified ones
  5. Account Management: Creating, maintaining, and eventually deleting user accounts adds administrative overhead

The Telegram Bot Approach Solves All of This:

Prerequisites

This article builds on an existing Home Assistant package for managing scheduled house sitter access. That package creates some Home Assistant helpers:

If you haven’t set this up yet, check out my previous article on automated house sitter access control first.

Architecture Overview

The bot works as a bridge between Telegram and your Home Assistant:

Telegram Message → N8N Workflow → AI Agent → Home Assistant Action
                        ↓
                  MongoDB Config
                        ↓
                   Data Cache

Key Components:

  1. Telegram Bot: Your house sitter chats with it naturally
  2. N8N: Orchestrates the workflow and handles authorization
  3. MongoDB: Stores authorized users and chat configurations (optional)
  4. AI Agent (Claude Sonnet 4.5): Interprets natural language and makes access decisions
  5. Data Cache: Avoids hammering Home Assistant with repeated state queries
  6. Home Assistant: Executes physical actions (unlock gate, open door, etc.)


Step 1: Setting Up the Telegram Bot

Talk to @BotFather on Telegram:

/newbot
Bot Name: Your Home Assistant Bot
Username: your_home_bot

Save the API token BotFather gives you.



Step 2: Configure MongoDB for Authorization

Create a MongoDB database with a bots collection. Store authorized users and chats:

{
  "bot": "<your_bot_name>",
  "allowed_users": [
    {
      "user_id": 123456789,
      "ruolo": "owner",
      "description": "Homeowner"
    },
    {
      "user_id": 234567890,
      "ruolo": "owner",
      "description": "Homeowner's wife"
    },
    {
      "user_id": 987654321,
      "ruolo": "sitter",
      "description": "House sitter"
    }
  ],
  "allowed_chats": [
    {
      "chat_id": -1001234567890,
      "description": "House sitting group chat"
    }
  ]
}

User Roles:

If you don’t have a MongoDB instance, you can hardcode allowed users/chats in the N8N workflow, but using a database allows dynamic updates without redeploying.



Step 3: Add the Cache Refresh Automation

This is the only extension needed in Home Assistant; you can add it to your existing housesitter package. Since the N8N workflow relies on cached data in order to reduce API calls, this automation notifies N8N whenever access settings change:

automation:
  - id: refresh_chatbot_cache
    alias: Notify n8n when House Sitter access settings change
    trigger:
      - trigger: state
        entity_id:
          - input_boolean.housesitter_access_enabled
          - input_datetime.next_housesitter_access
          - input_number.tempo_massimo_accesso_housesitter
    action:
      - action: rest_command.fetch_chatbot_cache_refresh
        data: {}

rest_command:
  fetch_chatbot_cache_refresh:
    url: "https://your-n8n-instance.com/webhook/YOUR-WEBHOOK-ID"
    method: GET
    headers:
      Content-Type: application/json
      n8n-API-Key: !secret n8n-API-Key
    timeout: 10

Replace the URL with your N8N webhook endpoint and secure it with an API key stored in Home Assistant secrets.



Step 4: Build the N8N Workflow

The workflow handles everything from message receipt to action execution. Let’s walk through each major section.

Phase 1: Authentication & Authorization

Telegram TriggerGet ConfigurationGet Auth InfoCheck Authorized Users

When a message arrives:

  1. Telegram Trigger receives the message with user and chat metadata
  2. Get Configuration fetches allowed users/chats from MongoDB: if you don’t have MongoDB, you can hardcode this in a JavaScript node or Set node.
  3. Get Auth Info (JavaScript code node) matches the sender against allowed users:
const inputchat = $('Telegram Trigger').first().json.message.chat;
const inputuser = $('Telegram Trigger').first().json.message.from;
const config = $input.first().json;

const allowedChat = config.allowed_chats.find(
  chat => Number(chat.chat_id) === Number(inputchat.id)
);

const allowedUser = config.allowed_users.find(
  user => Number(user.user_id) === Number(inputuser.id)
);

const authorized = !!allowedChat && !!allowedUser;

Both chat AND user must be authorized. If not, the bot sends an “unauthorized” message and optionally leaves the chat.


Phase 2: Smart Caching

To avoid repeated Home Assistant API calls (which consume resources and slow response time), we cache the access state:

The Webhook + Delete Cache flow (triggered by the Home Assistant automation above) clears the cache whenever access settings change, forcing a fresh fetch on the next message.

The Insert Cache node (Data Table) stores the combined state for future requests. Instead of a traditional key-value store, we use a single-row table with JSON columns. This allows us to store complex structured data (like the entire access state) without needing multiple nodes or complex logic to manage keys.

So the Data Table schema becomes really simple:

Data Table

and here is the content of the data field:

{"active":false,"planned_datetime":"2026-05-12 15:00:00","duration":"4","planned":true,"ongoing":false}

that is the {{ $json.toJsonString() }} generated by the Collect HA Data node, which combines all three Home Assistant entities into a single JSON structure.

Data tables are a powerful feature in n8n that allow you to store and manipulate structured data without needing an external database. This approach simplifies our architecture while still providing the benefits of caching. It has some limitations (e.g. no TTL or expiration logic), but for our use case, it works perfectly since we control when the cache is cleared via the webhook trigger from Home Assistant.

I could also use MongoDB for caching (since I already used it in this workflow), but I wanted to demonstrate how to leverage n8n’s built-in features to keep the architecture simple and self-contained.


Phase 3: Data Preparation

Collect HA DataPrepare Data for Agent

{
  "access": {
    "active": true,
    "planned_datetime": "2026-05-10 14:00:00",
    "duration": "4",
    "planned": false,
    "ongoing": true
  },
  "user": {
    "name": "Mary Poppins",
    "role": "sitter"
  },
  "message": "I'm here! Can you open the gate?"
}

Phase 4: AI Decision-Making

AI Agent (with Anthropic Claude Sonnet 4.5 + Structured Output Parser)

This is where the magic happens. The AI agent receives:

  1. System Prompt: Rules for authorization, natural language interpretation, and response formatting
  2. User Data: The JSON structure above containing access state, user info, and the message

The system prompt teaches the agent:

Authorization Logic:

Output Format:

{
  "messaggio": "Welcome Mary Poppins! I open the gate for you! 🏠",
  "azione_richiesta": "cancello",
  "valore": null
}

Possible actions (azione_richiesta):

The Structured Output Parser enforces JSON schema validation, ensuring the AI always returns parseable, consistent output. Here is the schema definition:

{
  "type": "object",
  "properties": {
    "messaggio": {
      "type": "string",
      "description": "The friendly message to send back to the user"
    },
    "azione_richiesta": {
      "type": ["string", "null"],
      "enum": ["cancello", "porta", "arrivederci", "durata", "appuntamento", null],
      "description": "The action to perform in Home Assistant, or null if no action is needed"
    },
    "valore": {
      "type": ["string", "null"],
      "description": "Additional value needed for certain actions (e.g., new duration or schedule), or null if not applicable"
    }
  },
  "required": ["messaggio", "azione_richiesta"]
}

Here is the fully optimized system prompt (translated into English, although in the workflow you will find it in Italian):

Manage home access via Telegram. Interpret user messages, verify permissions based on the user's role and the current access status, and prepare friendly responses with the actions to be executed.

## Input JSON
{
  "access": {
    "active": boolean,           // access enabled
    "planned_datetime": string,  // "YYYY-MM-DD HH:MM:SS"
    "duration": string,          // hours (e.g. "4")
    "planned": boolean,          // future appointment scheduled
    "ongoing": boolean           // access window currently open
  },
  "user": {
    "name": string,              // e.g. "Mary Poppins", "Moreno"
    "role": string               // "owner" or "sitter"
  },
  "message": string              // user message
}

## Authorization Rules

**Owner**:

* Can ALWAYS open the gate/door and leave
* Can set the duration (3-10 hours)
* Can schedule appointments (time between 7:00 and 20:00, future dates only)

**Sitter (house sitter)**:

* Can open the gate/door ONLY if `access.ongoing = true`
* If `ongoing = false`: politely deny access and explain when access will be available
* CANNOT modify the duration or appointments

## Required Output JSON

**Basic format:**

```json
{
  "messaggio": "response text",
  "azione_richiesta": "cancello" | "porta" | "arrivederci" | null
}
```

**Extended format (only when the owner is configuring settings):**

```json
{
  "messaggio": "response text",
  "azione_richiesta": "durata" | "appuntamento",
  "valore": "3-10" | "YYYY-MM-DD HH:MM:SS"
}
```

### Actions

* `"cancello"`: open the entrance gate
* `"porta"`: open the main door
* `"arrivederci"`: user is leaving (closing routine)
* `"durata"`: owner sets a new duration (value: `"3"` to `"10"`)
* `"appuntamento"`: owner sets a date/time (value: `"YYYY-MM-DD HH:MM:SS"`)
* `null`: no physical action

## Decision Logic

### Opening Requests (gate/door/arrival)

* **Owner**: always `"cancello"` or `"porta"`
* **Sitter + ongoing=true**: `"cancello"` or `"porta"`
* **Sitter + ongoing=false + planned=true**: `null`, explain the scheduled time
* **Sitter + ongoing=false + planned=false**: `null`, suggest contacting the owner

### Leaving Requests

* **Owner**: always `"arrivederci"`
* **Sitter + ongoing=true**: `"arrivederci"`
* **Sitter + ongoing=false**: `null`, say goodbye without performing any action

### Duration Configuration (owner only)

* Validate range 3-10 hours
* If valid: `"durata"` + `"valore": "N"`
* If invalid: `null`, explain the limits
* If requested by a sitter: `null`, politely deny

### Appointment Configuration (owner only)

* Parse natural language expressions: "tomorrow", "next Monday", "May 15 at 14:00"
* Validate: future date + time between 7:00 and 20:00
* If valid: `"appuntamento"` + `"valore": "YYYY-MM-DD HH:MM:SS"`
* If invalid: `null`, explain the error
* If requested by a sitter: `null`, politely deny

### Status Questions / Last Access

* Always `null` (informational only, no action)
* If `planned=false` and a past `planned_datetime` is available: show the last scheduled access
* Format dates in Italian style: DD/MM/YYYY alle HH:MM

## Style Rules

1. **Always use the user's name** in responses
2. **Friendly tone**: polite with the sitter, informal with the owner
3. **Appropriate emojis**: 🚪🏠✅⏰🔒👋😊⚠️📋
4. **Italian date format**: "05/05/2026 alle 15:00"
5. **Concise responses**: clear and direct
6. **Explain refusals**: always provide a reason when denying a request
7. **Valid JSON**: use `null`, not `"null"`

## Critical Examples

**1. Sitter arrives early:**

```json
// Input
{"access": {"ongoing": false, "planned": true, "planned_datetime": "2026-05-10 14:00:00"}, "user": {"name": "Mary Poppins", "role": "sitter"}, "message": "I'm here"}

// Output
{"messaggio": "Hi Mary Poppins! Your access is from 14:00. I can't open the gate right now ⏰", "azione_richiesta": null}
```

**2. Sitter during active window:**

```json
// Input
{"access": {"ongoing": true}, "user": {"name": "Mary Poppins", "role": "sitter"}, "message": "open the gate"}

// Output
{"messaggio": "Gate opened! ✅", "azione_richiesta": "cancello"}
```

**3. Owner sets duration:**

```json
// Input
{"user": {"name": "Moreno", "role": "owner"}, "message": "set duration to 6 hours"}

// Output
{"messaggio": "Perfect Moreno! Duration set to 6 hours ✅", "azione_richiesta": "durata", "valore": "6"}
```

**4. Owner schedules an appointment:**

```json
// Input (today is 10/05/2026)
{"user": {"name": "Moreno", "role": "owner"}, "message": "new appointment tomorrow at 14:30"}

// Output
{"messaggio": "Perfect Moreno! Appointment scheduled for 11/05/2026 at 14:30 ✅", "azione_richiesta": "appuntamento", "valore": "2026-05-11 14:30:00"}
```

**5. Last access request with past date:**

```json
// Input
{"access": {"planned": false, "planned_datetime": "2026-05-05 15:00:00", "duration": "4"}, "user": {"name": "Mary Poppins", "role": "sitter"}, "message": "when was the last time?"}

// Output
{"messaggio": "The last scheduled access was on 05/05/2026 at 15:00 with a duration of 4 hours 📋", "azione_richiesta": null}
```

**6. Sitter attempts configuration:**

```json
// Input
{"user": {"name": "Mary Poppins", "role": "sitter"}, "message": "can you set it to 5 hours?"}

// Output
{"messaggio": "Sorry Mary Poppins, only the owner can modify the duration 🔒", "azione_richiesta": null}
```

**7. Owner arrives:**

```json
// Input
{"user": {"name": "Moreno", "role": "owner"}, "message": "I'm here"}

// Output
{"messaggio": "Hi Moreno! Opening gate 🚪", "azione_richiesta": "cancello"}
```

## Important Validations

* **Duration**: integers only, from 3 to 10
* **Appointment time**: only between 7:00 and 20:00 (reject 6:59 or 20:01)
* **Appointment date**: future dates only (compare with NOW)
* **Output**: ALWAYS valid JSON, never free text
* **null vs "null"**: use `null` as a value, not a string


Phase 5: Action Execution

Send Reply + Switch → Home Assistant Actions

The workflow splits:

  1. Send Reply: Always sends the friendly message back to Telegram
  2. Switch: Routes to appropriate Home Assistant action based on azione_richiesta

Switch Outputs:


Real-World Conversation Examples

Sitter arrives during access window

Mary Poppins: Hi! I'm here 😊
Bot: Hi Mary Poppins! Opening gate. Welcome! 🏠
[Gate unlocks automatically]

Sitter arrives early

Mary Poppins: Hi! I'm here
Bot: Hi Mary Poppins! Your access is from 14:00. I can't open the gate right now ⏰

Owner remote access

Owner: Open the gate
Bot: Hi Moreno! Opening gate 🚪
[Gate unlocks immediately, regardless of schedule]

Owner schedules new access

Owner: New appointment tomorrow at 15:30
Bot: Perfect Moreno! Appointment scheduled for 11/05/2026 at 15:30 ✅
[Home Assistant schedule updated automatically]

Sitter tries to configure (Denied)

Mary Poppins: Can you set it to 6 hours?
Bot: Sorry Mary Poppins, only the owner can modify the duration 🔒

The power of natural language understanding

The AI agent handles linguistic variations without rigid command syntax:

Gate Opening Requests (all work):

Departure Notifications:

Schedule Queries:

The prompt includes critical examples showing the AI how to handle edge cases: early arrivals, late departures, communication-only messages, and configuration requests from unauthorized roles.

Security considerations

  1. Two-Factor Authorization: Both user ID and chat ID must be in the allow list
  2. Role-Based Access Control: Sitter role is tightly restricted to access windows
  3. API Key Protection: N8N webhook requires authentication header
  4. Telegram’s Security: Leverages Telegram’s built-in user authentication
  5. Audit Trail: N8N logs all interactions for review
  6. Easy Revocation: Remove user from MongoDB, access immediately revoked

Advantages over app-based access

AspectHome Assistant AppTelegram Bot
Setup Time10-20 minutes< 1 minute (just add to bot)
User TrainingRequiredNone (everyone knows messaging)
Network RequirementsPublic IP/Endpoint or VPNJust internet
MaintenanceOngoing (updates, permissions)Set and forget
FlexibilityLimited to defined UINatural language requests
RevocationDelete account, verify removalRemove from list

Extending the system

Multi-Language Support: Adjust the prompt to detect language and respond accordingly

Multiple House Sitters: Create separate MongoDB entries with different roles

Notification Integrations: Add N8N nodes to send notifications on specific actions (gate opened, schedule changed, etc.)

Access Logging: Store all interactions in a database for audit purposes

Photo Verification: Add Telegram photo handling to request/store entry/exit photos (also automatically triggered by Home Assistant cameras)

Location Verification: Use Telegram’s location sharing to confirm sitter is physically present (house sitter smartphone configuration required)



Step 5: Enjoy

The Telegram bot approach transforms house sitter access from a technical configuration challenge into a simple messaging experience. Your house sitter opens Telegram, says “I’m here,” and the gate opens. No app to install, no credentials to remember, no UI to navigate.

For homeowners, it means one less account to manage, one less potential security exposure, and one less thing to troubleshoot when your house sitter can’t figure out how to open the gate.

The combination of N8N’s workflow orchestration, Claude’s natural language understanding, and Telegram’s ubiquity creates a system that’s both more powerful and easier to use than traditional approaches. It’s smart home automation that doesn’t feel like dealing with technology—and that’s exactly what automation should be.

If this trick has been useful to you, keep scrolling down and consider supporting me by clicking that beautiful blue button! 😅