Agent Runtime 架构

July 31, 2026 · View on GitHub

English | 中文

SmartPerfetto 后端现在把“模型 SDK”与“Perfetto 分析能力”分层。HTTP/CLI 会话层只依赖统一的 IOrchestrator 合约;具体运行时由 Provider 或 env 选择:

RuntimeSDKProvider 类型说明
claude-agent-sdkClaude Agent SDKAnthropic、Bedrock、Vertex、DeepSeek、Anthropic-compatible gateway默认运行时,继续支持 Claude Code 本地认证、MCP server、verifier 和 sub-agent
openai-agents-sdkOpenAI Agents SDKOpenAI、Ollama、OpenAI-compatible gateway原生 OpenAI runtime,通过 function tools 复用同一套 SmartPerfetto 工具
pi-agent-corePi Agent Corecustom only可选 public runtime;真实模型配置下复用 SmartPerfetto 共享 prompt/tool/report 管线,fake-stream 仅用于 smoke;不启用 .pi discovery、package extension、shell/file tools
opencodeOpenCode server / SDKcustom only可选 public runtime;使用显式 OpenAI-compatible 或 OpenCode model 配置、request-scoped SmartPerfetto MCP 工具和加固隔离的 OpenCode server;不读取本地 OpenCode 登录态/project state,也不启用内建 file/shell/web/edit tools
qoder-agent-sdkQoder Agent SDK / qoderclicustom only 或 env可选 public runtime;SDK 是 opt-in optional peer,使用本机 Qoder CLI 登录态或 PAT,只暴露 request-scoped SmartPerfetto MCP 工具,并隔离私有知识的流式输出、session 和 snapshot

入口

HTTP 主路径:

POST /api/agent/v1/analyze
  -> AgentAnalyzeSessionService.prepareSession()
  -> createAgentOrchestrator()
  -> ClaudeRuntime.analyze() | OpenAIRuntime.analyze() | PiAgentCoreRuntime.analyze() | OpenCodeRuntime.analyze() | QoderRuntime.analyze()

恢复和场景还原也走同一个 runtime factory:

POST /api/agent/v1/resume
POST /api/agent/v1/scene-reconstruct
  -> createAgentOrchestrator()

CLI 路径复用 AgentAnalyzeSessionService,因此 Provider/runtime 选择规则与 HTTP 一致。

CLI npm 包是独立终端产品,入口是 smp / smartperfetto;它不启动 Web UI,但会复用同一套 runtime、MCP 工具、Skill、report 和 session snapshot。

运行时选择

优先级从高到低:

  1. 请求体或会话内的 providerId
  2. Provider Manager 当前 active provider。
  3. SMARTPERFETTO_AGENT_RUNTIME env。
  4. 默认 claude-agent-sdk

SMARTPERFETTO_AGENT_RUNTIME 只接受 claude-agent-sdkopenai-agents-sdkpi-agent-coreopencodeqoder-agent-sdkdeepseekopenai 这类 provider 名称不能写在 runtime env 里;DeepSeek 应通过 Provider Manager 或 Claude/Anthropic-compatible env 配置。

环境变量不会被用来猜运行时。没有 active provider 且未设置 SMARTPERFETTO_AGENT_RUNTIME 时,即使同时存在 OPENAI_API_KEYANTHROPIC_API_KEY,默认仍是 claude-agent-sdk。Provider Manager 内的 active provider 会优先于 env;双端点 provider 通过 connection.agentRuntime 显式决定当前 SDK。

每个分析 session 会固定自己的 credential source:具体 Provider Manager profile,或显式的 env/default fallback。恢复历史 session 时不会重新读取后来切换的 active provider;如果快照绑定的 provider 已被删除,后端会 fail-fast,而不是静默回退到另一个 provider。

Provider 默认映射:

Provider typeRuntimeProtocol
anthropic / bedrock / vertex / deepseekclaude-agent-sdkClaude/Anthropic
openaiopenai-agents-sdkOpenAI Responses
ollamaopenai-agents-sdkOpenAI-compatible Chat Completions
customconnection.agentRuntimeconnection.openaiProtocol 决定显式配置;Pi Agent Core、OpenCode 和 Qoder 只允许 custom provider

