Satori 协议 的 C++ 客户端实现。配合 Satori 服务端(LLBot 等)使用,可接入 QQ、Telegram、Discord 等聊天平台。
C++20,依赖 ixwebsocket。
Satori 资源结构:已完整实现解析(Event、Message、Channel、User、Guild、GuildMember 等)
Satori 标准元素:已基本实现解析和封装( <at>、<sharp>、<file>、<img>、<video> 等)
Satori API:已完整实现所有标准 API(message / channel / guild / guild.member / guild.role / user / friend / login / reaction)
LLMClient:可选功能。鉴于 AI 热潮,目前也是主要支持方向。
#include "satori_client.h"
#include <ixwebsocket/IXNetSystem.h>
namespace se = satori::event;
namespace sel = satori::element;
int main()
{
ix::initNetSystem();
Bot bot("127.0.0.1:5600", "YOUR_TOKEN", "QQ", "YOUR_BOT_QQ");
bot.addOnMessageCallback([&bot](const se::Event& event)
{
if (!event.message || !event.channel) return;
sel::Elements elems = sel::parse(event.message->content.value_or(""));
bot.message.create(event.channel->id, "收到:" + elems.plainText);
});
bot.launch();
// bot.launchAsync() 异步执行
ix::uninitNetSystem();
}#include "satori_client.h"
#include "LLMClient/LLMClient.h"
#include "LLMClient/LLMAgent.h"
#include <ixwebsocket/IXNetSystem.h>
namespace se = satori::event;
namespace sel = satori::element;
int main()
{
ix::initNetSystem();
LLMClient llm(
"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
"sk-xxxxx",
"qwen3-14b"
);
Bot bot("127.0.0.1:5600", "YOUR_TOKEN", "QQ", "YOUR_BOT_QQ");
bot.addOnMessageCallback([&bot, &llm](const se::Event& event)
{
if (!event.message || !event.channel) return;
sel::Elements elems = sel::parse(event.message->content.value_or(""));
auto agent = LLMAgent::create(llm,
"你是服务器管理助手,名字叫小小北风。\n\n"
);
agent->ask(elems.plainText, [&bot, event](const std::string& llmreply)
{
auto reply = sel::Builder()
.img("weburl")
.text(llmreply)
.build();
bot.message.create(event.channel->id, reply);
});
});
bot.launch();
ix::uninitNetSystem();
}更多示例请参照demo.cpp
LLMAgent 支持 LLM 函数调用(tool calling)。通过注册工具,让 LLM 在需要时自动调用你定义的函数并获取结果。
#include "satori_client.h"
#include "LLMClient/LLMClient.h"
#include "LLMClient/LLMAgent.h"
#include "LLMClient/tool.hpp"
#include <ixwebsocket/IXNetSystem.h>
namespace se = satori::event;
namespace sel = satori::element;
int main()
{
ix::initNetSystem();
LLMClient llm(
"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
"sk-xxxxx",
"qwen3-14b"
);
Tool tool;
tool.toolRegister(
"get_time",
"获取当前系统时间",
{},
[](const nlohmann::json&) -> std::string {
auto now = std::chrono::system_clock::now();
auto t = std::chrono::system_clock::to_time_t(now);
return std::ctime(&t);
}
);
tool.toolRegister(
"echo",
"回显输入内容",
{{"text", "string", "要回显的文本", true}},
[](const nlohmann::json& args) -> std::string {
return "你说的是: " + args.value("text", "");
}
);
auto agent = LLMAgent::create(llm, "你是智能助手", tool);
agent->setToolHook([](const Tool::Call& call, const std::string& output) {
if (call.name == "fortune") {
// 工具执行后额外处理
}
});
Bot bot("127.0.0.1:5600", "YOUR_TOKEN", "QQ", "YOUR_BOT_QQ");
bot.addOnMessageCallback([&bot, agent](const se::Event& event)
{
if (!event.message || !event.channel) return;
sel::Elements elems = sel::parse(event.message->content.value_or(""));
if (event.user.has_value())
agent->setSystemPrompt("当前用户:" + event.user->id);
agent->ask(elems.plainText, [&bot, event](const std::string& reply)
{
bot.message.create(event.channel->id, reply);
});
});
bot.launch();
ix::uninitNetSystem();
}更多示例请参照 demo_toolcall.cpp。
tool.toolRegister(
"tool_name", // 工具名称,LLM 通过此名调用
"工具描述", // 告诉 LLM 何时调用
{ // 参数定义,可为空
{"param_name", "string", "参数描述", true /* 是否必填 */}
},
handler // 回调:接收 JSON args,返回 string 结果
);通过 agent->setToolHook(callback) 注册钩子,在每个工具执行完成后触发,可用于:
- 根据工具结果向消息缓冲区追加图片、@ 等元素
- 日志记录或额外副作用
钩子回调签名:void(const Tool::Call& call, const std::string& output)
上面的示例所有用户共用同一个 LLMAgent,对话历史会互相串台。SessionManager
为每个会话(频道 / 私聊 / 用户)维护一个独立的 LLMAgent,按 key 复用、线程安全,
适合多人同时使用的机器人。
#include "satori_client.h"
#include "LLMClient/LLMClient.h"
#include "LLMClient/LLMAgent.h"
#include "LLMClient/tool.hpp"
#include "SessionManager.h"
#include <ixwebsocket/IXNetSystem.h>
namespace se = satori::event;
namespace sel = satori::element;
int main()
{
ix::initNetSystem();
LLMClient llm(
"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
"sk-xxxxx",
"qwen3-14b"
);
Tool tool; // 所有会话共享同一套工具定义
SessionManager sessions; // 按 key 缓存各自的 LLMAgent
Bot bot("127.0.0.1:5600", "YOUR_TOKEN", "QQ", "YOUR_BOT_QQ");
bot.addOnMessageCallback([&bot, &llm, &tool, &sessions](const se::Event& event)
{
if (!event.message || !event.channel) return;
sel::Elements elems = sel::parse(event.message->content.value_or(""));
// 以 channel id 为 key,取出(或首次创建)该会话专属的 agent
auto agent = sessions.getOrCreate(
event.channel->id, llm, "你是智能助手", tool);
std::string channelId = event.channel->id;
agent->ask(elems.plainText, [&bot, channelId](const std::string& reply)
{
bot.message.create(channelId, reply);
});
});
bot.launch();
ix::uninitNetSystem();
}getOrCreate(key, llm, systemPrompt, tool):key 已存在则返回已有 agent(保留历史),
否则用给定参数创建一个新 agent 并缓存。完整示例见 demo_session.cpp。
| 依赖 | 说明 |
|---|---|
| ixwebsocket | WebSocket + HTTP,外部库,需要启用TLS支持 |
| nlohmann/json | JSON 解析,已内嵌 |
| tinyxml2 | XML 解析,已内嵌 |
# Ubuntu
sudo apt install libixwebsocket-dev
cmake -B build && cmake --build buildMIT License © 2026 Zhang Feng