iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
💬

Practical Approach to Building AI Agents with LINE

に公開

Hello! I'm peintangos. There are many AI interfaces we interact with daily, such as ChatGPT, Claude, Discord, and Slack. On the other hand, for personal communication in Japan, LINE has a significant presence. According to LY Corporation's FY2024 Integrated Report, LINE has approximately 98 million monthly active users in Japan. So, how well can an AI agent's responses be represented on LINE? In this article, I would like to organize the results of my experience experimenting with the Messaging API, LIFF, and the LINE Bot MCP Server.

Understanding LINE's two interfaces

Before diving into the verification, let's organize the overall picture of the LINE development platform. When you try to build something on LINE, there are broadly two layers.

Messaging API

This is a REST API for creating what is known as a "LINE Bot." When a user sends a message, a notification is sent to your server via a webhook, and you respond by hitting the API. You can send text, images, Flex Messages (rich card UI), and more. Since the interaction is completed within the chat screen, it provides a simple experience for the user: "just talking on LINE." However, the formats of messages you can send are limited to those defined by LINE. Experiences like streaming responses like ChatGPT, direct rendering of Markdown, or displaying AI-generated dynamic UI on the spot are difficult to achieve with just the Messaging API chat screen.

LIFF (LINE Front-end Framework)

LIFF is a mechanism for web apps that open within the LINE app. A WebView launches inside LINE, and you can display a web app you created there. Because you can use HTML/CSS/JavaScript, the UI flexibility is higher than the Messaging API, allowing for expressions closer to standard web apps. Using the LIFF SDK, you can obtain LINE user profiles within the scope of consent and, under certain conditions, send messages to the chat room.

Comparison Table

Messaging API LIFF
Overview REST API WebView within LINE
UI Flexibility Template-based High with HTML/CSS/JS
Streaming Not available Possible (SSE / WebSocket)
Markdown Not supported Possible with react-markdown etc.

Conclusion first

Here is a summary of the verification results. In addition to the two interfaces above, I have also included the "LINE Bot MCP Server" announced in April 2025 for comparison.

Function Messaging API LIFF MCP Server
Text sending / response ○ (Send)
Rich card UI (Flex Message) ○ (Send)
Follow-up suggestions (Quick Reply)
Loading animation
Streaming display
Markdown rendering
MCP UI-like interaction

In conclusion, I felt that the Messaging API is basically sufficient for creating AI agents on LINE. The Messaging API is capable of not only simple text responses but also displaying card UIs when necessary and providing next actions via Quick Reply.
On the other hand, the Messaging API does not support displaying message UIs other than those defined by LINE, and is not suitable for experiences like ChatGPT-like streaming, direct Markdown rendering, or complex UI such as forms or dashboards. In those cases, you would navigate to LIFF, but LIFF is technically almost a web app. In other words, the value of LIFF is not in "new UI technology" but in being able to use LINE's user context, traffic flow, and distribution channels. Therefore, realistically, I felt that a structure where you basically converse via the Messaging API and navigate to LIFF only when necessary is the best balance. Below, I will look at the concrete verification details.

Verification of Messaging API

Text response + loading animation

This is the simplest configuration. You receive the user's message via webhook, send it to Claude, and return it as text. However, AI inference can take from several to over ten seconds. Therefore, we use the loading animation API to indicate that the system is "processing."

Interaction via Messaging API
Simple chat bot

// lib/line/loading-animation.ts
export async function showLoadingAnimation(userId: string): Promise<void> {
  try {
    await lineClient.showLoadingAnimation({
      chatId: userId,
      loadingSeconds: 60,
    });
  } catch {
    // Ignore errors as this does not work in group chats
  }
}

There is one point to note. Webhooks are required to "return 200 within 2 seconds" from the LINE platform. If you wait for the AI inference to finish before returning, you won't make it in time. Therefore, you need a design that processes inference asynchronously and pushes the result after it's complete.

Representing Markdown with Flex Message

Text messages in the Messaging API do not support Markdown. Sending ### Heading or **Bold** will result in them being displayed as raw characters. However, things change if you use Flex Message. Flex Message is a message format that allows you to build rich card UIs based on CSS Flexbox.

Display via Flex Message
Representations like tables, titles, and bold are possible

In this experiment, I used a third-party library called markdown-flex-message to automatically convert Claude's Markdown output into Flex Message. When actually displayed, the rounded corners of the chat bubbles differ from standard text messages. Since Flex Message uses a custom layout, it looks a little different from regular chat bubbles.

// lib/line/flex/markdown-to-flex.ts
export async function markdownToFlex(
  markdown: string,
  altText?: string,
): Promise<FlexMessage | null> {
  try {
    const { flexMessage } = await convertToFlexMessage(markdown);
    if (altText) {
      flexMessage.altText = altText;
    }
    return flexMessage;
  } catch {
    return null;
  }
}

Quick Reply

I extracted "questions the user might ask next" from Claude's response and displayed them as buttons at the bottom of the chat.

Display via Quick Reply
Tapping a gray button sends a message

In AI chat, users may sometimes wonder what to ask next. By using Quick Reply, you can naturally present next-question candidates as a LINE UI. For example, after the AI provides a technical explanation, you can offer candidates like:

  • Ask for more details
  • Provide sample code
  • Compare pros and cons

Main message formats supported by the Messaging API

In this verification, I tried text / Flex Message / Quick Reply, but the Messaging API supports various other message formats as well.

