Skip to content

Connecting OpenClaw to LINE

Setting up a bot to talk to users where they already hang out is one of those tasks that sounds easy until you’re staring at webhook logs and signature errors. If you are building for users who live on LINE, you want a setup that handles the heavy lifting of the Messaging API so you can focus on the actual logic.

The LINE plugin for OpenClaw connects your gateway to the LINE Messaging API. It supports everything from basic text and group chats to media, locations, and those fancy Flex messages. While it doesn’t handle reactions or threads yet, it covers almost everything else you need for a solid integration.

First, you need to get the plugin into your environment. You can install it directly via the CLI:

Terminal window
openclaw plugins install @openclaw/line

If you are working from a local git repo and want to use a local checkout, use this instead:

Terminal window
openclaw plugins install ./path/to/local/line-plugin

To get things moving, you’ll need to head over to the LINE Developers Console.

  1. Create or select a Provider and add a Messaging API channel.
  2. Grab your Channel access token and Channel secret from the settings.
  3. Make sure you enable Use webhook in the Messaging API tab.
  4. Point your webhook URL to your gateway (it must be HTTPS):
https://gateway-host/line/webhook

The gateway handles both the GET request for verification and the POST events for actual messages. If you want a different path, you can change it in the config using channels.line.webhookPath or channels.line.accounts.<id>.webhookPath.

Just a heads-up on security: LINE uses body-dependent HMAC signatures. OpenClaw is pretty strict here—it uses the raw request bytes to verify signatures and ignores any body values modified by upstream middleware to keep things safe.

For a basic setup, you just need to drop your credentials into your config file.

Minimal config:

{
channels: {
line: {
enabled: true,
channelAccessToken: "LINE_CHANNEL_ACCESS_TOKEN",
channelSecret: "LINE_CHANNEL_SECRET",
dmPolicy: "pairing",
},
},
}

If you prefer using environment variables for the default account, you can use these:

  • LINE_CHANNEL_ACCESS_TOKEN
  • LINE_CHANNEL_SECRET

You can also store your credentials in files:

{
channels: {
line: {
tokenFile: "/path/to/line-token.txt",
secretFile: "/path/to/line-secret.txt",
},
},
}

Note that tokenFile and secretFile have to be regular files; symlinks won’t work.

If you are managing multiple LINE accounts, you can define them like this:

{
channels: {
line: {
accounts: {
marketing: {
channelAccessToken: "...",
channelSecret: "...",
webhookPath: "/line/marketing",
},
},
},
},
}

By default, direct messages use a “pairing” system. If someone unknown sends a message, they get a pairing code, and you’ll need to approve them before the agent starts responding.

Terminal window
openclaw pairing list line
openclaw pairing approve line <CODE>

You can control who gets through using policies:

  • channels.line.dmPolicy: Choose between pairing, allowlist, open, or disabled.
  • channels.line.allowFrom: A list of specific LINE user IDs allowed for DMs.
  • channels.line.groupPolicy: Choose between allowlist, open, or disabled.
  • channels.line.groupAllowFrom: User IDs allowed to use the bot in groups.
  • Per-group overrides: Use channels.line.groups.<groupId>.allowFrom.

Keep in mind that LINE IDs are case-sensitive. Users start with U, groups with C, and rooms with R, followed by 32 hex characters.

The plugin handles some of the quirks of the LINE platform for you:

  • Long text is automatically split into 5000-character chunks.
  • Markdown is stripped out, but the plugin tries to turn code blocks and tables into Flex cards.
  • Since LINE doesn’t support native streaming, responses are buffered. Your users will see a loading animation while the agent is thinking, and then receive the full chunks.
  • Media downloads are limited to 10MB by default, but you can change this with channels.line.mediaMaxMb.

If you want to send something more interesting than plain text, you can use channelData.line. This lets you send quick replies, locations, or complex Flex cards.

{
text: "Here you go",
channelData: {
line: {
quickReplies: ["Status", "Help"],
location: {
title: "Office",
address: "123 Main St",
latitude: 35.681236,
longitude: 139.767125,
},
flexMessage: {
altText: "Status card",
contents: {
/* Flex payload */
},
},
templateMessage: {
type: "confirm",
text: "Proceed?",
confirmLabel: "Yes",
confirmData: "yes",
cancelLabel: "No",
cancelData: "no",
},
},
},
}

There is also a handy /card command for quick Flex message presets:

/card info "Welcome" "Thanks for joining!"

The LINE plugin supports Agent Communication Protocol (ACP) conversation bindings. This is great for keeping a session tied to a specific chat.

  • Use /acp spawn <agent> --bind here to bind the current LINE chat to an ACP session.

Check out the ACP agents documentation for more on how this works.

When your agent needs to send files, the plugin handles the delivery path specifically for LINE:

  • Images: Sent as native image messages with previews.
  • Videos: Sent with proper preview and content-type handling.
  • Audio: Sent as native audio messages.

If a LINE-specific path isn’t available, it will try to fall back to the standard image route.

If things aren’t working as expected, check these common issues:

  • Webhook verification fails: Double-check that your URL is HTTPS and your channelSecret is exactly what’s in the LINE console.
  • No inbound events: Make sure the webhook path in your config matches what you entered in the LINE console and that your gateway is publicly reachable.
  • Media download errors: If files are getting cut off, try increasing the channels.line.mediaMaxMb limit.

Need help getting this running? Try the AI Setup Assistant.

OpenClaw

OpenClaw Expert

Still stuck?

If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.