Feishu/Lark Integration
AgentHub uses Feishu/Lark as a collaboration surface: bot messages, event subscriptions, interactive cards, and an H5/workbench entry. Product login and account binding still belong to TokenDance ID.
Identity boundary
Do not describe Feishu OAuth as AgentHub product login. Feishu user identifiers are collaboration context only. TokenDance ID remains the identity authority and owns account binding.
Integration Boundary
flowchart LR
Client["Feishu/Lark Client"] --> App["AgentHub Bot, Cards, H5"]
App --> Gateway["Feishu Integration Gateway"]
Gateway --> Hub["AgentHub Hub Server"]
Hub --> ID["TokenDance ID"]
ID --> Binding["Feishu Account Binding"]
The Feishu app should stay focused on collaboration entry points:
- receive direct messages and group @mentions;
- send bot replies and task cards;
- process card action callbacks;
- open AgentHub in an H5/workbench surface;
- hand off identity and binding to TokenDance ID.
Production Ingress
Production should keep an HTTPS webhook gateway as the durable event ingress. The gateway should expose separate routes for message events and card actions:
POST /integrations/feishu/events
POST /integrations/feishu/card-actions
The webhook path handles URL challenge, signature/encryption checks, event deduplication, token caching, message parsing, and fast acknowledgement. Slow AgentHub work should be queued asynchronously.
SDK long-connection receiving is useful for enterprise self-built app development and internal testing, but it should not be the only production path or the sole option for future cross-tenant event delivery.
App Setup Checklist
Use this checklist before claiming that a Feishu/Lark integration is ready for user testing. Keep real app ids, secrets, tenant ids, callback tokens, and approval screenshots out of this public repository.
| Step | Public-safe requirement | Evidence to keep |
|---|---|---|
| App model | Choose an enterprise self-built app or an explicitly approved deployment shape | Private implementation note with owner and tenant scope |
| Bot entry | Enable bot messages for direct messages and group @mentions | Screenshot or tenant config evidence in private ops docs |
| Event subscriptions | Subscribe only to im.message.receive_v1 and card.action.trigger for MVP | Event subscription list with approval owner |
| URL challenge | Webhook returns the platform challenge body before business logic | Redacted request id and success timestamp |
| Signature and encryption | Verify token and signature, and decrypt the payload before parsing the event body | Unit/integration test result, no raw payload in public docs |
| Scopes | Request only bot/message/card/H5 scopes required by the MVP | Scope review note and explicit rejection of broad read scopes |
| Idempotency | Derive idempotency from event_id, message_id, or action id | Retry test that does not create duplicate Hub tasks |
| Queue handoff | Acknowledge quickly, then enqueue AgentHub work | Latency evidence for callback ack and queue enqueue |
| Binding | Unbound users receive a TokenDance ID binding card | Redacted card screenshot and binding-state audit record |
| Failure UX | Unknown command, unauthorized action, queue failure, and binding failure have cards | Failure-state screenshots with synthetic ids |
Required Events
The MVP event set is deliberately small:
| Event | Purpose | Handling |
|---|---|---|
im.message.receive_v1 | Direct messages and group @mentions | Deduplicate message events by message_id; only parse commands and required context. |
card.action.trigger | Interactive card actions | Respond within 3 seconds; queue slow work; do not rely on HTTP redirects. |
Group chats should default to @mention-triggered behavior. Avoid requesting broad "read every group message" permissions unless the product requirement and security review are explicit.
Public-Safe Payload Examples
URL challenge should complete before business logic and return the platform-required challenge body. This example shows shape only:
{
"type": "url_verification",
"challenge": "challenge_string"
}
{
"challenge": "challenge_string"
}
Message event example:
{
"schema": "2.0",
"header": {
"event_id": "evt_123",
"event_type": "im.message.receive_v1",
"tenant_key": "tenant_123"
},
"event": {
"message": {
"message_id": "msg_123",
"chat_id": "chat_123",
"message_type": "text",
"content": "{\"text\":\"@AgentHub review docs\"}"
},
"sender": {
"sender_id": {
"open_id": "ou_xxx",
"union_id": "on_xxx"
}
}
}
}
Card action example:
{
"schema": "2.0",
"header": {
"event_id": "evt_card_123",
"event_type": "card.action.trigger"
},
"event": {
"operator": {
"open_id": "ou_xxx"
},
"action": {
"value": {
"action": "approve_run",
"taskId": "task_123",
"approvalId": "approval_123"
}
}
}
}
Fast acknowledgement should be small; slow work goes to a queue:
{
"ok": true,
"queued": true,
"requestId": "req_123"
}
If the user is not bound to TokenDance ID, return a binding card instead of creating a Hub task:
{
"card": {
"title": "Bind TokenDance ID",
"actions": [
{
"type": "button",
"label": "Continue",
"url": "https://id.example.invalid/bind/feishu?state=opaque_state"
}
]
}
}
These examples do not replace real platform signature, encryption, challenge, or card-schema validation. Implementations should follow the Feishu/Lark official docs and the owning AgentHub repository schemas.
MVP Acceptance Criteria
A Feishu/Lark MVP is not ready just because the bot can receive a message. It should meet all of the following criteria:
| Area | Acceptance criteria |
|---|---|
| App type | An enterprise self-built app or approved deployment shape is documented in the private implementation plan |
| Scopes | Only required bot/message/card/H5 scopes are requested; broad read scopes have explicit security review |
| Event subscription | im.message.receive_v1 and card.action.trigger are enabled and verified |
| Challenge response | URL verification responds with the expected challenge body before business logic |
| Signature/encryption | token, signature, and encrypted payload checks run before event parsing |
| Dedupe | message events dedupe by message_id; card actions dedupe by event or action id |
| Queue handoff | slow AgentHub work is queued asynchronously after fast acknowledgement |
| Retry policy | retries are idempotent and do not create duplicate Hub tasks |
| Binding failure UX | unbound users receive a TokenDance ID binding card, not a generic failure |
| Audit | Hub records actor, binding state, task id, action, result, request id, and redacted failure reason |
Cards And Actions
Cards are the primary Feishu-native interaction surface for AgentHub:
- task status cards;
- approval, retry, cancel, and view-detail actions;
- TokenDance ID binding cards for unbound users;
- run-state cards for running, completed, failed, or needs-input tasks.
Card actions should carry only a short action id and business object id. Do not place secrets, bearer tokens, full prompts, or sensitive workspace context in card payloads.
H5 And Workbench
The Feishu H5/workbench entry can open AgentHub inside the Feishu client, but it is not a second login system.
If the user is not bound, show a TokenDance ID binding path. Feishu JSAPI can improve the in-client experience, but the final product identity and authorization must resolve through TokenDance ID and AgentHub Hub Server permissions.
Binding Loop
The recommended user mapping is:
- Feishu event arrives with tenant and user context.
- Integration Gateway maps the Feishu user to a TokenDance ID binding.
- If no binding exists, the bot returns a binding card.
- The user completes TokenDance ID login and Feishu account binding.
- AgentHub receives a TokenDance ID
suband applies Hub Server permissions.
AgentHub should not store Feishu access tokens in Desktop or Web clients, and Feishu open_id, user_id, or union_id must not become the product user primary key.
Security Checklist
- Keep the verification token, encrypt key, app secret, and tenant tokens in server-side secret storage.
- Verify signatures and decrypt encrypted events before business handling.
- Acknowledge events and card callbacks within 3 seconds.
- Deduplicate
im.message.receive_v1withmessage_id; deduplicate other events with the event id when available. - Log event type, message id, event id, tenant, hashed chat id, action id, latency, result, and Feishu error code; avoid logging full message content by default.
- Keep Feishu OAuth, refresh tokens, and account binding inside TokenDance ID.
Next Steps
- Use the architecture guide to place the Integration Gateway beside the AgentHub Hub Server.
- Treat Feishu bot setup as in-development until the AgentHub runtime endpoints, card schemas, and binding callback evidence are published.
- Track production scopes and review material in the AgentHub implementation backlog.