Skip to content

Repository files navigation

🦞 openclaw-dev

Alpha — Experimental template for a secure, hosted OpenClaw. No production-readiness guarantees. Review all configurations before deploying with sensitive data.

openclaw-dev architecture

Your own always-on AI assistant, running safely in the cloud and reachable from Microsoft Teams on your phone — not on your laptop. It runs on Azure Container Apps, talks to Azure OpenAI in Foundry Models with a Managed Identity (no API keys), and can offload risky tool execution to ephemeral, isolated sandboxes. Deploy it in one command — or just ask your AI agent to do it for you.

→ Jump to: Ask your agent · Deploy with devclaw · What can I do? · Advanced & reference

Deploy by asking your agent

This repo ships an AI agent skill, so any assistant that reads .github/copilot-instructions.md or AGENTS.md — GitHub Copilot Chat, Claude Code, Cursor, Codex, and friends — can set up and run everything for you in plain English. No need to memorize azd env vars or scroll the troubleshooting tables.

How to use it: clone the repo, open it in VS Code with GitHub Copilot Chat (or your preferred agent), and just ask. (Already cloned? Your agent picks the skill up automatically. To add it to another workspace, run npx skills add microsoft/openclaw-dev.) Try:

  • "Deploy OpenClaw to eastus2."
  • "Run tool execution in ephemeral sandboxes."
  • "Connect it to Microsoft Teams so I can use it from my phone."
  • "Why is devclaw up failing?"
  • "Stop it to save money, then start it again tomorrow."
  • "Restrict access to just my team."
  • "Tear it all down cleanly."

The assistant follows the playbook in skills/openclaw-dev/SKILL.md and the always-on rules in .github/copilot-instructions.md — using this repo's own scripts, env-var contract, region list, and error catalog instead of guessing. It always confirms with you before any destructive action (devclaw down, az ad app delete, RBAC removal). The skill follows the open Agent Skills format, so it works across many agents.

Deploy with devclaw

Prefer to drive it yourself? devclaw is a thin wrapper over the Azure Developer CLI (azd).

Prerequisites

  • Azure CLI + Azure Developer CLI
  • An Azure subscription (free) and tenant where you can create Entra ID app registrations
  • Either local Docker Desktop running or use the default remoteBuild: true in azure.yaml (no local Docker needed; ACR builds the image)
  • PowerShell 7+ (pwsh) if you're on Windows — needed by devclaw teams to build the Teams sideload zip

Deploy

git clone https://github.com/microsoft/openclaw-dev
cd openclaw-dev

# macOS/Linux/WSL
./devclaw up

# Windows (cmd or PowerShell)
.\devclaw.cmd up

On first run, azd prompts for a subscription, region, and environment name (a new resource group rg-<env-name> is created automatically). First deploy takes ~6 minutes (provision ~2 min + remote build & deploy ~3.5 min). Subsequent devclaw deploy runs take ~3-4 minutes for a remote build, or ~30s if only the entrypoint changed.

Verify

devclaw status   # Container state, FQDN, RG
devclaw logs     # Tail logs until you see `[gateway] starting HTTP server`

devclaw test only prints a hint that points you at the in-container console — it does not exercise the model end-to-end. The fastest real smoke test is the WebChat UI below.

Open the WebChat UI

After deployment, open the URL from devclaw status in your browser. If Entra ID Easy Auth is configured, you'll be prompted to sign in with your Microsoft account — after that the chat UI loads automatically with no further credentials needed.

CLI reference

devclaw up         Deploy OpenClaw to Azure (provision + build + deploy)
devclaw test       Print a hint to run the in-container smoke test
devclaw status     Show container status, FQDN, RG
devclaw logs       Stream live container logs
devclaw start      Scale to 1 replica (resume after stop)
devclaw stop       Scale to 0 replicas ($0, state preserved)
devclaw restart    Restart the active revision
devclaw deploy     Rebuild and deploy after code changes
devclaw exec-mode <inproc|sandbox>   Choose where tools run (apply with up)
devclaw teams      Set up Microsoft Teams integration (build sideload zip)
devclaw clone      (sandbox host) Boot another OpenClaw from the existing image
devclaw down       Delete ALL Azure resources and Entra app regs (nuke & pave)
devclaw login      Switch Azure account