Provider connection 支持两套端点字段:

字段Runtime映射到 env
claudeBaseUrl / claudeApiKey / claudeAuthTokenclaude-agent-sdkANTHROPIC_BASE_URL / ANTHROPIC_API_KEY / ANTHROPIC_AUTH_TOKEN
openaiBaseUrl / openaiApiKey / openaiProtocolopenai-agents-sdkOPENAI_BASE_URL / OPENAI_API_KEY / OPENAI_AGENTS_PROTOCOL
piAgentCoreModulePath / piAgentCoreModelJson / piAgentCoreSystemPromptpi-agent-coreSMARTPERFETTO_PI_AGENT_CORE_MODULE_PATH / SMARTPERFETTO_PI_AGENT_CORE_MODEL_JSON / SMARTPERFETTO_PI_AGENT_CORE_SYSTEM_PROMPT
openCodeSdkModulePath / openCodeModelJson / openCodeSystemPrompt 加 OpenAI-compatible 端点字段opencodeSMARTPERFETTO_OPENCODE_SDK_MODULE_PATH / SMARTPERFETTO_OPENCODE_MODEL_JSON / SMARTPERFETTO_OPENCODE_SYSTEM_PROMPT;没有 model JSON 时使用 OPENAI_BASE_URL / OPENAI_API_KEY / OPENAI_MODEL
qoderAccessToken / qoderCliPath / qoderModel / qoderSystemPromptqoder-agent-sdkQODER_PERSONAL_ACCESS_TOKEN / QODERCLI_PATH / QODER_MODEL / SMARTPERFETTO_QODER_SYSTEM_PROMPT
baseUrl / apiKeylegacy/shared作为旧配置兼容或双协议共享 key

M10 独立反馈 triage

Agent 辅助 GitHub 反馈不是主分析 session 的 resume。分析完成时,新 RunManifest 可保存 providerSnapshotHash;用户点击反馈 CTA 后,后端重新解析持久化源 run,并要求当前可用 provider snapshot 与该 hash 完全一致。它不会读取后来切换的 active provider,也不会 回退到另一个 runtime。

Claude/Anthropic-compatible 源 run 通过无工具 Claude SDK 调用执行 triage; OpenAI/OpenAI-compatible 源 run 通过轻量 Chat Completions 调用执行。两者都只接收有界的 公开 source context,不共享主分析 SDK session。Pi Agent Core、OpenCode、Qoder、旧 manifest、凭据不可用、snapshot 漂移或非法模型输出在 V1 中使用明确的确定性 fallback, 不会伪装成同一 Agent 已复核。完整用户边界见 Agent 辅助 GitHub 反馈

关键文件

文件责任
backend/src/agentRuntime/runtimeSelection.tsruntime 选择与统一 orchestrator factory
backend/src/agentRuntime/runtimeKinds.tsproduction runtime kind 与当前注册集合
backend/src/agentRuntime/runtimeDescriptors.tsruntime descriptor、EngineCapabilities 和 canonical loader
backend/src/agentRuntime/engines/claude/claudeRuntime.tsClaude Agent SDK orchestrator
backend/src/agentRuntime/engines/openai/openAiRuntime.tsOpenAI Agents SDK orchestrator
backend/src/agentRuntime/engines/openai/openAiToolAdapter.tsshared MCP descriptor 到 OpenAI function tool 的适配
backend/src/agentRuntime/engines/pi/piAgentCoreRuntime.tsPi Agent Core runtime adapter
backend/src/agentRuntime/engines/opencode/openCodeRuntime.tsOpenCode server/runtime adapter 与 request-scoped MCP bridge
backend/src/agentRuntime/engines/qoder/qoderRuntime.tsQoder Agent SDK adapter、流式投影和 session 隔离
backend/src/agentv3/claudeMcpServer.tsSmartPerfetto 工具注册,仍是工具单一事实源
backend/src/agentv3/mcpToolRegistry.ts工具 descriptor、exposure level 和 allowlist 单一事实源
backend/src/services/agentResultNormalizer.ts统一 final result、client projection 和 report data 边界
backend/src/services/finalReportContractGate.ts执行 strategy final_report_contract 完整性检查
backend/src/services/providerManager/Provider 配置、runtime/protocol/env 映射
backend/src/agentv3/sessionStateSnapshot.ts统一会话快照,含 Claude/OpenAI SDK 状态和 Pi/OpenCode/Qoder runtime state
backend/src/services/externalIssueReporting/providerPin.tsM10 源 run provider snapshot 校验
backend/src/services/externalIssueReporting/triageRunner.tsM10 无工具 Agent triage 与确定性 fallback

