GoClaw:当 OpenClaw 用 Go 重写,企业级 AI Agent 的安全感终于来了
OpenClaw 60 天狂飙 250K Stars,成为 GitHub 史上增长最快项目。但它的 TypeScript 基因让企业用户心有顾虑。GoClaw 用 Go 重写了整个架构:单二进制部署、5 层安全防护、PostgreSQL 多租户、pgvector 混合检索——这才是企业敢用的 AI Agent 框架。
从「养龙虾」热潮到企业安全焦虑
2026 年春天,一款名为 OpenClaw 的开源 AI 助手在全球掀起「养龙虾」热潮。60 天内,它的 GitHub Stars 从零飙升至 250,829,超越 React 成为 GitHub 历史上 Star 数最多的软件项目。
中国大陆的「龙虾」吉祥物在微博、知乎病毒式传播。深圳龙岗区发布「龙虾十条」政策,腾讯云、阿里云争相上线部署服务。开发者们把 Agent 当成「电子宠物」,在 Telegram、WhatsApp、Discord 上与自己的 AI 助手日夜对话。
但热潮背后,企业的安全焦虑始终挥之不去:
-
CVE-2026-25253:一键远程代码执行漏洞,CVSS 评分 8.8,恶意网页可通过 WebSocket 窃取网关 Token -
Censys 扫描:发现 21,639 个互联网暴露的实例 -
ClawHavoc 事件:ClawHub 市场审计发现 341 个恶意技能(约 12%) -
凭证明文存储: ~/.openclaw/credentials/目录下的 API Key 以 JSON 明文存储
更根本的问题在于技术栈:OpenClaw 用 TypeScript/Node.js 编写。对于需要部署到生产环境的企业来说,这意味着:
-
必须安装 Node.js 22+ 运行时 -
启动时间 >5 秒,空闲内存占用 >1 GB -
缺乏企业级安全防护(无加密存储、无多租户隔离) -
无法在资源受限的边缘设备运行
于是,一个用 Go 重写的项目诞生了——GoClaw。
GoClaw 概览:企业级 Go 重写
GoClaw(github.com/nextlevelbuilder/goclaw)是 OpenClaw 的 Go 语言重写版本,面向生产环境和企业场景。它的核心卖点很直接:
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
一个命令就能部署:
# OpenClaw 需要 Node.js
curl -fsSL https://openclaw.ai/install.sh | bash # 安装 Node.js + npm 包
# GoClaw 单二进制
wget https://github.com/nextlevelbuilder/goclaw/releases/download/v2026.4/goclaw-linux-amd64
chmod +x goclaw-linux-amd64
./goclaw-linux-amd64 # 亚秒级启动
在 $5 VPS 上,GoClaw 可以同时服务 100+ 租户,每个租户的数据通过 PostgreSQL 行级安全完全隔离。这是 TypeScript 版本无法企及的架构。
五层安全防护:GoClaw 的企业底气
OpenClaw 的安全危机让企业不敢大规模部署。GoClaw 的解决方案是构建五层纵深防御体系:
Layer 1:速率限制(滑动窗口算法)
// internal/security/ratelimit.go
type RateLimiter struct {
windows map[string]*SlidingWindow
mu sync.RWMutex
maxReqs int// 每分钟最大请求数
windowSize time.Duration // 窗口大小(默认1分钟)
}
func(rl *RateLimiter)Allow(clientID string)bool {
rl.mu.Lock()
defer rl.mu.Unlock()
window, exists := rl.windows[clientID]
if !exists {
window = &SlidingWindow{
Timestamps: []time.Time{},
}
rl.windows[clientID] = window
}
now := time.Now()
// 移除窗口外的请求
cutoff := now.Add(-rl.windowSize)
valid := window.Timestamps[:0]
for _, t := range window.Timestamps {
if t.After(cutoff) {
valid = append(valid, t)
}
}
window.Timestamps = valid
iflen(window.Timestamps) >= rl.maxReqs {
returnfalse// 拒绝
}
window.Timestamps = append(window.Timestamps, now)
returntrue
}
滑动窗口比固定窗口更精准,避免了边界突刺问题。每个租户、每个用户、每个会话都有独立的速率限制,防止恶意请求耗尽资源。
Layer 2:SQL 注入检测(针对 CVE-2026-25253)
CVE-2026-25253 是 OpenClaw 的一键 RCE 漏洞,恶意 WebSocket 连接可窃取网关 Token。GoClaw 在数据库访问层专门检测 SQL 注入模式:
// internal/security/sqlinject.go
var injectionPatterns = []string{
`(?i)(\b(SELECT|INSERT|UPDATE|DELETE|DROP|UNION|ALTER|CREATE|TRUNCATE)\b)`,
`(?i)(\b(OR|AND)\b\s+\d+\s*=\s*\d+)`,
`(?i)(--|;|'|")`,
`(?i)(\bEXEC\b|\bEXECUTE\b)`,
`(?i)(\bCONCAT\b|\bCHAR\b|\bCHR\b)`,
`(?i)(\bLOAD_FILE\b|\bOUTFILE\b)`,
}
funcDetectSQLInjection(input string)bool {
for _, pattern := range injectionPatterns {
matched, _ := regexp.MatchString(pattern, input)
if matched {
returntrue// 检测到注入模式
}
}
returnfalse
}
// 在所有数据库查询前拦截
func(db *DB)Query(ctx context.Context, query string, args ...any)(Rows, error) {
if DetectSQLInjection(query) {
returnnil, ErrSQLInjectionDetected
}
return db.pg.Query(ctx, query, args...)
}
Layer 3:Prompt 注入检测
Agent 的最大风险是用户通过精心设计的 Prompt 绕过安全限制,让 Agent 执行危险操作。GoClaw 使用正则扫描常见的越狱模式:
// internal/security/promptinject.go
var jailbreakPatterns = []string{
`(?i)(ignore\s+(all|previous|above)\s+(instructions|rules))`,
`(?i)(disregard\s+(all|any|previous)\s+(instructions|rules))`,
`(?i)(bypass\s+(security|filter|restriction))`,
`(?i)(pretend\s+(to\s+be|you\s+are)\s+(admin|root|system))`,
`(?i)(act\s+as\s+(if|a)\s+(admin|root|developer))`,
`(?i)(system\s+override|admin\s+mode)`,
`(?i)(print\s+(all|your)\s+(instructions|rules|prompts))`,
}
funcDetectPromptInjection(prompt string)bool {
for _, pattern := range jailbreakPatterns {
matched, _ := regexp.MatchString(pattern, prompt)
if matched {
returntrue
}
}
returnfalse
}
检测到注入后,Agent 会拒绝执行并返回标准化的安全警告:
⚠️ 安全警告:检测到潜在的 Prompt 注入模式。
您的请求已被拦截。请使用正常方式与 Agent 交互。
Layer 4:SSRF 防护(阻止私有 IP)
Agent 可能被诱导访问内网资源。GoClaw 在 HTTP 客户端层拦截所有 RFC 1918 私有 IP:
// internal/security/ssrf.go
var privateIPRanges = []string{
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
"127.0.0.0/8",
"169.254.0.0/16", // Link-local
"0.0.0.0/8",
}
funcIsPrivateIP(ipStr string)bool {
ip := net.ParseIP(ipStr)
if ip == nil {
returnfalse
}
for _, cidr := range privateIPRanges {
_, network, _ := net.ParseCIDR(cidr)
if network.Contains(ip) {
returntrue
}
}
returnfalse
}
func(c *SafeHTTPClient)Do(req *http.Request)(*http.Response, error) {
host := req.URL.Hostname()
ips, err := net.LookupHost(host)
if err != nil {
returnnil, err
}
for _, ip := range ips {
if IsPrivateIP(ip) {
returnnil, ErrSSRFBlocked
}
}
return c.client.Do(req)
}
这阻止了 Agent 访问 http://192.168.1.1/admin 或 http://10.0.0.1/internal-api 等内网资源。
Layer 5:AES-256-GCM 静态加密
OpenClaw 的凭证存储是 JSON 明文。GoClaw 使用 AES-256-GCM 加密所有敏感数据:
// internal/security/crypto.go
type EncryptedStore struct {
key []byte// 32字节 AES-256 密钥
tableName string
db *sql.DB
}
func(es *EncryptedStore)StoreCredential(tenantID, keyName, value string)error {
// 生成随机 nonce(GCM 要求)
nonce := make([]byte, 12)
if _, err := rand.Read(nonce); err != nil {
return err
}
block, _ := aes.NewCipher(es.key)
gcm, _ := cipher.NewGCM(block)
// 加密
ciphertext := gcm.Seal(nil, nonce, []byte(value), nil)
// nonce + ciphertext 一起存储
encrypted := append(nonce, ciphertext...)
query := `INSERT INTO credentials (tenant_id, key_name, encrypted_value)
VALUES ($1, $2, $3)
ON CONFLICT (tenant_id, key_name) DO UPDATE SET encrypted_value = $3`
return es.db.Exec(query, tenantID, keyName, encrypted)
}
func(es *EncryptedStore)GetCredential(tenantID, keyName string)(string, error) {
query := `SELECT encrypted_value FROM credentials WHERE tenant_id = $1 AND key_name = $2`
var encrypted []byte
if err := es.db.QueryRow(query, tenantID, keyName).Scan(&encrypted); err != nil {
return"", err
}
// 前12字节是 nonce
nonce := encrypted[:12]
ciphertext := encrypted[12:]
block, _ := aes.NewCipher(es.key)
gcm, _ := cipher.NewGCM(block)
// 解密并验证认证标签
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
return"", ErrDecryptionFailed // 认证失败,数据被篡改
}
returnstring(plaintext), nil
}
GCM 模式提供认证加密(AEAD),不仅加密数据,还验证数据完整性。如果有人篡改数据库中的密文,解密时会失败。
密钥管理有两种模式:
-
开发环境:从环境变量 GOCLAW_ENCRYPTION_KEY加载 -
生产环境:建议集成 HashiCorp Vault 或 AWS KMS
PostgreSQL 多租户:行级安全(RLS)隔离
OpenClaw 是单用户设计,所有会话、记忆、凭证存储在 ~/.openclaw/ 目录下。GoClaw 用 PostgreSQL 实现真正的多租户隔离:
架构设计
// internal/tenant/manager.go
type TenantManager struct {
db *sql.DB
}
func(tm *TenantManager)CreateTenant(ctx context.Context, name, plan string)(*Tenant, error) {
query := `INSERT INTO tenants (name, plan, created_at)
VALUES ($1, $2, NOW())
RETURNING id, name, plan, created_at`
var tenant Tenant
err := tm.db.QueryRowContext(ctx, query, name, plan).Scan(
&tenant.ID, &tenant.Name, &tenant.Plan, &tenant.CreatedAt,
)
return &tenant, err
}
func(tm *TenantManager)SetTenantContext(ctx context.Context, tenantID string)context.Context {
// 设置 PostgreSQL 会话变量,启用 RLS
tm.db.ExecContext(ctx, `SET app.current_tenant = $1`, tenantID)
return context.WithValue(ctx, "tenant_id", tenantID)
}
PostgreSQL RLS 配置
-- 启用 RLS
ALTERTABLE sessions ENABLEROWLEVELSECURITY;
ALTERTABLEmemoryENABLEROWLEVELSECURITY;
ALTERTABLE credentials ENABLEROWLEVELSECURITY;
-- 创建策略:只允许访问自己租户的数据
CREATEPOLICY tenant_isolation_policy ON sessions
USING (tenant_id = current_setting('app.current_tenant'));
CREATEPOLICY tenant_isolation_policy ONmemory
USING (tenant_id = current_setting('app.current_tenant'));
CREATEPOLICY tenant_isolation_policy ON credentials
USING (tenant_id = current_setting('app.current_tenant'));
-- 超级用户可以绕过(用于运维)
ALTERTABLE sessions FORCEROWLEVELSECURITY; -- 强制启用,超级用户也受限制
每次请求开始时,GoClaw 设置 app.current_tenant 会话变量。之后所有 SQL 查询自动被 RLS 策略过滤,一个租户完全看不到其他租户的数据。
即使代码中有 bug 导致查询没有 WHERE 条件,RLS 也会在数据库层强制隔离:
// 错误的查询(缺少 WHERE tenant_id)
db.Query(`SELECT * FROM sessions`) // RLS 自动过滤,只返回当前租户的 sessions
pgvector 混合检索:BM25 + 向量 + Reranking
GoClaw 的 Agent 记忆系统使用 PostgreSQL + pgvector 实现。但单纯的向量检索不够精准——GoClaw 采用 BM25 + 向量的混合检索方案。
为什么需要混合检索?
-
BM25:擅长精确关键词匹配,如「CVE-2026-25253」「GoClaw」「PostgreSQL」 -
向量检索:擅长语义理解,如「如何防止 Agent 被入侵」可能匹配到「SSRF 防护」或「Prompt 注入检测」
两者结合,Reciprocal Rank Fusion(RRF)算法融合结果:
实现架构
// internal/memory/hybrid_search.go
type HybridSearcher struct {
db *sql.DB
embedder Embedder // 向量嵌入器
}
func(hs *HybridSearcher)Search(ctx context.Context, query string, topK int)([]SearchResult, error) {
// 1. BM25 全文检索(PostgreSQL FTS)
bm25Results, err := hs.bm25Search(ctx, query, topK*2)
if err != nil {
returnnil, err
}
// 2. 向量检索(pgvector)
vectorResults, err := hs.vectorSearch(ctx, query, topK*2)
if err != nil {
returnnil, err
}
// 3. RRF 融合
fused := hs.rrfFusion(bm25Results, vectorResults, 60)
// 4. 取 topK
iflen(fused) > topK {
fused = fused[:topK]
}
return fused, nil
}
func(hs *HybridSearcher)bm25Search(ctx context.Context, query string, limit int)([]SearchResult, error) {
sql := `SELECT id, content, ts_rank_cd(search_vector, websearch_to_tsquery('english', $1)) as score
FROM memory
WHERE search_vector @@ websearch_to_tsquery('english', $1)
ORDER BY score DESC
LIMIT $2`
rows, err := hs.db.QueryContext(ctx, sql, query, limit)
// ...
}
func(hs *HybridSearcher)vectorSearch(ctx context.Context, query string, limit int)([]SearchResult, error) {
// 生成查询向量
embedding, err := hs.embedder.Embed(query)
if err != nil {
returnnil, err
}
sql := `SELECT id, content, 1 - (embedding <=> $1) as score
FROM memory
ORDER BY embedding <=> $1
LIMIT $2`
rows, err := hs.db.QueryContext(ctx, sql, embedding, limit)
// ...
}
func(hs *HybridSearcher)rrfFusion(bm25, vector []SearchResult, k int) []SearchResult {
// RRF 公式:score = sum(1 / (k + rank))
scores := make(map[string]float64)
for rank, r := range bm25 {
scores[r.ID] += 1.0 / float64(k + rank + 1)
}
for rank, r := range vector {
scores[r.ID] += 1.0 / float64(k + rank + 1)
}
// 按融合分数排序
// ...
}
知识图谱:LLM 提取实体 + 关系遍历
GoClaw 还引入了知识图谱层,用 LLM 从对话中提取实体和关系:
// internal/knowledge/graph.go
type KnowledgeGraph struct {
db *sql.DB
llm LLMClient
}
type Entity struct {
ID string
Name string
Type string// "person", "project", "concept", "event"
TenantID string
}
type Relation struct {
SourceID string
TargetID string
Type string// "mentions", "uses", "creates", "depends_on"
}
func(kg *KnowledgeGraph)ExtractFromConversation(ctx context.Context, conv string)error {
// 用 LLM 提取实体和关系
prompt := `从以下对话中提取实体和关系,以 JSON 格式返回:
实体类型:person, project, concept, event, tool, api
关系类型:mentions, uses, creates, depends_on, implements
对话:
""" + conv + """
输出格式:
{"entities": [...], "relations": [...]}`
result, err := kg.llm.Complete(ctx, prompt)
// 解析并存储到 PostgreSQL
// ...
}
func(kg *KnowledgeGraph)Traverse(ctx context.Context, entityID string, depth int)([]Entity, error) {
// 递归遍历关系图
sql := `WITH RECURSIVE graph AS (
SELECT source_id, target_id, type, 1 as depth
FROM relations WHERE source_id = $1
UNION ALL
SELECT r.source_id, r.target_id, r.type, g.depth + 1
FROM relations r
JOIN graph g ON r.source_id = g.target_id
WHERE g.depth < $2
)
SELECT DISTINCT e.* FROM entities e
JOIN graph g ON e.id = g.target_id
WHERE e.tenant_id = current_setting('app.current_tenant')`
// ...
}
知识图谱让 Agent 可以回答「GoClaw 用了哪些技术?」这类需要关系推理的问题,而不仅是文本匹配。
20+ LLM Provider:Anthropic 原生 HTTP+SSE
GoClaw 支持 20+ LLM Provider,包括 Anthropic、OpenAI、OpenRouter、DeepSeek、DashScope、Ollama 等。其中 Anthropic 的集成值得一提——它使用原生 HTTP+SSE 实现,支持 Prompt Caching:
// internal/llm/anthropic.go
type AnthropicClient struct {
apiKey string
baseURL string
httpClient *http.Client
}
type MessageRequest struct {
Model string`json:"model"`
MaxTokens int`json:"max_tokens"`
System []SystemBlock `json:"system,omitempty"`
Messages []Message `json:"messages"`
Tools []Tool `json:"tools,omitempty"`
}
type SystemBlock struct {
Type string`json:"type"`// "text"
Text string`json:"text"`
CacheControl *struct {
Type string`json:"type"`// "ephemeral"
} `json:"cache_control,omitempty"`
}
func(ac *AnthropicClient)Stream(ctx context.Context, req MessageRequest)(iter.Seq2[*Event, error], error) {
body, _ := json.Marshal(req)
httpReq, _ := http.NewRequestWithContext(ctx, "POST",
ac.baseURL+"/v1/messages", bytes.NewReader(body))
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("X-API-Key", ac.apiKey)
httpReq.Header.Set("Accept", "text/event-stream")
resp, err := ac.httpClient.Do(httpReq)
if err != nil {
returnnil, err
}
returnfunc(yield func(*Event, error)bool) {
defer resp.Body.Close()
scanner := bufio.NewScanner(resp.Body)
for scanner.Scan() {
line := scanner.Text()
if !strings.HasPrefix(line, "data: ") {
continue
}
data := strings.TrimPrefix(line, "data: ")
if data == "[DONE]" {
return
}
var event Event
if err := json.Unmarshal([]byte(data), &event); err != nil {
if !yield(nil, err) {
return
}
continue
}
if !yield(&event, nil) {
return
}
}
}, nil
}
Prompt Caching:节省 90% Token 成本
Anthropic 的 Prompt Caching 允许缓存系统提示和上下文,在后续请求中复用。GoClaw 利用这一点缓存 Agent 的系统提示:
// 系统提示缓存标记
systemBlocks := []SystemBlock{
{
Type: "text",
Text: agentSystemPrompt, // 5000+ tokens
CacheControl: &struct{Type string`json:"type"`}{
Type: "ephemeral", // 缓存标记
},
},
}
// 首次请求:完整计费
// 后续请求:缓存部分 90% 折扣
对于多轮对话,系统提示缓存可以节省大量 Token 成本。
MCP 原生集成:三种传输模式
MCP(Model Context Protocol)是 Anthropic 主导的开放标准,让 AI Agent 通过统一 JSON-RPC 2.0 接口连接外部工具。GoClaw 原生支持三种 MCP 传输模式:
stdio 模式
最简单的模式,MCP Server 作为子进程运行,通过 stdin/stdout 通信:
// internal/mcp/stdio_transport.go
type StdioTransport struct {
cmd *exec.Cmd
stdin io.Writer
stdout io.Reader
}
func(st *StdioTransport)Start(ctx context.Context, command string, args ...string)error {
st.cmd = exec.CommandContext(ctx, command, args...)
stdinPipe, _ := st.cmd.StdinPipe()
stdoutPipe, _ := st.cmd.StdoutPipe()
st.stdin = stdinPipe
st.stdout = stdoutPipe
return st.cmd.Start()
}
func(st *StdioTransport)Send(request *JSONRPCRequest)(*JSONRPCResponse, error) {
// 写入 stdin
data, _ := json.Marshal(request)
st.stdin.Write(append(data, '\n'))
// 从 stdout 读取响应
scanner := bufio.NewScanner(st.stdout)
if scanner.Scan() {
var resp JSONRPCResponse
json.Unmarshal(scanner.Bytes(), &resp)
return &resp, nil
}
returnnil, scanner.Err()
}
SSE 模式(HTTP Server-Sent Events)
MCP Server 作为 HTTP 服务运行,通过 SSE 推送消息:
// internal/mcp/sse_transport.go
type SSETransport struct {
baseURL string
httpClient *http.Client
eventChan chan *JSONRPCResponse
}
func(st *SSETransport)Connect(ctx context.Context)error {
req, _ := http.NewRequestWithContext(ctx, "GET", st.baseURL+"/sse", nil)
resp, err := st.httpClient.Do(req)
if err != nil {
return err
}
// 后台读取 SSE 事件
gofunc() {
defer resp.Body.Close()
scanner := bufio.NewScanner(resp.Body)
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "data: ") {
data := strings.TrimPrefix(line, "data: ")
var event JSONRPCResponse
json.Unmarshal([]byte(data), &event)
st.eventChan <- &event
}
}
}()
returnnil
}
streamable-http 模式
最新的传输模式,支持双向流式通信:
// internal/mcp/streamable_http.go
type StreamableHTTPTransport struct {
baseURL string
httpClient *http.Client
sessionID string
}
func(st *StreamableHTTPTransport)Send(request *JSONRPCRequest)(iter.Seq2[*JSONRPCResponse, error], error) {
body, _ := json.Marshal(request)
req, _ := http.NewRequest("POST", st.baseURL+"/mcp", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
if st.sessionID != "" {
req.Header.Set("X-MCP-Session-ID", st.sessionID)
}
resp, err := st.httpClient.Do(req)
if err != nil {
returnnil, err
}
// 保存 session ID
st.sessionID = resp.Header.Get("X-MCP-Session-ID")
returnfunc(yield func(*JSONRPCResponse, error)bool) {
defer resp.Body.Close()
// 解析流式响应...
}, nil
}
三种模式让 GoClaw 可以连接任何 MCP 服务器——官方的 GitHub、PostgreSQL、Filesystem 工具,或社区的 200+ 工具。
Agent Teams:多 Agent 协作编排
GoClaw 引入了 Agent Teams 概念,让多个 Agent 组成团队,共享任务板,相互委托任务:
// internal/agent/team.go
type AgentTeam struct {
ID string
Name string
TenantID string
Agents []Agent
TaskBoard *TaskBoard
}
type TaskBoard struct {
Tasks []Task
Assignees map[string]string// task_id -> agent_id
}
func(at *AgentTeam)DispatchTask(ctx context.Context, task Task)error {
// 1. 分析任务类型
taskType := at.classifyTask(task.Description)
// 2. 选择最合适的 Agent
bestAgent := at.selectAgent(taskType)
// 3. 委托任务
return bestAgent.AcceptTask(ctx, task)
}
func(at *AgentTeam)classifyTask(desc string)string {
// 用 LLM 或规则分类
// "coding", "analysis", "communication", "research"
// ...
}
func(at *AgentTeam)selectAgent(taskType string) *Agent {
// 混合发现机制:
// 1. 查看每个 Agent 的 capabilities 标签
// 2. 查看历史任务完成率
// 3. 查看当前负载
// ...
}
同步/异步委托
// 同步委托:等待结果
result, err := agentA.DelegateAndWait(ctx, agentB, task)
// 异步委托:后台执行
err := agentA.DelegateAsync(ctx, agentB, task)
// agentB 完成后通过回调通知 agentA
OpenTelemetry 可观测性:OTLP 导出
GoClaw 支持可选的 OpenTelemetry 集成(通过构建标签 -tags telemetry 启用):
// internal/telemetry/tracer.go
var tracer trace.Tracer
funcInitTelemetry(serviceName, otlpEndpoint string)error {
exporter, err := otlptrace.New(context.Background(),
otlptracegrpc.NewClient(
otlptracegrpc.WithEndpoint(otlpEndpoint),
otlptracegrpc.WithInsecure(),
),
)
if err != nil {
return err
}
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
sdktrace.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceNameKey.String(serviceName),
)),
)
otelsdk.SetTracerProvider(tp)
tracer = tp.Tracer("goclaw")
returnnil
}
funcTraceLLMCall(ctx context.Context, provider, model string, tokensIn, tokensOut int) {
_, span := tracer.Start(ctx, "llm.call",
trace.WithAttributes(
attribute.String("provider", provider),
attribute.String("model", model),
attribute.Int("tokens.input", tokensIn),
attribute.Int("tokens.output", tokensOut),
),
)
defer span.End()
}
OTLP 导出兼容 Grafana Tempo、Jaeger、Datadog、New Relic 等主流 APM 系统。
GoClaw Lite:Wails 桌面版
除了服务端版本,GoClaw 还提供桌面版(GoClaw Lite),用 Wails v2 + React 构建:
// goclaw-lite/main.go
package main
import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
funcmain() {
// 初始化 SQLite 本地存储
db := initSQLiteDB()
app := &App{
DB: db,
Agent: NewAgent(db),
MCPClient: NewMCPClient(),
}
wails.Run(&options.App{
Title: "GoClaw Lite",
Width: 1024,
Height: 768,
AssetServer: &assetserver.Options{
Assets: Assets, // React 前端
},
Bind: []interface{}{
app,
},
})
}
type App struct {
DB *sql.DB
Agent *Agent
MCPClient *MCPClient
}
// Wails 绑定方法,前端可调用
func(a *App)SendMessage(message string)(string, error) {
return a.Agent.Process(message)
}
func(a *App)GetHistory()([]Message, error) {
return a.DB.QueryMessages()
}
桌面版适合个人用户,数据完全本地存储,无需服务器。
Go vs TypeScript:AI Agent 的技术栈抉择
GoClaw 的出现证明了一个事实:Go 比 TypeScript 更适合构建企业级 AI Agent 基础设施。
Go 的优势
-
单二进制部署:无需安装 Node.js 运行时,一个 wget就能运行 -
低资源占用:空闲内存 35 MB vs TypeScript 的 1 GB,适合边缘设备 -
原生并发:goroutine 处理 SSE 流、WebSocket 连接、MCP 通信更高效 -
强类型安全:编译时捕获错误,减少运行时 panic -
AES-256-GCM 加密:Go 的 crypto 库是业界标杆 -
PostgreSQL 集成:pgx 驱动性能优秀,pgvector 支持完善
TypeScript 的局限
-
运行时依赖:必须安装 Node.js,增加部署复杂度 -
高内存占用:V8 引擎本身占用大量内存 -
安全防护薄弱:缺乏原生加密库,依赖第三方实现 -
无多租户设计:OpenClaw 是单用户架构,企业需要自行改造
结语:Go 正在重塑 AI Agent 基础设施
OpenClaw 的 250K Stars 证明了「自托管 AI 助手」是真实需求。但 TypeScript 的基因让它更适合个人爱好者,而非企业生产环境。
GoClaw 用 Go 重写了整个架构,证明了 Go 在 AI Agent 领域的独特价值:
-
单二进制部署:DevOps 团队的最爱 -
5 层安全防护:让企业敢把 API Key 交给 Agent -
PostgreSQL 多租户:SaaS 模式的基石 -
pgvector 混合检索:BM25 + 向量 + 知识图谱 -
OpenTelemetry 可观测性:生产环境的标配
如果说 OpenClaw 是 AI Agent 的「iPhone」,让普通人爱上养龙虾;那么 GoClaw 就是「企业版 iPhone」,让银行、医院、政府敢把 Agent 放进生产环境。
Go 正在重塑 AI Agent 基础设施。这不是口号,而是正在发生的事实。
参考资料
-
GoClaw GitHub: github.com/nextlevelbuilder/goclaw -
GoClaw 安全架构: goclaw.sh/blog/goclaw-5-layer-security -
OpenClaw 官方文档: docs.openclaw.ai -
PostgreSQL RLS 文档: postgresql.org/docs/current/ddl-rowsecurity.html -
pgvector 扩展: github.com/pgvector/pgvector -
Anthropic Prompt Caching: docs.anthropic.com/claude/docs/prompt-caching -
MCP 协议规范: modelcontextprotocol.io -
OpenTelemetry Go SDK: opentelemetry.io/docs/instrumentation/go
推荐阅读

夜雨聆风