Integration Patterns

Agent 与 City AIService

理解 Agent、Town、City 和 AIService 在模型管理上的职责边界,以及集成时应该怎么用

Agent 与 City AIService

如果你在正常的 Downcity 项目里使用 Agent,模型通常不应该由 Agent 项目自己持有。

这时要把职责拆成四层:

  • City AIService:拥有模型目录、provider、API key、模型路由
  • Town:连接 City,读取模型目录,校验和解析 modelId
  • Agent 项目:只声明 execution.modelId
  • @downcity/agent session:真正执行 prompt

最重要的结论

在 Downcity 集成模式里:

  • 项目里保存的是 modelId
  • 不是 provider 配置
  • 不是 API key
  • 也不是本地模型实例

也就是说,下面这种心智模型才是对的:

downcity.json.execution.modelId
  -> Town 读取并校验
  -> City AIService 解析出目标模型
  -> Agent runtime 使用这个模型执行

为什么要这样分层

这样做的好处是:

  • 多个 Agent 可以复用同一套模型目录
  • provider key 不进入项目目录
  • provider 切换、模型增删、默认模型策略都可以在 City 侧统一管理

这也是 Town 当前真实实现的边界:

  • Town 不拥有模型池
  • Town 不解析 provider / apiKey / baseURL
  • 模型目录唯一来源是 City AIService

Agent 项目里实际写什么

项目里真正的绑定点是:

{
  "execution": {
    "type": "api",
    "modelId": "quality"
  }
}

也就是:

  • execution.type = "api"
  • execution.modelId = "<some-id>"

City 侧如何提供模型

City 侧通常会这样注册模型:

import { CityBase, AIService, Provider } from "@downcity/city";

const base = new CityBase({
  db,
  dialect: "sqlite",
  raw,
});

const deepseek = new Provider("deepseek", {
  baseURL: "https://api.deepseek.com/v1",
  envKey: "DEEPSEEK_API_KEY",
  passthroughModel: "deepseek-chat",
  text: myTextAction,
  stream: myStreamAction,
});

const ai = new AIService();
ai.use(
  deepseek.model({
    id: "quality",
    name: "DeepSeek Quality",
  }),
);

base.use(ai);

注册后,City AIService 就拥有了:

  • 模型目录
  • SDK 通路
  • OpenAI 兼容通路

Town 如何读取和校验模型

Town 启动 Agent 项目前,会去 City AIService 读取模型目录并校验 modelId

当前真实实现大致是:

  1. 读取 City 连接配置
  2. 通过 User City 调 city.ai.listModels()
  3. 检查 execution.modelId 是否存在
  4. 用它构造 Agent 可执行的模型绑定

这也是为什么:

  • execution.modelId 写错时,问题通常会在启动或首次执行阶段暴露
  • 而不是拖到对话跑了很多轮才发现

什么时候该用 session.set({ model })

应该用

适用于纯 SDK 嵌入模式:

  • 你自己在 Node 应用里 new Agent(...)
  • 你自己持有模型实例
  • 你不是通过 Town 去绑定 City 模型

不应该作为默认路径

在正常的 Downcity Agent 项目里,不应该把 session.set({ model }) 当默认用法。

这时应优先:

  • 在 City AIService 注册模型
  • 在项目里写 execution.modelId

一个完整的最短链路

1. City 注册模型

const ai = new AIService();
ai.use(provider.model({ id: "quality", name: "Quality" }));
base.use(ai);

2. Town 连接 City

town city use
town city status

3. Agent 项目绑定 modelId

{
  "execution": {
    "type": "api",
    "modelId": "quality"
  }
}

4. 启动或重启 Agent

town agent restart .

如果要远程访问 Agent

要区分两层:

  • 模型能力:来自 City AIService
  • session 能力:由本地 Agent 对外暴露

所以 RemoteAgent 连到的是:

  • 本地 Agent 暴露出的 session API

不是直接去连 City AIService 模型本身。

常见误区

误区 1:Agent 项目里应该保存 provider 配置

不是。项目里只保存 modelId

误区 2:RemoteAgent 可以远程传 session.set({ model })

不是。远程 session 当前不支持客户端直接传本地模型实例。

误区 3:Town 自己维护模型目录

不是。Town 只读取和校验 City AIService 暴露出的模型目录。

相关文档