Always-on agents · Open source and free

OpenClaw from zero: gateway, Telegram, scheduled jobs and the security checklist

OpenClaw is the most-starred open-source agent on GitHub and the one most people mean when they say they run an always-on agent at home. This is how I would set it up so that it can do useful work and cannot reach anything it should not, with the install done for real in a container on 20 October 2026 and the steps that need a phone or a bot token described honestly as steps I did not complete.

In short

Install OpenClaw with its one-line installer or npm, run onboarding against a local Ollama model so there is no API bill, keep the gateway on loopback, connect Telegram with pairing on so strangers get a code and nothing else, add one scheduled job, and run openclaw security audit. Then read the ClawHub and ClawJacked findings before installing any skill.

Part of the Always-on agents series, post 16 of 33.

I have a rule for any software that holds credentials and runs unattended: it gets its own machine, or at least its own user, and it starts with the smallest set of permissions that still does the job. OpenClaw is a good test of that rule, because its defaults are mostly sensible and its ecosystem has had real problems. I compared it with the alternatives in the open-source comparison; this post is the setup, in the order I would do it.

What was testedI installed OpenClaw 2026.10.5 inside a fresh Node 26 container on 21 October 2026, after two failed attempts the day before that taught me the npm prefix lesson below, pointed it at a local Ollama model in a second container, ran onboarding, started the gateway, created a scheduled job and ran the security audit. I did not complete the Telegram step, because that needs a bot token tied to a real account, and I say so where it comes up. The commands and outputs below are from that run; the documentation quoted is as read on 20 October. The containers were removed afterwards.

Before you install: the machine, the user, the model

Three decisions first, and I make them before I type the install command. The machine: something that stays on and that you do not also use for banking. A Mac mini is the community favourite; a small Linux box or a free cloud VM works. The guides for a Mac and Linux in this series cover keeping it awake and keeping it alive. The user: OpenClaw's own installer sets up a user-level service, so create a dedicated account for it rather than running it as you. The model: start local and free. OpenClaw talks to Ollama natively, and a local model means the agent can explore your files without a single token leaving the machine. Switch to a hosted model later, for the decisions that need it, once you know what the agent can see.

Step 1: install

The documented route is the installer script, which detects the operating system, installs Node if it is missing and starts onboarding. OpenClaw wants Node 24.16 or newer and recommends 26. I used the npm route in my container because the Node was already there:

Terminal# the documented one-liner (macOS, Linux, WSL2)
curl -fsSL https://openclaw.ai/install.sh | bash

# or, with Node 24.16+ already installed (npm 11.16+ needs the allow-scripts flag).
# As a non-root agent user, give npm a prefix it can write to first:
export NPM_CONFIG_PREFIX="$HOME/.npm-global"; mkdir -p "$NPM_CONFIG_PREFIX"
export PATH="$NPM_CONFIG_PREFIX/bin:$PATH"
npm install -g openclaw@latest --allow-scripts=openclaw
openclaw --version
Output$ node --version; npm --version
v26.12.0
11.20.0
$ npm prefix -g
/home/node/.npm-global
$ openclaw --version
OpenClaw 2026.10.5 (1b58cb9)

The prefix lines are there because my first two attempts failed. Running npm install -g as the unprivileged node user, which is exactly the dedicated-account setup I recommend, hit a permissions error on the image's root-owned global directory, and npm's advice was to run it as root. The better answer is a prefix the agent's user owns. The official installer script handles this for you by keeping OpenClaw and Node under its own directory; if you take the npm route on a Linux box, you have to do it yourself, and the error message will not tell you that.

Two notes from the install page that matter later. On macOS the background service is a LaunchAgent; on Linux and WSL2 it is a systemd user service; on native Windows it is a Scheduled Task. And openclaw onboard --install-daemon both configures the agent and installs that service, so if you want to look before it runs at boot, onboard first and install the service separately with openclaw gateway install.

Step 2: a free local model through Ollama

Onboarding has an Ollama choice. The non-interactive form is what I used, because my Ollama was in another container on a private network rather than on localhost:

Terminal# on the Ollama side: pull a model that can call tools
ollama pull qwen2.5:0.5b        # tiny, for the test; the docs suggest gemma4

