@zhin.js/agent
v1.0.3
Published
Zhin AI Agent — session, ZhinAgent, init; composes @zhin.js/core providers and tools
Readme
@zhin.js/agent
Zhin AI Agent 组合层:在 @zhin.js/core 的类型与 Provider 之上,提供会话管理、Agent 执行循环、ZhinAgent 与框架挂载(init)。
领域词汇见 CONTEXT.md。用户向文档:AI 模块、消息如何流转。
功能特性
- 🤖 agentLoop 统一路径:ZhinAgent、Subagent、Deferred Worker、AIService 均经
agentLoop(legacyAgent.run仅保留在@zhin.js/ai供单测) - 📝 会话持久化:
AgentSessionStore+ContextRepository+ImTranscriptStore(ADR 0009) - 🧠 ZhinAgent:与 Zhin 消息流集成的智能体(SOUL/TOOLS/AGENTS、工具收集、执行策略)
- 🔍 模型自动发现:
ModelRegistry调用listModels();结果写入provider.models并供getLlmTransportModel()校验 - 🔄 模型自动降级:首选模型失败时按
resolveModelCandidates候选链 fallback(文本 / 多模态 / standalone 均走 agentLoop) - 🛡️ 6 层 Bash 安全:
ExecPolicy纵深防御(危险黑名单、环境变量剥离、wrapper 剥离、复合命令拆分、只读放行、交互式审批) - 📂 文件访问安全:
FilePolicy路径检查、设备路径拦截、命令读写分类 - 📋 精简系统提示词:
PromptBuilder组装 Context、Style、Tools、Safety,并按需注入 Platform、Skills、Memory、Bootstrap - 🔌 框架挂载:
initAgentModule()注册ctx.ai、ctx.agent、定时任务、DB 模型等 - 📦 上下文与记忆:
ContextRepository(agent_messages)、AgentSessionStore、ImTranscriptStore(im_transcripts+chat_history);辅助:ContextManager、ConversationMemory、UserProfileStore - ⏰ 跟进与定时:
FollowUpManager、PersistentCronEngine、cron 工具 - 🔧 内置工具:bash、read_file、write_file、ask_user、web_search、
chat_history(按关键词/最近条数查im_transcripts)等 - 📐 Compaction(ADR 0010):生产
agentLoop接线 L1 micro + L2 LLM;IM/compact;yamlai.agent.compaction - 🌳 会话树:
parent_id+active_leaf;IM/tree、/reset;branch summarization;ConsoleGET/POST /api/agent/sessions/... - 🪝 Hook 系统:
registerAIHook、triggerAIHook等
依赖关系
- 依赖 @zhin.js/core(IM 类型与消息链)与 @zhin.js/ai(
agentLoop、Provider 抽象) - zhin.js 4.x 主包为 optional peer;运行时通过
zhin.js/agent子路径或本包 import;bootstrapNode在检测到本包时调用initAgentModule()
模块化架构(理想蓝图 8 模块)
迁移完成后,src/ 按职责拆分为 8 个理想模块 + Orchestration + IM 组合层(单包,可选 subpath export):
packages/im/agent/src/
core/ Agent Core — agentLoop 薄适配(ADR 0009)
tool/ Tool System — Source/Filter、deferred 解析、运行时
session/ Session System — IM/Agent 双 store、passive group、session-io
event/ Event System — Agent turn 域事件(不替代 Kernel RunEvent)
skill/ Skill System — SkillRegistry 统一出口
memory/ Memory System — Port → ContextRepository + compaction
subagent/ Subagent System — SubagentSystem + ImResultSink
context/ Context System — builder/injector 链、tail limit
prompt/ 系统提示词、assembly、workspace 模板
turn/ Turn pipeline、inbound 队列、auto-continue、metrics
config/ ZhinAgent 配置 SSOT、model harness
orchestrator/ Orchestration Kernel(ADR 0027 SSOT)
collaboration/ IM 入站/出站(阶段 4)
inbound-turn-pipeline.ts enrich → peerPolicy → plan → route → outbound
inbound-turn-enrich.ts 媒体/引用/subagent 通知
inbound-turn-route.ts Kernel 委派 / spawn / 本地 execute
inbound-turn-outbound-stage.ts 出站 batch + Kernel 投影
inbound-turn-endpoint.ts @ ID / aiAccess
zhin-agent/ ZhinAgent 门面类(单文件 index.ts)
init/ create-zhin-agent、composeZhinAgentRuntime、configure/dispose 生命周期阶段 4 — collaboration/ 入站编排子模块
| 文件 | 职责 |
|------|------|
| inbound-turn-pipeline.ts | enrich → peerPolicy → buildTurnPlan → route → outbound 纯编排 |
| inbound-turn-enrich.ts | 媒体/引用/subagent 通知 enrich |
| inbound-turn-route.ts | Kernel 委派、spawn_task、本地 executeInboundAgentTurn |
| inbound-turn-outbound-stage.ts | 出站 batch 解析、IM 发送、Kernel 投影 |
| inbound-turn-endpoint.ts | @ ID / aiAccess 解析 |
Agent Core:AgentCore.runText() / runVision() 为 AsyncGenerator<TurnEvent> SSOT;runTextTurn 为 collector。组合层经 composeZhinAgentRuntime 注入 8 模块 + createAgentCoreDepsForCompose。
Port 边界见 orchestrator/PORTS.md。
可选 subpath(package.json exports):
import { AgentCore } from '@zhin.js/agent/core'
import { ToolSystem } from '@zhin.js/agent/tool'
import { SessionSystem } from '@zhin.js/agent/session'
// …/event、/skill、/memory、/subagent、/context、/prompt、/turn、/config词汇与 Port 边界见 CONTEXT.md、orchestrator/PORTS.md。
安装
pnpm add @zhin.js/agent zod ai
pnpm add @ai-sdk/openai # 示例:按厂商安装 provider SDK仅 IM、不需要 Agent 时可只装 zhin.js(见 ADR 0019)。
使用
在 Zhin 项目中(推荐)
安装本包后,从 zhin.js/agent 或 @zhin.js/agent 引入:
import {
ZhinAgent,
AIService,
registerAIHook,
} from 'zhin.js/agent'
// 使用 ctx.ai (AIService)
useContext('ai', async (ai) => {
const result = await ai.runAgent('你好', { provider: 'ollama' })
// ...
})initAgentModule() 由 zhin.js/node 的 bootstrapNode 在启动时调用,插件一般无需手动 init。
非 Zhin 宿主 / 单独集成
import { initAgentModule, AIService } from '@zhin.js/agent'
import { OllamaProvider } from '@zhin.js/core'
initAgentModule()
// 程序化 Agent(agentLoop 隔离 context)
useContext('ai', async (ai) => {
const result = await ai.runAgent('你好', {
provider: 'ollama',
systemPrompt: '你是一个助手',
})
console.log(result.content)
})核心导出
| 类别 | 导出 |
|------|------|
| 初始化 | initAgentModule |
| Agent | ServiceAgent、CreateServiceAgentOptions(AIService.createAgent);legacy Agent / createAgent re-export 自 @zhin.js/ai |
| Model harness | MODEL_HARNESS_DEFAULTS, resolveModelHarness, mergeModelHarnessValues |
| 服务与会话 | AIService;会话/context 类型见 @zhin.js/ai(ContextRepository、AgentSessionStore、ImTranscriptStore) |
| ZhinAgent | ZhinAgent,以及 config / exec-policy / file-policy / @zhin.js/agent/tool / prompt / builtin-tools 等 |
| 安全策略 | checkExecPolicy, applyExecPolicyToTools, isDangerousCommand, stripEnvVarPrefix, stripSafeWrappers, splitCompoundCommand, extractCommandName, ExecPolicyResult, checkFileAccess, classifyBashCommand, isBlockedDevicePath |
| 提示词构建 | buildRichSystemPrompt, buildEnhancedPersona, buildUserMessageWithHistory, buildContextHint |
| 上下文与记忆 | ContextRepository, AgentSessionStore, ImTranscriptStore(@zhin.js/ai);ContextManager, ConversationMemory, UserProfileStore |
| 跟进与定时 | FollowUpManager, PersistentCronEngine, createCronTools, setCronManager, getCronManager |
| 压缩与 Bootstrap | compactSession, estimateTokens, loadBootstrapFiles, loadSoulPersona, loadToolsGuide, loadAgentsMemory |
| Hook | registerAIHook, unregisterAIHook, triggerAIHook, createAIHookEvent |
| IM 内置工具工厂 | createBuiltinTools、BuiltinBaseTool;具体工具见 src/builtin/* |
| 输出与检测 | parseOutput, renderToPlainText, renderToSatori, detectTone |
| 子代理 | SubagentSystem |
| 编排 | AgentOrchestrator、ToolRegistry、SkillRegistry、SubAgentRegistry、McpRegistry、HookRegistry |
| MCP 客户端 | McpClientManager、McpClientConnection、mcpToolToAgentTool、ensureMcpConnections(见下方「MCP」) |
| 限流 | RateLimiter |
| 存储抽象 | StorageBackend, MemoryStorageBackend, DatabaseStorageBackend, createSwappableBackend |
类型(如 ZhinAgentConfig、ContextConfig、AgentState、McpServerEntry 等)均从包入口导出或从 @zhin.js/core 再导出。
全局上下文
通过 initAgentModule() 挂载后,插件可声明:
declare module '@zhin.js/core' {
namespace Plugin {
interface Contexts {
ai: AIService // 会话、Provider、ZhinAgent、runAgent 等
agent: AgentOrchestrator // 工具/技能/子代理/MCP 条目/Hook 注册表
}
}
}| Context | 用途 |
|---------|------|
| ctx.ai | 业务侧 AI 服务:会话、createAgent(→ ServiceAgent)/ runAgent、全局 ZhinAgent |
| ctx.agent | 扩展编排资源:orchestrator.addTool、addSkill、addMcp 等;内置注册走 root.inject('agent') |
主包 zhin.js 的 Plugin.Contexts 类型已包含上述两项。
MCP(Client)
默认不注册 @modelcontextprotocol/server-memory;设 ai.memoryMcp: true 启用(data/knowledge-graph.jsonl)。另可通过 ai.mcpServers(或 ctx.agent.addMcp)注册更多 Server;每次 AI 回合前懒连接,mcp_{server}_{tool} 并入 ZhinAgent 工具池。需可选安装 @modelcontextprotocol/sdk(peer dependency)。
记忆:默认 文件三层(ai.memory → data/memory/);内置 read_memory / write_memory 已移除。ai.memoryMcp: true 时另注册 MCP 图谱(弃用路径)。工作区 AGENTS.md / TOOLS.md 由 bootstrap 注入。
ai:
memoryMcp: true # 默认 false,显式开启
mcpServers:
- name: filesystem
transport: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp/zhin-mcp-test"]限制:单 server 连接失败仅 warn,不阻塞回合;resources/prompts 暂不注入模型。与 packages/host/mcp(MCP Server)方向相反。验收见 examples/test-bot/ACCEPTANCE.md。
多 Agent 使用方式
1. 主 Agent + 子 Agent(内置)
框架已提供 SubagentSystem:主 ZhinAgent 通过工具 spawn_task 把复杂/耗时任务派给后台子 Agent 异步执行。子 Agent 使用受限工具集;完成后先交还主 Agent(写入主会话 + auto-continue 续聊),用户可见回复由主 Agent 整理发出。
- 主对话不阻塞,用户可继续聊天(异步
spawn_task)。 spawn_task在每轮turn-pipeline注入(createSpawnTaskTool),并默认列入deferredTools.alwaysLoadedTools。wait: true时同步等待,结果经 tool result 回到当前主 Agent turn。- 监听
ai.subagent.finish可做 log / 监控;需旧式「子任务摘要直推 IM」时设ai.agent.subagentDirectImDelivery: true。
并发与并行(ADR 0030)
| 配置 | 默认 | 说明 |
|------|------|------|
| toolExecution | tiered | 同轮 spawn_task + 只读工具并行;写/bash 顺序 |
| maxParallelSubagents | 5 | 并行子 agent 硬顶,超限拒绝 |
| subagentAutoContinue | true | 异步完成后唤醒主 Agent |
| subagentDirectImDelivery | false | 额外直发格式化摘要到 IM |
类型权限:ai.agents.<name>.permission.task(glob → allow/deny)控制主 Agent 可见的子 agent 预设。
关键路径:
src/subagent/—SubagentSystem、SubagentRuntime、onSubagentCompletesrc/builtin/spawn-task-tool.ts— 工具定义与permission.task校验src/turn/persist-subagent-context.ts/subagent-auto-continue.ts— 结果落库与续聊src/turn/turn-pipeline.ts— 每轮注入spawn_taskpackages/im/ai/src/llm/tiered-tool-buckets.ts— tiered 并行工具 SSOT
无需额外配置即可使用;若需放宽子 Agent 的工具范围,使用 ai.agent.subagentTools 显式追加白名单(不会自动继承主会话全部 skill/tool)。
2. 用 AIService 创建多个不同配置的 Agent
ctx.ai(AIService)可以按需创建多个互不共享状态的 Agent(ServiceAgent),每个可指定不同 provider、model、systemPrompt、tools;底层均为 runAgentLoopStandaloneTurn:
import { useContext } from 'zhin.js'
useContext('ai', async (ai) => {
const codeAgent = ai.createAgent({
provider: 'openai',
model: 'gpt-4o',
systemPrompt: '你只负责代码审查与建议,不闲聊。',
useBuiltinTools: true,
})
const codeResult = await codeAgent.run('审查这段 TypeScript 的类型安全')
const translateAgent = ai.createAgent({
provider: 'ollama',
model: 'qwen2.5',
systemPrompt: '只做中英互译,不解释。',
useBuiltinTools: false,
collectExternalTools: false,
})
const translated = await translateAgent.run('Hello world')
})适合:按场景/按接口使用不同「角色」的 Agent(代码、翻译、总结等),彼此独立。
3. 一次调用、单次任务(不持有 Agent 实例)
不需要长期持有 Agent 时,可直接用 runAgent 跑单次任务:
useContext('ai', async (ai) => {
const result = await ai.runAgent('总结以下内容:...', {
provider: 'deepseek',
systemPrompt: '只输出 3 条要点。',
})
console.log(result.content)
})4. 多 Agent 协作/编排(由 zhin.js 层实现)
本包只提供基础能力:ZhinAgent、ai.createAgent(ServiceAgent)、ai.runAgent 等。多 Agent 串联/并联编排(例如 A 的输出作为 B 的输入、按条件路由到不同专业 Agent)在 zhin.js 主包 runPipeline / runParallel / route 实现;插件侧通过 zhin.js 暴露的 API 使用即可。
工具命名策略
- 保留/内置工具名(如
bash、read_file、spawn_task)不可被插件或文件化工具覆盖。 - 非保留工具同名时采用 后注册覆盖前注册。
- 冲突统一以 warn 记录:包含
name、source、action(ignored/overridden)。
Provider 与模型列表
AIService 构造时:
- 按
ai.providers.<别名>实例化 Provider(须配置sdk,如openai或openai-compatible)。 registerLlmApiFromProviders:未写models的 provider 在 ApiRegistry 注册为空白名单,由后台ModelRegistry.discover()填充provider.models;写了models则用 yaml 白名单。createZhinAgent启动时loadCache()先恢复上次发现结果,再异步刷新/v1/models。
agents.<name>.model(如 mimo-v2.5-pro)须在发现列表中,或在中转 API 的 /v1/models 响应里出现;无需为每个模型手写 yaml,除非要锁定白名单。
ai:
providers:
openai-main:
sdk: openai-compatible
baseUrl: ${OPENAI_BASE_URL}
apiKey: ${OPENAI_API_KEY}
# models 省略 → 自动 GET /v1/models
cloudflare-flash:
sdk: openai-compatible
models: ["@cf/zai-org/glm-4.7-flash"] # 显式列表
agents:
zhin:
provider: openai-main
model: mimo-v2.5-proProvider 与模型列表
AIService 构造时:
- 按
ai.providers.<别名>实例化 Provider(须配置sdk,如openai或openai-compatible)。 registerLlmApiFromProviders:未写models的 provider 在 ApiRegistry 注册为空白名单,由后台ModelRegistry.discover()填充provider.models;写了models则用 yaml 白名单。createZhinAgent启动时loadCache()先恢复上次发现结果,再异步刷新/v1/models。
agents.<name>.model(如 mimo-v2.5-pro)须在发现列表中,或在中转 API 的 /v1/models 响应里出现;无需为每个模型手写 yaml,除非要锁定白名单。
ai:
providers:
openai-main:
sdk: openai-compatible
baseUrl: ${OPENAI_BASE_URL}
apiKey: ${OPENAI_API_KEY}
# models 省略 → 自动 GET /v1/models
cloudflare-flash:
sdk: openai-compatible
models: ["@cf/zai-org/glm-4.7-flash"] # 显式列表
agents:
zhin:
provider: openai-main
model: mimo-v2.5-proModel harness
按 provider / model 覆盖 Agent 循环默认参数(当前主要为 maxIterations)。
合并顺序(约定优先,详见 ADR 0007):
- TypeScript 默认表
MODEL_HARNESS_DEFAULTS(src/config/model-harness.ts+model-harness-runtime.ts) - YAML
ai.agent.modelHarness.providerPatterns(匹配当前 provider,支持*通配;按对象键插入顺序叠加) - YAML
ai.agent.modelHarness.models(model或provider:model精确键)
ai:
agent:
modelHarness:
providerPatterns:
"open*":
maxIterations: 7
models:
"gpt-4o":
maxIterations: 8
"openai:gpt-4o":
maxIterations: 9运行时由 resolveModelHarness(providerName, modelName, config?.modelHarness) 解析;包入口导出 MODEL_HARNESS_DEFAULTS、resolveModelHarness、mergeModelHarnessValues 与 ModelHarnessConfig 类型。未命中任何规则时回退 TS 默认行或空对象;当前仅消费 maxIterations,未知 YAML 字段会被忽略。
增补内置默认值:在 config/model-harness.ts 增加 ModelHarnessRow 并附测试;YAML 只做覆盖,不替代 TS 约定层。
IM 管理命令
由 register-management-tools.ts / register-introspection-commands.ts 注册(master / 有权限用户):
| 类别 | 命令 |
|------|------|
| 会话 | /compact · /tree · /tree N · /reset |
| 运维 | /models · /health |
| 内省 | /cmd · /endpoints · /bindings · /tools · /mcp |
zhin-package CLI:zhin packages(basic/cli)。详见 ADR 0010。
开发
项目结构
src/
├── index.ts # 包根导出:Orchestrator、ZhinAgent、init、builtin…
│
├── core/ # Agent Core — agentLoop 薄适配
├── tool/ # Tool System — 运行时工具收集
├── session/ # Session System — IM/Agent 双 store、session-io
├── event/ # Event System — turn 域事件 + session 事件
├── skill/ # Skill System
├── memory/ # Memory System
├── subagent/ # Subagent System + manager init
├── context/ # Context System — builder/injector、tail limit
├── prompt/ # 系统提示词、assembly、workspace 模板
├── turn/ # Turn pipeline、inbound 队列、auto-continue
├── config/ # ZhinAgent 配置 SSOT、model harness
│
├── orchestrator/ # ★ 编排中枢(Kernel SSOT,ADR 0027)
│ ├── index.ts # AgentOrchestrator class
│ ├── types.ts # ResourceScope, Skill, SubAgentDef, AIHook…
│ ├── resource-registry.ts
│ ├── tool-registry.ts
│ ├── skill-registry.ts
│ ├── subagent-registry.ts
│ ├── mcp-registry.ts
│ └── hook-registry.ts
│
├── mcp-client/ # MCP 客户端
│
├── init.ts # initAgentModule 入口
├── init/ # create-zhin-agent、compose/configure/dispose 生命周期
│
├── service.ts # AIService
│
├── zhin-agent/ # ZhinAgent 门面类(单文件)
│ └── index.ts
│
├── internal/ # host 契约、asPrivate、turn-context、phase/prompt trace
├── collaboration/ # 多 Endpoint 入站/出站
├── discovery/ # 文件化资源发现(tools / skills / agents)
├── security/ # exec-policy、file-policy
├── builtin/ # IM 内置工具
├── builtin-tools.ts # createBuiltinTools() 聚合
│
├── defaults/ # ★ 各注册表的默认资源
│ ├── skills.ts # 默认 common skills
│ ├── hooks.ts # 默认 common hooks
│ └── subagents.ts # 默认 subagent 模板
│
├── common-adapter-tools.ts # ← 从 core 迁移:群管工具工厂
├── subagent.ts
├── task-executor.ts
├── cron-engine.ts
├── bootstrap.ts
└── user-profile.tsinit/ 目录含 register-orchestrator.ts(provide('agent'))、register-ai-service.ts、register-builtin-tools.ts 等,见 src/init.ts。
构建
pnpm build # 或 npm run build
pnpm clean # 清理 lib许可证
MIT License