Two commands you'll likely add later: devclaw exec-mode sandbox (offload tool execution to ephemeral sandboxes) and devclaw teams (add the Microsoft Teams channel).

What can I do with this?

Your own always-on AI assistant — accessible from Teams on your phone, the WebChat UI, or any OpenClaw channel.

  • "Summarize my meeting notes" — paste transcripts via Teams, get action items
  • "Draft a reply to this email" — send the thread, get a polished response
  • "Explain this error log" — paste a stack trace, get a diagnosis
  • "Review this PR" — paste a GitHub PR link, get code review feedback
  • "Write my weekly status" — the agent tracks your sessions

Advanced & reference

Everything above gets you deployed. The rest — why cloud instead of your laptop, the full architecture, the security model, Teams internals, and troubleshooting — is reference detail. For the complete env-var contract and error catalog, see skills/openclaw-dev/SKILL.md.

Why cloud instead of your laptop?

OpenClaw runs arbitrary code and can be deceived by prompt injection. Don't run it on your work machine. This template gives you an isolated, ephemeral container instead.

Your laptop ❌ This template ✅
Isolation Shares your credentials Ephemeral container — nothing to compromise
Credentials API keys on disk Managed identity — no keys anywhere
Nuke & pave Reinstall OS devclaw down && devclaw up (~6 min)
Always on Only when open Always on. devclaw stop = $0
Teams/mobile Only when laptop is on Always connected
Cost Your hardware ~$2-5/day running, $0 stopped

How it works

openclaw-dev is one cloud "brain" plus many disposable sandboxes:

  • The openclaw brain runs on Azure Container Apps and calls Azure OpenAI in Foundry Models (default gpt-5.4-mini) over a Managed IdentitydisableLocalAuth: true, so there are no keys to leak.
  • Entra ID Easy Auth forces a Microsoft sign-in (scoped to your tenant) before anyone reaches the brain.
  • Turn on sandbox execution (devclaw exec-mode sandbox) and every untrusted tool run — shell, code, browser — is handed to an ephemeral, isolated ACA Sandbox that's destroyed after the task, so the brain is never exposed to the code it runs.
  • Microsoft Teams is an optional channel so you can reach it from your phone.

The diagram at the top of this README shows the full topology (docs/architecture-sandbox.svg).

Execution modes

Mode Turn on with What runs where
In-process (default) tools run inside the brain container
Sandbox execution devclaw exec-mode sandboxdevclaw up tools run in throwaway ACA Sandboxes; the brain stays on ACA. Teams-compatible.
Sandbox host (experimental) azd env set USE_SANDBOX truedevclaw up the whole brain runs in a sandbox; no Teams.

Architecture

Resource Purpose
Azure Container Apps Hosts the OpenClaw "brain" gateway — public HTTPS on :18789, ephemeral container (host layer is swappable)
ACA Sandboxes (with EXECUTION_MODE=sandbox) Ephemeral, isolated nodes the brain offloads untrusted tool execution to, via the sandbox MCP server (src/sandbox_mcp/); each is destroyed after the task
Azure OpenAI in Foundry Models LLM backend via the OpenAI-compatible /openai/v1/ API — keyless (disableLocalAuth: true). Default: gpt-5.4-mini. (Scope to add Claude and other Foundry Models in the near future)
Azure Bot Service Bot Framework registration that fronts the Teams channel; routes inbound Teams activity to the container's /api/messages
Managed Identity Container → model auth via short-lived Entra ID tokens
Entra ID Easy Auth Microsoft login required before reaching the WebChat UI. /api/messages is excluded so Bot Framework can call in with its own JWT
Azure Files Persists credentials, workspace, sessions across restarts
Container Registry Stores the container image
Log Analytics Container and gateway logs

