sebastienrousseau/rousseau-agent
GitHub: sebastienrousseau/rousseau-agent
一款自托管、容器原生的 AI 编程助手,通过九种聊天渠道与多种 LLM 提供商对接,在确保代码与数据完全本地化的前提下为开发团队提供智能编码辅助。
Stars: 0 | Forks: 0
rousseau-agent
自托管、容器原生且适用于无法将代码发送至云端 endpoint 的团队的 coding agent。
支持 9 种 chat transport · 5 种 LLM provider · MCP server · cron scheduler · 兼容 agentskills.io 的 skills loader · SLSA-3 provenance · SBOM · cosign 签名的 release · 采用降权配置的 rootless Podman。
## 目录
- [定位](#positioning)
- [功能](#capabilities)
- [支持的 transport](#supported-transports)
- [支持的 provider](#supported-providers)
- [企业级与供应链安全态势](#enterprise--supply-chain-posture)
- [安装说明](#installation)
- [快速开始](#quick-start)
- [部署](#deployment)
- [配置](#configuration)
- [嵌入 agent loop](#embedding-the-agent-loop)
- [仓库布局](#repository-layout)
- [质量门禁](#quality-gates)
- [安全与披露](#security--disclosure)
- [对比](#comparison)
- [贡献](#contributing)
- [许可证](#license)
## 定位
`rousseau-agent` 是一个围绕以下运维假设设计的 coding assistant:**workspace、auth material 和模型流量绝不会离开操作者控制的机器。** daemon 作为一个单一的静态 binary 在 rootless Podman container 中运行。LLM 要么通过 shell 调用你本地的 `claude` CLI(继承 Claude Code 已持有的任何 auth),要么访问你已建立合作关系的 provider endpoint —— Anthropic、AWS Bedrock、Google Vertex,或任何兼容 OpenAI 的 endpoint(包括自托管的 Ollama)。
九种 chat transport 让同一个 daemon 能够通过工程师们已经在使用的媒介接触到他们 —— WhatsApp、iMessage、Signal、Telegram、Matrix、Slack、Discord、SMS (Twilio / Vonage),或原生的 IMAP + SMTP。所有这些 transport 都与同一个 tool registry、session store 和 approval policy 交互。
没有 SaaS 的 control plane,没有 telemetry endpoint,没有 license server,也没有内置的 broker。唯一的出站流量是 LLM 调用和你启用的 transport。
## 功能
| 层级 | 交付内容 |
|---|---|
| **Agent loop** | 具备结构化 tool-use、流式响应、基于 session 的上下文、由 LLM 支持的 session 压缩,以及由 FTS5 支持的跨 session 检索的多轮规划器。 |
| **Tool registry** | 支持并发安全的 registry,内置 `read`、`write`、`edit`、`grep`、`bash`。采用严格的 JSON-schema 输入;`edit` 工具强制执行唯一字符串约束,以防止意外的批量替换。无需触动 agent 核心即可添加你自己的工具。 |
| **Approval policy** | `allow_all`、`deny_all` 或带有基于工具的允许/拒绝 regex 规则及可配置默认值的 `pattern` 模式。无人值守的 daemon 会自动选择合理的默认值。 |
| **Session store** | 持久化的 SQLite(`modernc.org/sqlite`,嵌入式,无 libc 耦合),采用 WAL journaling,`busy_timeout=15s`,并在 `Close` 时执行 WAL checkpoint。 |
| **MCP server** | 通过 stdio 通信的 JSON-RPC 2.0,规范版本为 2024-11-05。将 rousseau 的 tools 和 session 暴露给任何兼容 MCP 的 client(Claude Desktop、IDE 扩展、其他 agent)。 |
| **Cron scheduler** | 包含持久化任务存储的 robfig/cron/v3 goroutine;通过任何已注册的 transport 发送定时消息。 |
| **Skills loader** | 兼容 agentskills.io 的 Markdown + YAML frontmatter 格式。Skills 会从 `skills.dir` 中被发现,组合进 system prompt,并进行版本追踪。 |
| **TUI** | Bubble Tea client,具备 viewport、scrollback、streaming indicator 以及用于 chat transport 的输入反馈。 |
| **Container runtime** | Rootless Podman + systemd Quadlet unit。只读 rootfs,丢弃所有 capabilities,配置 `NoNewPrivileges`、seccomp filter,非 root 用户,以及 `keep-id` UID 映射。 |
## 支持的 transport
| Transport | 入站 | 出站 | 依赖库 / 协议 |
|---|:---:|:---:|---|
| WhatsApp | ✅ | ✅ | `go.mau.fi/whatsmeow` (兼容 Signal 协议) |
| Signal | ✅ | ✅ | `signal-cli` JSON-RPC subprocess |
| Telegram | ✅ | ✅ | Bot API (长轮询) |
| Matrix | ✅ | ✅ | Client-server API |
| Slack | ✅ | ✅ | Socket Mode (出站 WebSocket,无公开 webhook) |
| Discord | ✅ | ✅ | Gateway v10 (WebSocket + intents) |
| iMessage | ✅ | ✅ | BlueBubbles HTTP 轮询 |
| Email | ✅ | ✅ | IMAP 入站 + SMTP 出站 |
| SMS | ❌ | ✅ | Twilio REST / Vonage REST |
每个 transport 都是位于同一个 `transport.Transport` 接口(`Start`、`Stop`、`Deliver`)背后的轻量级 adapter。添加第十个 transport 只需要几百行 adapter 代码和测试;完全不需要改动 agent 核心。
## 支持的 provider
| Provider | 认证模型 | 备注 |
|---|---|---|
| **claudecli** (默认) | 继承 `claude` CLI 认证 | rousseau 的 config 中无需流转 API key。推荐个人操作者使用。 |
| **anthropic** | `ANTHROPIC_API_KEY` | 直连 API,精确锁定的 SDK,在最后两条消息上带有 prompt-cache 标记。 |
| **openai / openrouter / ollama** | 可配置 | 任何兼容 OpenAI 的 endpoint。Ollama 预设 `base_url` 为 `http://localhost:11434/v1`。 |
| **AWS Bedrock** | 标准 AWS 凭证链 | AWS 上企业级管理的 Claude。 |
| **Google Vertex AI** | GCP service-account JSON | GCP 上企业级管理的 Claude。 |
Provider 的抽象是 `agent.Provider` 和 `agent.StreamingProvider`。添加第六个 provider 只需实现单个 `Chat` / `ChatStream` 即可。
## 企业级与供应链安全态势
| 控制措施 | 实现方式 |
|---|---|
| 构建出处 | 通过 `slsa-framework/slsa-github-generator` 达到 **SLSA Level 3**。 |
| Release 签名 | **cosign** 对校验和进行签名;使用者可通过发布的公钥进行验证。 |
| 软件物料清单 (SBOM) | 将 **CycloneDX JSON** 附加到每个 release 中。 |
| 可复现构建 | 专门的 `reproducible-build` CI job 会验证全新 checkout 下的位一致输出。 |
| 漏洞扫描 | 每次 CI 运行均执行 `govulncheck`;使用 Dependabot 维护 `gomod` 和 `github-actions`。 |
| 静态分析 | golangci-lint v2 (18 个 linter) + CodeQL (Go)。 |
| 依赖锁定 | 在 `go.mod` 中进行精确版本锁定;冻结 `go.sum`。 |
| 运行时加固 | 只读 rootfs,`DropCapability=all`,`NoNewPrivileges=true`,默认 seccomp profile,非 root UID 1000,`keep-id` user namespace 映射。 |
| 无入站 HTTP 攻击面 | 每个需要接收传入消息的 transport 均使用出站 WebSocket (Slack Socket Mode, Discord Gateway) 或轮询。无需暴露任何 HTTP server。 |
| 竞态条件测试 | 在 Linux 和 macOS 环境矩阵上执行 `go test -race -count=1 -covermode=atomic ./...`。 |
| Fuzz 语料库 | 每个 parser 都有对应的 Fuzz 函数;`make fuzz` 运行全套测试。 |
可触及的 trust roots:GitHub Actions OIDC (SLSA)、Sigstore 公共透明度日志 (cosign),以及 pkg.go.dev (Go 模块校验和数据库)。
## 安装说明
### 前置条件
- Go **1.26+**
- 上述支持的 provider 路径之一(默认的 `claudecli` 会继承你本地安装的 `claude` CLI)。
### 从源码构建
```
git clone https://github.com/sebastienrousseau/rousseau-agent
cd rousseau-agent
make build # produces ./bin/rousseau
./bin/rousseau version
```
### 通过 `go install` 安装
```
go install github.com/sebastienrousseau/rousseau-agent/cmd/rousseau@latest
```
该 binary 是完全静态的(`CGO_ENABLED=0`)并内嵌了 `modernc.org/sqlite`;在 runtime 无需依赖任何 C 工具链或 libc。
### 从已签名的 release 安装
每个带有 tag 的 release 都会发布一个包含校验和的归档文件、一份 CycloneDX SBOM、一份 SLSA-3 provenance attestation,以及针对校验和文件的 cosign 签名。
```
cosign verify-blob \
--certificate-identity-regexp 'sebastienrousseau/rousseau-agent' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
--signature rousseau_
_checksums.txt.sig \
rousseau__checksums.txt
```
## 快速开始
### 终端聊天
```
rousseau chat
```
Bubble Tea TUI。按 Enter 发送,按 `Ctrl+C` 退出。Session 历史记录将持久化到 `~/.local/share/rousseau/sessions.db`。
### 九种 chat transport 之一
```
# WhatsApp(首次启动时通过扫描 QR 码配对)
rousseau whatsapp --allow 447000000000@s.whatsapp.net
# Slack Socket Mode
rousseau slack --app-token xapp-... --bot-token xoxb-...
# Discord Gateway
rousseau discord --token bot-token
# 通过 IMAP + SMTP 收发电子邮件
rousseau email --imap-addr imap.example.com:993 --imap-username u --imap-password p \
--smtp-addr smtp.example.com:587 --smtp-username u --smtp-password p \
--from bot@example.com
```
`rousseau --help` 会列出特定于该 transport 的 flag。每个 transport 都会从 `~/.config/rousseau/config.yaml` 读取默认值。
### MCP server
```
rousseau mcp # stdio, JSON-RPC 2.0, MCP spec 2024-11-05
```
## 部署
参考的生产环境部署方案是一个由 systemd Quadlet unit 管理的 rootless Podman container —— 这种单节点安装方式能够在重启后保留状态,无需依赖 Kubernetes 即可提供安全隔离,并且完全受操作者掌控。
### 构建 image
```
podman build -t rousseau-agent:local -f docker/Dockerfile .
```
多阶段构建:`golang:1.26-alpine` 构建器 → 包含 `claude` CLI 的 `node:22-alpine` runtime。Runtime image 大小约为 550 MB,且不为 agent 本身提供任何解释器 runtime;Node 层的存在仅仅是作为可选的 `claude` CLI subprocess 的运行环境。
### 安装 Quadlet unit
```
mkdir -p ~/.config/containers/systemd
cp docker/rousseau-agent.container ~/.config/containers/systemd/
systemctl --user daemon-reload
systemctl --user start rousseau-agent.service
journalctl --user -u rousseau-agent.service -f
```
### 运行时安全态势 (Quadlet unit)
| 设置 | 值 | 原因 |
|---|---|---|
| `Network=pasta` | Rootless 网络栈 | `slirp4netns` 已在近期的 Podman 版本中被移除 |
| `UserNS=keep-id` | Container UID 1000 → 宿主机 UID 1000 | Bind mount 的文件能保留宿主机的所有权 |
| `ReadOnly=true` | Root filesystem 只读 | Binary 无法修改 image |
| `Tmpfs=/tmp:rw,size=64m,mode=1777` | 可写的临时空间 | daemon 写入的任何内容都保存在 bind mount 上 |
| `DropCapability=all` + `NoNewPrivileges=true` | 最小权限原则 | 出站 socket 不需要任何提权 capabilities |
| `SeccompProfile=…` | 默认 seccomp filter | 内核级别的 syscall 门控 |
| `Volume=%h/.local/share/rousseau:…rw,Z` | 状态持久化 | WhatsApp 配对信息和 session store 在重启后依然存在 |
| `Volume=%h/.claude:…rw,Z` | `claude` CLI 认证 | 读取 / 刷新缓存的 OAuth token |
| `Volume=%h/team-rousseau-workspace:/workspace:rw,Z` | 仅 workspace 可见 | 宿主机上的其他任何内容都不会被挂载 |
### Kubernetes / OpenShift
`rousseau` 是一个无状态的单 binary daemon;只需一个最小化的 `Deployment` + 用于状态目录的 `PersistentVolumeClaim` 就足够了。因为没有入站 HTTP 攻击面,所以对于出站 WebSocket transport(Slack、Discord、WhatsApp、Matrix)而言,不需要配置 `Service` 或 `Ingress`。只有入站 webhook 类的 transport 才可能需要 `Service` —— 而 rousseau 默认不提供任何此类 transport。
## 配置
`rousseau` 按照以下优先级顺序解析配置:**flag > env > file > default**。该配置文件位于 `~/.config/rousseau/config.yaml`:
```
# LLM backend。默认的 "claudecli" 会调用 claude CLI 并
# 继承其认证;"anthropic" | "bedrock" | "vertex" | "openai" |
# "openrouter" | "ollama" 直接调用 API。
provider: claudecli
anthropic:
api_key: sk-ant-...
model: claude-sonnet-4-6
max_tokens: 4096
bedrock:
region: us-east-1
model: anthropic.claude-sonnet-4-6-20250101-v1:0
profile: default
vertex:
project: my-gcp-project
region: us-central1
model: claude-sonnet-4@20250101
credentials_file: ~/.config/gcloud/vertex-key.json
claudecli:
binary: claude
model: sonnet
permission_mode: bypassPermissions
extra_args: []
log:
level: info # debug, info, warn, error
format: json # json for production
state:
path: ~/.local/share/rousseau/sessions.db
agent:
system_prompt: "" # empty falls back to a sensible default
max_iterations: 32
skills_dir: ~/.config/rousseau/skills
compression:
enabled: true
trigger_messages: 60
keep_recent: 8
approver:
mode: pattern
default: deny
allow:
- {tool: read, match: ".*"}
- {tool: grep, match: ".*"}
- {tool: edit, match: "^./workspace/.*"}
deny:
- {tool: bash, match: "rm -rf|sudo|:\\(\\)\\{ :\\|:& \\};:"}
slack: {app_token: "", bot_token: "", allowlist: []}
discord: {token: "", allowlist: []}
telegram: {token: "", allowlist: []}
matrix: {homeserver_url: "", access_token: "", user_id: "", allowlist: []}
signal: {account: "+44…", allowlist: []}
whatsapp: {reply_header: "💎 *Rousseau Agent*\n\n"}
imessage: {base_url: "http://localhost:1234", password: "", poll_interval: 5s}
sms: {provider: twilio, from: "+15550000000", account_sid: "AC…", auth_token: ""}
email:
imap_addr: imap.example.com:993
smtp_addr: smtp.example.com:587
from: bot@example.com
poll_interval: 30s
```
## 嵌入 agent loop
`rousseau-agent` 既是一个 library,也是一个 daemon。Agent loop、tool registry 和 provider 抽象不依赖于任何 CLI;你可以将它们组合到你自己的 binary 中。
```
package main
import (
"context"
"fmt"
"log/slog"
"os"
"github.com/sebastienrousseau/rousseau-agent/internal/agent"
"github.com/sebastienrousseau/rousseau-agent/internal/llm/claudecli"
"github.com/sebastienrousseau/rousseau-agent/internal/tools"
"github.com/sebastienrousseau/rousseau-agent/internal/tools/builtin"
)
func main() {
provider := claudecli.New(claudecli.Config{
PermissionMode: "bypassPermissions",
})
registry := tools.NewRegistry()
registry.MustRegister(builtin.NewReadTool())
registry.MustRegister(builtin.NewGrepTool(0, 0))
ag := agent.New(provider, registry,
slog.New(slog.NewJSONHandler(os.Stdout, nil)),
agent.Options{SystemPrompt: "You are a careful, concise coding assistant."})
session := agent.NewSession("hello")
session.Append(agent.NewUserText("What does main.go do?"))
reply, err := ag.Turn(context.Background(), session)
if err != nil {
fmt.Fprintf(os.Stderr, "turn: %v\n", err)
os.Exit(1)
}
fmt.Println(reply.Content[0].Text)
}
```
完整的示例位于 [`examples/embed-agent`](./examples/embed-agent)。
## 仓库布局
```
cmd/rousseau/ Entry point (signal handling + Execute)
internal/agent/ Session, Message, Turn, agent loop, Provider interfaces, compression
internal/cli/ Cobra command tree (chat, per-transport commands, doctor, status, cron, mcp, skills, init, version)
internal/config/ Viper-based; flag > env > file > default precedence
internal/cron/ robfig/cron/v3 scheduler goroutine with durable job storage
internal/llm/anthropic/ Direct Anthropic API provider with cache markers
internal/llm/bedrock/ AWS Bedrock provider
internal/llm/claudecli/ Subprocess provider (claude CLI + JSON parser)
internal/llm/openai/ OpenAI-compatible provider (OpenAI, OpenRouter, Ollama, others)
internal/llm/vertex/ Google Vertex AI provider
internal/mcp/ MCP server (JSON-RPC 2.0 over stdio, spec 2024-11-05)
internal/skills/ agentskills.io-style skill loader + composition
internal/state/ Store interface + Summary type
internal/state/sqlite/ SQLite implementation (WAL, JIDMap, claude cache, FTS5 recall, cron table)
internal/tools/ Tool interface + concurrency-safe Registry
internal/tools/builtin/ read, write, edit, grep, bash
internal/transport/ Transport interface + Router (per-JID session, allowlist, dispatch)
internal/transport/{whatsapp,signal,telegram,matrix,slack,discord,sms,imessage,email}/
Nine transport adapters
internal/tui/ Bubble Tea model (viewport, textarea, spinner, streaming)
docker/ Dockerfile, Podman Quadlet unit, example nftables rules
docs/ Roadmap, gap analysis, competitor deep-dive
examples/embed-agent/ Minimal library-embedding example
```
这种分层边界是承重设计。`agent`依赖于 `tools` 暴露的接口、其自身的 `Provider` 类型以及标准库。具体的 provider、store 和 transport 都依赖于 `agent` —— 绝不反过来。
## 质量门禁
每次提交都会在 CI 中运行:
- `go vet ./...`
- `golangci-lint run` (18 个 linter:bodyclose, copyloopvar, errcheck, errorlint, forbidigo, gocritic, govet, ineffassign, misspell, nilerr, nolintlint, revive, staticcheck, unconvert, unparam, unused, usestdlibvars, whitespace + gofmt & goimports 格式化工具)
- 在 `ubuntu-latest` 和 `macos-latest` 上执行 `go test -race -count=1 -covermode=atomic ./...`
- 测试覆盖率底线检查(目前总体为 75%;核心 package 保持在 85–100%)
- `govulncheck ./...`
- CodeQL 静态分析 (Go)
- 可复现构建验证
- 为带有 tag 的 release 生成 SLSA-3 provenance
本地开发通过 `make check` 镜像 CI 流程。Dependabot 会为 `gomod` 和 `github-actions` 组自动提交 PR。
## 安全与披露
请参见 [SECURITY.md](./SECURITY.md)。
- **漏洞披露**:`sebastian.rousseau@gmail.com`。将在 72 小时内予以确认。
- **信任边界**:`bash` 工具会以用户的权限执行任意命令。Approval policy(带有拒绝规则的 pattern 模式)是操作者的主要控制手段;除非 daemon 处于无人值守状态,否则自带的合理默认值会拒绝 `bypassPermissions`。
- **供应链**:SLSA-3 provenance,cosign 签名的校验和,CycloneDX SBOM,精确锁定的依赖,以及在 CI 中配置的 `govulncheck` + CodeQL + Dependabot。
- **Runtime**:只读 rootfs,丢弃所有 capabilities,`NoNewPrivileges`,seccomp filter,非 root 用户,无入站 HTTP 攻击面。
## 对比
请查看 [`docs/COMPETITORS_2026_07_12.md`](./docs/COMPETITORS_2026_07_12.md) 获取完整的格局审计报告,其中包含了从 Hermes Agent、OpenClaw、TrustClaw、ZeroClaw、Claude Code、Aider、Cursor、Devin 和 OpenHands 收集的真实数据。
简而言之,以下是在自托管企业级核对清单中 rousseau 胜出的方面:
| 需求 | rousseau | 云托管替代方案 |
|---|:---:|:---:|
| 完全在操作者自己的基础设施内运行 | ✅ | ❌ |
| 无 SaaS 的 control plane、license server 或 telemetry | ✅ | ❌ |
| SLSA-3 provenance + cosign + SBOM | ✅ | 视情况而定 |
| 单个 binary 支持多家 LLM provider | ✅ | 极少数 |
| 九种 chat transport,且无需 broker | ✅ | 通常为 0–3 种 |
| MCP server(暴露 tools 和 session) | ✅ | 部分支持 |
| 采用降权配置的 rootless container | ✅ | 极少有文档说明 |
## 贡献
请参见 [CONTRIBUTING.md](./CONTRIBUTING.md)。
- 提交风格:[Conventional Commits](https://www.conventionalcommits.org/)。
- 每个导出的 identifier 都必须有 godoc 注释。
- 除非有书面合理理由,否则导出的 API 中禁止使用 `interface{}` / `any`。
## 许可证
基于 [MIT License](./LICENSE) 发布 © 2026 Sebastien Rousseau。 标签:AI编程助手, DLL 劫持, EVTX分析, Go, MCP, NIDS, Ruby工具, 大语言模型, 容器化, 日志审计, 自托管