内置工具大全

LibreFang 自带的工具目录远不止标准 agent 模板里看到的 file / shell / web 工具。本页覆盖那些一直只活在源码里的家族 —— 浏览器自动化、子进程生命周期、运行时调度、知识图谱、媒体生成、agent 间消息。

Per-agent capability 授权决定一个 agent 实际能调哪些家族。在 agent.toml [capabilities] 里(或用 librefang agent grant CLI)给 agent 开下面这些工具家族的权限。

元工具(Lazy Loading)

两个元工具让 agent 按需发现并加载工具,而不是每次 prompt 都带全部 schema。

工具用途
tool_search(query)返回名字/描述/标签匹配 query 的工具。无副作用,调用便宜。
tool_load(name)把某工具的完整 schema 拉进当前 session。后续轮次可以调它。

Lazy loading 在 manifest 用 lazy_tools = true 按 agent 开启。关掉则恢复"所有工具一直加载"的旧行为。这就是 Agent 模板 里 Lazy Tool Loading 提到的机制。


Agent 间消息(A2A)

不同 LibreFang 实例上的 agent 可以通过 A2A 协议互发任务。

工具参数用途
a2a_discoverurl探测远端 A2A 端点,返回 agent card(/.well-known/agent.json)。
a2a_sendagent_id、message、可选 task_id给远端 A2A agent 发任务并等回复。

a2a_send 从调用方视角是同步的 —— 阻塞到远端轮次完成(或任务 TTL 到)。要 fire-and-forget 投递,用 notify_owner 或 webhook target。


同 daemon 内 agent 间工具

跟同一 LibreFang daemon 里别的 agent 通话(无 A2A 协议开销) —— 直接 spawn、list、find、kill、发消息。

工具参数用途
agent_sendagent_id、message、可选 async给本 daemon 内别的 agent 发消息。默认非阻塞:立即返回 task_id,对方回复完成后投递到调用方 session。传 async: false 则阻塞并直接拿到回复。走进程内 kernel 路由器;受 agent_call 深度上限约束。
agent_spawntemplate、可选 name、goal从模板 spawn 子 agent。返回新的 agent_id。子 agent 默认禁 agent_spawn 和 agent_kill 防止 fork 炸弹。
agent_list—列出可访问 agent(id、name、status)。
agent_findquery按名字、ID 或 tag 搜 agent。
agent_killagent_id终止运行中的 agent。子 agent 上下文里默认禁。
goal_updategoal中途更新当前 agent 的目标。新目标写进 agent 的 manifest,后续 prompt 看得到。
agent_type_createname,可选 description、system_prompt、provider、model、tools、skills创建一个新的智能体类型(agent type)—— 一份存在 daemon 上的可复用 manifest,之后 agent_spawn、仪表盘和 TUI 都能从它生成 agent。这里只能设置这七个字段,manifest 的其余部分先取默认值,之后再改。名字若已被某个智能体类型或某个运行中的 agent 占用,会被拒绝而不是覆盖。

agent_type_create 走的是和 POST /api/templates 完全相同的 AgentTypeSpec 校验与同一个存储实现,所以 agent 自己写出来的类型和运维在仪表盘里写出来的没有任何区别。 工具、仪表盘和 TUI 统一用"智能体类型"这个说法;HTTP 路径仍旧只有 /api/templates 一个,不再为同一个资源加第二个别名。

[kernel] 里的 max_agent_call_depth(默认 5)封顶 agent_send 链能递归多深 —— 让 A→B→A 循环根本到不了生产。 下面的 workflow_run 若发生嵌套(某一步的目标 agent 又跑了一次 workflow)也计入同一份预算,因为每一步都会嵌套一整个 agent turn,效果跟 agent_send 跳一层一样。


Memory 工具(per-agent)

一共有两套记忆存储、两套工具族,名字相近,值得仔细区分。

memory_store / memory_recall / memory_list 是键值存储。memory_recall 只接受精确的 key,不做任何匹配 —— 它不是搜索。

工具参数用途
memory_storekey、value以精确 key 持久化一个值,只能用同一个 key 取回。
memory_recallkey按精确 key 查一个值。key 不是逐字符相同就返回“未找到”。
memory_list可选 limit、offset枚举键值存储里的 key 名(不含值)。

memory_semantic_* 是语义存储 —— 也就是自动召回机制每轮之前读取的那套向量存储。有了这些工具,agent 才能主动查询它,而不是只能被动接收注入的内容。