Inside the container there are three Node processes started by src/entrypoint.sh:

Process Port Role
gateway-proxy (src/gateway-proxy.mjs) 0.0.0.0:18789 (public) Terminates ACA ingress; routes POST /api/messages to the msteams plugin on :3978 and everything else to the OpenClaw gateway on :18788
OpenClaw gateway 127.0.0.1:18788 WebChat UI + WebSocket API; loads the msteams plugin which spawns the webhook on :3978
auth-proxy (src/auth-proxy.mjs) 127.0.0.1:18790 Injects a fresh Entra ID bearer token from DefaultAzureCredential on every forwarded request to AOAI
graph LR
    User["👤 User<br/>Browser / Mobile"]
    Teams["💬 Microsoft Teams<br/>Bot Framework"]
    EasyAuth["🔐 Entra ID Easy Auth<br/>Microsoft login gate<br/>(excludes /api/messages)"]
    subgraph Host["Host (Azure Container Apps today)"]
        Proxy["🔀 gateway-proxy<br/>:18789"]
        GW["🦞 OpenClaw Gateway<br/>:18788 · token auth"]
        MST["📥 @openclaw/msteams<br/>:3978 · /api/messages"]
        Auth["🔑 auth-proxy<br/>:18790 · injects MI bearer"]
    end
    AOAI["OpenAI-compatible model<br/>Microsoft Foundry Models / Azure OpenAI<br/>disableLocalAuth: true"]
    MI["Managed Identity<br/>Entra ID token"]
    AF["Azure Files<br/>credentials / workspace / sessions"]

    User -->|"HTTPS"| EasyAuth
    EasyAuth -->|"Authenticated"| Proxy
    Teams -->|"Bot Framework JWT"| Proxy
    Proxy -->|"/api/messages"| MST
    Proxy -->|"all other paths"| GW
    MST -->|"channel events"| GW
    GW -->|"OpenAI REST API"| Auth
    Auth -->|"Bearer token"| AOAI
    GW -.->|"Volume mount"| AF
    MI -.->|"RBAC: Cognitive Services User"| AOAI
Loading

SDKs and libraries

All dependencies are pinned at container build time (see src/Dockerfile).

SDK Version Role Notes
openclaw @latest (≥ 2026.5.26) The gateway runtime itself. Installed globally via npm install -g openclaw@latest Refreshed on every devclaw deploy (no version pin = always latest at build time)
@openclaw/msteams 2026.5.26 External OpenClaw plugin that owns the Teams channel: validates Bot Framework JWTs, parses activities, sends replies Installed via openclaw plugins install npm:@openclaw/msteams. Bundles its own copies of the Teams SDKs below
@microsoft/teams.api 2.0.11 (plugin-bundled) / 2.0.6 (Docker-side compat) Microsoft's current Teams SDK — REST client for the Bot Connector and Graph surfaces. Successor to the deprecated botbuilder line v2.0 line went GA in late 2024; roughly 12–18 months old (mid-2024 → May 2026)
@microsoft/teams.apps 2.0.11 (plugin-bundled) / 2.0.6 (Docker-side compat) High-level Teams app/agent framework — message routing, conversation state, adapters. Built on top of teams.api Same generation as teams.api; roughly 12–18 months old
@azure/identity 4.13.1 (plugin-bundled) / latest (auth-proxy) Used by the auth-proxy and the msteams plugin for DefaultAzureCredential and getBearerTokenProvider — fetches/caches/refreshes Entra ID tokens for AOAI and Bot Framework The 4.x line has been the active major since early 2024
http-proxy latest (auth-proxy install) Powers src/gateway-proxy.mjs — splits ingress by URL path Long-lived, stable library

