iTranslated by AI
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."

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.

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.

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).

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.

Claude Desktop side

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.
References
- Messaging API documentation - LINE Developers
- Messaging API reference - LINE Developers
- Flex Message elements - LINE Developers
- Loading indicator - LINE Developers
- LIFF documentation - LINE Developers
- Differences between LIFF browser and external browser - LINE Developers
- LIFF v2 API reference - LINE Developers
- line/line-bot-mcp-server - GitHub
- markdown-flex-message - GitHub
- LY Corporation Integrated Report FY2024
The End
Discussion