11 KiB
AI Core 与 Agent Core 开发说明
本文档用于团队开发和模块联调,记录当前已经落地的核心边界与使用方式。
更新日期:2026-09-01。第一阶段 AI Core、Agent Core、Extension Core 和 Model Core 主链路已经完成;第二阶段 Agent Trace 持久化和可恢复 SSE 已落地,后端当前回归基线为 81 项测试通过。
当前实现
当前已经建立第一条可运行链路:
FastAPI
→ Provider Registry
→ Agent Runtime
→ Permission Manager
→ Tool Registry
→ Skill Runtime / Plugin Runtime
→ Agent Trace / SSE
对应代码:
backend/app/
├── providers/
│ ├── base.py Provider Protocol 与统一 Turn
│ ├── registry.py Provider 注册、发现、模型列表和连接测试
│ └── mock.py 离线开发 Provider
├── agent/
│ ├── runtime.py Agent Loop、限制、取消、Trace 和 SSE
│ ├── trace_repository.py Run/Event SQLite 持久化、分页、摘要与脱敏
│ ├── tools.py Tool 注册、参数校验、隔离执行和结果转换
│ ├── permissions.py 权限策略、确认请求和会话授权
│ └── builtin_tools.py 无副作用的内置开发 Tool
├── extensions/
│ └── runtime.py Skill/Plugin Manifest、生命周期、依赖与 Tool Contribution
└── container.py AI Core 依赖组装
backend/extensions/
├── skills/knowledge-assistant/ 内置知识库 Skill
└── plugins/text-tools/ 内置示例 Plugin
Router 只负责 HTTP/SSE 与错误转换,不实现 Agent、Tool 或 Provider 业务逻辑。
模块边界
当前实现属于范涵宇负责的 AI Core / Agent Core:
- Provider 抽象与注册;
- Agent Run 生命周期;
- Tool Registry;
- Tool 参数校验与执行隔离;
- Permission;
- Step、Timeout、Token Budget、取消;
- Tool 并发上限与 run 级网络权限;
- SQLite Trace、分页快照与可恢复 SSE;
- Skill Manifest、Prompt、Tool/Permission/模型能力解析;
- Plugin Manifest、生命周期和 Tool Contribution;
- Skill 调用内置 Tool 与 Plugin Tool;
- 公共 Contract 和 API 接入。
以下内容保持接口,不在本模块实现:
- Note、NoteBlock、Markdown Parser:由 Knowledge Core 提供;
- FTS5、Vector、RRF、Reranker、Citation:由 Retrieval Core 提供;
- 文件系统和 API Key 明文读取:由 Rust Host 提供;
- MCP Plugin Host、Frontend Extension Slot:按技术基线放在第二阶段实现。
Provider
默认注册离线 Provider:
provider_id = mock
model = mock-1
它支持:
chat
tool_calling
streaming
普通 Chat 请求:
{
"provider_id": "mock",
"model": "mock-1",
"messages": [
{"role": "user", "content": "hello"}
]
}
POST /api/chat 返回 ModelEvent SSE。OpenAI-Compatible Adapter 直接消费上游 SSE,Ollama Adapter 直接消费 JSONL,TextDelta 是真实增量内容,不再等待整段回答完成。
另外已经实现以下可配置 Adapter:
openai_chat / openai_compatible
ollama
创建 Ollama Provider:
{
"provider_type": "ollama",
"name": "Local Ollama",
"base_url": "http://127.0.0.1:11434",
"default_model": "qwen3:latest"
}
创建 OpenAI-Compatible Provider:
{
"provider_type": "openai_compatible",
"name": "OpenAI Compatible",
"base_url": "https://api.openai.com/v1",
"default_model": "<model>",
"credential_id": "openai-main"
}
凭证 ID openai-main 可以对应开发环境变量 AINOTE_CREDENTIAL_OPENAI_MAIN。当前 Web 联调版也允许设置页通过 Credential API 提交 API Key,由 EncryptedCredentialStore 使用 Fernet 加密保存;前端 Store、Provider Config、日志和读取响应都不保存或返回明文。未来接入 Tauri 后,由 Rust Host 从 Stronghold 注入或替换存储实现。
Provider 配置生命周期接口已经可用:
GET /api/providers
GET /api/providers/presets
POST /api/providers
GET /api/providers/{provider_id}
PATCH /api/providers/{provider_id}
DELETE /api/providers/{provider_id}
GET /api/providers/{provider_id}/models
POST /api/providers/test
GET /api/credentials/{credential_id}
PUT /api/credentials/{credential_id}
DELETE /api/credentials/{credential_id}
设置页现已提供 OpenAI、DeepSeek 和 Ollama 预设,并在保存后自动获取、排序和去重模型列表。模型发现会区分凭据缺失、鉴权失败、限流、超时和上游不可用等错误。
Agent Run
创建普通 Agent Run:
{
"input": "hello",
"provider_id": "mock",
"model": "mock-1",
"max_steps": 10
}
请求:
POST /api/agent/runs
创建后通过以下接口读取状态和事件:
GET /api/agent/runs/{run_id}
GET /api/agent/runs/{run_id}/events
GET /api/agent/runs/{run_id}/trace?after_sequence=-1&limit=200
POST /api/agent/runs/{run_id}/cancel
Run 与 AgentEvent 已写入 SQLite,run_id + sequence 是幂等键。SSE 每帧包含 id: sequence;客户端可以通过 Last-Event-ID 请求头或 after_sequence 查询参数恢复缺失事件。Trace API 返回平铺事件、下一游标、分页状态、模型/工具调用统计、耗时、Token Usage 和创建 Run 时的配置快照,不负责生成前端树形布局。
运行时内存仍只保留最近 2000 个事件用于实时订阅,完整 Trace 以 SQLite 为准。AI Core 重启后,已经终止的 Run 可以继续查询和回放;重启前未终止的 Run 会收束为 AGENT_PROCESS_RESTARTED,避免永久停在 running。API Key、Authorization、Password、Secret、常见 sk-/Bearer 值在入库前脱敏。Event、Request 和配置快照中的超长字符串与集合会截断;作为查询事实来源的 AgentRun 只脱敏、不限长,保证重启前后 input/output 内容一致。
Tool Calling
当前注册以下内置 Tool:
system.echo
math.add
notes.search
rag.search
notes.read
notes.create
notes.update
notes.list
notes.move
tasks.create
tasks.update
tasks.list
attachments.read
audio.transcribe
Mock Provider 使用下面的开发语法产生 Tool Call:
/tool system.echo {"text":"hello tool"}
/tool math.add {"left":1,"right":2}
Agent Run 需要显式声明 allowed_tools:
{
"input": "/tool math.add {\"left\":1,\"right\":2}",
"provider_id": "mock",
"model": "mock-1",
"allowed_tools": ["math.add"]
}
Tool 参数由独立 Pydantic Model 再次校验。Tool 的异常、非法参数、超时和权限拒绝统一转换为 ToolResult,不会直接打断 API 进程。
notes.search / rag.search 返回的 Citation 会由 Agent Runtime 收集到 AgentRun.citations,并产生 Citation Trace Event。Note 写操作调用 note_service,检索调用 Retrieval Engine,不直接访问 SQLite。
Permission
Permission Policy 当前支持:
allow
confirm
deny
需要确认时,Agent 状态进入 waiting_permission,并发出 PermissionRequired 事件。前端使用:
POST /api/agent/runs/{run_id}/permissions/{request_id}
提交以下决策之一:
{"decision":"allow_once"}
{"decision":"allow_session"}
{"decision":"deny"}
默认需要确认的高影响权限包括 notes.write、notes.delete、tasks.write、network.request 和 secrets.use。权限命名空间采用白名单,未知权限默认拒绝。
Knowledge / Retrieval 接入
Knowledge Core 与 Retrieval Core 已通过 Tool Registry 接入 Agent。Agent Runtime 仍只依赖 Tool Contract,不直接依赖具体服务:
tool_registry.register(
definition=tool_definition,
arguments_model=arguments_model,
executor=executor,
)
第一批已经接入:
notes.search
notes.read
notes.create
notes.update
notes.list
rag.search
写操作 Executor 调用 Knowledge Core Service,不直接访问 SQLite;检索 Executor 调用 Retrieval Core Service,不直接拼接 FTS5 或 sqlite-vec SQL。
Extension Core
Skill Runtime
Skill Package 由 skill.yaml 和可选 prompt.md 组成。安装时使用 Pydantic 校验 Manifest,并解析:
permissions
tools
retrieval
model.required_capabilities
Skill 启用前检查 Tool 是否已注册、Tool 所需权限是否已在 Manifest 声明。创建 Agent Run 时,Skill Runtime 生成 Agent Configuration,注入 System Prompt、允许的 Tool、权限和 Retrieval Config。模型缺少 chat、tool_calling 等必要 Capability 时拒绝启动。
生命周期接口:
GET /api/skills
POST /api/skills/install
GET /api/skills/{skill_id}
POST /api/skills/{skill_id}/enable
POST /api/skills/{skill_id}/disable
DELETE /api/skills/{skill_id}
Plugin Runtime
第一阶段 Plugin Runtime 完成 Manifest 校验、安装、启用、停用、卸载和 Tool Contribution。第三方代码不会直接 import 到 AI Core;当前 Declarative Plugin Host 只执行宿主实现的白名单 handler,MCP Host 留到第二阶段。
启用 Plugin 时将 Tool 注册到统一 Tool Registry,并标记 source=plugin;停用或异常时注销 Tool。启用中的 Skill 依赖某 Plugin Tool 时,Plugin 不能直接卸载。
生命周期接口:
GET /api/plugins
POST /api/plugins/install
GET /api/plugins/{plugin_id}
POST /api/plugins/{plugin_id}/enable
POST /api/plugins/{plugin_id}/disable
PUT /api/plugins/{plugin_id}/permissions
DELETE /api/plugins/{plugin_id}
Plugin Manifest 中的权限只是声明,不代表已经授权。带权限的 Plugin 安装后进入 permission_required,Host 必须通过权限接口记录用户授权,之后才能启用。JSON Schema 在安装阶段校验,Tool 调用时再次校验实际参数。
内置示例 text-tools 注册 text.uppercase。内置 knowledge-assistant Skill 同时声明 notes.search 和 text.uppercase,用于验证完整链路:
Skill Manifest
→ Agent Configuration
→ Tool Registry
→ Plugin Tool
→ Tool Result
→ Agent Loop
当前限制与下一步
前端智能体页面已经完成中文联调:运行状态、Agent Event、内置 Tool、Permission 和常用事件详情字段均通过集中标签映射展示中文;notes.search 等技术 ID 继续保留,便于与后端 Trace、日志和接口契约对应。
- 已实现 Mock、OpenAI-Compatible Chat Completions 与 Ollama Adapter;OpenAI Responses 和 Anthropic Messages 尚未实现。
- Provider 配置暂存内存,后续通过 Repository 接入 SQLite;PATCH 已支持用显式
null清空 base URL、默认模型和凭据引用。 - Run/Trace 已通过 Repository 接入 SQLite;后续增加按保留策略归档和 Benchmark 引用保护。
- Permission 已有核心等待/恢复机制,前端确认 UI 已完成联调和中文展示。
- Task 已持久化到 SQLite;Attachment Tool 读取 Host 管理目录中的 UTF-8 文件。
audio.transcribe当前消费 Host 预生成的 transcript;faster-whisper 与说话人分离仍按技术基线在第二阶段接入。- Extension 安装记录暂存内存;后续接入持久化 Registry 与版本升级流程。
- 当前 Plugin Host 只支持内置声明式白名单 handler;MCP Bridge、独立进程健康检查与 UI Contribution 在第二阶段实现。