1. Введение
Обзор
В этой лабораторной работе вы развернете полностью постоянный, защищенный экземпляр OpenClaw — фреймворка для создания агентов искусственного интеллекта с открытым исходным кодом — в Cloud Run Instances . Вы будете взаимодействовать со своим агентом ИИ напрямую, используя встроенный веб-интерфейс OpenClaw (с возможностью подключения каналов обмена сообщениями, таких как Telegram или WhatsApp ), создавать резервные копии его рабочего пространства в Google Cloud Storage и безопасно управлять учетными данными API с помощью Google Cloud Secret Manager .
Прежде чем начать, вы можете ознакомиться с документацией OpenClaw , чтобы понять архитектуру OpenClaw, используемые инструменты и рабочие процессы агентов.
Что вы будете делать
- Включите необходимые API Google Cloud и создайте выделенную учетную запись службы с необходимыми разрешениями IAM.
- Надежно храните ключи API и пароли шлюзов в Secret Manager.
- Подготовьте конфигурационный файл
openclaw.jsonс настройками модели Gemini и включенным пользовательским интерфейсом шлюза. - Подготовьте хранилище Cloud Storage для сохранения состояния контейнера.
- (Необязательно) Загрузите плагин Cloud Run Sandbox Provider, чтобы обеспечить безопасное и изолированное выполнение кода через
/usr/local/gcp/bin/sandbox. - Разверните OpenClaw с помощью
gcloud beta run instances create. - Взаимодействуйте напрямую с вашим агентом OpenClaw AI, используя его встроенный веб-интерфейс.
- (Необязательно) Настройте канал обмена сообщениями ( Telegram или WhatsApp ).
- (Необязательно) Расширьте возможности своего агента, добавив пользовательские навыки в облачное хранилище.
Что вы узнаете
- Как развернуть OpenClaw на облачных экземплярах с помощью встроенного веб-интерфейса управления.
- Как подключить хранилища Cloud Storage к экземплярам Cloud Run.
- Как безопасно внедрить секреты Secret Manager в качестве переменных среды в Cloud Run.
- Как запускать длительные, постоянно выполняющиеся рабочие нагрузки агентов на экземплярах Cloud Run.
- Как настроить и загрузить пользовательские навыки агента в облачное хранилище.
2. Настройка и требования
Настройка проекта GCP
- Войдите в консоль Google Cloud .
- Создайте или выберите проект Google Cloud.
- Убедитесь, что для вашего проекта в Google Cloud включена функция выставления счетов.
Открытая облачная оболочка
Активируйте Google Cloud Shell с верхней панели инструментов Cloud Console.
Установите бета-компонент и настройте проект.
Убедитесь, что для gcloud beta run instances установлен компонент beta :
gcloud components install beta --quiet
export PROJECT_ID=<YOUR_PROJECT_ID>
export REGION="us-west1"
Включите необходимые API Google Cloud.
В Cloud Shell включите API Cloud Run, Secret Manager, Cloud Storage и Gemini:
gcloud services enable \
run.googleapis.com \
secretmanager.googleapis.com \
storage.googleapis.com \
generativelanguage.googleapis.com \
compute.googleapis.com
3. (Необязательно) Настройте интеграцию с мессенджерами (Telegram или WhatsApp)
Вы можете подключить OpenClaw к Telegram или WhatsApp . Выберите вариант A или вариант B ниже.
Вариант А: Настройка Telegram-бота
- Откройте Telegram и найдите
@BotFather. - Отправьте команду
/newbotи следуйте подсказкам, чтобы указать имя бота и имя пользователя. - Скопируйте сгенерированный HTTP API-токен (например,
123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ). - Найдите
@userinfobotв Telegram, отправьте/startи скопируйте свой числовой идентификатор пользователя (например,8035936176).
Вариант B: Настройка WhatsApp
- Получите свой личный номер телефона WhatsApp в международном формате без пробелов и символов (например,
+15551234567). - OpenClaw подключается через политику разрешенных каналов WhatsApp.
4. Создайте выделенный сервисный аккаунт.
Чтобы соблюсти принцип минимальных привилегий, создайте выделенную учетную запись службы IAM для OpenClaw:
export SERVICE_ACCOUNT_NAME="openclaw-sa"
gcloud iam service-accounts create ${SERVICE_ACCOUNT_NAME} \
--display-name="OpenClaw Service Account"
export SERVICE_ACCOUNT="${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"
5. Сохраните учетные данные в Secret Manager.
Мы будем хранить конфиденциальные учетные данные API в Google Cloud Secret Manager, чтобы Cloud Run мог безопасно внедрять их в контейнер при загрузке.
1. Получите и сохраните ключ API Gemini.
- Зайдите в Google AI Studio и войдите в систему, используя свою учетную запись Google.
- Нажмите «Создать ключ API» и выберите свой проект Google Cloud (
${PROJECT_ID}). - Скопируйте сгенерированный ключ API.
Сохраните ключ API в Secret Manager и предоставьте учетной записи службы доступ:
echo -n "YOUR_GEMINI_API_KEY" | gcloud secrets create gemini-api-key \
--data-file=- \
--replication-policy="automatic"
gcloud secrets add-iam-policy-binding gemini-api-key \
--member="serviceAccount:${SERVICE_ACCOUNT}" \
--role="roles/secretmanager.secretAccessor"
2. Сгенерируйте и сохраните пароль шлюза.
Для защиты общедоступного экземпляра OpenClaw сгенерируйте надежный случайный пароль и сохраните его в Secret Manager:
export OPENCLAW_GATEWAY_PASSWORD=$(openssl rand -hex 16)
echo "Generated Gateway Password: ${OPENCLAW_GATEWAY_PASSWORD}"
echo -n "${OPENCLAW_GATEWAY_PASSWORD}" | gcloud secrets create openclaw-gateway-password \
--data-file=- \
--replication-policy="automatic"
gcloud secrets add-iam-policy-binding openclaw-gateway-password \
--member="serviceAccount:${SERVICE_ACCOUNT}" \
--role="roles/secretmanager.secretAccessor"
3. (Необязательно) Создайте секретный канал (в Telegram или WhatsApp)
- Для Telegram :
echo -n "YOUR_TELEGRAM_BOT_TOKEN" | gcloud secrets create telegram-bot-token \ --data-file=- \ --replication-policy="automatic" gcloud secrets add-iam-policy-binding telegram-bot-token \ --member="serviceAccount:${SERVICE_ACCOUNT}" \ --role="roles/secretmanager.secretAccessor" - Для WhatsApp :
echo -n "YOUR_WHATSAPP_TOKEN_OR_KEY" | gcloud secrets create whatsapp-token \ --data-file=- \ --replication-policy="automatic" gcloud secrets add-iam-policy-binding whatsapp-token \ --member="serviceAccount:${SERVICE_ACCOUNT}" \ --role="roles/secretmanager.secretAccessor"
6. Подготовка хранилища Cloud Storage и конфигурации openclaw.json.
Для работы OpenClaw требуется конфигурационный файл openclaw.json , расположенный по адресу /home/node/.openclaw/openclaw.json .
- Создайте сегмент облачного хранилища и предоставьте к нему доступ :
export BUCKET_NAME="openclaw-state-${PROJECT_ID}" gcloud storage buckets create gs://${BUCKET_NAME} --location=${REGION} gcloud storage buckets add-iam-policy-binding gs://${BUCKET_NAME} \ --member="serviceAccount:${SERVICE_ACCOUNT}" \ --role="roles/storage.objectUser" - Создайте
openclaw.json: Создайте файл с именемopenclaw.jsonв Cloud Shell. Обновите разделchannelsв соответствии с выбранным вами каналом (Telegram или WhatsApp):{ "gateway": { "mode": "local", "port": 18789, "trustedProxies": ["0.0.0.0/0"], "bind": "lan", "auth": { "password": "${OPENCLAW_GATEWAY_PASSWORD}" }, "controlUi": { "dangerouslyDisableDeviceAuth": true, "allowedOrigins": ["*"], "enabled": true } }, "agents": { "defaults": { "model": { "primary": "google/gemini-3.1-pro-preview" }, "sandbox": { "mode": "all", "workspaceAccess": "rw", "backend": "cloud-run-sandbox" } } }, "channels": { "telegram": { "enabled": true, "defaultAccount": "default", "accounts": { "default": { "enabled": true, "dmPolicy": "allowlist", "allowFrom": [ "YOUR_TELEGRAM_USER_ID" ] } } }, "whatsapp": { "enabled": false, "defaultAccount": "default", "accounts": { "default": { "enabled": false, "dmPolicy": "allowlist", "allowFrom": [ "+15551234567" ] } } } }, "plugins": { "load": { "paths": [ "/home/node/.openclaw/plugins" ] }, "entries": { "google": { "enabled": true }, "telegram": { "enabled": true }, "whatsapp": { "enabled": false }, "cloud-run-sandbox-provider": { "enabled": true } } } } - Загрузите файл
openclaw.jsonв корневой каталог облачного хранилища :gcloud storage cp openclaw.json gs://${BUCKET_NAME}/openclaw.json - (Необязательно) Загрузите плагин Cloud Run Sandbox Provider : Когда
agents.defaults.sandbox.modeустановлено в значение"all", OpenClaw по умолчанию пытается запустить локальный демон Docker для выполнения инструментов в изолированной среде. Поскольку стандартные образы контейнеров в Cloud Run не используют Docker, вы можете включить плагин Cloud Run Sandbox Provider . При развертывании с флагом--sandbox-launcherв Cloud Run платформа автоматически внедряет собственный исполняемый файл песочницы микровиртуальной машины gVisor (/usr/local/gcp/bin/sandbox), обеспечивая безопасное и изолированное выполнение кода внутри экземпляра примерно за 25 мс.- Создайте локальную директорию для плагинов:
mkdir -p plugins/cloud-run-sandbox-provider - Создайте
plugins/cloud-run-sandbox-provider/package.json:{ "name": "cloud-run-sandbox-provider", "version": "1.0.0", "description": "Cloud Run Sandbox Provider for OpenClaw", "type": "module", "main": "index.mjs", "openclaw": { "extensions": [ "./index.mjs" ] } } - Создайте
plugins/cloud-run-sandbox-provider/openclaw.plugin.json:{ "id": "cloud-run-sandbox-provider", "name": "Cloud Run Sandbox Provider", "entry": "./index.mjs", "kind": "tool", "activation": { "onStartup": true }, "configSchema": { "type": "object", "properties": {} } } - Создайте
plugins/cloud-run-sandbox-provider/index.mjs:import { spawn } from "node:child_process"; import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry"; import { registerSandboxBackend } from "openclaw/plugin-sdk/sandbox"; const SANDBOX_BINARY_PATH = process.env.OPENCLAW_SANDBOX_BINARY_PATH || "/usr/local/gcp/bin/sandbox"; function runCommandRaw(command, args, stdin = null) { return new Promise((resolve) => { const child = spawn(command, args, { env: { ...process.env } }); let stdout = Buffer.alloc(0); let stderr = Buffer.alloc(0); child.stdout.on("data", (data) => { stdout = Buffer.concat([stdout, data]); }); child.stderr.on("data", (data) => { stderr = Buffer.concat([stderr, data]); }); child.on("error", (err) => { resolve({ code: -1, stdout, stderr: Buffer.from(err.message) }); }); child.on("close", (code) => { resolve({ code: code ?? 0, stdout, stderr }); }); if (stdin != null) { child.stdin.write(stdin); } child.stdin.end(); }); } async function ensureSandboxRunning(sandboxId, workspaceDir) { const check = await runCommandRaw(SANDBOX_BINARY_PATH, ["exec", sandboxId, "--", "/bin/true"]); if (check.code === 0) { return; } const runArgs = [ "run", "--detach", "--write", "--mount", `type=bind,source=${workspaceDir},destination=${workspaceDir}`, sandboxId ]; const start = await runCommandRaw(SANDBOX_BINARY_PATH, runArgs); if (start.code !== 0) { throw new Error(`Failed to start Cloud Run sandbox ${sandboxId}: ${start.stderr.toString("utf8")}`); } } class CloudRunSandboxHandle { constructor(params) { this.id = "cloud-run-sandbox"; this.runtimeId = params.sessionKey; this.runtimeLabel = `cloud-run-sandbox:${params.sessionKey}`; this.workdir = params.workspaceDir; this.workspaceDir = params.workspaceDir; } async buildExecSpec(params) { const { command, args, workdir, env, usePty } = params; const positional = ["sh", ...(args || [])]; const execArgs = ["exec"]; if (env) { for (const [key, val] of Object.entries(env)) { execArgs.push("-e", `${key}=${val}`); } } const activeWorkdir = workdir || this.workdir; if (activeWorkdir) { execArgs.push("--workdir", activeWorkdir); } execArgs.push( this.runtimeId, "--", "/bin/sh", "-c", command, ...positional ); return { argv: [SANDBOX_BINARY_PATH, ...execArgs], env: { ...process.env }, stdinMode: usePty ? "pipe-open" : "pipe-closed" }; } async runShellCommand(params) { await ensureSandboxRunning(this.runtimeId, this.workspaceDir); const spec = await this.buildExecSpec({ command: params.script, args: params.args, workdir: params.workdir, env: params.env, usePty: params.usePty, }); return new Promise((resolve, reject) => { const child = spawn(spec.argv[0], spec.argv.slice(1), { env: spec.env }); let stdout = Buffer.alloc(0); let stderr = Buffer.alloc(0); child.stdout.on("data", (data) => { stdout = Buffer.concat([stdout, data]); }); child.stderr.on("data", (data) => { stderr = Buffer.concat([stderr, data]); }); child.on("error", reject); child.on("close", (rawCode) => { const code = rawCode ?? 0; if (code !== 0 && !params.allowFailure) { const stderrStr = stderr.toString("utf8"); const summary = stderrStr.trim().split("\n").slice(-3).join(" | ").slice(0, 400); reject(Object.assign( new Error(`Cloud Run sandbox shell exited with code ${code}: ${summary}`), { code, stdout, stderr }, )); return; } resolve({ code, stdout, stderr }); }); if (params.stdin != null) { child.stdin.write(params.stdin); } child.stdin.end(); }); } } export const cloudRunSandboxManager = { async describeRuntime({ entry }) { const check = await runCommandRaw(SANDBOX_BINARY_PATH, ["exec", entry.containerName, "--", "/bin/true"]); return { running: check.code === 0, actualConfigLabel: "cloud-run-sandbox", configLabelMatch: true, }; }, async removeRuntime({ entry }) { await runCommandRaw(SANDBOX_BINARY_PATH, ["delete", entry.containerName, "--force"]); } }; export default definePluginEntry({ id: "cloud-run-sandbox-provider", name: "Cloud Run Sandbox", kind: "tool", register(api) { registerSandboxBackend("cloud-run-sandbox", { factory: async (params) => { const sanitizedSessionKey = params.sessionKey.replace(/[^a-zA-Z0-9-]/g, "-").toLowerCase(); await ensureSandboxRunning(sanitizedSessionKey, params.workspaceDir); return new CloudRunSandboxHandle({ ...params, sessionKey: sanitizedSessionKey }); }, manager: cloudRunSandboxManager }); } }); - Загрузите папку плагина в облачное хранилище:
gcloud storage cp -r plugins gs://${BUCKET_NAME}/ - Проверьте структуру хранилища Cloud Storage : убедитесь, что структура вашего хранилища содержит
openclaw.jsonв корневом каталоге и файлы плагинов вplugins/cloud-run-sandbox-provider/.gs://${BUCKET_NAME}/ ├── openclaw.json └── plugins/ └── cloud-run-sandbox-provider/ ├── package.json ├── openclaw.plugin.json └── index.mjs
- Создайте локальную директорию для плагинов:
7. Разверните OpenClaw на облачных экземплярах.
Разверните OpenClaw с помощью gcloud beta run instances create :
gcloud beta run instances create openclaw-instance \
--image ghcr.io/openclaw/openclaw:latest \
--service-account ${SERVICE_ACCOUNT} \
--port 18789 \
--cpu 4 \
--memory 4Gi \
--public \
--sandbox-launcher \
--add-volume mount-path=/home/node/.openclaw,type=cloud-storage,mount-options="uid=1000;gid=1000;file-mode=0700;dir-mode=0700",bucket=${BUCKET_NAME} \
--set-secrets GEMINI_API_KEY=gemini-api-key:latest,OPENCLAW_GATEWAY_PASSWORD=openclaw-gateway-password:latest \
--region ${REGION}
Разбивка по ключевым параметрам:
-
--image ghcr.io/openclaw/openclaw:latest: Образ контейнера OpenClaw. -
--service-account ...: Подключает выделенную учетную запись службыopenclaw-sa. -
--sandbox-launcher: Включает средство запуска песочницы Cloud Run, внедряя исполняемый файл/usr/local/gcp/bin/sandboxв контейнер для безопасного выполнения кода в изоляции с помощью gVisor. -
--add-volume ...: Монтирует хранилище Cloud Storage непосредственно в/home/node/.openclaw. Использованиеfile-mode=0700;dir-mode=0700обеспечивает правильные права доступа для OpenClaw. -
--set-secrets ...: Внедряет учетные данные непосредственно из Secret Manager в переменные среды. (Необязательно: если вы настроили Telegram на дополнительных шагах, добавьте,TELEGRAM_BOT_TOKEN=telegram-bot-token:latestк--set-secrets.) -
--public: Предоставляет публичный доступ к URL-адресу.
8. Взаимодействуйте напрямую через веб-интерфейс OpenClaw.
В OpenClaw встроен веб-интерфейс управления, позволяющий управлять вашим ИИ-агентом и общаться с ним непосредственно из браузера:
- Получите URL-адрес вашего экземпляра Cloud Run : В Cloud Shell выполните следующую команду:
gcloud beta run instances describe openclaw-instance \ --region ${REGION} \ --format="value(status.urls[0])" - Получите доступ к пользовательскому интерфейсу управления OpenClaw :
- Откройте URL-адрес результата в своем веб-браузере.
- При запросе аутентификации в пользовательском интерфейсе OpenClaw Control:
- Введите сгенерированный пароль шлюза (
${OPENCLAW_GATEWAY_PASSWORD}) из Secret Manager. - Если во всплывающем окне входа отображаются отдельные поля «Имя пользователя» и «Пароль» , оставьте поле «Имя пользователя» пустым (или введите
admin) и укажите${OPENCLAW_GATEWAY_PASSWORD}в поле «Пароль».
- Введите сгенерированный пароль шлюза (
- Начните отправлять сообщения своему агенту :
- После аутентификации вы увидите панель управления OpenClaw.
- Вы можете отправлять запросы в Gemini непосредственно из интерфейса чата, просматривать активные сеансы агентов, проверять файлы постоянного рабочего пространства и управлять инструментами!
9. (Необязательно) Проверьте интеграцию каналов обмена сообщениями.
Если вы настроили Telegram или WhatsApp на дополнительных этапах настройки, описанных выше, вы можете проверить доставку сообщений:
- Проверьте журналы экземпляра в Cloud Shell:
gcloud run instances logs read openclaw-instance --region ${REGION} --limit 20 - Откройте Telegram (или WhatsApp) и отправьте сообщение (например
/startилиHello OpenClaw!). - Бот проверит ваш идентификатор пользователя по списку разрешенных пользователей в файле
openclaw.jsonи ответит, используя Gemini!
10. (Необязательно) Расширьте возможности своего агента, добавив новые навыки.
OpenClaw поддерживает Skills — модульные пакеты возможностей, которые обучают вашего агента конкретным рабочим процессам, специализированным инструментам командной строки и инструкциям, специфичным для данной области.
Как работают навыки
Каждый навык представляет собой каталог, содержащий файл SKILL.md . Он начинается с метаданных в формате YAML ( name и description ), за которыми следуют инструкции в формате Markdown:
---
name: summarize-logs
description: Summarize Cloud Run error logs into actionable bullet points.
---
# Log Summarizer Skill
When asked to analyze or summarize logs:
1. Parse error stack traces and group similar errors by frequency.
2. Identify root causes such as memory limits, timeouts, or permission errors.
3. Propose concrete remediation steps.
name: Идентификатор навыка (также может быть вызван напрямую как команда со слэшем, например/summarize-logs).-
description: Указывает модели OpenClaw , когда следует автоматически активировать этот навык в естественном разговоре.
Добавьте пользовательский навык в свой облачный накопитель.
Поскольку ваш сегмент Cloud Storage монтируется непосредственно в /home/node/.openclaw , навыки, размещенные по адресу gs://${BUCKET_NAME}/skills/ автоматически загружаются при загрузке и сохраняются после перезапуска экземпляра:
- Создайте локальный каталог навыков :
mkdir -p my-skill cat << 'EOF' > my-skill/SKILL.md --- name: summarize-logs description: Summarize Cloud Run error logs into actionable bullet points. --- # Log Summarizer Skill When asked to analyze or summarize logs, group errors by frequency and suggest actionable fixes. EOF - Загрузите навык в облачное хранилище :
gcloud storage cp -r my-skill gs://${BUCKET_NAME}/skills/ - Используйте навык в чате :
- Вернуться в веб-интерфейс управления OpenClaw.
- Теперь вы можете управлять своим агентом с помощью команды
/summarize-logsили задавать вопросы на естественном языке, соответствующие описанию навыка!
11. Уборка
Чтобы избежать списания средств с вашего аккаунта Google Cloud за ресурсы, использованные в этом практическом задании:
- Удалите экземпляр Cloud Run :
gcloud beta run instances delete openclaw-instance --region ${REGION} --quiet - Удалить секреты менеджера секретов :
gcloud secrets delete gemini-api-key --quiet gcloud secrets delete telegram-bot-token --quiet gcloud secrets delete openclaw-gateway-password --quiet - Удалить корзину облачного хранилища :
gcloud storage rm -r gs://${BUCKET_NAME} - Удалить выделенный сервисный аккаунт :
gcloud iam service-accounts delete ${SERVICE_ACCOUNT} --quiet
12. Заключение
Поздравляем! Вы успешно развернули защищенный, полностью постоянный экземпляр OpenClaw на Cloud Run Instances, использующий Cloud Storage, Secret Manager и предпочитаемый вами канал обмена сообщениями!