backend/src/agentOpenAI/ 以及 agentv3/claudeRuntime.ts 等具体文件继续提供 旧 import path 的 compatibility re-export;agentv3/ 目录内的 MCP、strategy、 planning 和 verifier 仍是 canonical shared layers。

工具层

SmartPerfetto 的分析能力由 createClaudeMcpServer() 实现,并通过 McpToolRegistry 描述和筛选。工具面不是固定数量,而是按 request scope 生成:quick/full、artifact store、codebase permission、referenceTraceId、comparison context 都会影响最终可见工具。

Claude runtime 直接把这些工具暴露为 in-process MCP server。

OpenAI runtime 不复制工具逻辑,而是读取同一份 McpToolRegistry,把每个 tool descriptor 适配为 OpenAI Agents SDK function tool。工具名称保留 mcp__smartperfetto__* 前缀,便于 SSE、日志和报告复用现有语义。

当前注册的 production runtime 在 SmartPerfetto 边界上保持同一个产品合约:输入是同一份分析请求,输出归一化为同一组 SSE event、AnalysisResult 和 HTML report。它们的 SDK/server 机制并不相同:Claude runtime 使用 Claude SDK 的 in-process MCP server、tool allowlist、SDK session resume、verifier/sub-agent;OpenAI runtime 使用从同一工具注册表适配出来的 function tools,Responses API 通过 previousResponseId 恢复,Chat Completions-compatible provider 通过历史消息恢复;Pi Agent Core 使用 request-scoped native tools、共享系统 prompt、plan/hypothesis 工具和同一条 route-owned finalization/claim-verification/report 管线;OpenCode 使用加固隔离的 OpenCode server,并通过每次分析的 MCP bridge 暴露 request-scoped SmartPerfetto 工具,同时禁用或拒绝内建 project discovery、file、shell、web 和 edit tools;Qoder 通过 SDK in-process MCP bridge 复用共享工具,禁用 SDK built-in tools,并在 SSE 前使用共享 private-output guard 投影每个答案 token。模型的工具调用节奏、流式事件、恢复能力和成本/超时语义都可能不同。

分析模式

模式行为
fast轻量系统 prompt、核心证据工具子集和 runtime-specific quick budget。Claude 使用 CLAUDE_QUICK_MAX_TURNS,OpenAI 使用 OPENAI_QUICK_MAX_TURNS,Pi/OpenCode/Qoder 复用 shared run spec 和各自 adapter 的超时/步骤语义
full完整工具、plan gate、notes、artifact 和质量门禁。Claude 保留 verifier/sub-agent 配置;OpenAI、Pi、OpenCode、Qoder 通过共享工具和质量管线补齐产品合约
auto规则和轻量分类器路由;不能判断时走完整分析,显式 fast 时走轻量路径

SSE 事件

所有 runtime 都向路由层发同一类 SmartPerfetto streaming update:

Event含义
progress阶段变化
thought中间推理或阶段提示
agent_task_dispatched工具调用开始
agent_response工具结果
answer_token最终答案 token
conclusionSDK 结论已到达
analysis_completedHTML report 已生成,终态事件
error错误

analysis_completed 仍由 route 层生成 report 后发出,所以报告链路不关心底层 SDK。

Pi Agent Core 的真实模型路径复用 SmartPerfetto 的 scene strategy、系统 prompt、SQL/Skill、plan/hypothesis、artifact、route-owned quality/finalization/report 管线。它不会把 SmartPerfetto 运行时变成 Pi coding-agent harness,也不读取 .pi 项目配置、package extension、shell tool 或 file tool。Provider Manager 只允许 custom provider 选择 pi-agent-core,并且必须提供 Pi model JSON 或等价 env 配置。SMARTPERFETTO_PI_AGENT_CORE_FAKE_STREAM=1 只用于本地 smoke/test,输出必须继续标记为 capability-limited。

