diff --git a/content/learning-paths/laptops-and-desktops/openclaw_continuum/1_architecture.md b/content/learning-paths/laptops-and-desktops/openclaw_continuum/1_architecture.md index 13ffb4c3c8..6744a47c58 100644 --- a/content/learning-paths/laptops-and-desktops/openclaw_continuum/1_architecture.md +++ b/content/learning-paths/laptops-and-desktops/openclaw_continuum/1_architecture.md @@ -1,24 +1,25 @@ --- -title: Understand the Architecture and Local Data Boundaries +title: Understand the architecture and local data boundaries +description: Map OpenClaw Arm Continuum's Telegram request flow, local data boundaries, and shared inference API across NVIDIA DGX Spark and CPU-only Arm systems. weight: 2 ### FIXED, DO NOT MODIFY layout: learningpathall --- -## Transition from Inference to an Assistant +## Transition from inference to an assistant Running a local LLM gives you private text generation, but not a complete assistant. You still need an interface for questions, saved information, document searches, and reminders. -In this Learning Path, you will deploy [OpenClaw Arm Continuum](https://github.com/odincodeshen/openclaw-arm-continuum) and use it from Telegram. You will save a household note, query a local document, search the web, and schedule a notification. Inference, embeddings, documents, vector memory, and task state remain on hardware you control. +In this Learning Path, you'll deploy [OpenClaw Arm Continuum](https://github.com/odincodeshen/openclaw-arm-continuum) and use it from Telegram. You'll save a household note, query a local document, search the web, and schedule a notification. Inference, embeddings, documents, vector memory, and task state remain on hardware that you control. -Telegram is the messaging interface for this tutorial. The runtime can support another platform through a gateway that translates its messages and events. +Telegram is the messaging interface. The runtime can support another platform through a gateway that translates its messages and events. -OpenClaw provides the foundation for the assistant. The reference runtime connects it to Telegram, local generation through vLLM or llama.cpp, Ollama embeddings, Qdrant memory, browser search, and scheduled tasks. It routes each request to the relevant local service or tool. +OpenClaw provides the foundation for the assistant. The reference runtime connects it to Telegram, local generation through vLLM or `llama.cpp`, Ollama embeddings, Qdrant memory, browser search, and scheduled tasks. It routes each request to the relevant local service or tool. ## Understand the data boundary -Local-first does not mean that every byte stays offline. Telegram and web search use external services, while the core AI data remains under your control. +Local-first doesn't mean that every byte stays offline. Telegram and web search use external services, while the core AI data remains under your control. | Data or operation | Location | External interaction | |---|---|---| @@ -30,13 +31,13 @@ Local-first does not mean that every byte stays offline. Telegram and web search | External data lookup | Local skill | Public data service selected by the skill | | Browser search | Local Playwright worker | Search engine and selected public pages | -The runtime does not use a public cloud LLM API. Telegram transports bot messages, and browser searches send requests to external websites. +The runtime doesn't use a public cloud LLM API. Telegram transports bot messages, and browser searches send requests to external websites. {{% notice Note %}} -This Learning Path uses synthetic or public data. Do not enter real personal, household, or organizational information. If the host already contains personal runtime data, set the environment variables in the next chapter. +Don't enter real personal, household, or organizational information. Instead, use synthetic or public data. If the host already contains personal runtime data, set environment variables by following the instructions in [Configure and start the OpenClaw runtime on DGX Spark](/learning-paths/laptops-and-desktops/openclaw_continuum/3_dgx_runtime_deploy/). {{% /notice %}} -## Trace the Application Request Path +## Trace the application request path The architecture shows how Telegram requests reach local services and persistent data: @@ -53,6 +54,10 @@ Cron schedule Slash commands follow fixed routes. For example, `/search` always selects browser search, while a plain-language weather question selects the weather skill. +{{% notice Note %}} +The runtime uses a text-first architecture, fixed skill routes, and one local LLM endpoint. This Learning Path doesn't cover multi-model routing, multi-agent handoffs, or hardware benchmarking. +{{% /notice %}} + ## Understand the shared API contract across Arm platforms The same workflow uses an inference engine suited to each platform: @@ -60,7 +65,7 @@ The same workflow uses an inference engine suited to each platform: | Platform | Inference engine | |---|---| | NVIDIA DGX Spark | vLLM server | -| Radxa Orion O6 | llama.cpp server | +| Radxa Orion O6 | `llama.cpp` server | Both expose an OpenAI-compatible chat-completions API, so only the configured endpoint and model name change. @@ -68,4 +73,4 @@ Both expose an OpenAI-compatible chat-completions API, so only the configured en You now understand the runtime components, data boundary, and shared inference API. -Next, you will deploy the baseline runtime on NVIDIA DGX Spark. +Next, you'll prepare the NVIDIA DGX Spark and configure Ollama and Qdrant. diff --git a/content/learning-paths/laptops-and-desktops/openclaw_continuum/2_dgx_deploy.md b/content/learning-paths/laptops-and-desktops/openclaw_continuum/2_dgx_deploy.md index 1381718f59..82838a2014 100644 --- a/content/learning-paths/laptops-and-desktops/openclaw_continuum/2_dgx_deploy.md +++ b/content/learning-paths/laptops-and-desktops/openclaw_continuum/2_dgx_deploy.md @@ -1,14 +1,13 @@ --- -title: Deploy an OpenClaw-based Reference Runtime with vLLM on DGX Spark +title: Prepare the DGX Spark host and local services +description: Prepare an NVIDIA DGX Spark host with Docker, Ollama embeddings, Qdrant vector storage, and the pinned OpenClaw Arm Continuum repository. weight: 3 ### FIXED, DO NOT MODIFY layout: learningpathall --- -## Prepare the DGX Spark Host Environment - -DGX Spark needs Docker Engine, the Docker Compose plugin, the NVIDIA driver, and NVIDIA Container Toolkit for this section. The repository supplies the runtime and vLLM container, but you will install Ollama and Qdrant separately. +## Prepare the DGX Spark host environment Confirm that the Arm CPU and NVIDIA GPU are visible: @@ -24,7 +23,7 @@ aarch64 ``` {{% notice Note %}} -This Learning Path uses Docker Engine and Docker Compose to run its services. If Docker is not installed on your DGX Spark, follow the [Install Docker Engine](https://learn.arm.com/install-guides/docker/docker-engine/) guide before continuing. +You'll use Docker Engine and Docker Compose to run services on your DGX Spark. For Docker installation steps, see the [Docker Engine install guide](https://learn.arm.com/install-guides/docker/docker-engine/). {{% /notice %}} Confirm Docker GPU access: @@ -33,11 +32,13 @@ Confirm Docker GPU access: docker run --rm --gpus all ubuntu nvidia-smi ``` -You do not need to install the vLLM Python package or start a vLLM server directly on the DGX Spark host. The project's `compose.yaml` pulls a container image that already includes vLLM and starts the local inference server for you. The NVIDIA driver and NVIDIA Container Toolkit are still required so that this container can access the GPU. +Install the NVIDIA driver and NVIDIA Container Toolkit so that this container can access the GPU. + +You don't need to install the vLLM Python package or start a vLLM server directly on the DGX Spark host. The project's `compose.yaml` pulls a container image that already includes vLLM and starts the local inference server for you. -## Configure Ollama for Local Embeddings +## Configure Ollama for local embeddings -Unlike vLLM, Ollama is not included as a service in the project's `compose.yaml`. Install and run Ollama separately on the DGX Spark host before starting the reference runtime. +Unlike vLLM, Ollama isn't included as a service in the project's `compose.yaml`. Install and run Ollama separately on the DGX Spark host before starting the reference runtime. Install Ollama using the [official Linux installer](https://docs.ollama.com/linux): @@ -45,7 +46,7 @@ Install Ollama using the [official Linux installer](https://docs.ollama.com/linu curl -fsSL https://ollama.com/install.sh | sh ``` -The project containers connect to Ollama through the Docker host gateway. Create a systemd override that configures Ollama to listen on the host interfaces: +The project containers connect to Ollama through the Docker host gateway. Create a `systemd` override that configures Ollama to listen on the host interfaces: ```bash sudo install -d -m 0755 /etc/systemd/system/ollama.service.d @@ -67,7 +68,7 @@ The output should include the override: Environment="OLLAMA_HOST=0.0.0.0:11434" ``` -Reload systemd and restart Ollama: +Reload `systemd` and restart Ollama: ```bash sudo systemctl daemon-reload @@ -75,7 +76,7 @@ sudo systemctl enable --now ollama sudo systemctl restart ollama ``` -Pull the embedding model used by this Learning Path: +Pull the embedding model that you'll use: ```bash ollama pull nomic-embed-text @@ -87,7 +88,7 @@ Confirm that Ollama lists the model: curl http://127.0.0.1:11434/api/tags ``` -The response should include these fields: +The output is similar to: ```output { @@ -100,7 +101,7 @@ The response should include these fields: } ``` -## Start Qdrant for Persistent Vector Storage +## Start Qdrant for persistent vector storage Create a Docker volume so that vector data remains available when the Qdrant container is replaced: @@ -132,7 +133,7 @@ Confirm that the Qdrant API responds: curl http://127.0.0.1:6333/collections ``` -Before the reference runtime creates its collections, the response is similar to: +The output is similar to: ```output { @@ -141,15 +142,15 @@ Before the reference runtime creates its collections, the response is similar to } ``` -The empty list is expected. The runtime creates collections when you save or ingest content. +The empty list is expected at this stage before the reference runtime creates its collections. The runtime creates collections when you save or ingest content. {{% notice Warning %}} The project containers need access to Ollama and Qdrant. Restrict ports `11434`, `6333`, and `6334` to the host and its Docker networks. {{% /notice %}} -## Clone the Reference Repository +## Clone the reference repository -Clone the repository and check out the release used by this Learning Path: +Clone the repository and check out the release that you'll use: ```bash git clone https://github.com/odincodeshen/openclaw-arm-continuum.git @@ -159,257 +160,8 @@ git checkout v1.2 The tag fixes the tutorial source version. Unversioned container images and model artifacts can still change when downloaded. -## Configure the Telegram bot environment variables - -You need a Telegram account, a bot token, and the numeric chat ID for the account that will use the bot. Create a Telegram account if you do not already have one. You can use the Telegram desktop, mobile, or web client for the following steps. - -To create a bot and obtain its token: - -1. Open Telegram and start a chat with **BotFather**. -2. Send the following command: - - ```text - /newbot - ``` - -3. Follow BotFather's prompts to name the bot and choose a username. -4. Copy the HTTP API token that BotFather returns. You will add it to the `.env` file later. - -See the official [Telegram Bot tutorial](https://core.telegram.org/bots/tutorial) for more information about creating and managing bots. - -Next, obtain the chat ID for your Telegram account: - -1. Open a chat with the bot that you created and send a test message, such as `Hello`. This creates an update that the Telegram Bot API can return. -2. Open a terminal on your local machine and query the updates. Replace `` with the HTTP API token from BotFather: - - ```bash - curl "https://api.telegram.org/bot/getUpdates" - ``` - -The output is similar to: - -```output -{ - "ok": true, - "result": [ - { - "update_id": (...), - "message": { - (...) - }, - "chat": { - (...) - }, - "date": (...), - "text": "Hello" - } - } - ] -} -``` - -Copy the `message.chat.id` value. You will use this value for `` in the `.env` file. If the `result` array is empty, send another message to the bot and run the command again. - -Copy the DGX Spark environment template: - -```bash -cp .env.example .env -``` - -Keep `.env` in the `openclaw-arm-continuum` repository root, alongside `.env.example`. The deployment command reads it from this location. - - -Then, generate a Gateway token: - -```bash -openssl rand -hex 32 -``` - - -Edit `.env` and set the four private values: - -```text -OPENCLAW_TELEGRAM_BOT_TOKEN= -OPENCLAW_TELEGRAM_ALLOWED_CHAT_IDS= -OPENCLAW_CRON_CHAT_IDS= -OPENCLAW_GATEWAY_TOKEN= -``` - -Set `OPENCLAW_CRON_TIMEZONE` to your local [IANA timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Scheduled jobs use UTC when this setting is omitted: - -```text -OPENCLAW_CRON_TIMEZONE= -``` - -For example, use `Europe/London`, `America/New_York`, or `Asia/Singapore`. Weather questions in this Learning Path name their location explicitly, so you do not need to configure `OPENCLAW_DEFAULT_WEATHER_LOCATION`. - -{{% notice Note %}} -Do not share your Telegram bot token or chat ID with anyone, and do not include them in screenshots, logs, or public repositories. -{{% /notice %}} - -Only allowlisted chat IDs can send commands to this runtime. - -The main tutorial flow uses the default personal collections: - -```text -personal_tracker_memory -personal_knowledge_base -``` - -You do not need to add collection settings to `.env` for this default path. Use only the synthetic data provided in the exercises. - -{{% notice Note %}} -If this host already contains personal runtime data, or if you are preparing a public demonstration, add the following optional settings to `.env` to isolate the tutorial data: - -```text -OPENCLAW_TRACKER_COLLECTION=demo_tracker_memory -OPENCLAW_KNOWLEDGE_COLLECTION=demo_knowledge_base -OPENCLAW_RUNTIME_LABEL=DGX Spark Demo -``` - -If you choose this option, replace the `personal_*` collection names in later verification commands with the corresponding `demo_*` names. -{{% /notice %}} - -The DGX model used in this Learning Path is text-first. Disable experimental vision routing: - -```text -OPENCLAW_VISION_ENABLED=false -``` - - -## Initialize and Start the Runtime Stack - -The Gateway runs as user ID `1000` inside its container and needs write access to its persistent state directory. Prepare the directory before starting the stack: - -```bash -mkdir -p gateway-data/state -sudo chown -R 1000:1000 gateway-data -sudo chmod -R u+rwX gateway-data -``` - -Start the complete DGX Spark stack: - -```bash -docker compose --env-file .env -f compose.yaml up -d -``` - -The first start takes longer than subsequent starts because vLLM downloads the approximately 30 GiB Qwen model before loading it. The download time depends on your network connection and can make the initial startup longer. Subsequent starts use the cached model. A running container does not mean that its API is ready. - -Check service status and API readiness: - -```bash -docker compose --env-file .env -f compose.yaml ps -a -docker logs --tail 80 openclaw-vllm -docker logs --tail 80 openclaw-gateway -docker logs --tail 80 openclaw-telegram -docker logs --tail 80 openclaw-cron -``` - -Follow the vLLM log during the first startup: - -```bash -docker logs -f openclaw-vllm -``` - -Wait for `Application startup complete`. Press `Ctrl+C` to leave the log view without stopping the container. - -Confirm that the model API is ready: - -```bash -curl http://127.0.0.1:8000/v1/models -``` - -Verify that a project container can reach both host services through the Docker host gateway: - -```bash -docker exec openclaw-telegram python -c "import urllib.request; print(urllib.request.urlopen('http://host.docker.internal:11434/api/tags').status)" -docker exec openclaw-telegram python -c "import urllib.request; print(urllib.request.urlopen('http://host.docker.internal:6333/collections').status)" -``` - -Both commands should print HTTP status `200`. - -Confirm the local Gateway dashboard endpoint: - -```bash -curl -I http://127.0.0.1:18789/ -``` - -An HTTP `200` response confirms that the Gateway dashboard is reachable. - -## Run the First Telegram Test - -Creating the bot with BotFather registers its name and username in Telegram. The `openclaw-telegram` container uses the token in `.env` to connect the Telegram bot to the local Gateway and AI services on DGX Spark. - -Find the bot in Telegram by searching for the username that you chose in BotFather. You can also replace `` in `https://t.me/` with that username and open the URL. Select **Start** to open a chat. The bot does not start a chat with you or automatically appear in your chat list. - -Messages then follow this path: - -```text -Telegram client -> Telegram Bot API -> openclaw-telegram container on DGX Spark - -> local Gateway and AI services -> openclaw-telegram container -> Telegram client -``` - -After the containers are running and you have started the Telegram chat, send: - -```text -/help -``` - -The bot should return the OpenClaw command card. Next, send a short general message: - -```text -Explain one benefit of running an AI assistant locally in one sentence. -``` - -Watch the Telegram and vLLM logs while the request is processed: - -![Telegram conversation showing the tutorial prompt and a response from the local reasoning model#center](openclaw_telegram_1.jpg "Telegram response from the local reference runtime") - -```bash -docker logs --tail 10 openclaw-telegram -``` - -The output should look similar to: - -```output -2026-07-17T15:38:47+00:00 [telegram] chat_id= text_chars=69 -2026-07-17T15:38:47+00:00 [runtime] start chat_id= active=1 -2026-07-17T15:38:51+00:00 [runtime] done chat_id= task_id= agent=chat_agent duration_ms=4153 answer_chars=180 -``` - -```bash -docker logs --tail 10 openclaw-vllm -``` - -The recent log should include a successful local completion request similar to: - -```output -(APIServer pid=1) INFO: 172.18.0.7:48686 - "POST /v1/chat/completions HTTP/1.1" 200 OK -``` - -The request appearing in the local logs confirms the runtime path. The model's text alone is not evidence that inference was local. - -## Execute Test Suites - -Run the repository tests from the host: - -```bash -OPENCLAW_OLLAMA_BASE_URL=http://127.0.0.1:11434 \ -OPENCLAW_QDRANT_BASE_URL=http://127.0.0.1:6333 \ -PYTHONPATH=app python3 -m unittest discover -s tests -``` - -The final lines are similar to: - -```output -Ran 121 tests in 4.256s -OK (skipped=5) -``` - -The count and time can change. `OK` confirms that the software behavior tests passed; these are not hardware benchmarks. - -## What you've learned and what's next +## What you've accomplished and what's next -You have deployed the personal reference runtime on NVIDIA DGX Spark, connected it to your Telegram bot, verified the local vLLM endpoint, and checked the runtime tests. +You've prepared the DGX Spark host, configured local embeddings, started Qdrant, and checked out the reference repository. -Next, you will use the deployment as a local-first household assistant and confirm that memory is stored in local Qdrant collections. +Next, you'll configure the Telegram bot and start the OpenClaw runtime. diff --git a/content/learning-paths/laptops-and-desktops/openclaw_continuum/3_dgx_runtime_deploy.md b/content/learning-paths/laptops-and-desktops/openclaw_continuum/3_dgx_runtime_deploy.md new file mode 100644 index 0000000000..5e0d3517aa --- /dev/null +++ b/content/learning-paths/laptops-and-desktops/openclaw_continuum/3_dgx_runtime_deploy.md @@ -0,0 +1,270 @@ +--- +title: Configure and start the OpenClaw runtime on DGX Spark +description: Configure Telegram credentials and environment variables, start the OpenClaw runtime with vLLM on DGX Spark, and verify its services and test suite. +weight: 4 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## Configure the Telegram bot environment variables + +With the host and local services ready, configure the Telegram bot. + +You need a Telegram account, a bot token, and the numeric chat ID for the account that will use the bot. Create a Telegram account if you don't already have one. You can use the Telegram desktop, mobile, or web client for the following steps. + +To create a bot and obtain its token: + +1. Open Telegram and start a chat with BotFather. +2. Send the following command: + + ```text + /newbot + ``` + +3. Follow BotFather's prompts to name the bot and choose a username. +4. Copy the HTTP API token that BotFather returns. You'll add it to the `.env` file later. + +For more information about creating and managing bots, see the official [Telegram Bot tutorial](https://core.telegram.org/bots/tutorial). + +Next, obtain the chat ID for your Telegram account: + +1. Open a chat with the bot that you created and send a test message, such as `Hello`. The message creates an update that the Telegram Bot API can return. +2. Open a terminal on your local machine and query the updates. Replace `` with the HTTP API token from BotFather: + + ```bash + curl "https://api.telegram.org/bot/getUpdates" + ``` + + The output is similar to: + + ```output + { + "ok": true, + "result": [ + { + "update_id": (...), + "message": { + (...) + }, + "chat": { + (...) + }, + "date": (...), + "text": "Hello" + } + ] + } + ``` + + Copy the `message.chat.id` value. You'll use this value for `` in the `.env` file. If the `result` array is empty, send another message to the bot and run the command again. + +Copy the DGX Spark environment template: + +```bash +cp .env.example .env +``` + +Keep `.env` in the `openclaw-arm-continuum` repository root, alongside `.env.example`. The deployment command reads it from this location. + + +Then, generate a Gateway token: + +```bash +openssl rand -hex 32 +``` + + +Edit `.env` and set the four private values: + +```text +OPENCLAW_TELEGRAM_BOT_TOKEN= +OPENCLAW_TELEGRAM_ALLOWED_CHAT_IDS= +OPENCLAW_CRON_CHAT_IDS= +OPENCLAW_GATEWAY_TOKEN= +``` + +Set `OPENCLAW_CRON_TIMEZONE` to your local [IANA timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). For example, use `Europe/London`, `America/New_York`, or `Asia/Singapore`: + +```text +OPENCLAW_CRON_TIMEZONE= +``` + +Scheduled jobs use UTC when this setting is omitted. + +You'll name the location explicitly when asking weather-related questions, so you don't need to configure `OPENCLAW_DEFAULT_WEATHER_LOCATION`. + +{{% notice Note %}} +Don't share your Telegram bot token or chat ID with anyone, and don't include them in screenshots, logs, or public repositories. +{{% /notice %}} + +Only allowlisted chat IDs can send commands to this runtime. + +The main tutorial flow uses the default personal collections: + +```text +personal_tracker_memory +personal_knowledge_base +``` + +You don't need to add collection settings to `.env` for this default path. Use only the synthetic data provided in the exercises. + +{{% notice Note %}} +If this host already contains personal runtime data, or if you're preparing a public demonstration, add the following optional settings to `.env` to isolate the tutorial data: + +```text +OPENCLAW_TRACKER_COLLECTION=demo_tracker_memory +OPENCLAW_KNOWLEDGE_COLLECTION=demo_knowledge_base +OPENCLAW_RUNTIME_LABEL=DGX Spark Demo +``` + +If you choose this option, replace the `personal_*` collection names in later verification commands with the corresponding `demo_*` names. +{{% /notice %}} + +The DGX model that you'll use is text-first. Disable experimental vision routing: + +```text +OPENCLAW_VISION_ENABLED=false +``` + + +## Initialize and start the runtime stack + +The Gateway runs as user ID `1000` inside its container and needs write access to its persistent state directory. Prepare the directory before starting the stack: + +```bash +mkdir -p gateway-data/state +sudo chown -R 1000:1000 gateway-data +sudo chmod -R u+rwX gateway-data +``` + +Start the complete DGX Spark stack: + +```bash +docker compose --env-file .env -f compose.yaml up -d +``` + +{{% notice Note %}} +The first start takes longer than subsequent starts because vLLM downloads the approximately 30 GiB Qwen model before loading it. The download time depends on your network connection and can make the initial startup longer. Subsequent starts use the cached model. A running container doesn't mean that its API is ready. +{{% /notice %}} + +Check service status and API readiness: + +```bash +docker compose --env-file .env -f compose.yaml ps -a +docker logs --tail 80 openclaw-vllm +docker logs --tail 80 openclaw-gateway +docker logs --tail 80 openclaw-telegram +docker logs --tail 80 openclaw-cron +``` + +Follow the vLLM log during the first startup: + +```bash +docker logs -f openclaw-vllm +``` + +Wait for `Application startup complete`. Press `Ctrl+C` to leave the log view without stopping the container. + +Confirm that the model API is ready: + +```bash +curl http://127.0.0.1:8000/v1/models +``` + +Verify that a project container can reach both host services through the Docker host gateway: + +```bash +docker exec openclaw-telegram python -c "import urllib.request; print(urllib.request.urlopen('http://host.docker.internal:11434/api/tags').status)" +docker exec openclaw-telegram python -c "import urllib.request; print(urllib.request.urlopen('http://host.docker.internal:6333/collections').status)" +``` + +Both commands should print HTTP status `200`. + +Confirm the local Gateway dashboard endpoint: + +```bash +curl -I http://127.0.0.1:18789/ +``` + +An HTTP `200` response confirms that the Gateway dashboard is reachable. + +## Run the first Telegram test + +Creating the bot with BotFather registers its name and username in Telegram. The `openclaw-telegram` container uses the token in `.env` to connect the Telegram bot to the local Gateway and AI services on DGX Spark. + +Find the bot in Telegram by searching for the username that you chose in BotFather. You can also replace `` in `https://t.me/` with that username and open the URL. Select **Start** to open a chat. The bot doesn't start a chat with you or automatically appear in your chat list. + +Messages use the following path: + +```text +Telegram client -> Telegram Bot API -> openclaw-telegram container on DGX Spark + -> local Gateway and AI services -> openclaw-telegram container -> Telegram client +``` + +After the containers are running and you've started the Telegram chat, send: + +```text +/help +``` + +The bot should return the OpenClaw command card. Next, send a short general message: + +```text +Explain one benefit of running an AI assistant locally in one sentence. +``` + +![Telegram conversation showing the tutorial prompt and a response from the local reasoning model#center](openclaw_telegram_1.jpg "Telegram response from the local reference runtime") + +Watch the Telegram logs while the request is processed: + +```bash +docker logs --tail 10 openclaw-telegram +``` + +The output is similar to: + +```output +2026-07-17T15:38:47+00:00 [telegram] chat_id= text_chars=69 +2026-07-17T15:38:47+00:00 [runtime] start chat_id= active=1 +2026-07-17T15:38:51+00:00 [runtime] done chat_id= task_id= agent=chat_agent duration_ms=4153 answer_chars=180 +``` + +Watch the Telegram logs while the request is processed: + +```bash +docker logs --tail 10 openclaw-vllm +``` + +The recent log should include a successful local completion request similar to: + +```output +(APIServer pid=1) INFO: 172.18.0.7:48686 - "POST /v1/chat/completions HTTP/1.1" 200 OK +``` + +The request appearing in the local logs confirms the runtime path. The model's text alone isn't evidence that inference was local. + +## Execute test suites + +Run the repository tests from the host: + +```bash +OPENCLAW_OLLAMA_BASE_URL=http://127.0.0.1:11434 \ +OPENCLAW_QDRANT_BASE_URL=http://127.0.0.1:6333 \ +PYTHONPATH=app python3 -m unittest discover -s tests +``` + +The final lines are similar to: + +```output +Ran 121 tests in 4.256s +OK (skipped=5) +``` + +The count and time can change. `OK` confirms that the software behavior tests passed. These aren't hardware benchmarks. + +## What you've accomplished and what's next + +You've now deployed the personal reference runtime on NVIDIA DGX Spark, connected it to your Telegram bot, verified the local vLLM endpoint, and checked the runtime tests. + +Next, you'll use the deployment as a local-first household assistant and confirm that memory is stored in local Qdrant collections. diff --git a/content/learning-paths/laptops-and-desktops/openclaw_continuum/3_household_memory.md b/content/learning-paths/laptops-and-desktops/openclaw_continuum/4_household_memory.md similarity index 66% rename from content/learning-paths/laptops-and-desktops/openclaw_continuum/3_household_memory.md rename to content/learning-paths/laptops-and-desktops/openclaw_continuum/4_household_memory.md index 9628acad7a..774f5c15d5 100644 --- a/content/learning-paths/laptops-and-desktops/openclaw_continuum/3_household_memory.md +++ b/content/learning-paths/laptops-and-desktops/openclaw_continuum/4_household_memory.md @@ -1,28 +1,31 @@ --- -title: Validate Memory Persistence and Routing with Telegram and Qdrant -weight: 4 +title: Validate memory persistence and routing with Telegram and Qdrant +description: Store and retrieve synthetic household data through Telegram, verify its Qdrant persistence, and inspect OpenClaw agent routing and external weather requests. +weight: 5 ### FIXED, DO NOT MODIFY layout: learningpathall --- -## Define the Household Test Scenario +## Define the household test scenario -In this section, you will create a shared household assistant to test local memory. You will save and retrieve a synthetic maintenance reminder without sending it to a public cloud LLM. +You'll create a shared household assistant to test local memory. You'll save and retrieve a synthetic maintenance reminder without sending it to a public cloud LLM. Telegram transports the messages. Ollama, Qdrant, and the local LLM process them on your host. -This tutorial treats household data as shared. It does not implement separate access control for each family member. +{{% notice Note %}} +Household data is treated as shared data. You won't implement separate access control for each family member. +{{% /notice %}} -## Store and Query Local Memory +## Store and query local memory -Send this command to the Telegram bot: +Send the following command to the Telegram bot: ```text /mem #home The boiler should be inspected every October. ``` -The runtime stores the reminder through this path: +The runtime stores the reminder through the following path: ```text Telegram / Mem command @@ -37,12 +40,12 @@ Wait for the confirmation, then retrieve the memory: /rag memory: When should the boiler be inspected? ``` -The response should mention October. +The response should mention October: ![Telegram conversation showing the boiler reminder saved with the mem command and retrieved with the rag memory query#center](openclaw_telegram_2.jpg "Saving and retrieving a household memory in Telegram") -The retrieval request follows this local path: +The retrieval request uses the following local path: ```text Telegram question @@ -53,7 +56,7 @@ Telegram question -> Telegram answer ``` -## Verify Qdrant Vector Collections +## Verify Qdrant vector collections Confirm that the personal memory collection exists: @@ -85,7 +88,7 @@ The relevant fields are similar to: The point count depends on existing data. A `green` status with `optimizer_status` set to `ok` confirms collection health. The vector size of `768` matches `nomic-embed-text`. -The collection metadata does not prove that the boiler reminder was stored. Query the point payload directly to verify the synthetic record: +The collection metadata doesn't prove that the boiler reminder was stored. Query the point payload directly to verify the synthetic record: ```bash curl -sS -X POST \ @@ -110,7 +113,7 @@ curl -sS -X POST \ Look for the boiler reminder in the returned payload. The filter finds it even when the personal collection contains other records. This verifies the stored data directly instead of relying on the assistant's response. -## Inspect Active Agents and Task Execution +## Inspect active agents and task execution Send the following command to the Telegram bot: @@ -120,7 +123,7 @@ Send the following command to the Telegram bot: The response lists the thin agents registered by the reference runtime, including memory, RAG, browser search, weather, and chat routes. -To inspect recent tasks, send this command to the Telegram bot: +To inspect recent tasks, send the following command to the Telegram bot: ```text /tasks last 5 @@ -128,7 +131,7 @@ To inspect recent tasks, send this command to the Telegram bot: Task history shows which agent handled the request, its status, and its runtime. All routes use the configured LLM endpoint. -## Test External Skill Integration +## Test external skill integration Send a weather question in plain language: @@ -136,12 +139,10 @@ Send a weather question in plain language: Cambridge weather tomorrow ``` -The runtime sends this question to the weather skill. Do not add `/search`, which selects the general browser worker instead. +The runtime sends this question to the weather skill. Don't add `/search`, which selects the general browser worker instead. This request contacts the public [wttr.in](https://wttr.in/) weather service, but generation still uses the local model. -## Check your work - Your household assistant should now: 1. Save and retrieve the synthetic boiler reminder from Telegram. @@ -149,6 +150,8 @@ Your household assistant should now: 3. Show the selected agent in `/agents` and `/tasks last 5`. 4. Return weather data through the external weather skill. -## What you've learned and what's next +## What you've accomplished and what's next + +You've now saved and retrieved a synthetic household memory, verified it in Qdrant, and inspected both local and external request paths. -You saved and retrieved a synthetic household memory, verified it in Qdrant, and inspected both local and external request paths. Next, you will add document RAG, browser search, and a proactive cron reminder. +Next, you'll add document RAG, browser search, and a proactive cron reminder. diff --git a/content/learning-paths/laptops-and-desktops/openclaw_continuum/4_workflows.md b/content/learning-paths/laptops-and-desktops/openclaw_continuum/5_workflows.md similarity index 69% rename from content/learning-paths/laptops-and-desktops/openclaw_continuum/4_workflows.md rename to content/learning-paths/laptops-and-desktops/openclaw_continuum/5_workflows.md index b2c9bd9215..6b7186823e 100644 --- a/content/learning-paths/laptops-and-desktops/openclaw_continuum/4_workflows.md +++ b/content/learning-paths/laptops-and-desktops/openclaw_continuum/5_workflows.md @@ -1,17 +1,18 @@ --- -title: Validate Document RAG, Web Search, and Proactive Tasks -weight: 5 +title: Validate document RAG, web search, and proactive tasks +description: Run document RAG, deterministic browser search, and proactive Telegram cron workflows with OpenClaw, then verify local storage and runtime behavior. +weight: 6 ### FIXED, DO NOT MODIFY layout: learningpathall --- -## Ingest and Query Document RAG +## Ingest and query document RAG Create a small text file on the device where you use Telegram. {{% notice Note %}} -Telegram uploads files from the device running the client, not from DGX Spark unless Telegram runs there. Common locations are `Downloads`, `Documents`, or `Desktop` on a computer and `Downloads` in the Files app on a phone or tablet. +Telegram uploads files from the device running the client, not from DGX Spark, unless Telegram runs there. Common locations are `Downloads`, `Documents`, or `Desktop` on a computer, and `Downloads` in the Files app on a phone or tablet. {{% /notice %}} @@ -25,13 +26,13 @@ Clean the heating filter on the first Saturday of every third month. Keep the service reference number with the maintenance record. ``` -Save the file as `household-maintenance.txt`, then upload it to your bot with this caption: +Save the file as `household-maintenance.txt`, then upload it to your bot with the following caption: ```text /knowledge ``` -The document follows this path: +The document uses the following path: ```text File on the Telegram client device @@ -57,11 +58,14 @@ In Telegram, ask a question using the returned filename. Replace ` When should the heating filter be cleaned? ``` -The filename limits retrieval to this upload, so existing records do not affect the result. A general `/rag` query without a filename searches all configured memory and knowledge collections. The screenshot shows this general query, but use the filename-specific command for this test. +The filename limits retrieval to this upload, so existing records don't affect the result. A general `/rag` query without a filename searches all configured memory and knowledge collections. + +The following screenshot shows a general query: ![Telegram conversation showing household-maintenance.txt uploaded with the knowledge caption, saved to personal_knowledge_base, and retrieved with a general rag question#center](openclaw_telegram_3.jpg "Uploading and querying a household document in Telegram") -The answer should mention the first Saturday of every third month. + +Use the command with the filename for this test. The answer should mention the first Saturday of every third month. To verify the stored document directly in Qdrant, filter the collection by the returned filename: @@ -88,9 +92,9 @@ curl -sS -X POST \ The payload should contain chunks from `household-maintenance.txt`, confirming that Qdrant stored and indexed the upload. -## Execute Deterministic Web Search +## Execute deterministic web search -Use the browser agent for current public information. Send this command to the bot: +Use the browser agent for current public information. Send the following command to the bot: ```text /search Arm Learning Paths local AI development @@ -117,7 +121,7 @@ docker logs --tail 20 openclaw-browser-scraper Look for a successful `POST /scrape` request. The Telegram response should cite the retrieved sources and include the path to the saved web Markdown file. -Finally, send this command in Telegram: +Finally, send the following command in Telegram: ```text /tasks last 5 @@ -125,25 +129,27 @@ Finally, send this command in Telegram: Confirm that the search task reports `browser_search_agent`. -## Schedule Proactive Cron Tasks +## Schedule proactive cron tasks + +Choose a time a few minutes in the future, using `OPENCLAW_CRON_TIMEZONE`. -Choose a time a few minutes in the future, using `OPENCLAW_CRON_TIMEZONE`. Create a daily reminder: +Create a daily reminder, replacing `21:15` with your test time: ```text /cron add daily 21:15 Heating check :: Remind the household to review the heating maintenance notes. ``` -Replace `21:15` with your test time. Then list the job in Telegram: +Then, list the job in Telegram: ```text /cron list ``` -The bot returns a job ID, and `/cron list` shows the schedule as `[on]`. +The bot returns a job ID, and `/cron list` shows the schedule as `[on]`: ![Telegram conversation showing a daily Heating check cron job created, listed as enabled, and triggered at the configured time#center](openclaw_telegram_4.jpg "Creating and triggering a scheduled reminder in Telegram") -Creating the job does not run it immediately. At the configured time, the bot sends the Heating check message. +Creating the job doesn't run it immediately. At the configured time, the bot sends the Heating check message. After the configured time, verify that the cron worker delivered the scheduled job: @@ -161,9 +167,9 @@ To test without waiting, copy the job ID from `/cron list` and send: The result should be delivered as a Telegram push message. -## Inspect Cron From the Gateway Dashboard +## Inspect cron from the gateway dashboard -The Gateway dashboard listens on localhost. If you are working directly on the DGX Spark desktop, open: +The Gateway dashboard listens on localhost. If you're working directly on the DGX Spark desktop, open: ```text http://127.0.0.1:18789/ @@ -182,15 +188,17 @@ Then open `http://127.0.0.1:18789/` locally and enter the `OPENCLAW_GATEWAY_TOKE Confirm that the dashboard and Telegram show the same cron job and run history. {{% notice Warning %}} -Keep the Gateway and its admin RPC endpoint behind localhost, an SSH tunnel, or a trusted private network. Do not expose the dashboard directly to the public internet. +Keep the Gateway and its admin RPC endpoint behind localhost, an SSH tunnel, or a trusted private network. Don't expose the dashboard directly to the public internet. {{% /notice %}} -## Check your work - -You have now validated three runtime paths. Document questions use the RAG skill, Qdrant, and the local LLM. Current public queries use the browser-search agent and Playwright. Proactive reminders run through the cron worker and arrive as Telegram messages. +You've now validated three runtime paths. Document questions use the RAG skill, Qdrant, and the local LLM. Current public queries use the browser-search agent and Playwright. Proactive reminders run through the cron worker and arrive as Telegram messages. The LLM is one replaceable part of the application. The local memory, tools, schedules, and interaction paths remain available around it. ## What you've learned and what's next -You validated document RAG, explicit browser search, and a proactive reminder for the household assistant. Next, you will move the same workflows to a CPU-only Armv9 system. +You've now validated document RAG, explicit browser search, and a proactive reminder for the household assistant. + +You can optionally extend the same workflow to a CPU-only Armv9 system. For more information, see [(Optional) Port the app to a CPU-only Armv9 system](/learning-paths/laptops-and-desktops/openclaw_continuum/6_cpu_only/). + +You've moved beyond a local-model demo and built a self-managed OpenClaw-based runtime that you can adapt to different Arm compute configurations. diff --git a/content/learning-paths/laptops-and-desktops/openclaw_continuum/5_cpu_only.md b/content/learning-paths/laptops-and-desktops/openclaw_continuum/6_cpu_only.md similarity index 57% rename from content/learning-paths/laptops-and-desktops/openclaw_continuum/5_cpu_only.md rename to content/learning-paths/laptops-and-desktops/openclaw_continuum/6_cpu_only.md index 183ba25975..df5ac76773 100644 --- a/content/learning-paths/laptops-and-desktops/openclaw_continuum/5_cpu_only.md +++ b/content/learning-paths/laptops-and-desktops/openclaw_continuum/6_cpu_only.md @@ -1,27 +1,28 @@ --- -title: (Optional) Port the App to a CPU-Only Armv9 System -weight: 6 +title: (Optional) Port the app to a CPU-only Armv9 system +description: Port the OpenClaw workflow from NVIDIA DGX Spark to a CPU-only Armv9 system with llama.cpp, then validate shared services, routing, and data boundaries. +weight: 7 ### FIXED, DO NOT MODIFY layout: learningpathall --- -## Overview of Cross-Platform Portability +## Cross-platform portability -As an optional step, you will now move the runtime from NVIDIA DGX Spark to a CIX-based Radxa Orion O6 running Debian 12. llama.cpp provides local generation on the Armv9 CPU. +You can optionally move the runtime from NVIDIA DGX Spark to a CIX-based Radxa Orion O6 running Debian 12. `llama.cpp` provides local generation on the Armv9 CPU. The Telegram interface, local memory and RAG, browser search, scheduled workflows, and deterministic routing remain unchanged. Only the local generation backend changes: | Platform | Local generation backend | Runtime API contract | |---|---|---| | NVIDIA DGX Spark | vLLM | OpenAI-compatible API | -| Radxa Orion O6 | llama.cpp | OpenAI-compatible API | +| Radxa Orion O6 | `llama.cpp` | OpenAI-compatible API | {{% notice Note %}} -These backends match the environments used in this Learning Path and [Run ERNIE-4.5 Mixture of Experts model on Armv9 with llama.cpp](/learning-paths/cross-platform/ernie_moe_v9/). You can use another local backend with a compatible OpenAI chat-completions API. +These backends match the environments used in this Learning Path and in the [Run ERNIE-4.5 Mixture of Experts model on Armv9 with `llama.cpp`](/learning-paths/cross-platform/ernie_moe_v9/) Learning Path. You can use another local backend with a compatible OpenAI chat-completions API. {{% /notice %}} -## Verify System Requirements on Armv9 Host +## Verify system requirements on Armv9 host On Orion O6, confirm the operating system, architecture, CPU features, memory, and disk capacity: @@ -37,7 +38,7 @@ Confirm that the host reports `aarch64` and has enough available memory and stor ## Prepare llama.cpp and the ERNIE model -Follow [Set up llama.cpp on an Armv9 development board](/learning-paths/cross-platform/ernie_moe_v9/2_llamacpp_installation/). Install the dependencies, compile llama.cpp, download the ERNIE-4.5 Thinking Q4 GGUF model, and run its basic inference test. +To set up `llama.cpp` and the ERNIE model, see [Set up `llama.cpp` on an Armv9 development board](/learning-paths/cross-platform/ernie_moe_v9/2_llamacpp_installation/). Install the dependencies, compile `llama.cpp`, download the ERNIE-4.5 Thinking Q4 GGUF model, and run its basic inference test. The following commands use these installation paths: @@ -46,7 +47,7 @@ $HOME/llama.cpp/build/bin/llama-server $HOME/models/ernie-4.5/ERNIE-4.5-21B-A3B-Thinking-Q4_0.gguf ``` -## Deploy llama.cpp OpenAI-Compatible Server +## Deploy a llama.cpp OpenAI-compatible server Start the server on the host: @@ -81,9 +82,9 @@ curl -sS http://127.0.0.1:8080/v1/chat/completions \ }' ``` -Do not continue until this local endpoint generates a valid response. +Don't continue until this local endpoint generates a valid response. -Press `Ctrl+C` in the server shell after the smoke test. Create a user systemd service so that llama.cpp starts automatically and restarts after a failure: +Press `Ctrl+C` in the server shell after the smoke test. Create a user `systemd` service so that `llama.cpp` starts automatically and restarts after a failure: ```bash mkdir -p $HOME/.config/systemd/user @@ -120,7 +121,7 @@ Confirm that the managed endpoint responds: curl http://127.0.0.1:8080/v1/models ``` -## Provision Supporting Local Services +## Provision Ollama and Qdrant Install Ollama on the Orion O6 host: @@ -147,13 +148,13 @@ Check whether the Qdrant container already exists: docker ps -a --filter name=openclaw-qdrant ``` -If it already exists, start it: +If the container already exists, start it: ```bash docker start openclaw-qdrant ``` -Otherwise, create persistent storage and start Qdrant. Bind its ports to localhost: +Otherwise, create persistent storage and start Qdrant. Bind its ports to `localhost`: ```bash docker volume create openclaw-qdrant-data @@ -173,7 +174,7 @@ Confirm that the local API responds: curl http://127.0.0.1:6333/collections ``` -## Configure the CPU-Only Runtime Environment +## Configure the CPU-only runtime environment Clone the same release on Orion O6: @@ -185,7 +186,7 @@ git checkout v1.2 cp .env.arm-cpu-only.example .env ``` -Create a separate bot for this runtime with the [Telegram Bot tutorial](https://core.telegram.org/bots/tutorial). Do not reuse the DGX Spark bot token because two polling runtimes can compete for its updates. Have each account send a message to the new bot, then repeat the `getUpdates` process from the DGX Spark setup to obtain each `message.chat.id` value. +Create a separate bot for this runtime with the [Telegram Bot tutorial](https://core.telegram.org/bots/tutorial). Don't reuse the DGX Spark bot token because two polling runtimes can compete for its updates. Have each account send a message to the new bot, then repeat the `getUpdates` process from the DGX Spark setup to obtain each `message.chat.id` value. Generate a new Gateway token: @@ -215,9 +216,9 @@ OPENCLAW_TRACKER_COLLECTION=personal_tracker_memory OPENCLAW_KNOWLEDGE_COLLECTION=personal_knowledge_base ``` -The `VLLM` variable name is retained for compatibility, but it can point to llama.cpp. +The `VLLM` variable name is retained for compatibility, but it can point to `llama.cpp`. -Using the same collection names keeps the configuration consistent, but it does not copy Qdrant data from DGX Spark. Each host keeps its own data. +Using the same collection names keeps the configuration consistent, but it doesn't copy Qdrant data from DGX Spark. Each host keeps its own data. Keep the CPU-only context small and disable unused voice transcription: @@ -229,7 +230,7 @@ OPENCLAW_WEB_CONTEXT_CHARS=1800 OPENCLAW_WHISPER_ENABLED=false ``` -## Launch the CPU-Only Application Stack +## Launch the CPU-only application stack Start the full tutorial stack: @@ -258,14 +259,14 @@ docker exec openclaw-browser-scraper python -c "import socket; print(socket.geth ``` {{% notice Note %}} -If this command cannot resolve the hostname, inspect the Orion host DNS configuration with `cat /etc/resolv.conf`. Then update `OPENCLAW_DNS_SERVER_1` and `OPENCLAW_DNS_SERVER_2` in `.env` with DNS servers that are reachable from your network, restart the stack, and run the check again. +If this command can't resolve the hostname, inspect the Orion host DNS configuration with `cat /etc/resolv.conf`. Then update `OPENCLAW_DNS_SERVER_1` and `OPENCLAW_DNS_SERVER_2` in `.env` with DNS servers that are reachable from your network, restart the stack, and run the check again. {{% /notice %}} -## Validate Shared Workflows on CPU +## Validate shared workflows on CPU -Test the CPU-only deployment with a simple budget assistant shared by two household members. +Test the CPU-only deployment with a budget assistant shared by two household members. -Create a file named `budget.txt` on the device where you use Telegram: +Create a file named `budget.txt` on the device that you use Telegram on: ```text Shared household weekly budget: £120. @@ -284,26 +285,67 @@ After both entries are saved, either member can ask: /rag Based on the shared budget and the saved budget entries, how much remains? ``` -Replace `` with the filename returned when you uploaded `budget.txt`. +Replace `` with the filename that was returned when you uploaded `budget.txt`. The response should report that £55 remains. Both members use the same local collection, without separate per-member access controls. -The response alone does not prove which inference backend generated it. Inspect the Telegram runtime log: +The response alone doesn't prove which inference backend generated it. Inspect the Telegram runtime log: ```bash docker logs --tail 20 openclaw-telegram ``` -Look for the memory write handled by `memory_agent` and the completed retrieval request handled by `rag_agent`. Then inspect the llama.cpp service log: +Look for the memory write handled by `memory_agent` and the completed retrieval request handled by `rag_agent`. Then, inspect the `llama.cpp` service log: ```bash journalctl --user -u openclaw-llama.service -n 30 --no-pager ``` -Look for a successful request to `/v1/chat/completions`. The Telegram response and both log entries confirm that the OpenClaw-based workflow is now using llama.cpp for local generation on the Armv9 CPU. +Look for a successful request to `/v1/chat/completions`. The Telegram response and both log entries confirm that the OpenClaw-based workflow is now using `llama.cpp` for local generation on the Armv9 CPU. -## What you've learned and what's next +## Compare Arm deployment architectures -You have moved the OpenClaw-based runtime from DGX Spark to a CPU-only Armv9 system by replacing the inference endpoint rather than rewriting the application. +You've now built a local-first household assistant with memory, document RAG, browser search, and scheduled notifications. You ran the assistant with vLLM on NVIDIA DGX Spark, then moved it to `llama.cpp` on Radxa Orion O6. -Next, you will review the software portability result and identify the current implementation boundaries. +The following comparison shows what stayed the same across the two Arm-based implementations and what changed with the local generation backend: + +| Layer | NVIDIA DGX Spark | Radxa Orion O6 | +|---|---|---| +| Reference runtime services | Same services | Same services | +| User interface | Telegram | Telegram | +| Skills | Memory, RAG, search, weather, cron | Same skills | +| Vector memory | Qdrant | Qdrant | +| Embeddings | Ollama | Ollama | +| Generation API | OpenAI-compatible | OpenAI-compatible | +| Generation engine | vLLM | `llama.cpp` | +| Inference compute | Arm CPU + NVIDIA GPU | Arm CPU | + +Each platform uses model and context settings suited to its compute while preserving the same application contract. + +## Review data privacy boundaries + +The runtime keeps the following under your control: + +- Inference requests +- Generated context +- Qdrant collections +- Uploaded files +- Cron history +- OpenClaw tasks +- Gateway state + +Telegram still transports messages and uploads. Weather and browser searches contact public services, while setup downloads models and containers from external registries. + +For sensitive deployments, review network exposure, Telegram suitability, host access, backups, model provenance, and the contents of every enabled tool. + +## What you've accomplished + +You've now moved the OpenClaw-based runtime from DGX Spark to a CPU-only Armv9 system by replacing the inference endpoint. + +The same endpoint-driven design can support additional deployment shapes: + +- An always-on CPU-only Arm server with a compact local model +- An Arm edge gateway connected to a trusted private-LAN inference server +- A heterogeneous Arm AI workstation hosting larger local models + +Each deployment changes the compute and trust boundary. It shouldn't silently change where personal data is stored or which external services are contacted. diff --git a/content/learning-paths/laptops-and-desktops/openclaw_continuum/6_summary.md b/content/learning-paths/laptops-and-desktops/openclaw_continuum/6_summary.md deleted file mode 100644 index 7a1617d55a..0000000000 --- a/content/learning-paths/laptops-and-desktops/openclaw_continuum/6_summary.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: Review the Deployment Across Arm Platforms -weight: 7 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -## Compare Arm Deployment Architectures - -You built a local-first household assistant with memory, document RAG, browser search, and scheduled notifications. You ran it with vLLM on NVIDIA DGX Spark, then moved it to llama.cpp on Radxa Orion O6. - -The following comparison shows what stayed the same across the two Arm-based implementations and what changed with the local generation backend: - -| Layer | NVIDIA DGX Spark | Radxa Orion O6 | -|---|---|---| -| Reference runtime services | Same services | Same services | -| User interface | Telegram | Telegram | -| Skills | Memory, RAG, search, weather, cron | Same skills | -| Vector memory | Qdrant | Qdrant | -| Embeddings | Ollama | Ollama | -| Generation API | OpenAI-compatible | OpenAI-compatible | -| Generation engine | vLLM | llama.cpp | -| Inference compute | Arm CPU + NVIDIA GPU | Arm CPU | - -Each platform uses model and context settings suited to its compute while preserving the same application contract. - -## Review Data Privacy Boundaries - -The runtime keeps inference requests, generated context, Qdrant collections, uploaded files, cron history, OpenClaw tasks, and Gateway state under your control. - -Telegram still transports messages and uploads. Weather and browser searches contact public services, while setup downloads models and containers from external registries. - -For sensitive deployments, you should review network exposure, Telegram suitability, host access, backups, model provenance, and the contents of every enabled tool. - -## Identify Current System Scope - -This Learning Path uses a text-first architecture, fixed skill routes, and one local LLM endpoint. It does not cover multi-model routing, multi-agent handoffs, or hardware benchmarking. The AgentRegistry and TaskDispatcher keep command behavior predictable within this scope. - -## Explore Other Arm Deployment Topologies - -The same endpoint-driven design can support additional deployment shapes: - -- An always-on CPU-only Arm server with a compact local model -- An Arm edge gateway connected to a trusted private-LAN inference server -- A heterogeneous Arm AI workstation hosting larger local models - -Each deployment changes the compute and trust boundary. It should not silently change where personal data is stored or which external services are contacted. - -## Key Takeaways and Next Steps - -You can now: - -- Explain the local and external data boundaries of the reference runtime -- Deploy an operational OpenClaw-based runtime with local vLLM inference on DGX Spark -- Use Telegram memory, RAG, browser search, cron, and Gateway workflows -- Verify local persistence through Qdrant and runtime logs -- Move the same application workflow to llama.cpp on a CPU-only Armv9 platform - -You have moved beyond a local-model demo and built a self-managed OpenClaw-based runtime that can adapt to two different Arm compute configurations. diff --git a/content/learning-paths/laptops-and-desktops/openclaw_continuum/_index.md b/content/learning-paths/laptops-and-desktops/openclaw_continuum/_index.md index 1d14ba4e99..9a26d52552 100644 --- a/content/learning-paths/laptops-and-desktops/openclaw_continuum/_index.md +++ b/content/learning-paths/laptops-and-desktops/openclaw_continuum/_index.md @@ -1,21 +1,17 @@ --- -title: Extend OpenClaw for a Local-First AI Assistant Across Arm Platforms - -draft: true -cascade: - draft: true +title: Extend OpenClaw for a local-first AI assistant across Arm platforms description: Extend OpenClaw with local memory, document RAG, browser search, deterministic routing, and proactive scheduling, then move the same local-first runtime from NVIDIA DGX Spark with vLLM to a CPU-only Armv9 system with llama.cpp. minutes_to_complete: 120 -who_is_this_for: This is an advanced topic for developers who want to extend OpenClaw into a customizable local-first assistant with persistent memory, document RAG, explicit browser search, deterministic routing, and proactive scheduling. You will deploy the reference runtime on NVIDIA DGX Spark with vLLM, then move the same workflows to a CPU-only Armv9 system with llama.cpp. +who_is_this_for: This is an advanced topic for developers who want to extend OpenClaw into a customizable local-first assistant with persistent memory, document RAG, explicit browser search, deterministic routing, and proactive scheduling. learning_objectives: - - Explain the local and external data boundaries of an OpenClaw-based runtime - - Deploy and validate the reference runtime with local vLLM inference on NVIDIA DGX Spark - - Verify persistent memory, document RAG, explicit browser search, deterministic routing, and proactive scheduling with Telegram and Qdrant - - Move the same application workflows to a CPU-only Armv9 system through an OpenAI-compatible llama.cpp endpoint + - Explain the local and external data boundaries of an OpenClaw-based runtime. + - Deploy and validate the reference runtime with local vLLM inference on NVIDIA DGX Spark. + - Verify persistent memory, document RAG, explicit browser search, deterministic routing, and proactive scheduling with Telegram and Qdrant. + - Optionally move the same application workflows to a CPU-only Armv9 system through an OpenAI-compatible llama.cpp endpoint. prerequisites: - An NVIDIA DGX Spark system with NVIDIA drivers, Docker and NVIDIA Container Toolkit @@ -24,10 +20,59 @@ prerequisites: - Familiarity with Linux, Docker Compose, and command-line tools - (Optional) A Radxa Orion O6 or comparable CPU-only Armv9 system running Debian 12, Docker, and at least 30 GB of memory +# START generated_summary_faq +generated_summary_faq: + template_version: summary-faq-v3 + generated_at: '2026-08-10T15:59:32Z' + generator: ai + ai_assisted: true + ai_review_required: true + model: gpt-5 + prompt_template: summary-faq-v3 + source_hash: 8160160b7c59c2294a7666d9748b9f1f0115219431558ed7b378d6d3421d86e8 + summary_generated_at: '2026-08-10T15:59:32Z' + summary_source_hash: 8160160b7c59c2294a7666d9748b9f1f0115219431558ed7b378d6d3421d86e8 + faq_generated_at: '2026-08-10T15:59:32Z' + faq_source_hash: 8160160b7c59c2294a7666d9748b9f1f0115219431558ed7b378d6d3421d86e8 + summary: >- + You'll extend OpenClaw into a local-first assistant that runs across Arm platforms with local + inference and explicit external-data boundaries. First, you'll prepare a DGX Spark with Docker, Ollama, Qdrant, and vLLM. Then, you'll validate memory and + document RAG, browser search, weather, routing, and scheduled notifications. You can optionally + move the same workflows to a CPU-only Armv9 system with an OpenAI-compatible llama.cpp endpoint. + faqs: + - question: What should I check on the DGX Spark host before starting the containers? + answer: >- + Run `uname -m` and confirm the architecture is `aarch64`. Use `nvidia-smi` to verify GPU + visibility, then run `docker run --rm --gpus all ubuntu nvidia-smi` to confirm GPU access from + containers. + - question: How do I get the Telegram bot token and chat ID for the runtime configuration? + answer: >- + Start a chat with **BotFather**, send `/newbot`, and copy the HTTP API token it returns. Send a + test message to your new bot, call `curl "https://api.telegram.org/bot/getUpdates"`, + and copy `message.chat.id`. Set both values in `.env` before starting the services. + - question: How do I know that local memory persistence is working? + answer: >- + Send `/mem #home The boiler should be inspected every October.` in Telegram, then ask + `/rag memory: When should the boiler be inspected?`. You should see October in the response. Confirm + the record directly in the `personal_tracker_memory` Qdrant collection with the documented + payload query. + - question: Where do I upload documents for RAG, and how can I confirm ingestion? + answer: >- + Create the file on the device running your Telegram client and upload it with the `/knowledge` + caption. Copy the returned filename, wait for indexing, and ask `/rag ` a + question about the file. Check the `personal_knowledge_base` Qdrant payload for that filename + to confirm ingestion. + - question: How do I verify that proactive scheduling is active? + answer: >- + Create a job with `/cron add`, confirm it's enabled with `/cron list`, and wait for the + configured time. Check Telegram for the notification and inspect `docker logs --tail 30 openclaw-cron` + for the `[cron] dynamic job sent` entry. You can use `/cron run ` to test + the job without waiting. +# END generated_summary_faq author: Odin Shen -generate_summary_faq: true +generate_summary_faq: false rerun_summary: false rerun_faqs: false