Files
NotesAgentic/docs/AI-Core与Agent-Core开发说明.md
admin 694c1b27c1 docs(backend): 记录全面审阅问题与修复方案
按原因、后果、解决思路、落地方案和回归测试复盘 10 类后端问题。

同步更新接口实现状态、Plugin 权限接口、真实 Streaming、Citation 偏移约定、第一阶段 Tool 列表和测试数量。
2026-08-28 09:57:02 +08:00

9.4 KiB
Raw Permalink Blame History

AI Core 与 Agent Core 开发说明

本文档用于团队开发和模块联调,记录当前已经落地的核心边界与使用方式。

当前实现

当前已经建立第一条可运行链路:

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
│   ├── 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 级网络权限;
  • 内存 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 直接消费上游 SSEOllama Adapter 直接消费 JSONLTextDelta 是真实增量内容,不再等待整段回答完成。

另外已经实现以下可配置 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 对应 Sidecar 进程中的临时环境变量 AINOTE_CREDENTIAL_OPENAI_MAIN。环境变量由 Rust Host 从 Stronghold 读取后注入,不写入 Provider Config、日志或前端 Store。

Provider 配置生命周期接口已经可用:

GET    /api/providers
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

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
POST /api/agent/runs/{run_id}/cancel

当前 Run 与 Trace 保存在内存中,AI Core 重启后清空。Runtime 最多保留 200 个 Run,每个 Run 最多保留 2000 个事件,并限制单轮 Tool Call 数量,避免长时间运行时无界增长。后续数据库层接入时替换 Repository,不改变 API Contract。

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.writenotes.deletetasks.writenetwork.requestsecrets.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。模型缺少 chattool_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.searchtext.uppercase,用于验证完整链路:

Skill Manifest
→ Agent Configuration
→ Tool Registry
→ Plugin Tool
→ Tool Result
→ Agent Loop

当前限制与下一步

  • 已实现 Mock、OpenAI-Compatible Chat Completions 与 Ollama AdapterOpenAI Responses 和 Anthropic Messages 尚未实现。
  • Provider 配置暂存内存,后续通过 Repository 接入 SQLitePATCH 已支持用显式 null 清空 base URL、默认模型和凭据引用。
  • Run/Trace 暂存内存;下一步抽象 Repository 并接入 SQLite。
  • Permission 已有核心等待/恢复机制,前端确认 UI 尚未联调。
  • Task 已持久化到 SQLiteAttachment Tool 读取 Host 管理目录中的 UTF-8 文件。
  • audio.transcribe 当前消费 Host 预生成的 transcriptfaster-whisper 与说话人分离仍按技术基线在第二阶段接入。
  • Extension 安装记录暂存内存;后续接入持久化 Registry 与版本升级流程。
  • 当前 Plugin Host 只支持内置声明式白名单 handler;MCP Bridge、独立进程健康检查与 UI Contribution 在第二阶段实现。