OpenCode 路径同样只允许 custom provider。它可以使用带 providerID / modelID / baseUrl / apiKeySMARTPERFETTO_OPENCODE_MODEL_JSON,也可以回退到 OpenAI-compatible 的 OPENAI_* env/provider 字段。SmartPerfetto 不复用用户自己的 OpenCode CLI 登录态、配置文件或 project extension;回滚路径是把 custom provider 或 SMARTPERFETTO_AGENT_RUNTIME 切回 claude-agent-sdk / openai-agents-sdk

Qoder 在 Provider Manager 中同样只允许 custom provider,也可以通过 env 显式选择。SDK 默认不安装,用户必须先审阅条款再 opt in。公开分析可按 Qoder SDK session id 恢复;一旦请求获准访问私有 codebase 或外部知识源,就不会恢复或保存该 provider opaque session,也不会把中间状态写入 durable snapshot。

Final Result 与质量产物

所有 runtime 的原始输出都会被归一化为共享的 AnalysisResult,再进入质量和持久化链路:

runtime result
  -> agentResultNormalizer
  -> finalReportContractGate
  -> evidence contract / claim verification / identity resolutions
  -> HTML report / CLI turn files / analysis-result snapshot
  -> frontend visible projection

final_report_contract 来自 strategy frontmatter。Verifier 已知误诊规则同样来自 strategy frontmatter 的 verifier_misdiagnosis_patterns:运行时按 scene 载入匹配规则,global 规则可跨 scene 共享,regex 必须通过 validate:strategies 编译校验,severity 只允许 warninginfo。claim verification 和 identity resolution 依赖 Skill/DataEnvelope 中的结构化证据。前端可以对可见 chat conclusion 做噪音过滤,但不能删除 report、CLI 或 snapshot 需要的 provenance。

Session 与恢复

统一快照由 route 层调用 orchestrator.takeSnapshot() 生成,恢复时调用 restoreFromSnapshot()

Claude runtime 持久化 sdkSessionId 并通过 Claude SDK resume 恢复上下文。

OpenAI runtime 持久化 openAIHistoryopenAILastResponseId 和预留的 openAIRunState。恢复后优先用 SDK history 继续多轮对话;Responses API 可附带 previousResponseId,Chat Completions-compatible provider 使用完整 history。

Pi Agent Core、OpenCode 和 Qoder 只在 adapter 支持且不涉及私有知识时保存 runtime-specific opaque state,但仍会保留 provider/runtime identity,避免 resume、report 或 snapshot 静默切到另一个引擎。

快照还会携带 final result 质量相关字段,例如 conclusion contract、claim verification result 和 identity resolutions,以便 resume、report export 和 analysis-result comparison 复用。

Raw trace comparison session 还必须持久化 referenceTraceIdcomparisonSourcecomparisonReportSection。同一个 session 不能从 comparison 降级成 single-trace, 也不能静默切到另一个 reference trace;恢复时 runtime-specific session state 和 provider/runtime identity 都必须按 comparison identity 读写。

发布与平台边界

  • 源码和 npm CLI 要求 Node.js >=24 <25
  • 免安装包自带 Node.js 24、后端、预构建 frontend/ 和固定 trace processor。
  • Docker 不读取宿主机 Claude Code 登录态,必须用 Provider Manager 或 env provider。
  • 默认 Docker、portable 和 npm 安装不包含 Qoder SDK;接受其条款并显式安装 optional peer 后才能启用。
  • 任何 runtime/provider/session 改动都要检查 Web UI、CLI、API、报告、Docker 和免安装包;详见 ../../.claude/rules/product-surface.md

健康检查

带鉴权的 GET /api/runtime-health 中,aiEngine.runtime 会显示实际选择的 runtime;公开 GET /health 只返回存活状态与版本:

{
  "aiEngine": {
    "runtime": "openai-agents-sdk",
    "providerMode": "openai_responses",
    "diagnostics": {
      "protocol": "responses",
      "model": "gpt-5.4-mini"
    }
  }
}

这能区分“Provider 连接测试通过”和“真实分析 runtime 已切换”这两件事。