工具参数用途
memory_semantic_searchquery、可选 limit、min_confidence按语义搜索记忆片段,每条结果都带可用于撤回的 id。min_confidence 会过滤置信度已衰减的片段,让调用方可以选择“宁可什么都不要,也不要噪声”。
memory_semantic_addcontent主动记录一条持久事实。内容会经过记忆抽取器,可能被提炼、被合并进已有记忆,或因冗余而被拒绝 —— 返回结果会如实说明实际写入了什么,包括“什么都没写”。
memory_semantic_forgetmemory_id撤回一条记忆,使其不再被召回。这是修正“陈旧记忆持续与 agent 直接观测到的事实相矛盾”的手段。
memory_semantic_stats—按层级与类别的计数,以及 auto-memorize、自动召回、LLM 抽取是否开启。用于区分“存储是空的”和“存储被关掉了”。

只有 memory_semantic_search 每轮都会带上 schema;其余三个通过 tool_search / tool_load 获取。

语义工具需要同时满足两个条件:capabilities.tools 允许它们(memory_* 这样的 glob 即可),并且记忆 scope 覆盖 agent 自己的记忆 —— search / stats 看 capabilities.memory_read,add / forget 看 capabilities.memory_write。未声明 scope 时保持开放;若声明的 scope 只覆盖键值存储(memory_read = ["kv:*"]),语义工具会被收回,键值工具不受影响。[proactive_memory] enabled = false 时它们也会被完全收回,因为此时存储根本没有构建。

条目 schema、scope、衰减公式、整合触发器见内存系统。


任务队列工具

共享任务板让 agent 发布工作给别的 agent 认领。适合 fan-out、oncall 交接、长跑异步任务。

工具参数用途
task_posttitle、body、可选 assignee、priority在共享队列创建新任务。
task_claim可选 priority_filter认领最高优先级 pending 任务。TTL 是 [task_board] claim_ttl_secs(默认 600s)。
task_completetask_id、可选 result标记已认领任务为完成。
task_list可选 status、assignee带可选过滤条件列出任务。
task_statustask_id按 ID 查询单个任务,返回 status、result、title、assigned_to、created_at、completed_at。comms_task_status MCP bridge 工具的 native 版本——通过 task_post 委派工作的 agent 可以直接轮询结果,不必加载 bridge。

claim TTL 用来从 worker 崩溃中恢复 —— 认领者没在 TTL 内 task_complete,sweeper 把任务重置回 pending 给别的 worker 接手。


Channel 工具

工具参数用途
channel_sendchannel、target、content(文本 / 图 / 文件 / poll)给某 channel 用户发消息、图片、文件或 poll —— 不走 agent 循环。适合推告警、异步结果、带外通知。
channel_dmuser_id、message把消息私下发给当前这轮所在群会话中的某一位成员,而不是发到所有人都能看到的群里。
channel_members可选 channel、chat_id列出群会话中已知的成员 —— 守护进程见过发言的每个人的 user_id、display_name、username。只读。

channel_send 是 [deliver_only] webhook 模式内部用的工具;agent 也能直接调。Capability:channel.*。

channel_members 读取 channel bridge 在观察群消息时建立的花名册,因此它列出的是在该会话中发过言的人,而不是平台的完整成员列表。 两个参数都默认取当前消息所在的会话,所以在处理消息时可以完全不带参数调用;私聊没有花名册。 指定当前轮次所在 channel 上的另一个会话会被拒绝,理由与 channel_send 拒绝跨会话投递相同 —— 一个群不能枚举另一个群的成员。 用它把请求归属到提出请求的人,并拿到外部系统通知此人所需的平台 user_id。

在群里只找一个人

在群会话里,channel_send 只能发给群本身 —— 把它改指向某个人会被跨会话派发守卫拒绝,因为一个能任意指定收件人的 agent,也就能被诱导指错人。 channel_dm 是那个收窄过的例外:它只接受 user_id 和 message,别的都不接受。 channel、会话和机器人账号全部来自正在处理的这一轮,而收件人必须已经出现在该会话的名册里 —— 也就是 daemon 见过其发言、并且 channel_members 会列出的人。 因此 agent 无法给一个素未谋面的平台 id 发消息,也无法借一个会话伸进另一个会话。

带外场景(cron、trigger、API 触发的运行)没有会话,也就没有名册可以授权任何人;channel_dm 在那里按设计不可用,该用带显式 recipient 的 channel_send。

