Deploy nanobot — a lightweight, self-hostable AI agent — on Render in one click. Get your own private agent with a browser chat UI, tools, and persistent memory.
nanobot-compressed.mp4
One Render web service running nanobot's gateway and its bundled WebUI. You chat with the agent from your browser; it can use tools (web search/fetch, filesystem, shell, MCP servers) and remembers past sessions on a persistent disk. Access is gated by a secret you set.
This is not a free deploy. Expect:
- Render Starter plan — ~$7/mo for the web service. Runs the core experience well; resource-intensive tasks (npm-based CLI Apps, image rendering) may need a larger plan — see Resource sizing under Deploy.
- 1 GB persistent disk — ~$0.25/mo for sessions and memory.
- Anthropic API usage — billed separately by Anthropic based on your agent's LLM calls.
-
Generate a
NANOBOT_WEB_TOKEN— this is the access secret for your WebUI. Create a strong random value with one of:openssl rand -hex 32 # or, if you don't have openssl: python3 -c "import secrets; print(secrets.token_hex(32))"
Copy the output — you'll paste it in step 3, and again when you first open the WebUI.
-
Click Deploy to Render above (or create a new Blueprint from your fork of this repo). Render reads
render.yamland prompts for the environment variables below. -
Enter your
ANTHROPIC_API_KEYand theNANOBOT_WEB_TOKENyou generated, then Apply. -
Wait for the service to reach Live, then open its
onrender.comURL. -
The WebUI shows an access prompt — paste the same
NANOBOT_WEB_TOKENto sign in. It's stored only in your browser. -
Send a message. You're talking to your agent.
The Starter plan comfortably runs the core experience — chat, web search/fetch, and persistent memory. Resource-intensive actions, such as installing npm-based CLI Apps or generating/rendering images, can briefly overwhelm the small instance: it may trigger a ~15s restart before recovering, or fail with No space left on device. To run these reliably, upgrade to a larger plan (e.g. Standard, 2 GB) under Settings → Instance Type, and/or increase your persistent disk to 5 GB or larger on the Disk page, in your Render dashboard.
Chat history persistence needs the disk, not a bigger plan. Sessions, memory, and the chat transcripts the WebUI renders all live on the persistent disk and survive deploys on the default Starter plan. Upgrading the instance type is only about RAM/CPU for heavy in-process work — it doesn't affect what's retained across deploys.
Some CLI Apps do work the chat service isn't sized for. Two limits to know:
- System dependencies aren't bundled. Installing a CLI App only runs its package-manager install (
npm install -g,pip, etc.) — it does not install system binaries likeffmpegor a headless browser (Chrome/Chromium). Apps that need those (for example, browser-based video renderers) won't run on the stock image, because the container runs as a non-root user and can'tapt installat runtime. Getting them working means baking those packages into theDockerfileand rebuilding. - In-process rendering is memory-hungry. A single headless-browser +
ffmpegrender can need 1–2 GB of RAM and multiple cores — more than Starter (512 MB) and often more than Standard (2 GB). Baking the dependencies in doesn't change this; the render process is what consumes the memory, so it will still hit the instance's cap.
Because this is a chat app, the recommended approach is not to grow the web service around occasional heavy renders. Instead, offload the render: use the app's own hosted/cloud render if it has one (for example, hyperframes' HeyGen cloud render — no local browser or ffmpeg needed), which keeps this service small and responsive. Only bake in the system dependencies and size up the plan if you specifically want rendering to happen in-process on this instance.
Example — set up HeyGen for the hyperframes CLI App. Some installable apps benefit from wiring up a hosted render backend. To render video with hyperframes without local Chrome/ffmpeg or a plan upgrade:
- Get a HeyGen API key (HeyGen renders are HeyGen-hosted and pay-per-credit).
- In the Render dashboard, add a
HEYGEN_API_KEYenvironment variable on the service (Settings → Environment), then let the service redeploy. - Ask the agent to render via
hyperframes cloud render …; it picks up the key from the environment.
Don't try hyperframes auth login — it's an interactive browser flow that can't complete inside a headless container. Use the HEYGEN_API_KEY env var instead. It isn't part of the base Blueprint, so add it only if you install hyperframes; the default deploy keeps just ANTHROPIC_API_KEY and NANOBOT_WEB_TOKEN.
Render prompts for these on deploy (both are sync: false, so no secret is ever committed):
| Variable | What it's for | Where to get it |
|---|---|---|
ANTHROPIC_API_KEY |
Powers the agent's LLM calls (default model anthropic/claude-opus-4-8). |
console.anthropic.com |
NANOBOT_WEB_TOKEN |
The access secret for the WebUI — the only gate on your public agent. | Generate it yourself (see step 1 above): openssl rand -hex 32 or python3 -c "import secrets; print(secrets.token_hex(32))". |
PORT is set for you in the Blueprint. Configuration lives in render-config.json; the two secrets are referenced there as ${ANTHROPIC_API_KEY} and ${NANOBOT_WEB_TOKEN} and resolved at startup.
A deployed nanobot is a capable agent: anyone who gets past NANOBOT_WEB_TOKEN can make it run shell commands and use tools inside its container, with your API key.
- This template ships hardened defaults (
restrictToWorkspace, self-modification writes off) and runs as a non-root user in an isolated container — but the token is still your primary defense. - Rotate the token (and your API key) if you suspect it leaked.
DEMO mode lets you host a public, no-auth demo of nanobot that anyone can chat with immediately — no NANOBOT_WEB_TOKEN prompt. It's what powers the hosted demo of this template.
Forks default to full auth. DEMO is false/unset unless you deliberately turn it on, so forking this template gives you the normal token-gated agent. Only set DEMO=true if you actually want an open, locked-down demo.
How it works. When DEMO=true, entrypoint.sh starts the gateway with render-demo-config.json instead of render-config.json. That config is locked down and the WebSocket channel runs in demo mode: the WebUI bootstrap skips the auth gate and mints short-lived anonymous tokens.
Session isolation. Because demo mode is unauthenticated, the anonymous token identifies no one — so the server treats it as no identity for session access. Each connection gets its own fresh chat (websocket:{uuid}, an unguessable id), and the session-browsing API is closed off: GET /api/sessions returns an empty list and every per-session read/delete route (/messages, /webui-thread, /file-preview, /automations, /delete) returns 403. Visitors can chat in their own session but cannot list, open, or delete anyone else's. Transcripts are still written to the persistent disk like any other session (they aren't ephemeral, and they accumulate across deploys), but each is keyed by an unguessable per-connection id and is never browsable or cross-accessible.
The lockdown (what the demo agent can and can't do). Chat + web search/fetch only. Everything else is off:
| Capability | Demo | Why |
|---|---|---|
| Web search / fetch | ✅ on | The one useful tool; SSRF-guarded (see below). |
| Shell / exec | ❌ off | Would expose env vars incl. your ANTHROPIC_API_KEY. |
| Filesystem (read/write/edit/find) | ❌ off | Would let it read files/config. |
Subagents (spawn) |
❌ off | New tools.subagent.enable flag, off in demo. |
| Cron / scheduled tasks | ❌ off | The agent is chat-only, no background work. |
| MCP servers | ❌ off | No external tool servers. |
Self-modification (my) |
❌ off | No runtime config changes. |
| Image generation | ❌ off | Cost control. |
The demo also sets restrictToWorkspace: true, webuiAllowLocalServiceAccess: false, and a cheaper default model (anthropic/claude-haiku-4-5) for cost defense-in-depth. The WebUI hides the settings / apps / automations / skills UI and shows a "Demo mode" banner.
Abuse / cost limits. Two env vars bound public usage (they apply only when DEMO=true):
| Variable | Default | Meaning |
|---|---|---|
DEMO_RATE_LIMIT_PER_MINUTE |
10 |
Max messages per minute, per WebSocket connection. |
DEMO_MAX_MESSAGES_PER_SESSION |
30 |
Max total messages per browser session. |
When a cap trips, the agent replies "Demo limit reached — deploy your own nanobot to keep chatting." and stops the turn.
Changing or disabling the limits on your fork. Set the env vars in render.yaml (or the Render dashboard → Environment). Raise them for a busier demo, or set either to 0 to disable that limit entirely (unlimited). They have no effect unless DEMO=true.
Security caveats.
- Web fetch is SSRF-guarded in nanobot core: requests to loopback, link-local (incl. cloud metadata
169.254.169.254), and RFC1918 private ranges are blocked, and every redirect hop is re-validated (nanobot/security/network.py). The demo adds nossrf_whitelist, so nothing is exempted. - With shell and filesystem tools off, the agent has no way to read the process environment or on-disk config, so the resolved
ANTHROPIC_API_KEY(in-memory only) is unreachable. - A demo is still a public LLM on your API key. Keep the limits sane, watch spend in the Anthropic console, and prefer the cheaper default model.
Edit render-config.json to change the model, provider, enabled tools, or channels, then redeploy. To use a different provider (OpenAI, etc.), swap the providers block and the model, and add the matching key to render.yaml as a sync: false env var.
For everything nanobot can do — chat channels (Telegram, Discord, Slack, …), MCP, skills, memory — see the upstream project: HKUDS/nanobot and its docs.
Logs live in the Render dashboard → your service → Logs. Start there for any failure.
- Deploy fails or the service won't go Live. The most common cause is a missing or mistyped
ANTHROPIC_API_KEY. Check it under the service's Environment tab, then trigger a redeploy. The logs also print[entrypoint] …lines showing how the container started. - Can't sign in to the WebUI. The token prompt expects the exact
NANOBOT_WEB_TOKENyou set on deploy — paste it verbatim (no surrounding spaces). If you've lost it, set a new value under Environment, redeploy, and sign in with the new one. - Chat connects but the agent doesn't respond. Usually an Anthropic-side issue — an invalid key or exhausted credit. The logs will show the provider error.
This repo is a fork of HKUDS/nanobot. To pull in new nanobot releases:
git remote add upstream https://github.com/HKUDS/nanobot.git # once
git fetch upstream
git merge upstream/main
git push # your forkRender auto-deploys the new commit. If you ever re-sync the Blueprint, confirm the service's Docker Command still routes through /usr/local/bin/entrypoint.sh — it's defined in render.yaml, so a clean sync preserves it.
Built on nanobot (MIT). This repo is a Render deploy template — see render.yaml.