OpenClaw Hooks — Notify Discord at gateway startup

Step-by-step guide to create a startup hook that sends a Discord notification 03/17/2026

I recently set up Alfred — my personal coding assistant — and needed a reliable way to know exactly when it's ready to work. Unlike always-on services, Alfred runs on-demand: I boot it via Wake-on-LAN when I need it and shut it down when I'm done. To receive a notification when the gateway becomes operational, I implemented an OpenClaw hook.

This article explains step by step how to create a hook that sends a Discord notification at gateway startup. Whether you want to track availability, monitor boot performance, or simply get a ping when your assistant is ready, this guide will get you there.

Prerequisites

Before we begin, make sure you have:

  • OpenClaw installed and configured on your machine
  • Administrative access to the machine where the gateway runs
  • A Discord account and a channel or DM where you want to receive notifications
  • Basic familiarity with JavaScript/Node.js for the handler implementation

You'll also need to decide whether you want to use OpenClaw's built-in Discord integration (which uses openclaw message send) or connect directly via a Discord webhook.

Hook anatomy

Every OpenClaw hook consists of two parts: a manifest (HOOK.md) that declares what the hook does and when it fires, and a handler (typically handler.js) that implements the actual logic.

The manifest is a YAML front-matter document that specifies the hook's metadata. Here's a minimal example:


---
name: discord-notify
description: "Sends a Discord DM when the gateway boots"
metadata: {
  "openclaw": {
    "emoji": "🚀",
    "events": ["gateway:startup"]
  }
}
---
                

Key fields:

  • name: unique identifier for the hook
  • description: brief summary of its purpose
  • metadata.openclaw.emoji: an emoji to display in hook listings
  • metadata.openclaw.events: array of events that trigger this hook (in this case, gateway:startup)

Available events include gateway:startup, gateway:shutdown, agent:spawn, and more. For our use case, gateway:startup is exactly what we need.

Handler implementation

The handler is a JavaScript module that exports an async function. OpenClaw passes an event object containing contextual information about what triggered the hook.

Here's a complete example that sends a message via OpenClaw's native Discord integration:


import { execSync } from 'child_process';

const handler = async (event) => {
  if (event.type !== "gateway" || event.action !== "startup") return;

  // Extract useful information from the context
  const version = event.context?.cfg?.meta?.lastTouchedVersion || "Unknown";
  const aiModel = event.context?.cfg?.agents?.defaults?.model?.primary || "Default model";
  const bootTime = new Date().toLocaleTimeString('en-US');

  const message =
    `🚀 **Alfred is online!** | 🤖 Model: ${aiModel} | 📦 Version: ${version} | ⏰ ${bootTime}`;

  console.log(`[discord-notify] Sending Discord report (${aiModel} - v${version})...`);

  try {
    // Replace with your target channel or DM ID
    execSync(
      `openclaw message send --channel discord --target "YOUR_CHANNEL_ID" --message "${message}"`
    );
  } catch (error) {
    console.error("Discord notification failed:", error.message);
  }
};

export default handler;
                

Notes on this approach:

  • We check the event.type and event.action to ensure we're responding to the right event.
  • Information about the AI model, version, and boot time is extracted from the event context.
  • The message is formatted with Markdown and sent via the openclaw message send command.

Alternative approach: Instead of using OpenClaw's Discord integration, you can send directly via a Discord webhook:


import { execSync } from 'child_process';
import { readFile } from 'fs/promises';

const handler = async (event) => {
  if (event.type !== "gateway" || event.action !== "startup") return;

  const version = event.context?.cfg?.meta?.lastTouchedVersion || "Unknown";
  const aiModel = event.context?.cfg?.agents?.defaults?.model?.primary || "Default model";
  const bootTime = new Date().toLocaleTimeString('en-US');

  const webhookUrl = process.env.DISCORD_WEBHOOK_URL;
  if (!webhookUrl) {
    console.error("DISCORD_WEBHOOK_URL environment variable not set");
    return;
  }

  const message = {
    content: `🚀 **Alfred is online!** | 🤖 Model: ${aiModel} | 📦 Version: ${version} | ⏰ ${bootTime}`
  };

  console.log(`[discord-notify] Sending webhook notification...`);

  try {
    execSync(
      `curl -X POST -H "Content-Type: application/json" -d '${JSON.stringify(message)}' "${webhookUrl}"`,
      { stdio: 'inherit' }
    );
  } catch (error) {
    console.error("Webhook notification failed:", error.message);
  }
};

export default handler;
                

This variant uses environment variables to securely store your webhook URL and makes a direct HTTP POST to Discord's API.

Install & enable

Once your hook is ready, follow these steps to install and test it:

  1. Create the hook directory — each hook lives in its own folder:
    
    mkdir -p ~/.openclaw/hooks/discord-notify
                            
  2. Add the files — place HOOK.md and handler.js in the new directory:
    
    ~/.openclaw/hooks/discord-notify/
    ├── HOOK.md
    └── handler.js
                            
  3. Enable the hook:
    
    openclaw hooks enable discord-notify
                            
  4. Verify installation:
    
    openclaw hooks list
                            
  5. Test it by restarting the gateway:
    
    openclaw gateway restart
                            

After the gateway restarts, you should receive a Discord notification with the model name, version, and boot time.

Security considerations

When implementing hooks, keep these security best practices in mind:

  • Never store credentials in plain text. Use environment variables or OpenClaw's secure configuration system.
  • Be cautious with shell commands. Hooks that execute external commands may trigger approval requirements depending on your security policy.
  • Validate event data. Don't blindly trust information from the event object, especially if you're using it in shell commands.
  • Use the principle of least privilege. Only request permissions that are absolutely necessary for your hook to function.

For webhook-based notifications, storing the webhook URL in an environment variable is safer than hardcoding it in your handler script.

Variants & troubleshooting

Once you have the basic hook working, you can extend it in various ways:

  • Different destinations: Send to a public channel instead of a DM, or create multiple hooks for different purposes.
  • Enriched notifications: Add more details like local IP address, system uptime, or a changelog of the current version.
  • Other events: Trigger on agent:spawn, session:ready, or custom events specific to your use case.
  • Error handling: Implement retry logic with exponential backoff for transient failures.
  • Logging: Add structured logging for debugging and monitoring hook behavior in production.

Troubleshooting tips:

  • If you don't receive a notification, check the hook logs with openclaw hooks logs discord-notify.
  • Verify that your Discord credentials or webhook URL are correctly configured.
  • Ensure the gateway has network access to Discord's API (especially for webhook-based approaches).
  • Test your handler locally by simulating the event if debugging is needed.

Conclusion

OpenClaw hooks provide a powerful and straightforward way to automate tasks at key moments in your assistant's lifecycle. For my use case with Alfred, they give me a reliable signal when the gateway is ready — and open the door to automating post-boot tasks like health checks, context reloading, or monitoring tasks.

The combination of a simple manifest-based interface and JavaScript handlers makes it easy to customize notifications, integrations, and workflows to your exact needs. Whether you're tracking availability, monitoring boot performance, or just getting a friendly ping when your assistant comes online, hooks are the right tool for the job.

For more information, check out the official OpenClaw hooks documentation.

Share On