How AOAI/Foundry is accessed: OpenClaw speaks the OpenAI-compatible REST API — the Chat Completions API (api: "openai-completions" in src/openclaw.json) at /openai/v1/chat/completions — directly. It does not depend on the official openai npm SDK or the older @azure/openai SDK. Requests flow gateway → auth-proxy → AOAI/Foundry; the auth-proxy attaches the MI bearer token at the wire level, so AOAI's disableLocalAuth: true works without API keys anywhere in the system. The auth-proxy is path-agnostic (it forwards req.url as-is), so the same proxy works for any OpenAI-compatible surface — chat completions, responses, embeddings, audio, images — if you swap the model adapter in openclaw.json.

How Teams is accessed: Inbound activities come in over HTTPS from Bot Framework to /api/messages. The @openclaw/msteams plugin validates the JWT and uses @microsoft/teams.api + @microsoft/teams.apps for everything from there — activity dispatch, replies, streaming, adaptive cards.

Security

Defense in depth

This template applies four independent layers of security. An attacker must defeat all of them to reach the AI backend:

Layer What it does
1. Entra ID Easy Auth Microsoft login required before any request reaches the container. Deployed automatically by devclaw up. Unauthenticated requests get a 401. Scoped to your tenant.
2. Gateway token A random per-container token is injected into the SPA at startup. Even an authenticated user cannot call the WebSocket API without it.
3. Managed Identity (no API keys) The container authenticates to the model endpoint via short-lived Entra ID tokens. disableLocalAuth: true means API keys don't even exist.
4. Ephemeral container State is on Azure Files; the container itself is disposable. devclaw down && devclaw up = clean slate in 6 minutes.

What to be aware of

  • Skills run arbitrary code — a malicious skill can access the managed identity. Only install trusted skills
  • Prompt injection — OpenClaw is susceptible. Nuke and repave if behavior changes
  • Container runs as root — add a non-root user for hardened deployments
  • Conversations flow through the model endpoint — don't paste highly sensitive data

Adding Entra ID Easy Auth

Easy Auth is configured automatically by devclaw up. The preprovision hook creates an Entra ID app registration, Bicep enables the auth config on the Container App, and the postprovision hook updates the redirect URI. No manual steps needed.

To restrict access to specific users or groups, update the app registration in the Azure Portal:

  1. Azure PortalEntra IDApp registrationsopenclaw-auth-<env>
  2. PropertiesAssignment required?Yes
  3. Enterprise applications → assign specific users/groups

Usage guidelines

  1. Don't paste confidential data — conversations flow through the configured model endpoint
  2. Don't install credential-heavy skills — no email, bank, or internal API skills
  3. Nuke and pave regularlydevclaw down && devclaw up if anything seems off
  4. Monitor logsdevclaw logs

Teams Setup

Connect OpenClaw to Microsoft Teams so you can chat with it from your phone.

Step 1: Enable Teams and build the app package

devclaw teams

This automatically:

  • Enables the Microsoft Teams channel on your Azure Bot (created by devclaw up)
  • Builds a sideloadable Teams app package (teams/openclaw-teams-app.zip)

Step 2: Install in Teams

  1. Teams → AppsManage your appsUpload a custom app
  2. Select teams/openclaw-teams-app.zip
  3. Add → DM the bot to test

How the Teams integration works

The Teams channel is handled by @openclaw/msteams — an external OpenClaw plugin installed at container-build time. It opens its own Express server on :3978 for the Bot Framework webhook (/api/messages). Because ACA exposes only a single public port, src/gateway-proxy.mjs listens on :18789 and routes /api/messages to the plugin and everything else to the OpenClaw gateway.

The plugin must be explicitly activated in src/openclaw.jsonchannels.msteams.enabled: true alone is not enough for external (non-bundled) plugins. The repo ships with the required block already in place:

"plugins": {
  "enabled": true,
  "allow": ["msteams"],
  "entries": { "msteams": { "enabled": true } }
}