"私下"在各平台上的含义并不相同,这个工具也不假装相同。 Slack 允许机器人与工作区内任意成员开启 DM,所以 U… id 总能送达。 Telegram 和 Discord 的机器人无法主动联系从未给它发过消息的人,这种发送会失败 —— 它绝不会悄悄退回到发群里,因为一条本该私密、却无声变成公开的通知,比报错更糟。

notify_owner 不是它的替代品:那产生的是面向运维者的通知,通过运维者自己的界面带外送达,没有任何 channel adapter 会把它转给会话参与者。


Workflow / Event 工具

工具参数用途
workflow_runworkflow_id、可选 inputs同步执行存好的 workflow 并返回结果。嵌套深度受与 agent_send(上文)相同的 max_agent_call_depth 预算约束;超深的 run 会被拒绝,而不是任其递归。
event_publishevent_type、payload把结构化事件发到事件总线。监听该 event_type 的 trigger(agent manifest 里的 [[trigger]] 块)会触发。
system_time—取 daemon 当前墙钟时间(RFC3339 UTC)。便宜,不调外部 clock。

event_publish 是 agent 与 trigger 系统的桥梁 —— 检测到"/inbox 落了新文件"的 agent 可以发 inbox.new_file,任何配在该事件上的 trigger 就跑起来。


技能进化(扩展)

除了上面文档化的 skill_evolve_patch(带 5 策略模糊匹配器)和 skill_read_file,还有:

工具参数用途
skill_evolve_createname、manifest、可选 body从零创建新 skill。
skill_evolve_updatename、body整体替换 skill body(不模糊匹配,直接覆盖)。
skill_evolve_deletename删除整个 skill。
skill_evolve_rollbackname、可选 version回退 skill 到之前的版本。不指定 version 就回退一步。
skill_evolve_write_fileskill、path、body在 references/ / templates/ / scripts/ / assets/ 加支持文件。
skill_evolve_remove_fileskill、path删支持文件。

每次 skill_evolve_* 操作都追加到 skill 的进化历史;GET /api/skills/{name} 返回完整审计轨迹。


浏览器自动化

8 个工具包了一个 Playwright 控制的无头浏览器。所有工具都需要 agent 有 browser.* capability,且 config.toml 里配了 [browser] 段(见核心配置)。

工具用途
browser_navigate(url)在活跃 tab 打开/导航 URL。
browser_back()在 tab 历史栈里后退一步。
browser_click(selector)点 CSS / 文本选择器匹配的元素。
browser_type(selector, text)聚焦元素后逐键 debounced 输入文本。
browser_scroll(direction, amount?)上/下滚动或滚到某选择器。
browser_wait(condition, timeout_ms?)等选择器/network-idle/时间。
browser_screenshot(full_page?)截屏(viewport 或整页)为 ContentBlock::ImageFile。
browser_read_page()抽取页面完整文本 + 结构化大纲(模型只要文本时比 screenshot 便宜)。
browser_run_js(script)在页面上下文跑任意 JS,返回 JSON 序列化结果。
browser_close()关闭活跃 tab,释放 slot。

Agent 打开的页面绑在该 agent 的 tab 池里(默认 4)。池满时 browser_navigate 用 ToolError::ResourceExhausted 拒绝,而不是悄悄 evict 别的 tab。


子进程生命周期

5 个工具管长跑子进程(build watch、test loop、log tailer、sidecar daemon)。stdin / stdout / stderr 暴露成 agent 可 poll 的流。

工具用途
process_start(command, cwd?, env?)spawn 子进程。返回 process_id。
process_write(process_id, data)给子进程 stdin 写字节。
process_list()列出该 agent 的活跃子进程(id、cmd、age、pid)。
process_poll(process_id, max_bytes?)自上次 poll 起读最多 max_bytes 新输出。非阻塞。
process_kill(process_id, signal?)发信号(默认 SIGTERM);超过宽限期 runtime 升级到 SIGKILL。

子进程默认继承 agent 的 workspace 作为 cwd、agent 的环境变量(去除其他 provider 的 secret),agent 关闭时一并停掉。墙钟预算由 [exec_policy] 段强制。


运行时调度

manifest [[cron]] 是静态的安排方式。这些工具让 agent 从循环里动态创建/列出/暂停/恢复调度。

