@rowan-agent /代理
持久代理运行时。公共接口包括 AgentRuntime、耐用
存储、配置提供程序、运行句柄和运行事件。Agent是一个持久化对象
标识,而不是进程本地会话对象。
快速启动
import {
AgentRuntime,
InMemoryStore,
loadPhases,
loadSkills,
} from "@rowan-agent/agent/runtime";
const skills = await loadSkills("./.rowan/skills");
const phases = await loadPhases("./.rowan/phases");
const runtime = await AgentRuntime.init({
store: new InMemoryStore(),
});
await runtime.loadAgents({
sourceId: "workspace",
values: [{
name: "workspace-assistant",
description: "Assist with the current workspace.",
prompt: "You are helpful.",
contexts: ["workspace"],
}],
});
await runtime.loadSkills({ sourceId: "workspace", values: skills });
await runtime.loadPhases({
sourceId: "workspace",
values: [...phases.phases.values()],
});
const agentId = await runtime.createAgent({
identity: "example:v1", // Stable config snapshot identity, not the Agent ID
model: {
provider: "openai",
id: "gpt-4o",
protocol: "openai-responses",
baseUrl: "https://api.openai.com/v1",
apiKey: process.env.OPENAI_API_KEY!,
},
definition: { name: "workspace-assistant" },
resourceView: {
agents: ["workspace"],
tools: [],
skills: ["workspace"],
phases: ["workspace"],
},
contexts: [{
name: "workspace",
value: { root: process.cwd() },
}],
});
const run = await runtime.start(agentId, "Summarize the workspace.", {
idempotencyKey: "run-example", // One Agent can have multiple independent Runs
});
const observing = (async () => {
for await (const event of run.observe()) {
if (event.kind === "message_delta") process.stdout.write(event.text);
}
})();
const boundary = await run.wait();
await observing;
await runtime.close();
公众的生命周期
AgentRuntime.init({ store })默认情况下,使用内存中的配置提供程序打开运行时所有者。通过configs当配置必须存在于进程边界时。createAgent()创建持久代理标识并绑定配置快照。start()创建一个队列运行;run(runId)返回无状态的Run句柄。observe()遵循display-orientedRunEvent值;wait()等待权威边界。respondInteraction()持续一个input_required运行;cancel()终止未完成的运行。close()封存所有者并释放存储。
AgentRuntime 不公开进程本地代理、会话、绑定、
邮箱或兼容性工厂。耐久库是真理的源泉;
运行句柄不保存业务状态。
编程阶段可以使用执行范围
RunInteractionDriver 对于持久类型
交互、挂起检查点和取消。
这是一般的罗文边界;传输和提供程序语义保留
嵌入主机。
商店
InMemoryStore:测试和单进程嵌入。SqliteStore:局部持久化;数据库在第一天初始化openOwner().InMemoryConfigProvider:没有外部配置服务的测试和嵌入。
运行时为普通的代理创建生成一个等幂键。调用者
需要在未知结果通过稳定参数后重试相同的创建
idempotencyKey 明确。其他写命令保留其文档
幂等性身份。Store为运行、事件、工具提供了原子性
生命周期和所有者围栏。
工具的生命周期
工具在源代码下注册,由定义选择,并保存 通过:
pending → running → completed | failed | indeterminate
当无法确认外部副作用时,工具必须变为
indeterminate;然后运行失败,并且永远不会自动重试。
运行时,工具可能调用 context.reportProgress(progress: ToolProgress) 使用
标准MCP进度形状({ progress: number; total?: number; message?: string; _meta?: JsonObject })。
形状用有限数验证;无效报告将被删除,并显示警告。
工具私有进度数据消失 _meta 键,并应报告连续输出
累积的(例如一个尾巴),因为瞬时更新合并每 toolCallId.
进度报告触发工具的表示功能并发出瞬态 tool_state_changed
更新。进度是实时的,可能会被删除;最终完成或失败的工具调用状态
是持久的。
事件
run.observe() 提供 RunEvent 现场演示的值:
- 瞬态
message_delta和tool_state_changed(进度)事件仅限直播和 最优; - 耐用
message_committed,run_state_changed,tool_state_changed事件是可重玩的; - 一个持久的
message_committed事件是权威的完整内容 瞬态δ被合并或脱落。
runtime.consume() 只提供 DurableRunEvent 价值观:
message_committedrun_state_changedtool_state_changed
持久事件及其相应的运行聚合更改同时提交 存储事务。可靠的消费者通过游标和 检查点;瞬态事件永远不会进入持久存储。
资源
AgentRuntime 拥有一个资源注册表。注册代理定义、工具、
技能,和阶段下稳定 sourceId 值,然后为
代理通过 resourceView:
const runtime = await AgentRuntime.init({
store: new InMemoryStore(),
bootstrap: async (registry) => {
await registry.loadExtensions({
sourceId: "workspace.extensions",
directory: "./extensions",
});
},
});
await runtime.loadAgents({
sourceId: "workspace",
values: [{
name: "workspace-assistant",
description: "Assist with the current workspace.",
prompt: "You are helpful.",
}],
});
const agentId = await runtime.createAgent({
identity: "workspace:v1",
definition: { name: "workspace-assistant" },
resourceView: {
agents: ["workspace"],
tools: [],
skills: [],
phases: [],
},
model: {
provider: "openai",
id: "gpt-4o",
protocol: "openai-responses",
baseUrl: "https://api.openai.com/v1",
apiKey: process.env.OPENAI_API_KEY!,
},
});
每一个 load*() 调用自动替换一个源;使用 directory 或内联
values. resourceView 控制可见性,因此同名资源可以存在
在孤立的源中,但在一起选择时发生碰撞。运行时提供
核心 read/bash/edit/write 工具和内置 default/stop/compact 阶段。
主机定义的资源(包括由扩展注册的工具和阶段)替换
按名称内置,保留内置状态(被替换的核心工具始终保持不变)
没有明确的定义选择;替换后的核心阶段保持不变
内置的角色)。保留的控件名称(route 的工具, continue 阶段)
主机源不能声明。
扩展是运行时全局的。只在 AgentRuntime.init() 通过
bootstrap;初始化后,它们将被冻结,直到运行时关闭。
扩展可以管理运行范围内的内存状态(api.state.run(runId)), agent-scoped
持久状态(api.state.agent(agentId)),以及扩展范围的持久状态
(api.state.global())通过配置的 ExtensionHost.
定义名称列表缩小了所选择的工具、技能和阶段:遗漏
继承所有候选者, [] 不选择,并且跳过缺少的名称。这个
同样的规则也适用于 definition.contexts.
降价代理定义和 PHASE.md 文件共享一个元数据规则:
rowan已知的键保留字段,而其他所有json安全键都是扁平的
metadata. 一个显式的 metadata: 映射也是平面化的。编写
入口出口 normalizeDefinitionMetadata(kind, frontmatter) 对于宿主来说
在浏览器安全的上下文中解析相同的标题。看到
阶段。md格式 为相场集合和
元数据错误。
注册、定义和查看
注册、选择和可见性有不同的作用:
- 一、 源 供应资源。工具携带它们的可执行文件
execute(), 技能和阶段携带它们装载的内容,而定义携带其装载的内容 提示。将它们注册为runtime.loadAgents/loadSkills/loadPhases/loadTools. - 这个 定义 声明一个代理使用什么。
tools,skills,contexts,phases是基于名称的选择器;他们不能创造一个 没有选择源保存的资源。 - 这个 资源视图 决定代理可以看到哪些源 稳定源ID。
上下文是例外: contexts 和 additionalContexts 随船而行
配置请求,因为它们携带主机值而不是已注册的
资源。当多个代理共享一个候选池时使用选择器:
definition: {
name: "read-only-assistant",
description: "Inspect the workspace without changing it.",
prompt: "You are helpful.",
tools: ["read"],
contexts: ["workspace"],
phases: { entryPhaseId: "review", phaseIds: ["review"] },
}
每次运行都会将其视图解析为一个不可变的配置快照和 固定在它:替换一个源之后不能改变一个活动的或 输入等待运行,重新启动的运行时重新解析相同的源id。