Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/GuaiZai233/FrostAgent/llms.txt

Use this file to discover all available pages before exploring further.

FrostAgent ships a built-in OneBot v11 WebSocket server that acts as a reverse adapter. Instead of FrostAgent dialing out to your bot client, your OneBot-compatible client (go-cqhttp, Lagrange, NapCat, and so on) establishes a connection inward to FrostAgent’s WebSocket endpoint. Once connected, events flow from the client to FrostAgent, and FrostAgent sends back OneBot actions — including rich message chains with text, @-mentions, images, voice, and file segments.

How It Works

FrostAgent listens for incoming WebSocket connections and processes each OneBot event as it arrives. The flow from connection to reply is straightforward:
1

Client connects

Your OneBot client opens a WebSocket connection to FrostAgent at ws://<host>:1234/ws/frostagent. The listen address is controlled by WS_LISTEN_ADDR and defaults to 0.0.0.0:1234.
2

Event received

FrostAgent’s HandleWS handler reads the raw JSON frame and deserialises it into an OneBotEvent. Heartbeat meta-events (meta_event_type: "heartbeat") are silently discarded.
3

Event dispatched

Each non-heartbeat event is handed off to processEvent in its own goroutine so that one slow LLM call never blocks another incoming message.
4

LLM called and reply sent

FrostAgent extracts user text, enriches it with any image descriptions (see Vision), builds a session-aware prompt, calls the LLM engine, and writes the resulting OneBotAction back over the same WebSocket connection.

Configuration

The adapter is driven entirely by environment variables. Set them in your .env file at the project root.
VariableDefaultDescription
WS_LISTEN_ADDR0.0.0.0:1234Host and port for the OneBot WebSocket server.
WS_ALLOWED_ORIGINS(empty)Comma-separated list of trusted browser Origins (e.g. https://bot.example.com). Non-browser clients that omit the Origin header are always permitted.
ENABLE_AT_IN_GROUP_MSGtrueWhen true, FrostAgent prepends an at segment (@ mention) to plain-text group replies.
Sample .env snippet for the OneBot adapter:
# WebSocket server bind address
WS_LISTEN_ADDR=0.0.0.0:1234

# Trust an extra browser origin (optional)
WS_ALLOWED_ORIGINS=https://bot.example.com

# @ the user when replying in group chats
ENABLE_AT_IN_GROUP_MSG=true
Leave WS_ALLOWED_ORIGINS empty unless you are connecting to the WebSocket from a browser page hosted on a different origin. Bot clients like NapCat and Lagrange do not send an Origin header and are always accepted.

Message Handling

HandleWS is the HTTP handler registered at /ws/frostagent. After upgrading the connection it reads frames in a loop and calls processEvent for each valid event:
  • Group messages — processed only when the bot is @-mentioned. IsMentionedBot walks every at segment in the event and compares the qq field against the bot’s own self_id. Because different OneBot implementations encode the QQ number as a string, a float64, or a json.Number, FrostAgent normalises all three variants before comparing.
  • Private messages — always processed; no mention check is required.
Session continuity is maintained via historyKey:
// group conversation
"group:<group_id>"

// private conversation
"private:<user_id>"
Each session key maps to an independent message history so that group and private conversations never bleed into each other.

Supported Incoming Message Segments

extractUserText converts the raw OneBot message array into a plain-text string that is passed to the LLM. Every standard OneBot v11 segment type is handled:
Segment typeRepresentation passed to LLM
textLiteral text content
at[@<qq>]
face[表情:<id>]
image[图片] (image is separately described by the vision model)
record[语音]
video[视频]
file[文件:<name>]
reply[回复:<id>]
location[位置:<lat>,<lon> <title>]
json / xml[json:<data>] / [xml:<data>]
(unknown)Raw JSON of the segment object
When a message contains an image segment, FrostAgent automatically calls the vision model and appends a Chinese-language description (【图片内容】: <description>) to the user text before sending it to the main LLM. See Vision for details.

Outgoing Message Segments

When the LLM invokes the send_message tool, BuildOneBotMessage translates the tool’s abstract message types into a concrete OneBot v11 segment chain:
send_message typeOneBot segmentKey field
plaintextdata.text — the text content
mention_useratdata.qq — the target user’s QQ number
quotereplydata.id — the message ID to quote
imageimagedata.file — URL or file://<path>
recordrecorddata.file — URL or file://<path>
videovideodata.file — URL or file://<path>
filefiledata.file — URL or file://<path>
For media types, the url field takes precedence. If only a local path is supplied, FrostAgent prefixes it with file:// automatically. A send_message call can mix multiple types in a single array to build rich composite messages — for example, a quote followed by a mention_user followed by plain text.

Concurrency

The wsConnection struct wraps gorilla/websocket.Conn with a sync.Mutex on all write operations:
type wsConnection struct {
    conn    *websocket.Conn
    writeMu sync.Mutex
}
Every incoming event is dispatched in its own goroutine via go processEvent(...), so multiple messages can be processed concurrently. The write mutex ensures that concurrent goroutines never interleave their WebSocket frames on the shared connection.

Origin Security

WS_ALLOWED_ORIGINS controls which browser-originated WebSocket connections are accepted. The check logic follows these rules in order:
  1. No Origin header — the connection is always allowed. Most OneBot client implementations (go-cqhttp, Lagrange, NapCat) do not send this header.
  2. Origin host matches the server’s own host — allowed.
  3. Origin (full URL or host only) is in WS_ALLOWED_ORIGINS — allowed.
  4. Any other origin — rejected with an error log entry.
# Allow connections from a browser-hosted admin panel
WS_ALLOWED_ORIGINS=https://admin.example.com,https://bot.example.com
Do not set WS_ALLOWED_ORIGINS to a wildcard or an untrusted domain. Any browser page listed here can open a WebSocket and send events to your bot engine.

Build docs developers (and LLMs) love