| name | stello-agent-usage |
| description | StelloAgent 运行时使用教程。覆盖 Session 生命周期、createSession、turn/stream 对话、fork 配置合成链、orchestrator-facing 数据 SDK、runtime 管理、热更新等运行时 API。 |
StelloAgent 运行时使用教程
前置知识:createStelloAgent(config) 的配置方式见 skill stello-agent-creation。
本文档聚焦于 Agent 构建完成后的运行时操作。
1. Root Session 创建
对话起点是一个普通 Session(parentId === null),由 agent.createSession() 创建——不传 parentId 即为新 root。
const root = await agent.createSession({ label: 'Main' })
await agent.enterSession(root.id)
agent.createSession({ parentId?, label? }) 做了什么:
- 调用
sessions.createSession({ parentId, label }) 创建拓扑节点(parentId 缺省即 parentId === null)
- 返回
TopologyNode(含 id / parentId / children / refs / depth / label 等)
Root 没有特殊待遇——它就是一个普通 Session。多个 root 合法(森林)。全局默认 systemPrompt / skills 等配置在 sessionDefaults 即可。
2. Session 生命周期
createSession → enterSession → turn / stream (× N) → leaveSession → archiveSession
2.1 进入 Session
const bootstrap = await agent.enterSession(sessionId)
行为:触发 lifecycle.bootstrap(),初始化 Engine runtime。如果该 session 已有活跃 Engine,复用而非重建。
2.2 运行对话轮次(turn)
const result = await agent.turn(sessionId, '帮我分析市场趋势')
2.3 流式模式(stream)
const streamResult = await agent.stream(sessionId, '帮我分析市场趋势')
for await (const chunk of streamResult) {
process.stdout.write(chunk)
}
const result = await streamResult.result
console.log(result.turn.finalContent)
2.4 TurnRunnerOptions
await agent.turn(sessionId, input, {
maxToolRounds: 5,
signal: abortController.signal,
onToolCall: (toolCall) => { },
onToolResult: (result) => { },
})
2.5 离开与归档
await agent.leaveSession(sessionId)
await agent.archiveSession(sessionId)
3. Fork — 创建子 Session
3.1 两种触发方式
| 方式 | 触发者 | 入口 |
|---|
| LLM 发起 | LLM 调用 stello_create_session 内置 tool | 需在 capabilities.tools opt-in 注册 |
| 代码发起 | 应用层调用 agent.forkSession() | 手动编排 |
3.2 forkSession 参数
const child = await agent.forkSession(sessionId, {
label: '市场分析-深度研究',
systemPrompt: '你是市场分析专家...',
llm: specializedLlm,
tools: customTools,
skills: ['search', 'summarize'],
consolidateFn: customConsolidateFn,
compressFn: customCompressFn,
prompt: '请深入分析半导体行业',
context: 'inherit',
topologyParentId: otherNodeId,
profile: 'researcher',
profileVars: { region: '北美' },
})
Fork 后需要单独 enterSession(child.id) 才能在子 session 上 turn()。
3.3 上下文继承策略(context)
await agent.forkSession(sessionId, { label: '子任务', context: 'none' })
await agent.forkSession(sessionId, { label: '深度研究', context: 'inherit' })
await agent.forkSession(sessionId, {
label: '摘要子任务',
context: async (parentMessages) => parentMessages.slice(-10),
})
3.4 Fork 配置合成链
fork 时按 sessionDefaults → 父 session 固化 config → ForkProfile → EngineForkOptions 顺序合成,后者覆盖前者。root 也是普通 session,从 root fork 会正常继承 root 的固化 config。
详见 skill fork-design。
4. Orchestrator-facing 数据 SDK
需要在创建 agent 时注入 storage: SessionStorage(顶层)。这套 API 让外部 orchestrator(应用层 / Claude Code / Codex / Kitkit 等)能够在对话之外直接读取和回写每个 Session 的数据。
4.1 拓扑与 Session 列表
const roots = await agent.listRoots()
const forest = await agent.getTopology()
const node = await agent.getTopologyNode(sessionId)
const sessions = await agent.listSessions({ status: 'active' })
4.2 单个 Session 视图
const view = await agent.getSessionMetadata(sessionId)
4.3 批量 digest
const digests = await agent.listSessionDigests({ status: 'active' })
应用层把这份数据喂给反思层 LLM,由它产出 per-session insight,再调用 agent.putInsight 定向回写。完整模式见 skill session-usage。
4.4 L3 消息读取
const messages = await agent.listMessages(sessionId, { limit: 100 })
4.5 写入
await agent.putMemory(sessionId, '当前进展摘要...')
await agent.putInsight(sessionId, '需要重新评估方向...')
await agent.clearInsight(sessionId)
未在 agent 创建时注入 storage 时,这些方法会抛错。
5. Runtime 管理(多连接场景)
适用于 WebSocket 等多客户端连接场景,通过引用计数管理 Engine 生命周期。
await agent.attachSession(sessionId, connectionId)
await agent.detachSession(sessionId, connectionId)
agent.hasActiveEngine(sessionId)
agent.getEngineRefCount(sessionId)
回收策略:
createStelloAgent({
runtime: {
resolver: myResolver,
recyclePolicy: { idleTtlMs: 30_000 },
},
})
agent.updateConfig({ runtime: { idleTtlMs: 60_000 } })
6. 典型使用模式
6.1 单 root 对话
const root = await agent.createSession({ label: 'Main' })
await agent.enterSession(root.id)
await agent.turn(root.id, '你好')
await agent.turn(root.id, '继续上个话题')
await agent.leaveSession(root.id)
6.2 代码驱动的并行 Fork
const root = await agent.createSession({ label: 'Main' })
await agent.enterSession(root.id)
await agent.turn(root.id, '我需要研究三个市场')
const children = await Promise.all([
agent.forkSession(root.id, { label: '美国市场', systemPrompt: '你是美国市场专家' }),
agent.forkSession(root.id, { label: '欧洲市场', systemPrompt: '你是欧洲市场专家' }),
agent.forkSession(root.id, { label: '亚洲市场', systemPrompt: '你是亚洲市场专家' }),
])
await Promise.all(
children.map(async (child) => {
await agent.enterSession(child.id)
await agent.turn(child.id, '分析半导体供应链')
await agent.leaveSession(child.id)
}),
)
6.3 多 root 并存(森林)
const research = await agent.createSession({ label: 'Research' })
const writing = await agent.createSession({ label: 'Writing' })
await agent.enterSession(research.id)
await agent.turn(research.id, '调研材料 ...')
await agent.enterSession(writing.id)
await agent.turn(writing.id, '基于已有材料写一份 ...')
const all = await agent.listRoots()
6.4 外部 reflection 循环(自行实现 integrate)
async function reflect(agent: StelloAgent, llm: LLMAdapter): Promise<void> {
const digests = await agent.listSessionDigests({ status: 'active' })
for (const [id, content] of Object.entries(insightsByTarget)) {
await agent.putInsight(id, content)
}
}
详见 stello-agent-creation §7。
6.5 WebSocket 连接管理
ws.on('connection', async (socket) => {
const holderId = socket.id
socket.on('enter', async ({ sessionId }) => {
await agent.attachSession(sessionId, holderId)
await agent.enterSession(sessionId)
})
socket.on('message', async ({ sessionId, input }) => {
const stream = await agent.stream(sessionId, input)
for await (const chunk of stream) {
socket.send(JSON.stringify({ type: 'chunk', data: chunk }))
}
const result = await stream.result
socket.send(JSON.stringify({ type: 'done', data: result }))
})
socket.on('close', async () => {
for (const sessionId of socket.sessions) {
await agent.detachSession(sessionId, holderId)
}
})
})
7. 并发语义
- 同 sessionId 内串行:同一 session 上的 turn() 不会并发执行
- 不同 sessionId 之间并行:可同时在多个 session 上 turn()
- 所有异步副作用 fire-and-forget:consolidation / hooks 不阻塞 turn() 返回
- 错误不中断对话:副作用抛错时 emit error 事件,对话循环继续
8. 公开方法速查
编排
| 方法 | 返回值 | 说明 |
|---|
createSession({ parentId?, label? }) | Promise<TopologyNode> | 创建拓扑节点(不传 parentId 即新 root;多 root 合法) |
enterSession(id) | Promise<BootstrapResult> | 进入 session,触发 bootstrap |
turn(id, input, opts?) | Promise<EngineTurnResult> | 同步对话轮次(含 tool call 循环) |
stream(id, input, opts?) | Promise<EngineStreamResult> | 流式对话轮次 |
leaveSession(id) | Promise<{ sessionId }> | 离开 session,触发 consolidation 调度 |
forkSession(id, opts) | Promise<TopologyNode> | 创建子 session,执行配置合成链 |
archiveSession(id) | Promise<{ sessionId }> | 归档 session |
consolidateSession(id) | Promise<void> | 手动触发该 session 的 consolidation |
attachSession(id, holderId) | Promise<OrchestratorEngine> | 附着 runtime 持有者 |
detachSession(id, holderId) | Promise<void> | 释放 runtime 持有者 |
hasActiveEngine(id) | boolean | 是否有活跃 Engine |
getEngineRefCount(id) | number | 当前引用计数 |
updateConfig(patch) | void | 热更新运行时配置 |
Orchestrator-facing 数据 SDK(需注入 storage)
| 方法 | 返回值 | 说明 |
|---|
listSessions(filter?) | Promise<SessionMeta[]> | 列出所有 session |
listRoots() | Promise<TopologyNode[]> | 列出所有 root |
getTopology() | Promise<SessionTreeNode[]> | 完整森林(嵌套树) |
getTopologyNode(id) | Promise<TopologyNode | null> | 单个节点 |
getSessionMetadata(id) | Promise<{ memory, insight }> | 单 session 的 memory + insight |
listSessionDigests(filter?) | Promise<SessionDigest[]> | 批量收集所有 Session 的 digest |
listMessages(id, options?) | Promise<Message[]> | 读取 L3 消息 |
putMemory(id, content) | Promise<void> | 写入 memory |
putInsight(id, content) | Promise<void> | 写入 insight(一次性) |
clearInsight(id) | Promise<void> | 清除 insight |
只读属性
| 属性 | 类型 | 说明 |
|---|
config | StelloAgentConfig | 归一化后的完整配置 |
sessions | SessionTree | 拓扑树 |
memory | MemoryEngine | 记忆引擎 |
storage | SessionStorage | undefined | 数据存储(未注入时 data-IO 方法不可用) |
profiles | ForkProfileRegistry | undefined | Fork 模板注册表 |