If you ever see startup logs like [gateway] http server listening (N plugins: …) without msteams in the list, that block is missing or has been overwritten by a stale state file on Azure Files — the entrypoint restores src/openclaw.json from the canonical copy on every boot to prevent this drift.

Troubleshooting

Container won't start

Symptom Cause Fix
Activating for >2 min Token acquisition retrying Normal — allows up to 5 min. Check devclaw logs
ActivationFailed Container crashed Check Azure Portal → Container App → Log stream
Cannot find module '@buape/carbon' Cached broken Docker layer docker build --no-cache ./src then devclaw deploy
Config invalid: Unrecognized key Old config format Config must be {"gateway":{"mode":"local"}}
azd provision fails with Circular dependency detected on resource ... containerApps Old aca.bicep with existing self-reference Pull latest — the template now uses a containerImage parameter sourced from SERVICE_OPENCLAW_IMAGE_NAME

Auth issues

Symptom Cause Fix
401 invalid issuer RBAC not propagated Wait 5 min. Verify: az role assignment list --assignee <principal-id> --all
Token retries failing IMDS slow to initialize Normal — retries for 60s
disableLocalAuth blocks list-keys By design Expected — managed identity only

Gateway issues

Symptom Cause Fix
HTTP 500 on all routes Missing plugin deps Rebuild with docker build --no-cache ./src
pairing required Missing dangerouslyDisableDeviceAuth or trustedProxies in config Ensure src/openclaw.json has both settings (see repo)
Proxy headers detected from untrusted address Reverse proxy not trusted Add gateway.trustedProxies with your proxy CIDRs
WebChat shows login screen Token not injected Check entrypoint.sh runs successfully — see devclaw logs

Teams / msteams plugin issues

Symptom Cause Fix
POST /api/messages returns 502 msteams plugin didn't load → nothing listening on :3978 Confirm plugins.entries.msteams.enabled: true and plugins.allow: ["msteams"] are present in src/openclaw.json, then devclaw deploy. Look for [gateway] http server listening (… msteams …) in devclaw logs
POST /api/messages returns 401 with {"error":"Unauthorized"} Working as designed — Bot Framework JWT auth is rejecting the unsigned curl request None. Real Teams traffic carries a valid bearer token and is accepted
Diagnostic block in logs says @openclaw/msteams package: MISSING openclaw plugins install npm:@openclaw/msteams failed during the Docker build Rebuild with docker build --no-cache ./src and check the build output
Bot replies in WebChat but not in Teams Teams channel not enabled on Azure Bot, or sideload uses wrong botId Re-run devclaw teams (re-enables the channel and rebuilds the zip with the current bot app id)
[gateway] http server listening (7 plugins: browser, canvas, …) with no msteams Plugin activation rule not met (see "How the Teams integration works" above) Verify the plugins block in src/openclaw.json matches the canonical copy shipped in the repo

CLI issues

Symptom Cause Fix
az containerapp exec crashes Azure CLI Unicode bug (🦞) Use Azure Portal Console instead
az containerapp logs hangs SSL issue Use Azure Portal Log stream
azd up warns about permissions azd heuristic Safe to proceed. Or add User Access Administrator role

Testing the model endpoint directly

The deployed model is reachable via the OpenAI-compatible /openai/v1/ API:

TOKEN=$(az account get-access-token --resource "https://cognitiveservices.azure.com" --query accessToken -o tsv)
ENDPOINT=$(az cognitiveservices account list -g <rg> --query "[0].properties.endpoint" -o tsv)

curl -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"model":"gpt-5.4-mini","messages":[{"role":"user","content":"Hello"}]}' \
  "$ENDPOINT/openai/v1/chat/completions"

Clean up

devclaw down    # Destroys ALL resources

About

An OpenClaw agent hosted in the cloud for development, testing and single tenant use cases.

Resources

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages