Unified Agent + reusable Go agent core.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

docs: document Slack and Lark image permissions

Lyric 781dc248 3664af8a

+64 -11
+6 -1
assets/config/config.example.yaml
··· 105 105 image: 106 106 # Enabled source whitelist. 107 107 # Supported values: telegram, slack, line, lark, remote_download. 108 + # Slack image input also needs Slack bot scope files:read. 109 + # Lark image input also needs message resource permission, commonly im:resource. 108 110 sources: ["telegram", "line"] 109 111 110 112 logging: ··· 494 496 slack: 495 497 # Slack Web API base URL (override for mock/testing only). 496 498 base_url: "https://slack.com/api" 497 - # Bot token with chat:write + history scopes. Prefer env var: MISTER_MORPH_SLACK_BOT_TOKEN 499 + # Bot token with chat:write + history scopes. Add files:read when enabling Slack image input. 500 + # Prefer env var: MISTER_MORPH_SLACK_BOT_TOKEN 498 501 bot_token: "" 499 502 # App-level token for Socket Mode. Prefer env var: MISTER_MORPH_SLACK_APP_TOKEN 500 503 app_token: "" ··· 567 570 verification_token: "" 568 571 # Event subscription encrypt key. 569 572 encrypt_key: "" 573 + # For image input, grant message resource permission in the Feishu/Lark developer console 574 + # (commonly im:resource) and subscribe to im.message.receive_v1. 570 575 # Optional allowlist of chat IDs. Empty means allow all chats. 571 576 allowed_chat_ids: [] 572 577 # Group trigger mode:
+9 -1
docs/feat/feat_20260430_slack_lark_multimodal_images.md
··· 79 79 80 80 No new channel-specific config is needed in V1. 81 81 82 + Required platform permissions: 83 + 84 + - Slack: add bot scope `files:read` when `slack` is enabled in `multimodal.image.sources`; Slack file URLs such as `url_private` and `url_private_download` require a bearer token with that scope. Keep existing message scopes and Socket Mode `connections:write`. 85 + - Lark/Feishu: grant the message resource permission used by the `/im/v1/messages/:message_id/resources/:file_key` API. In current consoles this is usually found by searching for `im:resource` or the label for getting/uploading image or file resources. Keep message send/reply permissions and `im.message.receive_v1` event subscription. 86 + - After changing permissions, publish/reinstall the app so the runtime token receives the new grants. 87 + 82 88 ## 5) Shared Data Model 83 89 84 90 The smallest useful shape is still `[]string` of local image paths. ··· 154 160 - Enforce max image bytes before or during download. 155 161 - Only accept image MIME types. 156 162 - Use secure child directory creation, matching existing cache rules. 163 + - Document that Slack image download needs bot scope `files:read`. 157 164 158 165 ### 7.3 Runtime Wiring 159 166 ··· 223 230 - Enforce max image bytes. 224 231 - Only accept image MIME types. 225 232 - Keep the API method local to Lark runtime; do not create a broad Lark SDK. 233 + - Document that Lark image download needs the app permission for message resources, commonly surfaced as `im:resource`. 226 234 227 235 ### 8.3 Runtime Wiring 228 236 ··· 351 359 Download only supported image MIME types into `file_cache_dir/lark/`, enforce size limits, and pass local paths into the current LLM message. 352 360 353 361 6. Update config support lists. 354 - Add `lark` where the UI or config template lists supported image sources. 362 + Add `lark` where the UI or config template lists supported image sources, and document Slack/Lark platform permissions. 355 363 356 364 7. Add focused tests. 357 365 Cover parsing, config flags, download validation, bus image path preservation, prompt image parts, disabled image fallback, and text-only model fallback.
+30 -9
docs/lark.md
··· 1 - # Lark (Feishu) Support Plan 1 + # Lark (Feishu) Runtime 2 2 3 - This document defines the implemented `mistermorph lark` runtime shape for V1. 3 + This document defines the implemented `mistermorph lark` runtime shape. 4 4 5 5 Status on 2026-03-06: 6 6 - implemented for `private + group` text messaging 7 7 - webhook ingress, token exchange, bus runtime, delivery adapter, contacts integration, and manual sender routing are in place 8 - - V1 intentionally excludes cards, files, images, reactions, and extra identity namespaces 8 + 9 + Status on 2026-04-30: 10 + - inbound image messages can be downloaded and sent to image-capable models when `lark` is enabled in `multimodal.image.sources` 11 + - V1 still excludes cards, generic file browsing, outbound rich media, reactions, and extra identity namespaces 9 12 10 13 ## 1. Verified Platform Facts 11 14 ··· 15 18 - `tenant_access_token` is valid for 2 hours 16 19 - bot apps can subscribe to the message receive event and get messages from both private and group chats 17 20 - outbound delivery has both a general send API and a dedicated reply API 21 + - message resources, including images, are fetched through the message resource API with the app tenant token 18 22 - the same API family is exposed under both: 19 23 - `open.feishu.cn` 20 24 - `open.larksuite.com` ··· 36 40 ## 2. Scope 37 41 38 42 - Add `mistermorph lark` as a long-running webhook runtime. 39 - - Support `private + group` text conversations in V1. 43 + - Support `private + group` text conversations. 44 + - Support inbound image understanding for the current user message when `lark` is listed in `multimodal.image.sources`. 40 45 - Reuse the existing channel pipeline: 41 46 - inbound event -> bus -> per-conversation worker -> `run*Task` -> outbound bus -> delivery adapter 42 47 - Reuse shared group-trigger logic: `strict | smart | talkative`. ··· 45 50 46 51 ## 3. Non-Goals (V1) 47 52 48 - - No cards, rich post bodies, files, or image multimodal input in the first pass. 53 + - No cards, rich post bodies, generic file browsing, video, audio, or outbound rich media. 49 54 - No `message_react` parity in V1. 50 55 - No app-store or multi-tenant install flow in V1. 51 56 - No separate execution architecture just for Lark. ··· 114 119 - Start with `msg_type=text` only. 115 120 - Keep reply/send selection in the delivery adapter, not in agent logic. 116 121 117 - ## 8. Proposed CLI and Config Surface 122 + ## 8. CLI and Config Surface 118 123 119 - Planned command: 124 + Run command: 120 125 121 126 ```bash 122 127 go run ./cmd/mistermorph lark \ ··· 126 131 --lark-webhook-path /lark/webhook 127 132 ``` 128 133 129 - Planned config: 134 + Config: 130 135 131 136 ```yaml 132 137 lark: ··· 144 149 addressing_interject_threshold: 0.6 145 150 task_timeout: "0s" 146 151 max_concurrency: 3 152 + 153 + multimodal: 154 + image: 155 + sources: ["telegram", "line", "lark"] 147 156 ``` 148 157 149 158 Field notes: ··· 155 164 - typical deployment shape: 156 165 - Feishu app -> one `mistermorph lark` instance with Feishu `base_url` 157 166 - Lark app -> another `mistermorph lark` instance with Lark `base_url` 167 + - when `lark` is listed in `multimodal.image.sources`, inbound image messages are downloaded under `file_cache_dir/lark/` and passed to image-capable models as image parts 168 + - the current runtime accepts PNG, JPEG, and WebP images, keeps at most 3 images per message, and rejects images larger than 5 MiB each 158 169 159 170 Environment note: 160 171 ··· 169 180 - a self-built app with bot capability enabled 170 181 - event subscription enabled for message receive events 171 182 - message send and reply permissions granted 183 + - message resource download permissions granted when image input is enabled 172 184 - the app has been added to the target group chats or users can reach it in private chat 173 185 174 - We should not hard-code permission names into runtime logic. Validate them through startup checks and actionable logs. 186 + Set this up in the Feishu/Lark developer console: 187 + 188 + - Enable bot capability. 189 + - Subscribe to event `im.message.receive_v1`. 190 + - Grant message send/reply permission. In current Feishu/Lark consoles this is usually `im:message` or the equivalent send-as-bot message permission. 191 + - Grant receive-message permissions for the conversations you expect to handle. For group messages, use the console permission corresponding to `im:message.group_msg:readonly`; for private messages, use the corresponding P2P message permission when your tenant requires it. 192 + - Grant message resource permission for images. Search for `im:resource` or the current console label for "get/upload image or file resources". 193 + - Publish a new app version after changing permissions, then reinstall or refresh the app in the tenant. 194 + 195 + If image download fails with a "lack of permissions" style error, check `im:resource`, group/P2P message read permission, app publication status, and whether the bot is in the chat. 175 196 176 197 ## 10. Implementation Plan 177 198
+19
docs/slack.md
··· 69 69 - `im:history` 70 70 - `mpim:history` 71 71 - `chat:write` 72 + - `files:read` (required for image attachments when `slack` is enabled in `multimodal.image.sources`) 72 73 - `users:read` 73 74 74 75 Optional `Bot Token Scopes`: ··· 80 81 81 82 - `connections:write` (on `xapp-...`) 82 83 84 + Event subscriptions for Socket Mode: 85 + 86 + - `app_mention` 87 + - `message.channels` 88 + - `message.groups` 89 + - `message.im` 90 + - `message.mpim` 91 + 92 + Image attachments arrive through normal message events. The runtime reads Slack file objects from those events and downloads `url_private_download` or `url_private` with the bot token. Slack requires the token used for those URLs to have `files:read`. 93 + 83 94 After adding or changing any scope: 84 95 85 96 1. Click `Reinstall to Workspace`. ··· 113 124 addressing_interject_threshold: 0.6 114 125 task_timeout: "0s" 115 126 max_concurrency: 3 127 + 128 + multimodal: 129 + image: 130 + sources: ["telegram", "line", "slack"] 116 131 ``` 132 + 133 + When `slack` is listed in `multimodal.image.sources`, inbound Slack images are downloaded under `file_cache_dir/slack/` and passed to image-capable models as image parts. The current runtime accepts PNG, JPEG, and WebP images, keeps at most 3 images per message, and rejects images larger than 5 MiB each. If `slack` is not listed, image-only messages get a text fallback asking the user to describe the image. 117 134 118 135 ## 7. Run Example 119 136 ··· 131 148 - `xoxb` is invalid/expired/mis-copied, or installed in the wrong workspace. 132 149 - `slack users.info failed: missing_scope` 133 150 - Bot token is missing `users:read`, or scope changed without reinstall/token refresh. 151 + - `slack image download http 403` or image-only messages cannot be read 152 + - Bot token is missing `files:read`, the app was not reinstalled after adding it, or the bot is not in the conversation where the file was shared. 134 153 - `slack_emoji_catalog_load_failed ... slack emoji.list failed: missing_scope` 135 154 - Bot token is missing `emoji:read`; `message_react` will not be registered until emoji catalog can be loaded. 136 155 - `slack apps.connections.open failed: not_allowed_token_type`