# on the OpenClaw side
export OLLAMA_API_KEY=ollama-local   # any value; local hosts need no real key
openclaw onboard --non-interactive --accept-risk --skip-health \
  --auth-choice ollama \
  --custom-base-url "http://ao-ollama:11434" \
  --custom-model-id "qwen2.5:0.5b"
openclaw models list --provider ollama
OutputDefault Ollama model: qwen2.5:0.5b
Workspace OK: ~/.openclaw/workspace
Sessions OK: ~/.openclaw/agents/main/sessions
Updated config: ~/.openclaw/openclaw.json
  Backup: ~/.openclaw/openclaw.json.bak

$ openclaw models list --provider ollama
Model                   Input   Ctx    Local  Auth  Tags
ollama/qwen2.5:0.5b     text    33k    no     yes   default

Two things worth noticing. Onboarding backs up the config before it writes it, which I appreciated more than I expected to. And the model shows as Local: no, because from OpenClaw's point of view my Ollama was on another host on the private network; on a single machine with Ollama on localhost it would say yes.

The one trap the docs call out, and which I would have fallen into: point OpenClaw at Ollama's native URL, not the OpenAI-compatible /v1 endpoint. The compatibility endpoint breaks tool calling and the model starts printing raw tool-call JSON as text. Also, automatic model discovery only considers models with tool support and at least 16K of context that are already loaded in memory, so name the model explicitly as I did above rather than expecting it to be found.

Step 3: the gateway, and where it listens

The gateway is the long-lived process: it holds the chat connections, runs the scheduler and serves a dashboard. The security page says that on a regular host install it binds to loopback, so nothing outside the machine can reach it, and that container images are the exception: they default to an exposed bind and must be paired with auth. I checked what mine did:

Terminalopenclaw gateway            # foreground, for a first look
openclaw gateway status
# dashboard: http://127.0.0.1:18789/
Output$ openclaw gateway status
Service: no supported service manager detected (diagnostic only, not the check target)
File logs: /tmp/openclaw/openclaw-2026-10-21.log
Gateway: bind=loopback (127.0.0.1), port=18789 (env/config)
Check target: ws://127.0.0.1:18789
Dashboard: http://127.0.0.1:18789/
Check note: Loopback-only gateway; only local clients can connect.
CLI version: 2026.10.5 (~/.npm-global/bin/openclaw)
Gateway version: 2026.10.5

$ grep listening /tmp/openclaw/openclaw-2026-10-21.log
[gateway] http server listening (14 plugins: anthropic, browser, canvas, cua-computer, device-pair, file-transfer, geolocation, github, linux-node, memory-core, ollama, openai, talk-voice, xai; 3.9s)

Loopback, as documented, and it took about four seconds to come up with fourteen plugins loaded, several of which I would rather were not there on a box that only needs Ollama and Telegram. The no supported service manager line is because my container has no systemd; on a real Linux install openclaw gateway install creates a user service, which is the always-on part, and the Linux guide in this series covers keeping it alive. openclaw doctor also suggested two environment variables for low-power hosts, a Node compile cache and OPENCLAW_NO_RESPAWN=1, which I would set on a Raspberry Pi.

If you ever need the dashboard from another device, the docs point at Tailscale or an SSH tunnel rather than opening the port, and they have an exposure runbook with a pre-flight and rollback checklist. I would not expose it at all. Everything I want from the agent arrives in a chat app.

Step 4: Telegram, with pairing on

This is the step I could not finish in a container, because a bot token is tied to a real Telegram account and I was not going to put mine in a test box. Here is exactly what the setup page says to do, and the part I care about is the default.

  1. Create the bot. Message @BotFather in Telegram, send /newbot, follow the prompts, copy the token. Check the handle is exactly @BotFather; impostors exist.
  2. Give OpenClaw the token. Either openclaw channels add --channel telegram --token <bot-token>, or the config block below, or the TELEGRAM_BOT_TOKEN environment variable. A tokenFile beats botToken, which beats the environment variable.
  3. Start the gateway and probe. openclaw gateway start, then openclaw channels status --probe.
  4. Approve yourself. Send the bot any message. It answers with a pairing code. Run openclaw pairing list telegram, then openclaw pairing approve telegram <CODE>. Codes expire after an hour.
~/.openclaw/openclaw.json{
  channels: {
    telegram: {
      enabled: true,
      botToken: "123:abc",          // from @BotFather; or tokenFile, or TELEGRAM_BOT_TOKEN
      dmPolicy: "pairing",          // unknown senders get a pairing code, nothing else
      groups: { "*": { requireMention: true } },
    },
  },
}