Message format Overview
Text Plain text + LINE emojis
Sticker Sent with package ID + sticker ID
Image Original image URL + preview URL
Video Video URL + preview image. Plays on tap
Audio Audio file URL + playback duration
Location Map including title, address, latitude/longitude
Image Map Multiple tap areas set on a single image
Template 4 types: button / confirm / carousel / image carousel
Flex Message Free layout based on CSS Flexbox

As for AI agent responses, text + Flex Message will be the main approach. However, it is also possible to expand to include returning image messages in combination with AI image generators or providing answers that include location information. Next, let's look at LIFF.

Verification of LIFF

SSE streaming

The Messaging API does not support streaming displays. However, since LIFF is a web app, you can achieve token-by-token streaming similar to ChatGPT by using SSE (Server-Sent Events).

Streaming display in LIFF
Since it is streamed, the user waiting time is short

On the server side, I use streamText from the Vercel AI SDK, and on the client side, I receive it using the useChat hook. When you open the LIFF screen, you get an experience similar to ChatGPT within the LINE app. It feels like the characters are smoothly streaming in. This experience is fundamentally different from the "loading -> full text display" approach of the Messaging API.

// app/api/liff/chat/route.ts
const result = streamText({
  model: anthropic("claude-haiku-4-5-20251001"),
  system: SYSTEM_PROMPT,
  messages: modelMessages,
});

return result.toUIMessageStreamResponse();

Markdown rendering

Since LIFF is a web app, you can use react-markdown as it is. It also supports GFM tables with remark-gfm and syntax highlighting with rehype-highlight. For technical answers that frequently involve code and tables, rendering Markdown directly on LIFF is more natural than converting it to Flex Messages in the Messaging API.

Criteria for choosing LIFF

You might think after reading this far, "Isn't that just a regular web app?" In fact, technically, it is almost the same. In this experiment, the only LIFF-specific function I used was displaying the profile. The value of LIFF lies not in UI technology, but in user linkage without authentication via liff.getProfile() and the navigation path that allows transition with a single tap from the chat screen or rich menu. That said, for many use cases, the Messaging API is sufficient. You should consider transitioning to LIFF when streaming, beautiful Markdown rendering, or custom UIs like forms or dashboards are necessary. However, please be aware that since the user is transitioning from the chat screen to a WebView, the continuous experience for the user may be lost.

Verification of LINE Bot MCP Server

LINE Bot MCP Server is an MCP server released by the official LINE team in April 2025. It allows you to operate the Messaging API from MCP clients such as Claude Desktop. For setup, add the following to claude_desktop_config.json.

{
  "mcpServers": {
    "line-bot": {
      "command": "npx",
      "args": ["@line/line-bot-mcp-server"],
      "env": {
        "NPM_CONFIG_IGNORE_SCRIPTS": "true",
        "CHANNEL_ACCESS_TOKEN": "YOUR_TOKEN",
        "DESTINATION_USER_ID": "YOUR_USER_ID"
      }
    }
  }
}

Just by saying "Send 'Hello' on LINE" in Claude Desktop, the message is delivered to LINE.

Sending from Claude Desktop
Claude Desktop side

Received on LINE
Message received on the LINE side

It is currently a preview version, but it supports 12 tools.

Tool Name Overview
push_text_message Send text to a specific user
push_flex_message Send Flex Message to a specific user
broadcast_text_message Broadcast text to all followers
broadcast_flex_message Broadcast Flex Message to all followers
get_profile Get user profile
get_follower_ids Get list of follower IDs
get_message_quota Show monthly message limit and usage
get_rich_menu_list Get list of rich menus
create_rich_menu Create rich menu (including image generation)
delete_rich_menu Delete rich menu
set_rich_menu_default Set default rich menu
cancel_rich_menu_default Cancel default rich menu

Criteria for using LINE Bot MCP Server

If you just want to "send messages to LINE from an AI agent," this is sufficient without needing to implement the Push API yourself. However, this is not a bot that automatically responds to webhooks, but a sending and management tool for operating the official LINE account from an MCP client. In other words, it is suitable for cases where you want to send notifications to LINE from a local AI assistant like Claude Desktop. If you are building an AI agent that runs 24/7 on the cloud, it is simpler to use the Messaging API's Webhook, Reply API, and Push API directly. Note that recently, mechanisms like MCP Apps (where tools can return interactive UI components as an MCP extension) have emerged, providing experiences where AI dynamically generates UI to display on the spot. LINE does not have such a mechanism, and at this point, its position is an interface that "receives and displays AI output."

Summary

  • Even with just the Messaging API, you can create a decent AI chat experience using Flex Message + Quick Reply + loading animations. For many use cases centered on questions and answers, this is enough.
  • You can use LIFF in situations where streaming or Markdown is required. However, LIFF is technically close to a regular web app, and the unique value of LINE lies in the "user context" and the "navigation path from the chat screen."
  • The LINE Bot MCP Server is convenient for AI → LINE messaging. However, since it is a sending/management tool for local AI assistants, it may be simpler to use the Messaging API's Push API directly when running AI agents in the cloud.
  • Realistically, I felt that a combination of "conversing via the Messaging API and transitioning to LIFF only when necessary" is the best-balanced approach.

If the purpose is to call a personal resident AI assistant from LINE, options like existing platforms such as OpenClaw come into play. However, for business-oriented bots, unique UIs, granular permission management, log management, and integration with existing systems, the design of using the Messaging API as a base and combining it with LIFF as needed is a viable approach, which was the result of this experiment.

https://github.com/peintangos/line-app-sample

References

The End

Discussion