内置工具
模型工具使用下划线别名,例如 fs.read 对应 fs_read;文本命令保留原名。插件可以增加或覆盖工具,实际集合以 ,help 和 ,tool.describe 为准。
文本命令支持位置值和 key=value;布尔值使用 true / false,列表使用 JSON 字符串,含空格的值使用引号。
文件、Shell 和 代码模式 操作使用当前会话的 Environment,默认直接在宿主机执行,而非安全沙箱中。
bash(command, cwd=None, timeout_seconds=30, background=False)| 参数 | 类型 | 说明 |
|---|---|---|
command |
str |
Shell 命令 |
cwd |
str | None |
工作目录;相对路径由当前环境解析 |
timeout_seconds |
float |
前台等待秒数;超时后转入后台并返回 shell_id |
background |
bool |
是否直接在后台启动;此模式忽略 timeout_seconds |
非零退出状态返回工具错误并保留输出;前台无输出时返回 (no output)。
bash.output
Section titled “bash.output”bash.output(shell_id, offset=0, limit=None)| 参数 | 类型 | 说明 |
|---|---|---|
shell_id |
str |
后台 Shell ID |
offset |
int |
字符偏移;限制在 0 到当前输出长度之间 |
limit |
int | None |
最多读取的字符数 |
返回 status、exit_code、output 和 next_offset;进程运行期间 exit_code 为 null。
bash.kill
Section titled “bash.kill”bash.kill(shell_id)终止后台进程并返回最终状态和退出码;进程已结束时也可调用。
fs.read
Section titled “fs.read”fs.read(path, offset=0, limit=None)| 参数 | 类型 | 说明 |
|---|---|---|
path |
str |
UTF-8 文本文件路径 |
offset |
int |
从 0 开始的行号 |
limit |
int | None |
最多返回的行数 |
省略分页参数时返回整个文件。
.png、.jpg、.jpeg、.webp、.gif 文件会作为图片返回给模型查看,上限 10 MiB,此时忽略 offset 和 limit。
fs.write
Section titled “fs.write”fs.write(path, content)写入完整文本并创建缺失的父目录;已有文件会被覆盖,不支持追加或补丁。
fs.edit
Section titled “fs.edit”fs.edit(path, old, new, start=0)| 参数 | 类型 | 说明 |
|---|---|---|
path |
str |
文件路径 |
old |
str |
待替换文本 |
new |
str |
替换后的文本 |
start |
int |
从 0 开始的查找行号 |
替换指定范围内的所有字面匹配;找不到匹配时返回错误,不进行语法解析。
web.fetch
Section titled “web.fetch”web.fetch(url, headers=None, timeout=10)| 参数 | 类型 | 说明 |
|---|---|---|
url |
str |
请求 URL |
headers |
dict | None |
HTTP 请求头;可覆盖默认的 Accept: text/markdown |
timeout |
float |
整个请求的总秒数 |
发送 HTTP GET 请求,返回最终 url、status、content_type 和响应正文;非成功状态返回工具错误。
技能与工具发现
Section titled “技能与工具发现”skill(name=None)省略 name 时列出当前可用技能;传入名称时返回技能位置和正文。找不到时返回 (no such skill)。
tool.describe
Section titled “tool.describe”tool.describe(names)names 是运行时名称或模型别名组成的列表。返回工具名称、描述和参数 schema;未知名称列入 unknown,已加载名称列入 already_loaded。
延迟工具从下一个 Step 起可调用,加载记录保存在当前 Tape 中,直到 Tape 重置。
tape.info
Section titled “tape.info”无参数。返回 Tape 名称、条目数、anchor 数、最近 anchor、该 anchor 后的条目数,以及最近的 token 用量和缓存命中率。
tape.search
Section titled “tape.search”tape.search(query, limit=20, start=None, end=None, kinds=["message", "tool_result"])| 参数 | 类型 | 说明 |
|---|---|---|
query |
str |
在 kind、日期、payload 和 meta 的 JSON 文本中进行不区分大小写的包含匹配 |
limit |
int |
最多返回的条目数 |
start / end |
str | None |
包含边界的 ISO 日期或时间 |
kinds |
list[str] |
条目类型列表 |
返回 matches 和 filtered 数量,并过滤搜索命令自身产生的输出。
内置 FuzzyFileTapeStore 从最新条目向回查找,支持去重和模糊匹配;短于 3 个字符的查询只做包含匹配。其他后端的行为由实现决定。
tape.anchors
Section titled “tape.anchors”无参数。按记录顺序返回 anchor 名称;没有时返回 (no anchors)。
tape.handoff
Section titled “tape.handoff”tape.handoff(name="handoff", summary="")| 参数 | 类型 | 说明 |
|---|---|---|
name |
str |
anchor 名称 |
summary |
str |
保存到 state.summary 的文本 |
写入 anchor 并移动默认上下文起点,旧记录仍保留。不会自动生成摘要;默认上下文在 anchor 之后读取,边界 anchor 本身不进入模型输入;以 anchor=None 读取时,默认选择器会把 anchor 转为 assistant 消息 [Anchor created: <name>]: <state JSON>。
tape.reset
Section titled “tape.reset”tape.reset(archive=False)清空当前 Tape 并创建新的 session/start anchor。archive=True 时先将主 Tape 和 sidecar 归档到 bub.home/tapes/。
子 Agent
Section titled “子 Agent”subagent
Section titled “subagent”subagent(prompt, agent=None, description=None, model=None, reasoning_effort=None, session="temp", allowed_tools=None, allowed_skills=None, timeout_seconds=None)| 参数 | 类型 | 说明 |
|---|---|---|
prompt |
str | list |
交给子 Agent 的任务 |
agent |
str | None |
子 Agent 配置名;调用中未给出的参数取自配置 |
description |
str | None |
任务列表中显示的简短标签;默认取 prompt 第一行 |
model |
str | None |
子运行的 provider:model;默认取配置中的模型或当前配置 |
reasoning_effort |
str | None |
子 Agent 模型的推理强度 |
session |
str |
子 Agent 的会话策略,默认 "temp" |
allowed_tools |
list[str] | None |
可用工具;默认为父 Agent 本轮的工具 |
allowed_skills |
list[str] | None |
可用技能;默认为父 Agent 本轮的技能,[] 禁用技能发现 |
timeout_seconds |
int | None |
超时即停止子 Agent;默认取配置中的时限,再取 BUB_SUBAGENT_TIMEOUT_SECONDS |
工具名支持运行时名称和模型别名;技能名不区分大小写。子 Agent 的工具和技能不会超过父 Agent:默认就是父 Agent 本轮允许的范围,指定范围外的工具会报错。子 Agent 不能启动或管理子 Agent,subagent 和 subagent.* 始终被排除。
session |
行为 |
|---|---|
temp |
新建空的 temp/<task_id> 会话,结束后丢弃 |
fork |
从当前对话(包括本轮已有内容)的副本开始,结束后丢弃;inherit 为其别名 |
| 其他字符串 | 使用指定的会话 ID,会话会被保留,之后可用 subagent.send 继续 |
fork 在调用时复制父 Agent 的 Tape,子 Agent 看不到父 Agent 之后记录的内容。每个子 Agent 拥有自己的轮次状态:父状态的浅拷贝,但去掉了父 Agent 的 steering 键、工具范围和运行中的 Tape,因此发给父 Agent 的 steering 消息仍归父 Agent。
返回结构:
{ "task_id": "sub-1a2b3c4d", "session_id": "temp/sub-1a2b3c4d", "status": "completed", # queued、running、completed、failed 或 cancelled "output": "...", "errors": [],}子 Agent 在后台运行:工具立即以 queued 或 running 状态返回,output 为空。任务结束时,父 Agent 会收到一条消息:
<subagent-notification task_id="sub-1a2b3c4d" status="completed">...</subagent-notification>output 是子 Agent 的最终答案,即它最后一个没有工具调用的步骤的文本。启动了子 Agent 的运行在结果全部送达前不会结束:某一步结束且没有工具调用时,运行会等待下一个任务结束,并带着它的通知继续。如果运行失败、被取消或达到 max_steps 后任务才结束,结果会通过会话的 steering 收件箱送达:运行中的轮次在下一步之前读到,否则随下一轮送达。用 subagent.wait 读过的结果不再发送通知。
进程内同时运行的子 Agent 最多 BUB_SUBAGENT_MAX_CONCURRENCY 个,其余以 queued 状态排队。运行时退出,或对某个会话执行 quit 命令,会取消运行中的子 Agent。temp 或 fork 子 Agent 结束时,它启动的后台 Shell 会被停止。
subagent.wait
Section titled “subagent.wait”subagent.wait(task_ids=None, timeout_seconds=60)返回任务结果,最多等待 timeout_seconds 让任务结束;0 只查看不等待。不传 task_ids 时覆盖本会话尚未读取的任务。超时后仍在运行的任务以当前状态返回。
subagent.send
Section titled “subagent.send”subagent.send(task_id, message)给任务发消息。运行中的任务在下一步之前读到它。使用命名会话且已结束的任务会作为新的后台任务继续该对话,工具范围受当前运行约束;已结束的 temp 或 fork 任务无法继续。
subagent.cancel
Section titled “subagent.cancel”subagent.cancel(task_id)停止运行中的任务。状态变为 cancelled,已有的部分输出会保留。
每个任务都会在 Agent 的事件总线(agent.events)上发布事件,state 为发起它的那次运行的轮次状态:
| 事件 | 时机 |
|---|---|
SubagentStarted |
任务离开队列,子运行即将开始 |
SubagentOutput |
子运行产生一个流事件,见 event |
SubagentFinished |
任务以 completed、failed 或 cancelled 结束 |
每个事件都带有 task(SubagentTask),包含 task_id、session_id、parent_session_id、parent_call_id、description、model、profile、status、output、errors、usage、步数和工具调用数以及时间戳。它们可从 bub.builtin.subagents 导入。处理器抛出的异常只会被记录,不会让子运行失败。
子 Agent 与父 Agent 共享 BubAgent、插件 Hooks、模型凭据、工作区、Environment、文件和外部系统。会话策略只隔离对话记录和模型上下文,不隔离文件、网络或进程副作用。在对话中参数由模型生成,allowed_tools 本身不构成安全边界。
代码模式 与 spill
Section titled “代码模式 与 spill”run_code
Section titled “run_code”run_code(code, timeout_seconds=120)在 代码模式 中执行 Python。使用 await tools.<name>(key=value) 调用工具;只有 print() 输出和显式附加的媒体进入结果。
attach_image / attach_audio / attach_video
Section titled “attach_image / attach_audio / attach_video”attach_image(image)attach_audio(audio)attach_video(video)将图片、音频或视频附加到当前 run_code 调用的结果。对应参数接受 republic.Image、republic.Audio 或 republic.Video 对象,也可传入字符串,指定当前 Environment 中的文件路径、http(s) / gs URL 或 data URL;本地文件通过当前环境解析和读取。
这些工具的 exposure 为 "code",只能在 run_code 内调用。每次调用将媒体追加到结果并返回确认字符串。
spill.read
Section titled “spill.read”spill.read(handle, cursor=0, count=1, from_end=False)| 参数 | 类型 | 说明 |
|---|---|---|
handle |
str |
原工具输出中的 spill 句柄 |
cursor |
int |
块位置 |
count |
int |
读取块数,每次最多 4 块 |
from_end |
bool |
是否从末尾向前读取 |
返回 next_cursor 和 complete;complete=True 表示已到达当前方向的边界。
spill 只在当前工具集包含 spill.read 时创建。阈值由 BUB_SPILL_THRESHOLD 控制;设为 0 时停止创建新 spill,已有结果仍可读取。
超出阈值的大型工具结果写入 spill sidecar,主对话只保留预览和句柄。Sidecar 是与会话 Tape 配套的另一份 Tape:随主 Tape 一起分支、合并和重置,但它的条目不会进入主上下文。概念见 Sidecar。
这些工具的 exposure 为 command,只能通过文本命令调用:
| 命令 | 参数 | 作用 |
|---|---|---|
,help |
无 | 列出内部命令和命令前缀 |
,model |
model_id |
切换当前会话模型 |
,reasoning_effort |
reasoning_effort |
设置当前会话推理力度 |
,code_mode |
enable=true / false |
开关当前会话的 代码模式 |
,quit |
无 | 清理待处理消息、运行中任务和后台 Shell |
命令前缀由 BUB_COMMAND_PREFIX 决定。会话设置从下一次 Turn 起生效,并持久化在会话 Tape 中。