工具用途
schedule_create(when, prompt, channel?)在某未来时间戳调度一次性轮次。
schedule_list()列出 agent 已调度的轮次。
schedule_delete(schedule_id)暂停(禁用)已调度的轮次 —— 保留配置而非删除。
schedule_resume(schedule_id)恢复被暂停的已调度轮次。
cron_create(expression, prompt, channel?)5 字段 cron 调度循环轮次。
cron_list()列出 agent 运行时创建的 cron 任务。
cron_cancel(cron_id)暂停(禁用)运行时 cron 任务 —— 保留配置而非删除。
cron_enable(cron_id)重新启用被暂停的运行时 cron 任务。

agent 不能硬删除已调度的任务:schedule_delete / cron_cancel 只会暂停它,因此即使是行为异常或过于激进的 agent 也无法静默丢失一个已配置好的调度。 永久删除是仅限人类的操作,通过 dashboard 完成(#6159)。 这些工具创建的运行时任务和 manifest cron 共用持久化存储 —— 跨 daemon 重启依然存在。 cron_id / schedule_id 是不透明的;通过 cron_list() 往返获取。


知识图谱

每个 agent 私有的知识图谱存实体和带类型的关系。适合做结构化召回("哪些项目用哪些库"),用扁平 memory 记录不好表达的那种。

工具用途
knowledge_add_entity(name, type, attributes?)插入或更新实体。
knowledge_add_relation(from, to, type, weight?)在两个实体之间加有向关系。
knowledge_query(start, depth?, relation_filter?)从 start 做 BFS,返回可达节点 + 边。

图谱按 agent 私有,与 agent 的 session 历史一起持久化在 SQLite。非结构化召回用 proactive-memory 工具。


媒体生成与分析

调用 provider 专属媒体 API 的工具。需要按工具单独授权 capability。

工具用途
image_generate(prompt, size?, style?)文生图(OpenAI / Replicate / Vertex)。
image_analyze(image, question)对已有图像做 vision Q&A。
media_describe(image_or_video)给已有媒体素材生成 caption / 描述。
media_transcribe(audio_or_video, language?, prompt?, start_sec?, max_secs?, out_path?)音频转文本;也接受视频容器,服务端会提取其中的音轨。无法识别的扩展名会被拒绝。start_sec / max_secs 只转写一个时间窗口,并在响应中返回 has_more / next_start_sec 以便继续;out_path 会把转写结果写入工作区文件,只返回路径、字节数、sha256 和一段预览。长录音两者都需要,详见下文。
speech_to_text(audio_or_video, language?, prompt?)支持的提供商和视频容器与 media_transcribe 相同;遇到无法识别的扩展名时不拒绝,而是退回一个宽松的猜测 MIME 类型。不支持时间窗口和 out_path,因此需要其中任何一项的长录音应改用 media_transcribe。
text_to_speech(text, voice?)TTS 合成。
music_generate(prompt, lyrics?)音乐生成(Suno / Replicate)。
video_generate(prompt, duration_secs?)提交视频生成任务,返回 task_id。
video_status(task_id)poll 视频任务。
canvas_present(html)在 dashboard 渲染交互式 HTML canvas。

provider 间成本和延迟差别很大 —— 在 config.toml 里配 [media] providers 控制每个工具走哪个 provider。

转写长录音

整场会议的转写结果无法通过单次工具返回完整送达 agent:超过 [tool_results] spill_threshold_bytes(默认 16 KB)的结果会被内核转存到 artifact store,agent 只拿到一个占位;而单次转写请求受一个不随输入长度变化的挂钟超时约束。 这两个限制远早于任何文件大小限制被触及 —— 十分钟的录音提取出来只有两三兆音频。

所以要按时间窗口转写,并写入文件:

media_transcribe(path="meeting.mp4", max_secs=600, out_path="meeting.txt")
→ { "written_to": "...", "file_bytes": 16831, "has_more": true, "next_start_sec": 600.0, "window_preview": "..." }

media_transcribe(path="meeting.mp4", start_sec=600, max_secs=600, out_path="meeting.txt")
→ ... 只要 has_more 为 true 就继续

start_sec 为 0 的窗口会新建文件,后续窗口以换行分隔追加到同一个文件,因此多次调用会拼装成一份完整转写,而其内容始终不进入 agent 的上下文。 推进时请使用 next_start_sec 而不是自行加 max_secs:seek 会落到关键帧上,且最后一个窗口偏短,所以只有实际产出的长度才是不会漂移的边界。

也不要自行猜测 start_sec。 如果窗口起点超出录音结尾约十秒以上,返回的并不是空结果:ffmpeg 会放弃 seek 并返回录音的开头,而这段内容看起来就像你所请求的那一段。 这个余量是绝对值,不随录音长度按比例放大,因此在长录音上只占很小一部分——对一场四十五分钟的会议请求第五十分钟即可触发。

如果调用超时,就调小 max_secs。 一次请求能容纳多少媒体取决于 provider 的速度,自托管端点可能比托管服务慢一个数量级。

如果调用因超出提取后的音频预算而被拒绝,同样应调小 max_secs。 这里有两个大小限制,衡量的是不同的对象:输入容器在读取之前按 50 MB 的视频上限检查,而从中提取出的音轨在发送给 provider 之前按 20 MB 的音频上限检查。 长录音真正会碰到的是后者,因为离开进程的正是这条提取出的音轨——拒绝信息会同时给出实测大小和上限,因此窗口可以据此缩小,而不必靠猜。


Owner 通知

工具用途
notify_owner(reason, summary, urgency?)给 agent owner 发私信,不进 chat。

notify_owner 写到 owner 的 inbox,可选地扇出到配好的旁路通道(Telegram、email)。和正常回复不同 —— 消息不进活跃 chat 历史,不会污染下游摘要。线上结构见 API 参考里的 ReplyEnvelope.owner_notice。


地理定位、Docker、Skills

工具用途
location_get()当前位置(默认 IP 基础;可按 agent 覆盖)。
docker_exec(container, command)在 agent 已被授权访问的运行中 Docker 容器内跑命令。
skill_read_file(skill, file)读 skill 的支持文件(references/、templates/、scripts/、assets/)。和 skill_evolve_* 配套。

docker_exec 要求 agent 在 [capabilities] docker.* 允许列表里,且容器名在 [exec_policy] docker_allowlist。两者缺一,调用以 ToolError::Forbidden 拒绝。


apply_patch 移动语义

apply_patch 接受 UpdateFile { path, move_to, hunks } 形状。move_to 设了时,patch 先把 path 重命名为 move_to,然后对新路径应用 hunks。这把 rename + edit 折叠成单次工具调用,patch 是原子的 —— 读者不会看到改名后的旧路径文件。

hunks 空、move_to 非空 = 纯重命名。在重构多文件、其中一个文件改路径但内容不变时有用。


skill_evolve_patch 模糊匹配

skill_evolve_patch 就地修改已装的 skill。为了能扛住上游小幅漂移,匹配器按 5 个策略走,首匹配胜:

  1. Exact — 字节级相同(Levenshtein 0)。
  2. Line-trimmed — 去每行尾空白和 CRLF 后再比。
  3. Whitespace-normalised — 把行内连续空白合并;忽略 tab vs space 漂移。
  4. Indent-flexible — 去每行行首空白;忽略重排成不同缩进的修改。
  5. Block-anchor — 在目标里找连续 N 行 anchor(默认 3 行),把新内容拼到锚周围。

5 个全失败时,patch 用精确 diff 上下文拒绝,下一轮就能看到漂移在哪。没有自动"尽力"合并 —— 模糊匹配是有界的。

配套工具 skill_evolve_write_file 和 skill_evolve_remove_file 不走 patch 语义,直接管 skill 支持文件(references/、templates/、scripts/、assets/)。


在源码里去哪看

  • 工具注册与 schema — crates/librefang-runtime/src/tool_runner/definitions.rs —— builtin_tool_definitions() 给出每个内置工具的名字、描述和 LLM 看到的 JSON schema。
  • 分发 — crates/librefang-runtime/src/tool_runner/dispatch.rs —— 把工具名路由到处理函数的那个 match;处理函数本身按域拆在同目录的 agent.rs、workflow.rs、memory.rs 等文件里。
  • Capability 把关 — crates/librefang-types/src/capability.rs,加上 execute_tool 里的 allowed_tools 检查 —— 哪些 agent 能调哪些工具。
  • 浏览器池 — crates/librefang-runtime/src/browser.rs 和 browser_tools.rs。
  • Schedule / cron 运行时工具 — crates/librefang-runtime/src/tool_runner/schedule.rs 和 cron.rs。

不确定的时候,工具结构体上的 rustdoc 是权威规约。Dashboard 的 "Tools" inspector 也会按当前 capability 授权渲染实际可用的工具集。