02 · The Unified Mental Model
Given the three projects sketched in 01-nemoclaw-user-overview.md, the real question is: when I send a Telegram message to my NemoClaw assistant and it browses the web and calls an LLM, who is doing what at each step? This doc answers that. (For deeper per-project detail, see docs 05–07.)
The layered picture
┌───────────────────────────────────── YOUR HOST ─────────────────────────────────────┐
│ │
│ nemoclaw CLI (host) openshell CLI (host) │
│ │ │ │
│ │ orchestrates │ orchestrates │
│ ▼ ▼ │
│ ┌───────────────────────────────────────────────────────────────────────────┐ │
│ │ OpenShell gateway (host) │ │
│ │ credential store · inference proxy · policy engine · device auth │ │
│ │ │ │
│ │ ┌────────────────────── SANDBOX CONTAINER ─────────────────────────┐ │ │
│ │ │ │ │ │
│ │ │ OpenClaw Gateway (ws://127.0.0.1:18789) │ │ │
│ │ │ │ │ │ │
│ │ │ ├── Pi agent ── "tool call: browser.open(url)" │ │ │
│ │ │ ├── Channels ── Telegram / Discord / Slack clients │ │ │
│ │ │ ├── Tools ── browser, canvas, cron, skills │ │ │
│ │ │ └── NemoClaw plugin (adds /nemoclaw slash command) │ │ │
│ │ │ │ │ │
│ │ │ L7 proxy sidecar ◄── all egress flows through here │ │ │
│ │ │ Landlock (read‑only FS) · seccomp · netns · run_as_user=sandbox│ │ │
│ │ │ │ │ │
│ │ └──────────────────────────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────────┘
│ │
│ │
▼ ▼
Telegram/Slack/Discord APIs NVIDIA Endpoints / Anthropic /
(policy‑gated per host) OpenAI / local Ollama / vLLM
Three things to notice:
- OpenClaw's Gateway still exists — it's just now running inside a container at
127.0.0.1:18789of the sandbox, not your laptop. - Everything leaving the sandbox passes through the L7 proxy — no "secret side channel". If a policy doesn't cover it, it's blocked.
- The OpenShell gateway is the credential custodian. The sandbox never sees the real token for Telegram, or the real API key for NVIDIA. It sees placeholders, and the L7 proxy substitutes real values at egress.
End‑to‑end request flow
Let's trace a real message: "Hey, summarize the top Hacker News stories and DM me."
Step 1 — inbound on Telegram
Telegram delivers the message to api.telegram.org/bot<TOKEN>/getUpdates.
- A Telegram channel client runs inside the sandbox (it's just Node polling Telegram).
- Its egress hits the L7 proxy. The policy
telegram_botallowsGET /bot*/**from/usr/local/bin/node. The<TOKEN>in the URL is actually a placeholder; the proxy rewrites it to the real bot token stored in the OpenShell provider. - The response flows back in.
Step 2 — OpenClaw Gateway accepts the event
The Telegram client turns the update into an OpenClaw message event over the local WS (ws://127.0.0.1:18789). OpenClaw's session model routes it to the right session (DM pairing / allowlist still applies exactly as in standalone OpenClaw).
Step 3 — Pi agent runs
The Pi agent wants to think. It sends a chat completion to its model endpoint. Inside the NemoClaw sandbox that endpoint is rewritten to inference.local — or directly to integrate.api.nvidia.com.
- If it's
integrate.api.nvidia.com: the policynvidiaallowsPOST /v1/chat/completionsfrom/usr/local/bin/openclaw(seepolicies/openclaw-sandbox.yaml). The L7 proxy swaps the placeholderNVIDIA_API_KEYfor the real one. - If it's
inference.local: the sandbox L7 proxy routes to the OpenShell gateway's inference proxy, which forwards to whatever provideropenshell inference setpointed at — and from the agent's point of view the response is identical.
Step 4 — Agent calls the browser tool
The agent decides to call browser.open('https://news.ycombinator.com'). OpenClaw launches its managed Chromium.
- That Chromium runs inside the sandbox.
- The outbound fetch to
news.ycombinator.comhits the L7 proxy. Is there a policy for it? In the baseline — no. The request is blocked. - A blocked‑request event surfaces in
openshell term. You (the operator) see host, binary, method+path, and can approve it for the session. - If you approve, subsequent requests to that host flow. If you want it permanent, you put it into the YAML base or a preset and reapply — see doc 06.
Step 5 — Agent calls the NVIDIA LLM to summarize
Same path as step 3 — already allowed by the nvidia policy block, bound to /usr/local/bin/openclaw.
Step 6 — Reply to Telegram
OpenClaw sends a message via the Telegram adapter. POST /bot*/** is allowed by the telegram_bot preset; token substitution happens at the proxy; the user receives the DM.
Nothing you did inside the sandbox touched the real Telegram bot token or the real NVIDIA API key. That is the whole design.
Who owns which knob
| Thing you care about | Who owns it | How you change it |
|---|---|---|
| Which model you talk to | NemoClaw blueprint + OpenShell inference route | nemoclaw onboard (permanent) or openshell inference set (swap at runtime) |
| Which model provider credential is used | OpenShell provider | nemoclaw onboard collects it; openshell provider create manual fallback |
| Which hosts the agent can reach | NemoClaw base policy + presets + runtime approvals | Edit policies/openclaw-sandbox.yaml, add a preset, or approve in openshell term |
| Which HTTP methods/paths on those hosts | Same policy file | Add allow: { method: POST, path: "/..." } under the right network_policies block |
| Which binaries may use each policy | binaries: list on the policy |
Edit the YAML |
| Which sandbox image, digest, OpenClaw version | NemoClaw blueprint | Bump components.sandbox.image + top‑level digest: together, rerun onboard |
Per‑session OpenClaw tuning (/model, /thinking, /elevated on) |
Still OpenClaw | Slash commands, exactly as standalone |
| DM pairing, channel activation, group rules | Still OpenClaw | Gateway config / openclaw pairing approve / session slash commands |
| Filesystem layout (what's read‑only, what's writable) | NemoClaw policy filesystem_policy: |
Edit openclaw-sandbox.yaml → nemoclaw onboard to recreate (locked at creation) |
| Process user, seccomp | NemoClaw policy process: + OpenShell defaults |
Edit policy → rerun onboard (locked at creation) |
| Inference endpoint target | openshell inference set |
Hot‑reloadable at runtime |
Two invariants worth memorizing
- Static at creation vs hot‑reloadable. Filesystem and process policies are Landlock + seccomp — they cannot change on a running sandbox. Network and inference policies can change on a running sandbox. This is why some changes need
nemoclaw onboard(recreate) and some only needopenshell policy set. - The sandbox never holds real credentials. If a secret shows up in the sandbox env, either OpenShell injected it at runtime (OK, ephemeral), or it's a placeholder that the L7 proxy will substitute at egress (OK, never leaves the sandbox as plaintext). If you find yourself pasting a real key into the sandbox, you are fighting the model.
Next: 03-command-map.md — OpenClaw command → NemoClaw equivalent.