AgnesCode 协议 & 认证深度分析报告
报告日期: 2026-07-24
分析版本: v1.0.17
分析范围: ACP 协议、认证流程、后端 API、MCP 集成、反向代理实现指南
1. ACP 协议详解
1.1 协议概述
ACP (Agent Client Protocol) 是 AgnesCode 的核心通信协议,基于 JSON-RPC 2.0,运行于 WebSocket 之上。
协议特征:
- 传输层: WebSocket (WSS)
- 消息格式: JSON-RPC 2.0
- 认证: Token via URL 参数 +
X-Secret-KeyHTTP 头 - 流式: 支持 SSE (Server-Sent Events) 进行流式传输
- 双向: 支持 Request/Response 和 Notification (无响应)
1.2 连接建立
WebSocket URL 构造:
// 函数 Vj(e, t) 构造 ACP WebSocket URL
function Vj(baseUrl, token) {
const r = new URL(baseUrl);
r.pathname = `${r.pathname.replace(/\/+$/, "")}/acp`;
r.protocol = r.protocol === "https:" ? "wss:" : "ws:";
r.searchParams.set("token", token);
return r.toString();
}
// 示例: wss://127.0.0.1:{port}/acp?token={secretKey}HTTP 头:
Acp-Connection-Id: 连接级 SSE 流标识Acp-Session-Id: 会话级 SSE 流标识X-Secret-Key: API 认证密钥 (HTTP API 用)Content-Type:application/json
1.3 消息格式 (JSON-RPC 2.0)
Request 消息
{
"jsonrpc": "2.0",
"id": 1,
"method": "session/prompt",
"params": { ... }
}Response 消息
{
"jsonrpc": "2.0",
"id": 1,
"result": { ... }
}错误响应
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Method not found: xxx",
"data": { "method": "xxx" }
}
}Notification 消息 (无响应)
{
"jsonrpc": "2.0",
"method": "session/cancel",
"params": { ... }
}1.4 标准 ACP 方法
| 方法 | 类型 | 方向 | 描述 |
|---|---|---|---|
session/new | Request | Client→Server | 创建新会话 |
session/prompt | Request | Client→Server | 发送提示词 |
session/cancel | Notification | Client→Server | 取消当前请求 |
session/close | Request | Client→Server | 关闭会话 |
session/fork | Request | Client→Server | 分叉会话 |
session/list | Request | Client→Server | 列出会话 |
session/load | Request | Client→Server | 加载会话 |
session/resume | Request | Client→Server | 恢复会话 |
session/set_mode | Request | Client→Server | 设置模式 (smart/expert) |
session/set_model | Request | Client→Server | 设置模型 |
session/set_config_option | Request | Client→Server | 设置配置项 |
session/request_permission | Request | Server→Client | 请求权限 |
session/update | Notification | Server→Client | 会话更新推送 |
initialize | Request | Client→Server | 初始化连接 |
authenticate | Request | Client→Server | 认证 |
logout | Request | Client→Server | 登出 |
1.5 扩展方法 (Agnes 自定义)
所有 Agnes 扩展方法以 _agnes/unstable/ 为前缀:
| 方法 | 描述 |
|---|---|
_agnes/unstable/tools/list | 列出工具 |
_agnes/unstable/tools/call | 调用工具 |
_agnes/unstable/tools/permissions/set | 设置工具权限 |
_agnes/unstable/resources/read | 读取资源 |
_agnes/unstable/session/info | 获取会话信息 |
_agnes/unstable/session/export | 导出会话 |
_agnes/unstable/session/import | 导入会话 |
_agnes/unstable/session/history/load | 加载会话历史 |
_agnes/unstable/session/extensions/add | 添加会话扩展 |
_agnes/unstable/session/extensions/remove | 移除会话扩展 |
_agnes/unstable/session/extensions/list | 列出会话扩展 |
_agnes/unstable/session/system-prompt/set | 设置系统提示 |
_agnes/unstable/session/working-dir/update | 更新工作目录 |
_agnes/unstable/session/steer | 控制会话方向 |
_agnes/unstable/session/archive | 归档会话 |
_agnes/unstable/session/unarchive | 取消归档 |
_agnes/unstable/session/rename | 重命名会话 |
_agnes/unstable/session/share/nostr | 分享会话 (Nostr) |
_agnes/unstable/session/conversation/truncate | 截断对话 |
_agnes/unstable/session/recipe/request-params | 请求配方参数 |
_agnes/unstable/session/project/update | 更新会话项目 |
_agnes/unstable/side-chat/start | 启动侧边聊天 |
_agnes/unstable/side-chat/cancel | 取消侧边聊天 |
_agnes/unstable/side-chat/dispose | 销毁侧边聊天 |
_agnes/unstable/config/read | 读取配置 |
_agnes/unstable/config/read-all | 读取所有配置 |
_agnes/unstable/config/upsert | 更新/插入配置 |
_agnes/unstable/config/remove | 删除配置 |
_agnes/unstable/config/prompts/list | 列出提示词 |
_agnes/unstable/config/prompts/get | 获取提示词 |
_agnes/unstable/config/prompts/save | 保存提示词 |
_agnes/unstable/config/prompts/reset | 重置提示词 |
_agnes/unstable/config/extensions/add | 添加扩展配置 |
_agnes/unstable/config/extensions/remove | 移除扩展 |
_agnes/unstable/config/extensions/list | 列出扩展 |
_agnes/unstable/config/extensions/set-enabled | 启用/禁用扩展 |
_agnes/unstable/defaults/read | 读取默认值 |
_agnes/unstable/defaults/save | 保存默认值 |
_agnes/unstable/defaults/clear | 清除默认值 |
_agnes/unstable/providers/list | 列出提供商 |
_agnes/unstable/providers/config/read | 读取提供商配置 |
_agnes/unstable/providers/config/save | 保存提供商配置 |
_agnes/unstable/providers/config/delete | 删除提供商配置 |
_agnes/unstable/providers/config/authenticate | 认证提供商 |
_agnes/unstable/providers/config/status | 提供商配置状态 |
_agnes/unstable/providers/secrets/list | 列出密钥 |
_agnes/unstable/providers/secrets/delete | 删除密钥 |
_agnes/unstable/providers/catalog/list | 列出提供商目录 |
_agnes/unstable/providers/catalog/template | 提供商模板 |
_agnes/unstable/providers/setup/catalog/list | 设置目录列表 |
_agnes/unstable/providers/custom/create | 创建自定义提供商 |
_agnes/unstable/providers/custom/read | 读取自定义提供商 |
_agnes/unstable/providers/custom/update | 更新自定义提供商 |
_agnes/unstable/providers/custom/delete | 删除自定义提供商 |
_agnes/unstable/providers/supported-models/list | 列出支持的模型 |
_agnes/unstable/providers/canonical-model-info | 规范模型信息 |
_agnes/unstable/providers/inventory/refresh | 刷新库存 |
_agnes/unstable/recipes/list | 列出配方 |
_agnes/unstable/recipes/delete | 删除配方 |
_agnes/unstable/recipes/encode | 编码配方 |
_agnes/unstable/recipes/decode | 解码配方 |
_agnes/unstable/recipes/parse | 解析配方 |
_agnes/unstable/recipes/save | 保存配方 |
_agnes/unstable/recipes/scan | 扫描配方 |
_agnes/unstable/recipes/schedule | 调度配方 |
_agnes/unstable/recipes/slash-command | 斜杠命令 |
_agnes/unstable/recipes/to-yaml | 配方转 YAML |
_agnes/unstable/onboarding/import/scan | 扫描导入 |
_agnes/unstable/onboarding/import/apply | 应用导入 |
_agnes/unstable/tools/list | 列出工具 |
_agnes/unstable/tools/call | 调用工具 |
_agnes/unstable/tools/permissions/set | 设置工具权限 |
_agnes/unstable/resources/read | 读取资源 |
_agnes/unstable/apps/list | 列出应用 |
_agnes/unstable/apps/export | 导出应用 |
_agnes/unstable/apps/import | 导入应用 |
_agnes/unstable/apps/delete | 删除应用 |
_agnes/unstable/capabilities/list | 列出能力 |
_agnes/unstable/diagnostics/get | 获取诊断 |
_agnes/unstable/sources/list | 列出源 |
_agnes/unstable/sources/create | 创建源 |
_agnes/unstable/sources/update | 更新源 |
_agnes/unstable/sources/delete | 删除源 |
_agnes/unstable/sources/export | 导出源 |
_agnes/unstable/sources/import | 导入源 |
_agnes/unstable/extensions/available | 可用扩展 |
_agnes/unstable/local-inference/models/list | 本地推理模型列表 |
_agnes/unstable/local-inference/models/download | 下载模型 |
_agnes/unstable/local-inference/models/download/progress | 下载进度 |
_agnes/unstable/local-inference/models/download/cancel | 取消下载 |
_agnes/unstable/local-inference/models/delete | 删除模型 |
_agnes/unstable/local-inference/models/evict | 驱逐模型 |
_agnes/unstable/local-inference/models/settings/read | 读取本地推理设置 |
_agnes/unstable/local-inference/models/settings/update | 更新本地推理设置 |
_agnes/unstable/local-inference/huggingface/search | HuggingFace 搜索 |
_agnes/unstable/local-inference/huggingface/repo/variants | HuggingFace 仓库变体 |
_agnes/unstable/local-inference/chat-templates/builtin/list | 内置聊天模板列表 |
_agnes/unstable/dictation/config | 听写配置 |
_agnes/unstable/dictation/transcribe | 听写转写 |
_agnes/unstable/dictation/models/list | 听写模型列表 |
_agnes/unstable/dictation/models/download | 下载听写模型 |
_agnes/unstable/dictation/models/download/progress | 下载进度 |
_agnes/unstable/dictation/models/download/cancel | 取消下载 |
_agnes/unstable/dictation/models/delete | 删除听写模型 |
_agnes/unstable/dictation/models/select | 选择听写模型 |
_agnes/unstable/dictation/secret/save | 保存听写密钥 |
_agnes/unstable/dictation/secret/delete | 删除听写密钥 |
_agnes/unstable/dictation/models/cancel | 取消听写模型操作 |
_agnes/unstable/scheduled-tasks/create | 创建定时任务 |
_agnes/unstable/scheduled-tasks/delete | 删除定时任务 |
_agnes/unstable/scheduled-tasks/list | 列出定时任务 |
_agnes/unstable/scheduled-tasks/get | 获取定时任务 |
_agnes/unstable/scheduled-tasks/update | 更新定时任务 |
_agnes/unstable/scheduled-tasks/pause | 暂停定时任务 |
_agnes/unstable/scheduled-tasks/unpause | 恢复定时任务 |
_agnes/unstable/scheduled-tasks/run-now | 立即运行 |
_agnes/unstable/scheduled-tasks/runs/list | 运行记录列表 |
_agnes/unstable/scheduled-tasks/sessions/list | 任务会话列表 |
_agnes/unstable/scheduled-tasks/running-job/inspect | 检查运行中任务 |
_agnes/unstable/scheduled-tasks/running-job/kill | 终止运行中任务 |
_agnes/unstable/schedules/* | 日程管理 (同 scheduled-tasks) |
_agnes/unstable/agent-mentions/list | 列出 Agent 提及 |
_agnes/unstable/slash-commands/list | 列出斜杠命令 |
_agnes/unstable/preferences/read | 读取偏好 |
_agnes/unstable/preferences/save | 保存偏好 |
_agnes/unstable/preferences/remove | 删除偏好 |
1.6 流式传输
ACP 支持两种流式传输方式:
1. 连接级 SSE 流 (Connection-scoped GET Stream)
GET /acp
Accept: text/event-stream
Acp-Connection-Id: {connectionId}用于接收服务器推送事件。
2. 会话级 SSE 流 (Session-scoped GET Stream)
GET /acp
Accept: text/event-stream
Acp-Connection-Id: {connectionId}
Acp-Session-Id: {sessionId}用于接收特定会话的推送事件。
1.7 错误码
| 代码 | 名称 | 描述 |
|---|---|---|
| -32700 | Parse Error | JSON 解析错误 |
| -32600 | Invalid Request | 无效请求 |
| -32601 | Method Not Found | 方法不存在 |
| -32602 | Invalid Params | 无效参数 |
| -32603 | Internal Error | 内部错误 |
| -32000 | Auth Required | 需要认证 |
| -32002 | Resource Not Found | 资源不存在 |
| -32800 | URL Elicitation Required | 需要 URL 引导 |
2. 认证与授权完整流程
2.1 完整认证数据流
┌─────────────────────────────────────────────────────────────────────────┐
│ 1. 用户点击"登录" │
│ │
│ 2. 渲染进程调用: │
│ window.electron.startAuthLogin() │
│ │
│ 3. 主进程: │
│ a. 生成 32 字节随机 state (crypto.randomBytes(32).toString('hex')) │
│ b. 构造登录 URL: │
│ const url = AGNES_SA_WEB_LOGIN_URL + '/login' │
│ url += '?client=agnes-code' │
│ url += '&redirect_uri=agnes://auth/callback' │
│ url += '&state=' + state │
│ c. 保存 state 和 windowId 的映射 │
│ d. shell.openExternal(url) 在系统浏览器中打开 │
│ e. 返回 { state } 给渲染进程 │
│ │
│ 4. 用户在浏览器中完成登录 │
│ │
│ 5. 浏览器重定向到: │
│ agnes://auth/callback?code={auth_code}&state={state} │
│ │
│ 6. 操作系统处理 agnes:// 协议,唤起 Electron 应用 │
│ a. macOS: app.on('open-url', ...) │
│ b. 其他平台: 通过命令行参数 / 自定义协议处理 │
│ │
│ 7. 主进程验证 state 匹配: │
│ if (savedState !== receivedState) → 拒绝 │
│ │
│ 8. 主进程通过 IPC 发送 auth-deeplink 给渲染进程: │
│ webContents.send('auth-deeplink', { code, state }) │
│ │
│ 9. 渲染进程调用 eX() 函数交换 code 获取 token: │
│ POST {AGNES_API_URL}/api/v1/code/auth/exchange-code │
│ Body: { │
│ code: auth_code, │
│ redirect_uri: 'agnes://auth/callback', │
│ state: state, │
│ client_id: 'agnes-code' │
│ } │
│ Response: { │
│ code: 0, // 成功时为 0 或 "000000" │
│ data: { │
│ access_token: '...', │
│ user_info: { ... } │
│ } │
│ } │
│ │
│ 10. 渲染进程保存 token: │
│ a. localStorage.setItem('token', access_token) │
│ b. localStorage.setItem('userinfo', JSON.stringify(user_info)) │
│ c. 通过 IPC 将 token 同步到密钥链: │
│ window.electron.setSetting('AGNES_AI_API_KEY', token) │
│ d. 触发 'agnes:userinfo-updated' 事件 │
│ │
│ 11. 后续 API 调用: │
│ a. 本地 agnesd API: X-Secret-Key 头 │
│ b. 远程 Agnes API: Authorization: Bearer {token} 头 │
└─────────────────────────────────────────────────────────────────────────┘2.2 Agnes API 地址
Agnes API 基地址: https://api.agnes-ai.com
通过环境变量 AGNES_API_URL 配置,可在构建时由 scripts/brand-dev-electron.cjs 脚本注入。
认证端点:
POST {AGNES_API_URL}/api/v1/code/auth/exchange-code订阅/信用端点:
GET {AGNES_API_URL}/api/v2/subscription/credits-balance
POST {AGNES_API_URL}/api/v1/subscription/credits-transactions2.3 Token 管理与存储
| 存储位置 | 键名 | 用途 |
|---|---|---|
localStorage | token | access_token,用于 API 认证 |
localStorage | userinfo | 用户信息 JSON |
| 密钥链 (Keychain) | AGNES_AI_API_KEY | 同步到密钥链 |
API 请求认证头:
Authorization: Bearer {access_token}
X-User-Language: {locale}登出: 清除 localStorage 中的 token、userinfo、userPptData,触发 agnes:userinfo-updated 事件。
2.4 401 处理
当 API 返回 401 时,自动清除 token 并触发登出。使用防抖机制(2秒内只触发一次):
let ff = false;
const dX = 2000;
function Iy(e) {
!e || e.status !== 401 || ff || (ff = true, clearToken(), setTimeout(() => { ff = false }, dX));
}2.5 订阅 URL 处理
订阅成功回调: agnes://subscription?status=success 或 agnes://subscription/success
3. agnest 后端 API 全集
3.1 架构
agnest 是 Rust 编写的本地后端服务:
- 二进制名称:
agnesd(Linux/macOS) /agnesd.exe(Windows) - 通信协议: HTTPS (自签名证书)
- 端口: 随机分配 (通过监听端口 0)
- 认证:
X-Secret-Key请求头 - 启动命令:
agnesd agent
3.2 环境变量 (传递给 agnest)
AGNES_PORT={port}
AGNES_SERVER__SECRET_KEY={random_32_byte_hex}
AGNES_KEYRING_SERVICE=com.agnes.code.secrets // 或 dev 版本
HOME={home_dir}
PATH={system_path}3.3 API 客户端配置
const client = createClient({
baseUrl: 'https://127.0.0.1:{port}',
headers: {
'Content-Type': 'application/json',
'X-Secret-Key': secretKey
}
});3.4 健康检查
// 轮询 GET /health_check 端点
// 超时: 30秒
// 请求超时: 2秒
// 间隔: 250ms
// 成功条件: 返回 200
// 错误判断: 400-499 (非 408, 429) 或证书错误3.5 启动流程
- 查找
agnesd二进制 (优先打包资源中的bin/agnesd) - 在随机端口启动
- 解析 stdout 中的
GOOSED_CERT_FINGERPRINT=行 - 验证自签名证书指纹
- 健康检查轮询
- 连接就绪后通知渲染进程
3.6 证书验证
// 自签名证书指纹验证
// 指纹格式: sha256/{base64}
// 信任策略: 只有 127.0.0.1 和 localhost 的连接被信任
// 首次连接: 记录指纹并信任
// 后续连接: 验证指纹匹配4. MCP 工具集成分析
4.1 MCP 概述
AgnesCode 集成了 MCP (Model Context Protocol) 标准,支持:
- 标准 MCP 工具定义
- 自定义工具链
- 扩展 (Extensions) 系统
- 技能 (Skills) 引擎
4.2 MCP 方法
| 方法 | 描述 |
|---|---|
tools/list | 列出工具 |
tools/call | 调用工具 |
notifications/tools/list_changed | 工具列表变更通知 |
resources/read | 读取资源 |
resources/list | 列出资源 |
resources/subscribe | 订阅资源变更 |
prompts/list | 列出提示词 |
prompts/get | 获取提示词 |
sampling/createMessage | 采样创建消息 |
completion/complete | 补全 |
logging/setLevel | 设置日志级别 |
notifications/message | 消息通知 |
roots/list | 列出根目录 |
notifications/roots/list_changed | 根目录变更通知 |
initialize | 初始化 MCP 连接 |
notifications/initialized | 初始化完成通知 |
4.3 MCP 工具定义
// 工具定义 schema
interface Tool {
name: string;
description?: string;
inputSchema: {
type: "object";
properties: Record<string, any>;
required?: string[];
};
outputSchema?: {
type: "object";
properties: Record<string, any>;
required?: string[];
};
annotations?: {
title?: string;
readOnlyHint?: boolean;
destructiveHint?: boolean;
idempotentHint?: boolean;
openWorldHint?: boolean;
};
execution?: {
taskSupport: "required" | "optional" | "forbidden";
};
}4.4 内容类型
MCP 支持的内容块类型:
| 类型 | 描述 |
|---|---|
text | 文本内容 |
image | 图片 (data: URI) |
audio | 音频 |
tool_use | 工具调用 |
tool_result | 工具调用结果 |
resource | 资源引用 |
resource_link | 资源链接 |
4.5 扩展 (Extensions) 系统
扩展通过 MCP 协议集成,支持三种类型:
| 扩展类型 | 传输方式 | 描述 |
|---|---|---|
http | HTTP | 通过 HTTP 端点通信 |
sse | SSE | 通过 Server-Sent Events 通信 |
terminal | 本地进程 | 通过本地子进程通信 |
扩展配置:
interface Extension {
name: string;
type: "http" | "sse" | "terminal";
// HTTP 类型
url?: string;
headers?: { name: string; value: string }[];
// 终端类型
command?: string;
args?: string[];
env?: { name: string; value: string }[];
}4.6 工具权限
// 权限级别
type PermissionLevel = "always_allow" | "ask_before" | "never_allow";
// 工具权限设置
interface ToolPermission {
name: string;
permission: PermissionLevel;
}4.7 本地工具
| 工具 | 描述 |
|---|---|
fs/read_text_file | 读取文本文件 |
fs/write_text_file | 写入文本文件 |
terminal/create | 创建终端会话 |
terminal/kill | 终止终端 |
terminal/output | 终端输出 |
terminal/release | 释放终端 |
terminal/wait_for_exit | 等待终端退出 |
session/update | 更新会话 |
session/request_permission | 请求权限 |
5. 会话与会话管理
5.1 会话生命周期
创建 (session/new) → 活跃 (prompt) → 关闭 (session/close)
→ 分叉 (session/fork)
→ 归档 (session/archive)5.2 会话上下文
会话模式:
smart: 自动路径选择expert: 手动控制模型、参数、工具、上下文
会话配置选项:
interface SessionConfig {
model?: string;
mode?: 'smart' | 'expert';
systemPrompt?: string;
workingDir?: string;
temperature?: number;
maxTokens?: number;
topP?: number;
stopSequences?: string[];
tools?: Tool[];
toolChoice?: 'auto' | 'required' | 'none';
extensions?: string[];
project?: {
id: string;
name: string;
};
}5.3 会话历史
interface SessionHistory {
sessionId: string;
messages: Message[];
// 消息结构
interface Message {
role: 'user' | 'assistant' | 'system' | 'tool';
content: ContentBlock[];
}
}5.4 侧边聊天 (Side Chat)
支持在会话中启动侧边聊天:
interface SideChat {
parentSessionId: string;
sideChatId: string;
runId: string;
userMessage: Message;
sideChatMessages: Message[];
context: {
includeRecentParentMessages: boolean;
includeWorkbench: boolean;
};
}6. AI 提供商路由
6.1 支持的提供商
从渲染代码中提取的提供商列表:
| 提供商 | 类型 | 描述 |
|---|---|---|
| Agnes 自有模型 | 内置 | 通过 Agnes API 访问 |
| OpenAI | 外部 | GPT-4, o1, o3 等 |
| Anthropic | 外部 | Claude 系列 |
| DeepSeek | 外部 | DeepSeek 系列 |
| Qwen | 外部 | Qwen 系列 |
| MoonshotAI | 外部 | Moonshot 系列 |
| Cohere | 外部 | Cohere 系列 |
| HuggingFace | 外部 | HuggingFace 推理 |
| Ollama | 本地 | 本地模型 |
| mesh-llm | 本地 | P2P 模型网络 |
| 腾讯云 | 外部 | 语音识别等 |
6.2 提供商配置
interface ProviderConfig {
providerId: string;
providerName: string;
providerType: 'agent' | 'model';
description: string;
defaultModel: string;
configured: boolean;
configKeys: ConfigKey[];
models: ModelInfo[];
supportsRefresh: boolean;
}
interface ConfigKey {
name: string;
required: boolean;
secret: boolean;
default?: string | number | boolean;
}
interface ModelInfo {
id: string;
name: string;
provider: string;
description?: string;
capabilities: string[];
}6.3 提供商认证流程
- 渲染进程通过 ACP 调用
_agnes/unstable/providers/config/authenticate - 用户输入 API Key 或其他凭证
- 凭证通过
_agnes/unstable/providers/config/save保存 - 密钥通过
_agnes/unstable/providers/secrets/**管理 - 提供商状态通过
_agnes/unstable/providers/config/status查询
6.4 模型选择
interface ModelPreferences {
hints?: { name?: string }[];
costPriority?: number; // 0-1
speedPriority?: number; // 0-1
intelligencePriority?: number; // 0-1
}7. 反向代理实现指南
7.1 方案比较
方案 A: AGNES_EXTERNAL_BACKEND (推荐)
难度: 低
控制粒度: 中
实现工作量: 中
原理:
1. 设置 AGNES_EXTERNAL_BACKEND=https://your-proxy-server.com
2. 设置 AGNES_SERVER__SECRET_KEY=your-secret-key
3. 实现符合 ACP 协议的后端服务
4. 后端处理认证、路由、工具调用
步骤:
a. 实现 ACP WebSocket 服务器 (JSON-RPC 2.0 over WebSocket)
b. 实现标准 ACP 方法 (session/new, session/prompt, session/cancel 等)
c. 实现 AI 提供商路由逻辑
d. 实现 MCP 工具调用
e. 启动后端服务
f. 设置环境变量启动 AgnesCode方案 B: 本地代理 (中间人)
难度: 中
控制粒度: 高
实现工作量: 高
原理:
1. 在本地启动代理服务器
2. 修改 hosts 或证书以拦截流量
3. 代理分析 ACP 消息并转发
步骤:
a. 实现 WebSocket 代理
b. 解析 ACP JSON-RPC 消息
c. 修改或重定向 AI 请求
d. 转发响应方案 C: 替换 agnesd 二进制
难度: 高
控制粒度: 高
实现工作量: 极高
原理:
1. 逆向 agnesd 二进制
2. 实现兼容的 Rust 后端
3. 替换打包的 agnesd 二进制
步骤:
a. 分析 agnesd 的 HTTP API
b. 实现兼容的 API 服务器
c. 处理自签名证书
d. 替换二进制7.2 推荐方案: 外部后端 (AGNES_EXTERNAL_BACKEND)
服务端实现要求
1. WebSocket 端点: /acp
// 连接建立
WebSocket URL: wss://your-server.com/acp?token={secretKey}2. 必须实现的方法:
initialize - 初始化连接
session/new - 创建新会话
session/prompt - 发送提示词 (核心方法)
session/cancel - 取消请求
session/close - 关闭会话
session/list - 列出会话
session/load - 加载会话
authenticate - 认证
logout - 登出3. 推荐实现的方法:
session/set_mode - 设置模式
session/set_model - 设置模型
session/set_config_option - 设置配置
session/fork - 分叉会话
session/resume - 恢复会话4. 推送通知:
session/update - 会话更新推送 (Server→Client)5. 错误处理:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Method not found",
"data": { "method": "xxx" }
}
}7.3 session/prompt 消息格式
请求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "session/prompt",
"params": {
"sessionId": "session-uuid",
"message": {
"role": "user",
"content": [
{ "type": "text", "text": "Hello" }
]
},
"model": "gpt-4o",
"mode": "smart",
"systemPrompt": "You are a helpful assistant",
"tools": [
{
"name": "read_file",
"description": "Read a file",
"inputSchema": {
"type": "object",
"properties": {
"path": { "type": "string" }
},
"required": ["path"]
}
}
]
}
}响应:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"sessionId": "session-uuid",
"message": {
"role": "assistant",
"content": [
{ "type": "text", "text": "Hello! How can I help?" }
]
},
"stopReason": "endTurn",
"model": "gpt-4o",
"usage": {
"inputTokens": 10,
"outputTokens": 5,
"totalTokens": 15
}
}
}7.4 认证代理
如果要绕过 Agnes OAuth 认证,可以直接在 authenticate 方法中返回成功:
// 服务端实现
async handleAuthenticate(params) {
// 直接返回成功,绕过 OAuth
return { success: true };
}7.5 最小反向代理实现示例
# Python 示例: 最小 ACP 代理
import asyncio
import json
import websockets
from typing import Any
class ACPProxy:
def __init__(self, host="0.0.0.0", port=8765):
self.host = host
self.port = port
self.sessions = {}
async def handle_message(self, websocket, message: dict):
method = message.get("method")
msg_id = message.get("id")
params = message.get("params", {})
if method == "initialize":
return await self.handle_initialize(msg_id)
elif method == "session/new":
return await self.handle_session_new(msg_id, params)
elif method == "session/prompt":
return await self.handle_session_prompt(websocket, msg_id, params)
elif method == "session/cancel":
return await self.handle_session_cancel(msg_id, params)
elif method == "authenticate":
return await self.handle_authenticate(msg_id, params)
else:
return {
"jsonrpc": "2.0",
"id": msg_id,
"error": {
"code": -32601,
"message": f"Method not found: {method}"
}
}
async def handle_authenticate(self, msg_id, params):
# 绕过 OAuth 认证
return {
"jsonrpc": "2.0",
"id": msg_id,
"result": {
"success": True,
"user": {
"id": "proxy-user",
"name": "Proxy User"
}
}
}
async def handle_session_prompt(self, websocket, msg_id, params):
# 转发到 AI API (例如 OpenAI)
messages = self._convert_to_api_format(params)
api_key = "your-api-key"
# 调用 AI API 并流式返回
response = await self._call_ai_api(messages, api_key)
return {
"jsonrpc": "2.0",
"id": msg_id,
"result": response
}
async def handler(self, websocket, path=None):
async for raw_message in websocket:
message = json.loads(raw_message)
response = await self.handle_message(websocket, message)
if response:
await websocket.send(json.dumps(response))
def start(self):
return websockets.serve(self.handler, self.host, self.port)7.6 关键配置
# 启动 AgnesCode 使用外部后端
export AGNES_EXTERNAL_BACKEND=https://your-proxy-server.com
export AGNES_SERVER__SECRET_KEY=your-secret-key
export AGNES_PORT=3000
# 可选: 替换登录 URL
export AGNES_SA_WEB_LOGIN_URL=https://your-auth-server.com
# 可选: 默认提供商和模型
export AGNES_DEFAULT_PROVIDER=openai
export AGNES_DEFAULT_MODEL=gpt-4o
# 启动
./AgnesCode8. 附录
8.1 关键代码路径
| 文件 | 路径 | 大小 |
|---|---|---|
| 主进程 | app.asar/.vite/build/main.js | 1.4 MB |
| 预加载脚本 | app.asar/.vite/build/preload.js | 2 KB |
| 渲染进程入口 | app.asar/.vite/renderer/main_window/assets/index-BXTNYseC.js | 320 KB |
| 应用主代码 | app.asar/.vite/renderer/main_window/assets/renderer-main-C4wZ9GTi.js | 1.45 MB |
8.2 关键函数索引
| 函数名 | 位置 | 描述 |
|---|---|---|
Oj() | main.js | 构造 OAuth 登录 URL |
Vj() | main.js | 构造 ACP WebSocket URL |
bs() | main.js | 处理 Deep Link 回调 |
A0() | main.js | 创建 API 客户端 |
bM() | main.js | 启动 agnesd 后端 |
iy() | main.js | 获取密钥 |
eX() | renderer | 交换 auth code 获取 token |
aX() | renderer | 保存 token 到 localStorage |
nX() | renderer | 同步 API Key 到密钥链 |
$8() | renderer | 初始化 ACP 连接 |
Z3 | renderer | ACP 传输层 (JSON-RPC) |
$3 | renderer | ACP 客户端 (方法封装) |
W3 | renderer | 扩展方法客户端 |
8.3 关键数据流图
用户输入 → React → ACP WebSocket → agnest → AI API
↓ ↓
localStorage Keychain
(token) (secrets)8.4 安全注意事项
- 自签名证书: agnest 使用自签名证书,仅信任 localhost 连接
- Secret Key: 随机 32 字节 hex,用于本地 API 认证
- Token 存储: access_token 存储在 localStorage 和系统密钥链
- CSP: 严格的 Content-Security-Policy 限制脚本和外连
- OAuth State: 32 字节随机 state 防 CSRF 攻击
- Deep Link 验证: 验证 state 匹配后才处理回调
8.5 版本演进
| 版本 | 日期 | 变化 |
|---|---|---|
| v1.0.15 | 2026-07-13 | 初始版本 |
| v1.0.17 | 2026-07-14 | 新增 Intel Mac 支持 |
| v1.0.19 | 2026-07-15 | 优化 |
| v1.0.23 | 2026-07-20 | 最新版本 |
免责声明: 本报告仅供教育和研究目的使用。反向工程应遵守相关法律法规和软件许可协议。