The default dmPolicy is pairing, which means an unknown sender gets a code and nothing else, and groups default to an allowlist behind a mention. Leave both alone. The permissions post in this series is largely about what happens when an agent answers whoever writes to it, and OpenClaw's defaults here are the right ones.

Step 5: one scheduled job

OpenClaw's scheduler is called Automations, with openclaw cron kept as an alias. It takes a cron expression or an interval, a timezone, and either a system event or a model-backed message. I created the smallest useful job, a morning note, and listed it:

Terminalopenclaw automations create "0 7 * * *" \
  --name "Morning note" \
  --message "Write one line: what is due today." \
  --session isolated \
  --tz Europe/London
openclaw automations list
Output{
  "id": "8044e91c-675d-4b79-b93a-5d2d2e1229ae",
  "name": "Morning note",
  "enabled": true,
  "schedule": { "kind": "cron", "expr": "0 7 * * *", "tz": "Europe/London" },
  "sessionTarget": "isolated",
  ...
}

$ openclaw automations list
ID        Declaration           Name                 Schedule                          Next     Status  Target    Delivery
5aad561b  heartbeat:main        Heartbeat (main)     every 30m                         in 28m   idle    main      not requested
de64bfec  memory-core:memory..  Memory Dreaming ...  cron 0 3 * * * (exact)            in 12h   idle    isolated  not requested
8044e91c  -                     Morning note         cron 0 7 * * * @ Europe/London..  in 15h   idle    isolated  announce -> last (last -> no route, will fail-closed)

The list is more interesting than my job. OpenClaw had already scheduled two automations of its own before I added one: a heartbeat on the main session every thirty minutes, and a nightly memory consolidation at three in the morning. And my job's delivery column says it will fail closed, because I had not connected a channel yet: with nowhere to announce the result, it refuses rather than dropping the output somewhere I would not see. That is the right default, and it is the reason the Telegram step belongs before the first scheduled job on a real install.

Two details from the schedules page worth knowing. Top-of-the-hour cron expressions are staggered by up to five minutes unless you add --exact, which is a kind choice for a shared machine and a surprise if you expected 07:00. And --session isolated gives each run a fresh session, which is what I want for a job: no memory of yesterday's run leaking into today's note. To deliver a job's result to a chat, add --announce --channel telegram --to <chat id>.

Step 6: run the audit, then read what researchers found

OpenClaw ships a one-command check of your own setup, and I ran it before anything else got installed:

Terminalopenclaw security audit
OutputOpenClaw security audit
Summary: 1 critical · 1 warn · 1 info

CRITICAL
models.small_params Small models require sandboxing and web tools disabled
  Small models (<=300B params) detected:
- ollama/qwen2.5:0.5b (0.5B) @ agents.defaults.model.primary (unsafe; sandbox=off; web=[web_search, web_fetch, browser])
Uncontrolled input tools allowed: web_search, web_fetch, browser.
  Fix: If you must use small models, disable web_search/web_fetch/browser globally or for each small model
  with tools.byProvider["provider/model"].deny=["group:web","browser"]; use agents.defaults.sandbox.mode="all"

WARN
gateway.trusted_proxies_missing Reverse proxy headers are not trusted

INFO
summary.attack_surface  groups: open=0, allowlist=0; tools.elevated: enabled; browser control: enabled
trust model: personal assistant (one trusted operator boundary), not hostile multi-tenant

The audit flagged me, and it was right. I had put a tiny model in charge and left it the web tools, which is the combination a prompt-injection attack wants: a model too small to notice it is being steered, reading pages an attacker can write. The fix it prints is the one I would apply before letting this agent read anything from the internet: deny the web group and the browser for the small model, or turn the sandbox on for everything. I did not apply it in the test container, so the output above is the honest before state. On the warn line, I would simply never put the dashboard behind a reverse proxy, so it stays a warning I accept.

