This Go module adapts the WeCom AI Bot WebSocket protocol to the unified Beak Channel SDK contract.
Module:
github.com/GuanceCloud/beak-agent-wecom
Platform key: wecom.
- Bot ID and Secret credential login.
- Host-owned WeCom AI Bot WebSocket connection.
- Direct and group inbound messages.
- Readable placeholders for inbound image, voice, file, video, and mixed messages.
- Quoted-message normalization through
ReferencedMessage. - Text or markdown delivery back to the original conversation.
- UTF-8-safe markdown splitting at the 20 KB platform limit.
- Inbound deduplication, chat isolation, and standard runtime health.
- Real WebSocket credential authentication.
The current version does not download or upload media, build template cards, update one message incrementally, or provide reactions/typing/read acknowledgements. External contacts, customer groups, and WeCom customer-service conversations are outside this connector's scope.
Create a WeCom AI Bot in the WeCom administration console and obtain:
| Field | Required | Purpose |
|---|---|---|
bot_id |
Yes | Stable AI Bot and account identity. |
secret |
Yes | AI Bot secret; Beak must store it encrypted. |
Users do not provide a callback URL, webhook URL, server IP, domain, or WebSocket URL. Production uses the official WeCom long-connection endpoint.
Only one active connection may exist for a Bot ID. A new connection causes WeCom to send disconnected_event to the old one. The SDK returns that event with Terminal=true; Beak must stop and fail that runtime instead of reconnecting two competing instances.
The connector uses host_stream ownership:
- Beak owns the socket, reconnect lifecycle, write serialization, request timeouts, and watchdog.
- The SDK owns WeCom authentication, heartbeat, callback, and response-frame semantics.
Startperforms account wiring and state initialization only.ConnectStreamreturns the endpoint, authenticationInitialFrames, andWaitForReady=true.HandleStreamFramereturnsReady=trueonly after a successful authentication response.Sendreuses the current account connection throughRuntime.Stream.Request.StreamFrameResult.ResponseTomaps a WeComheaders.req_idresponse back to the pending host request.
The common runtime surface is:
type Runtime struct {
// Other common fields omitted.
Stream StreamTransport
}
type StreamTransport interface {
Request(ctx context.Context, req StreamRequest) (*StreamResponse, error)
}The Beak adapter must not parse WeCom JSON or add platform == "wecom" send branches. It only maps equivalent types between Go modules.
connector := wecom.NewConnector()
result, err := connector.ValidateCredential(ctx, wecomsdk.CredentialValidationRequest{
Credential: map[string]any{
"bot_id": "your-bot-id",
"secret": "your-secret",
},
})Validation opens a short-lived WebSocket, sends the real subscription frame, and waits for the authentication response. It is not a non-empty-field check. Because WeCom allows one active connection per bot, use validation only when creating or updating an account, not as a periodic health probe.
- Beak calls
Startfor account wiring. - Beak calls
ConnectStream. - Beak dials the returned endpoint.
- Beak writes
InitialFramesin order. - Every received frame is passed to
HandleStreamFrame. - A successful authentication response returns
Ready=true. - Only then may Beak dispatch stream requests.
Authentication failures return a readable CloseReason, Terminal=true, stream_connection_state=reconnect_failed, and the standard error timestamps. Retrying an invalid secret indefinitely is prohibited.
| WeCom field | Beak field |
|---|---|
aibotid |
Bot identity |
msgid |
MessageID and dedupe identity |
chattype=single |
ChatType=direct |
chattype=group |
ChatType=group |
Direct from.userid |
ChatID |
Group chatid |
ChatID |
from.userid |
SenderID |
quote |
ReferencedMessage |
AI Bot callbacks are addressed to the current bot, so direct and group callbacks are normalized with MentionedMe=true. Beak does not reparse the message text for mentions.
Deduplication uses:
wecom:<account_uuid>:<msgid>
Session identity remains chat scoped:
wecom:<account_uuid>:<chat_type>:<chat_id>
The SDK records a message as seen only after CreateMessage succeeds.
Send uses the WeCom aibot_send_msg command with markdown content. For direct chats, ChatID is the user's userid; for group chats, it is the platform chatid.
WeCom limits one markdown body to 20,480 UTF-8 bytes. The SDK splits larger output on rune boundaries, waits for the platform response to every chunk, and returns an error as soon as any chunk fails.
The connector uses the common health keys, including connection state, connected/disconnected timestamps, last activity, ping, pong, event, error, and reconnect fields. A socket that has connected but not authenticated remains reconnecting; it becomes connected only after the authentication response. stream_last_event_at changes only after an inbound message reaches Beak.
go test ./...Also run the workspace beak-channel-sdk-conformance and beak-channel-sdk-conformance-tests modules. The shared scenarios cover the real SDK methods for authentication, readiness, heartbeat, direct/group inbound, quotes, dedupe, terminal disconnect, and correlated host-stream responses.
- Keep
secretonly in encrypted credentials; never copy it into account state or logs. - Treat inbound
response_urlas a short-lived authorization value. This SDK uses the authenticated host stream for outbound delivery and deliberately does not persist or expose that URL in normalized message metadata. - Logs may include account UUID, Bot ID, request ID, and platform error code, but never the full authentication frame.
NativeRuntime.WebSocketURLis a test or controlled-deployment override. It is not part ofCredentialSchemaand must not be shown to ordinary users.- Do not call
ValidateCredentialas a heartbeat. Runtime health comes from the active host-owned stream.