Feishu OpenPlatform Server SDK for Java

repository·v2_main·Indexed 43 days ago

https://github.com/larksuite/oapi-sdk-java

A high-level, type-safe Java SDK for interacting with Feishu/Lark services. It automates token management, security verification, and event handling. Features include the LarkChannel facade for building conversational bots and AI Agents with support for message normalization, streaming output, and WebSocket/Webhook transports, as well as tools for app registration and permission management.

Tokens
23.8K
Snippets
55
Records
91
Agent score
54%

What's inside Lark

  1. Overview of Feishu OpenPlatform Server SDK

    v2_main

    The Feishu OpenPlatform Server SDK is designed to simplify interacting with Feishu/Lark open APIs. It automates complex server-side logic such as:

    • Obtaining and maintaining access tokens.
    • Encrypting and decrypting data.
    • Verifying request signatures.
    • Providing a comprehensive type system and semantic programming interfaces to reduce coding overhead compared to raw API calls.
  2. What is LarkChannel and when to use it

    v2_main

    LarkChannel is a high-level abstraction in the Java SDK designed for conversational bots and AI Agents. It encapsulates WebSocket/Webhook event ingestion, message normalization, security policies, message sending, streaming output, resource management, and interactive components (cards/reactions) into a single unified interface.

    When to use LarkChannel:

    • Building AI Agents, customer service assistants, or knowledge base bots.
    • Long-term monitoring of 1-on-1 chats, group chats, card actions, reactions, or document comments.
    • When you need to convert raw Lark events into a unified NormalizedMessage format.
    • When you require built-in security policies like deduplication, expiration filtering, or @mention requirements.
    • When you need streaming responses (e.g., an Agent generating text incrementally).

    When to use Client instead:

    • If you only need to occasionally call a specific Open Platform API without maintaining a continuous conversational session.
    // Use LarkChannel for conversational logic, Client for one-off API calls.
    LarkChannel channel = LarkChannelFactory.createLarkChannel(...);
  3. How to request custom scopes, events, and callbacks during registration

    v2_main

    You can use the addons parameter in RegisterAppOptions to incrementally request specific permissions, event subscriptions, or callbacks. These are pre-filled on the user's confirmation page.

    Key Concepts

    • Additive Only: addons are merged on top of the platform's base template. You cannot remove base permissions via addons.
    • Base Template Switch:
      • addons.preset(true) (default): Uses the platform's default template.
      • addons.preset(false): Switches to a minimal base template (bot capability only). This allows you to declare the full configuration via addons.
    • Supported Types: Only tenant/user scopes, tenant/user events, and callbacks are supported. Sensitive configurations (like event request URLs or encryption keys) must be updated via the update application config OpenAPI instead.

    Usage Scenarios

    1. Create a new app with specific permissions

    RegisterApp.register(RegisterAppOptions.newBuilder()
            .addons(AppAddons.newBuilder()
                    .tenantScopes("im:message:send_as_bot")
                    .userScopes("calendar:calendar:read")
                    .tenantEvents("im.message.receive_v1")
                    .callbacks("card.action.trigger")
                    .build())
            .createOnly(true)
            .onQRCode(info -> System.out.println(info.getUrl()))
            .build());

    2. Update an existing app

    Pass the existing appId to allow the user to confirm incremental changes.

    RegisterApp.register(RegisterAppOptions.newBuilder()
            .appId("cli_xxx")
            .addons(AppAddons.newBuilder()
                    .tenantScopes("drive:drive.metadata:readonly")
                    .build())
            .onQRCode(info -> System.out.println(info.getUrl()))
            .build());

    3. Use a minimal base template

    Set preset(false) to ensure the confirmation page only shows the configuration you explicitly declare.

    RegisterApp.register(RegisterAppOptions.newBuilder()
            .addons(AppAddons.newBuilder()
                    .preset(false)
                    .tenantScopes("im:message:send_as_bot")
                    .build())
            .onQRCode(info -> System.out.println(info.getUrl()))
            .build());
  4. Configure the global Config object

    v2_main

    The Config object is the central configuration for the SDK. It requires your AppSettings and an implementation of IStore to manage access tokens (app_access_token, tenant_access_token) and temporary credentials (app_ticket).

    Important: It is highly recommended to use a Redis implementation for IStore to support distributed storage and to reduce the frequency of token refresh calls, which helps avoid rate limiting.

    // Using Domain enum (Recommended)
    Config config = new Config(Domain.FeiShu, appSettings, store);
    
    // Using a custom domain string
    Config config = new Config("https://open.feishu.cn", appSettings, store);
  5. When to use `includeRawEvent(true)`

    v2_main
    By default, the SDK provides normalized models for events. You should only enable includeRawEvent(true) if your application requires access to fields not exposed by these normalized models, such as raw event headers or specific tenant metadata.
  6. Integrate Channel and Agent with LarkChannel

    v2_main

    For AI Agents, bots, customer service assistants, or knowledge base Q&A, use the LarkChannel high-level session channel. It abstracts WebSocket/Webhook event ingestion, message normalization, security policies, reply sending, streaming output, resource management, card actions, and emoji reactions into a unified Java interface.

    When to use:

    • Use Client for occasional API calls.
    • Use LarkChannel for long-term message listening, context understanding, and automated responses.

    Core Workflow:

    1. Create a channel using LarkChannelFactory.createLarkChannel(...).
    2. Call connect() to start listening. It returns a CompletableFuture<BotIdentity> to access the bot's identity.
    3. Listen for events using .on("message", handler), .on("cardAction", handler), or .on("reject", handler).
    4. Respond using send(...) or stream results using stream(...).
    5. Configure security via policy(...) (e.g., group chat whitelists, single-chat mode, or requiring @mentions).
    6. Enable includeRawEvent(true) only if you specifically need original event fields.
    // Conceptual usage pattern
    LarkChannel channel = LarkChannelFactory.createLarkChannel(...);
    channel.connect().thenAccept(identity -> {
        channel.on("message", (context, event) -> {
            channel.send(...);
        });
    });
  7. How LarkChannel works: Core Concepts

    v2_main

    The LarkChannel facade is designed for chat workflows: Receive event $\rightarrow$ Normalize $\rightarrow$ Apply Safety $\rightarrow$ Execute Logic $\rightarrow$ Reply.

    Key abstractions include:

    • Lifecycle: Managed via connect() and disconnect() to handle WebSocket handshakes and resource release.
    • Normalization: NormalizedMessage provides a unified view of content, mentions, and context, shielding you from raw Feishu event differences.
    • Safety: PolicyConfig and SafetyConfig manage how the bot interacts with groups/DMs and how it handles message deduplication and stale events.
    • Transport: Supports websocket (default, best for Agents/local dev) and webhook (requires a dispatcher for HTTP entry points).
  8. Configure Channel security policies

    v2_main

    The SDK includes a PolicyConfig to control how the bot interacts with messages. By default, the SDK is optimized for Agent scenarios (e.g., requiring a mention in group chats).

    Key Policy Settings:

    • setGroupAllowlist(String chatId): Only allow messages from these groups.
    • setDmMode(String mode): Control Direct Message behavior (e.g., using an allowlist).
    • setDmAllowlist(String userId): Only allow DMs from these users.
    • setRequireMention(boolean): If true, the bot ignores group messages that don't @ it.
    • setRespondToMentionAll(boolean): If true, the bot responds to @all even if not specifically @'d.

    Handling Rejected Events: When a message is blocked by policy, a reject event is triggered. You can listen for this using channel.on("reject", ...) to inspect the RejectEvent, which contains the reason (e.g., no_mention, group_not_allowed, mention_all_blocked).

    LarkChannelOptions.PolicyConfig policy = new LarkChannelOptions.PolicyConfig();
    policy.setGroupAllowlist("oc_allowed_group");
    policy.setDmMode("allowlist");
    policy.setDmAllowlist("ou_allowed_user");
    policy.setRequireMention(true);
    policy.setRespondToMentionAll(false);
    
    LarkChannel channel = LarkChannelFactory.createLarkChannel(
            LarkChannelOptions.newBuilder(appId, appSecret)
                    .policy(policy)
                    .build()
    );
    
    // Listen for rejections
    channel.on("reject", new ChannelEventHandler<RejectEvent>() {
        @Override
        public void handle(RejectEvent event) {
            System.out.println(event.getReason().getValue());
        }
    });
  9. Understand Larksuite terminology

    v2_main

    Before developing, familiarize yourself with these core concepts:

    • Feishu (飞书): The name for Lark in China, operating on independent domains (e.g., feishu.cn).
    • Developer Documentation (开发文档): The reference for all Open Platform APIs. Use the search function for efficient querying.
    • Developer Console (开发者后台): The management interface for your applications.
    • Enterprise Self-built App (企业自建应用): An application that can only be installed and used within your own enterprise.
    • App Store App (应用商店应用): An application listed in the App Directory that various enterprises can choose to install.
  10. How to use LarkChannel for Agent and Bot integration

    v2_main

    LarkChannel is a high-level conversation facade designed for building conversational bots, AI Agents, support assistants, or knowledge-base assistants. It centralizes event intake, message normalization, safety policies, replies, streaming output, media management, and card actions into a single Java entry point.

    When to use LarkChannel vs Client:

    • Use LarkChannel: For long-running chat workflows, conversational bots, or services that need to receive messages and reply within the same chat context.
    • Use Client: For small, one-off API calls that do not require conversational state or event handling.
  11. Quick Start with LarkChannel

    v2_main

    Use LarkChannel for conversational bot and Agent scenarios. It provides a unified entry point for event intake (WebSocket/Webhook), message normalization, safety policies, and messaging (replies, streaming, media).

    To get started, create a channel using LarkChannelFactory, define an event handler for message events using NormalizedMessage, and call connect() to resolve the bot's identity.

    LarkChannel channel = LarkChannelFactory.createLarkChannel(
            LarkChannelOptions.newBuilder(System.getenv("APP_ID"), System.getenv("APP_SECRET"))
                    .transport("websocket")
                    .build()
    );
    
    channel.on("message", new ChannelEventHandler<NormalizedMessage>() {
        @Override
        public void handle(NormalizedMessage message) {
            channel.send(
                    message.getChatId(),
                    SendInput.markdown("Received: " + message.getContent()),
                    SendOptions.newBuilder().replyTo(message.getMessageId()).build()
            );
        }
    });
    
    BotIdentity identity = channel.connect().get();