Then the part that is not about your setup. Three findings from 2026 shaped how I treat OpenClaw, and I only list the ones I could trace to a primary report:

  • Malicious skills on ClawHub. Koi Security audited 2,857 skills on the marketplace and found 341 malicious ones, in a campaign they called ClawHavoc; 335 of them used fake prerequisites to install the Atomic Stealer macOS malware. Publishing to ClawHub needed only a week-old GitHub account. OpenClaw added skill reporting and auto-hiding in response (The Hacker News, 2 February 2026).
  • Skills that bypassed screening. Palo Alto Networks' Unit 42 reported five malicious skills that got past the marketplace's checks; OpenClaw removed them and banned the accounts.
  • ClawJacked. Oasis Security showed that JavaScript on any web page could open a WebSocket to the gateway on localhost and brute-force its password at hundreds of guesses a second, because the rate limiter exempted localhost and localhost pairings were auto-approved. Fixed in 2026.2.25, within a day of the report; the team rated it high severity.

There are larger numbers in circulation, including an audit figure in the hundreds of findings; I could not trace that one to a primary source, so I do not repeat it. What I take from the three above is simple: run a current version, install skills the way you would install a browser extension from a stranger, which is to say rarely and after reading the code, and keep the gateway where only you can reach it.

What I would not do

  • Run it as my own user on the machine I work on. It gets a user, or a machine.
  • Expose the gateway to the internet to reach the dashboard from my phone. Telegram is the phone interface.
  • Install a skill because the agent suggested it. Skills are code from strangers with the agent's permissions.
  • Give it a hosted model and my inbox on day one. Local model, read-only sources, one scheduled job, then earn the rest.

Sources

  1. OpenClaw docs, Install (accessed October 20, 2026)
  2. OpenClaw docs, Ollama setup (accessed October 20, 2026)
  3. OpenClaw docs, Ollama provider overview (accessed October 20, 2026)
  4. OpenClaw docs, Gateway security (accessed October 20, 2026)
  5. OpenClaw docs, Telegram setup (accessed October 20, 2026)
  6. OpenClaw docs, Automations: schedules (accessed October 20, 2026)
  7. OpenClaw docs, Automations: payloads (accessed October 20, 2026)
  8. The Hacker News, Researchers find 341 malicious ClawHub skills stealing data from OpenClaw users (accessed October 20, 2026)
  9. Oasis Security, OpenClaw vulnerability: website-to-local agent takeover (ClawJacked) (accessed October 20, 2026)
  10. Mallory (reporting Unit 42), Malicious OpenClaw skills bypassed ClawHub screening (accessed October 20, 2026)
  11. GitHub, openclaw/openclaw (accessed October 20, 2026)

Written by Lera Leonteva. Install and run outputs are from a Node 26 container on 21 October 2026; the Telegram step was not completed.

Frequently asked questions

Does OpenClaw need an API key or a subscription?

No. It talks to Ollama natively, so a free local model is enough to start, and any value works as the API key for a local host. Hosted providers are optional and I would add one only for the decisions a small model gets wrong.

Is the OpenClaw gateway exposed to the internet by default?

On a normal host install the documentation says it binds to loopback, so no. Container images are the exception and default to an exposed bind that must be paired with auth. Check with openclaw gateway status and openclaw security audit.

Is OpenClaw safe to run?

The core defaults are reasonable: loopback gateway, pairing for unknown senders, a built-in audit. The ecosystem is the risk. Researchers found 341 malicious skills on ClawHub in one audit and a localhost brute-force flaw fixed in version 2026.2.25. Keep it current and treat skills as untrusted code.

How do I schedule a recurring task in OpenClaw?

openclaw automations create with a cron expression, a name, a message or system event, a session mode and optionally a timezone. Add --announce --channel telegram --to to deliver the result to a chat. openclaw cron is an alias for the same commands.

Which machine should I run OpenClaw on?

One that stays on and that you do not use for anything sensitive. A Mac mini is the usual answer; a small Linux box or a free cloud VM is fine. Create a dedicated user for it either way.

Lera Leonteva
Lera Leonteva
CEO & Founder, Leo AI

Lera Leonteva is the founder and CEO of Leo AI, where she works on turning long-form footage into short-form video that earns attention on its own merits. She writes Video Scaling Strategies, taking one piece of content that worked and one that did not, and using what the market is doing to explain the gap.

The always-on agent I run for social video

Leo watches what your audience is responding to, picks a clip from footage you already have, edits it and books it on the calendar. Every hour, without being asked. It is the agent this whole series grew out of.

Keep going with the series

Every post in the Always-on agents series is on one page, newest first. If you would rather see the agent I run for social video, here it is.