内容
# 失败
> 编排代理。控制失败。
失败(Fiasco)是一个无头多代理编排器,使用Rust编写。它通过一个持久的运行时协调委托代理和长时间运行的后台作业,用于本地自动化和云工作负载。
运行时故意共享一个`AgentRunner`实现和一个工具合约,跨根代理和子代理。运行是可移植和可恢复的,无需数据库、分布式调度器、沙盒或审批系统。转录检查在存储中立的边界后面嵌入了fmtview;代理运行时本身保持无头。
## 功能
- OpenAI OAuth,带有设备登录、刷新、Codex身份验证导入和一个401重试
- OpenAI兼容的响应和聊天完成流式API
- Anthropic兼容的消息流式API
- 事件中的流式文本、片段式工具调用和用法/缓存令牌字段
- 紧凑的`read`、`write`和`bash`内置函数,以及可选的`web_search`;`read`支持有界UTF-8文本和图像附件,用于具有视觉能力的配置模型
- 具有CRLF/BOM保留的精确首选、原子多编辑写入
- 大型工具结果的本地运行工件溢出,具有有界的头部/尾部预览
- 可选的本地上下文压缩,记录为普通消息,具有只读正则表达式历史检索
- 具有渐进式`SKILL.md`加载的代理技能发现
- 通过一个`mcp`命令路由的渐进式记录MCP标准输入/输出服务器
- 运行和工具生命周期事件的命令钩子
- 未完成的调用在进程本地运行时句柄下继续的并发直接工具批次
- 异步委托的通用任务子代理,重用相同的运行时
- 基于图的编排的可安装技能,带有普通的 文件工具
- 使用普通文件工具维护的普通Markdown用户/项目内存
- 自包含的运行目录和可选的NDJSON事件
- 已完成和正在运行的运行的尾部优先转录检查
## 重要安全边界
失败在本次发布中不提供安全沙盒。内置工具、MCP服务器、钩子和子代理与失败进程具有相同的权限。仅在该访问权限适当的 环境中运行它。
## 安装
失败需要Rust和`rg`(ripgrep)。基于工件的紧凑历史搜索直接调用 `rg`,并期望它在 `PATH` 上。
```bash
cargo install --path .
```
二进制文件名为 `fiasco`。
## 快速入门
没有配置文件,失败使用确定性的回声提供程序:
```bash
fiasco run "hello"
```
运行带有机器可读事件的任务:
```bash
fiasco run --output ndjson "检查此存储库并运行其测试"
```
运行时输出存储在当前项目下:
```text
.fiasco/runs/<run-id>/
run.json
messages.jsonl
events.jsonl
final.md
artifacts/
```
在交互式终端上,检查打开当前换行符完整尾部,并延迟加载较旧的消息:
```bash
fiasco inspect <run-id>
fiasco inspect <run-id> --follow
```
`--follow` 刷新新完成的 消息行,同时保留fmtview的附加、分离和暂停浏览状态。重定向的 `--follow` 被拒绝,因为此模式需要交互式终端。
当stdout被重定向时,检查改为写入精确的换行符完整JSONL。显式形式在脚本中很有用。旧的元数据/最终输出视图仍然单独可用:
```bash
fiasco inspect <run-id> | jq -c .
fiasco inspect <run-id> --output ndjson
fiasco inspect <run-id> --summary
```
在修复消息尾部后,恢复中断或失败的运行:
```bash
fiasco resume <run-id>
```
## 提示布局
失败将其内置系统提示与工作空间、工具无关,并在正常代理调用之间保持不变。每个键入的 `tool.yaml` 都拥有其能力的 工作流指导以及其模式,因此删除工具也会删除其面向模型的指令。在每次运行开始时,第一个用户消息包含一个合成的 `<runtime-reminder>` 块,位于原始请求之前。提醒快照了工作空间路径、`AGENTS.md`(或规范名称缺失时的 小写 `agents.md`)、发现的技能元数据、内存位置和适用于该角色的任何委托任务指令。它还记录了角色和剩余的委托深度;通用任务指导位于此处,而不是在第二个系统提示中。内置工具模式对于根和通用任务是相同的、排序的和冻结的,用于运行;配置或文件更改在下一次运行时生效。
`messages.jsonl` 使用自包含的 `fiasco-message` 格式。每行都有一个短 `ref`(`m1`、`m2`,...),`created_at`、`role` 和类型 `content` 块。这些块是运行器重放的精确提供者中立消息,因此工具失败、工件引用、图像、推理和不透明的提供者继续项不需要边车或重建布局。 可选的压缩分类位于同一行的 `_fiasco` 下。
## 基于图的编排技能
失败将图规划作为可选的模型指导,而不是内置的运行时子系统。将存储库的 `orchestrate-with-graphs` 代理技能安装到项目中:
```bash
npx skills add siriusctrl/fiasco \
--skill orchestrate-with-graphs \
--agent universal
```
该技能教导编排器何时使用依赖图,如何在 `.agents/graphs/` 下存储它,如何区分接受的知识和实时执行,以及如何协调独立工作。它使用普通的 文件功能和显式代理控件。
## 提供商设置
配置从以下第一个存在路径加载:
1. `--config <path>`
2. `<workspace>/.fiasco/config.toml`
3. `$HOME/.fiasco/config.toml`
4. 内置回声默认值
配置文件不会合并,未知字段会被拒绝,因此拼写错误的设置会在启动时失败。
### OpenAI OAuth
```toml
[provider]
kind = "openai-oauth"
model = "gpt-5.6-sol"
modalities = ["text"]
```
一次性身份验证:
```bash
fiasco auth login
```
凭据存储在 `$FIASCO_HOME/auth.json`(默认 `$HOME/.fiasco/auth.json`)。如果没有失败的凭据,提供者可以导入兼容的 `$CODEX_HOME/auth.json` 或 `$HOME/.codex/auth.json`。
### OpenAI 兼容
```toml
[provider]
kind = "openai-compatible"
model = "my-model"
modalities = ["text"] # 仅在视觉模型中使用 ["text", "image"]
base_url = "http://127.0.0.1:8000/v1"
api_key = "${OPENAI_API_KEY}" # 或字面键
protocol = "chat-completions" # 或 "responses"
reasoning_effort = "medium" # 可选;提供者/模型特定
```
`api_key` 接受一个字面键或整个环境引用,如 `${OPENAI_API_KEY}`。在用户配置文件 `$HOME/.fiasco/config.toml` 中保留字面键,并具有限制性文件权限,而不是在可能共享的工作空间文件中。 如果省略 `api_key`,失败读取 `OPENAI_API_KEY`。 删除的 OpenAI 兼容 `api_key_env` 字段被拒绝;改为写入 `api_key = "${OPENAI_API_KEY}"`。
`reasoning_effort` 是可选的。失败将其作为 `reasoning_effort` 发送到聊天完成,并作为 `reasoning.effort` 发送到响应。 如果省略,使用提供者的模型默认值。常见值包括 `none`、`minimal`、`low`、`medium`、`high` 和 `xhigh`;接受的值取决于端点和模型。
当配置聊天完成推理时,`max_output_tokens` 作为 `max_completion_tokens` 发送,这是理性的聊天端点所必需的。
OpenAI兼容适配器重试初始HTTP 429,达到三次,指数退避。父请求和子请求还共享下面描述的运行时模型并发限制。
如果聊天完成流显式返回 `delta.reasoning_content`,失败将其存储在助手消息的可选 `reasoning_content` 字段中,位于 `messages.jsonl` 中,并向实时事件接收器发出瞬态 `model_reasoning_delta` 事件。 按块的文本和推理事件不会写入 `events.jsonl`;完整的助手消息是持久的轨迹。推理令牌计数在提供者报告时保存在持久的 `model_completed` 事件中。
使用以下命令检查运行的持久推理:
```bash
jq -c 'select(.role == "assistant" and has("reasoning_content")) | {role, reasoning_content}' .fiasco/runs/<run-id>/messages.jsonl
jq -c '.' .fiasco/runs/<run-id>/events.jsonl
```
`reasoning_content` 是OpenAI兼容端点的扩展,而不是官方的OpenAI聊天完成消息字段。 失败仅当端点显式返回推理文本时写入它,并在后续请求到该兼容聊天端点时重放为相同的独立字段。
### Anthropic 兼容
```toml
[provider]
kind = "anthropic-compatible"
model = "my-model"
modalities = ["text"]
base_url = "https://api.anthropic.com/v1"
api_key_env = "ANTHROPIC_API_KEY"
```
有关运行时、压缩、工件、MCP、钩子和内存设置的更多信息,请参见 [configuration.md](docs/configuration.md)。
## 上下文压缩和历史
默认情况下,自动本地压缩状态创建处于禁用状态。使用适用于模型上下文窗口的阈值启用它:
```toml
[runtime]
max_output_tokens = 8192
[compaction]
compact_at_tokens = 100000
context_window_tokens = 131072
keep_recent_tokens = 20000
summary_max_output_tokens = 4096
history_search_max_matches = 50
```
失败估计来自第一个请求的完整输入,并在有可用提供者报告的输入使用情况时用它替换。 当跟踪的输入达到 `compact_at_tokens` 时,它可以进行额外的模型调用。 调用接收到原始初始消息、任何先前的压缩状态、正在替换的本机较旧消息和一个最终压缩指令。 成功用户指令和确切的助手响应被追加到 `messages.jsonl`; 助手响应是持久的压缩状态。 后续正常请求省略压缩指令,并包含确切的助手消息和确切的最新后缀。
`context_window_tokens` 是模型的配置名义完整窗口。 在正常和压缩请求之前,失败检查其提供者中立的系统、模式、活动消息和配置的输出津贴的估计。 它必须大于 `compact_at_tokens`; 如果压缩无法将估计降低到其以下,则运行在本地失败。 这是一个早期安全检查,而不是基于标记器的精确提供者保证。 设置窗口需要一个显式的非零 `runtime.max_output_tokens`; 通用任务使用其单独配置的配置文件限制。 启动/完成/失败记录保留在 `events.jsonl` 中; 压缩重试有编号的尝试,而预检查拒绝没有启动事件或尝试,因为没有提供者请求发生。 兼容聊天 `reasoning_content` 和可重放的不透明提供者项目包含在调用间的估计中。
正常代理接收到 `history_search` 和 `history_read` 模式来自其第一个提供者请求,无论是否配置了 `compact_at_tokens`。 更改阈值仅控制压缩状态创建; 它不会更改正常系统提示或工具模式。 在压缩任何内容之前,历史工具简单地没有压缩前缀来搜索或读取。
两个只读工具恢复主动请求中省略的精确细节:
- `history_search({"pattern":"..."})` 仅将Rust正则表达式应用于压缩消息及其链接的文本工件结果。 结果按最新优先排序。 每个匹配项包含 `ref`、`source` 和 `snippet`:引用是运行本地序列地址,例如 `m37`(较旧的数字较小),而 `source` 是内联内容的 `message` 或链接完整溢出结果的 `artifact`。
- `history_read({"ref":"m37","before":2,"after":2})` 读取围绕一个ref的边界时间窗口。 它返回形状为 `{"ref":"m<N>","message":<OpenAI Chat-compatible message>}` 的JSONL记录,并将工具调用与结果配对。
本地读取器在完整的文本工件中调用 `rg` 进行边界内存搜索,因此ripgrep必须在 `PATH` 上用于 `history_search` 的该部分。 未来的远程读取器可以从数据库或服务中提供相同的接口。
两个工具都没有光标。 `history_search_max_matches` 将查询限制为其最新匹配项; 如果达到,则省略较旧的匹配项,模型必须细化正则表达式。 这与工件预览截断不同; 如果边界JSON/JSONL工具结果太大,则其完整返回的内容保存为工件,可以使用 `read` 检查,从返回的 `line_offset` 或 `byte_offset` 继续; `bash`/`rg` 也适用于有针对性的搜索。 查询限制省略在该工件中不存在。
每个装配的代理运行都有一个排序的、冻结的工具集。 运行仅当历史工具和至少一个工件检查工具(`read` 或 `bash`)存在时才压缩。 压缩请求重用相同的系统提示和工具模式; 拒绝工具调用响应而不是执行。
此版本仅实现本地模型生成的压缩状态。 它不使用OpenAI或其他提供者的服务器端压缩API。
## 大型工具结果
小型结果内联返回。 大型结果在当前运行下完整写入,并替换为模型上下文:
- 开始和结束预览
- 生成时间字节数和媒体类型
- 项目相对运行本地附件路径
模型可以使用有界的 `read` 调用检查完整输出,或使用 `bash` 和 `rg` 进行搜索。 路径命名一个可变的附件:后续检查观察其当前内容,而原始预览保持不变。 每个工具结果独立限制; 较早的大型结果不会抑制较晚的小型结果。 请参阅 [artifacts.md](docs/artifacts.md)。
## 工具与后台工作
启动工具界面故意设计得很小:
- `read`:有界限的UTF-8读取,用于已知路径,或模型附件,用于jpg、jpeg、png、gif、webp和bmp图像
- `write`:完整的文件创建/替换或有原子性的目标编辑列表
- `bash`:本地发现、`rg`、测试、构建和其他Bash命令;返回组合的stdout/stderr,并仅在不成功完成时添加状态行。它使用非登录shell并继承fiasco的环境,而不加载配置文件
- `history_search`:对压缩的轨迹前缀的正则表达式搜索
- `history_read`:围绕返回的历史引用的有限消息窗口
- `load_skill`:逐步加载编目技能的完整指令
- `delegate`:异步启动可重用的GeneralTask代理
- `list_handles`:发现所有可见的句柄或检查选定的句柄
- `wait`:等待任何选定的句柄更改或一个间隔过期
- `inspect`:读取子代理的消息的有限窗口
- `send_message`:现在发送`steer`输入或排队`followup`输入以供稍后使用
- `stop`:停止工具作业或可重用代理的当前活动
- `close`:如果需要,取消当前代理活动,然后永久关闭它
- `web_search`:可选的Brave支持的公共网络搜索
- `mcp`:可选的类似CLI的访问配置的MCP工件
根和GeneralTask接收相同的内置模式,包括`delegate`和每个运行时句柄控制。剩余的委托深度在运行时状态下冻结,并在运行时提醒中显示。在零时,`delegate`返回本地工具错误,而不创建子代理;其模式不会消失。内存添加路径到提醒中,而不是工具模式。`web_search`和单个`mcp`工具依赖于启动配置。配置的MCP工件仅贡献其命名空间、描述和源映射路径到运行时提醒中,而不是其远程模式。生成的模式在运行的第一个正常提供者调用之前排序并冻结。
`write`要求每个编辑目标在原始文件中标识一个非重叠区域。它首先尝试精确匹配,然后是保守的整行缩进规范。它不使用广泛的模糊相似性,这可能会默默地修改错误的代码。
在一个助手消息中的所有直接工具调用都并发启动并共享一个前台窗口。如果所有调用都提前完成,fiasco会立即返回。在配置的截止日期,它保留每个未完成的精确未来,仅移动那些在进程本地`j_<ulid>`句柄下的调用,并返回这些句柄;不会停止或重新启动任何工具。助手消息、工具结果消息(按原始调用顺序)和任何附件消息都会按该顺序追加;每行完整的内容都会独立显示。
结果保留其原始的`tool_calls_id`,即使完成事件可以按其他顺序到达。模型应仅在单个批处理中放置独立调用,并在看到结果后发出依赖性工作。
工具结果是一个无状态的`<runtime_handle>`通知,包含句柄、类型和名称;它仅确认工作正在运行。
`delegate`需要一个非空的模型提供的显示名称,并异步启动一个独立的可重用的`general-task`代理。其句柄是子运行ID,因此句柄在活动和进程重启期间都指向相同的持久记录。在下一个模型边界,一个用户/运行时消息批次包含每个就绪的`<runtime_handle status="...">`通知。
句柄控制调用故意设计得很小:
```text
delegate({"name":"inspect_tests","prompt":"inspect the failing tests and report the cause"})
wait({"handles":["01J..."]})
list_handles({"include_closed":false})
list_handles({"handles":["01J..."]})
inspect({"handle":"01J...","limit":6,"before_seq":42})
send_message({"handle":"01J...","message":"check the failing test first","mode":"steer"})
send_message({"handle":"01J...","message":"then compare the alternatives","mode":"followup"})
stop({"handle":"01J..."})
close({"handle":"01J..."})
```
`wait`会在任何选定的句柄有结果或状态更改时立即返回,而其快照可能仍显示其他选定的句柄正在运行。省略或空的`handles`列表意味着所有可见的句柄。`list_handles`返回当前运行拥有的所有子代理以及当前进程的工具作业,包括空闲的可重用代理和可选的已关闭代理。当指定句柄时,它返回其当前快照;`include_closed`影响发现而不是命名查找。
`before_seq`是独有的且可选的;检查返回`next_before_seq`,如果存在较旧的消息。
## 技能
Fiasco从最低优先级到最高优先级发现Agent技能:
1. `$HOME/.agents/skills/*/SKILL.md`
2. `<workspace>/.agents/skills/*/SKILL.md`
3. `<workspace>/skills/*/SKILL.md`
只有技能名称和描述进入稳定的提示前缀。`load_skill`返回指令正文而不重复该元数据,以及解决引用文件所需的绝对技能目录路径。
```bash
fiasco skills list
```
## MCP 工件
每个配置的MCP源都有一个模型生成的命名空间和渐进式工件,其中包含`MCP.md`、精确捕获的`catalog.json`和可选的功能引用。只有命名空间、简短描述和绝对`MCP.md`路径进入运行时提醒。模型读取该源映射和相关引用,然后使用一个固定的`mcp`工具:
```text
mcp("github search_code query='McpRuntime' language=rust limit=20")
```
实际的提供者工具模式有一个`command`字符串。Fiasco解析shell引用,将前两个令牌解析为命名空间和精确的远程工具名称,使用捕获的输入模式转换`name=value`参数,并调用配置的stdio服务器。具有一个输入属性的工具也接受一个位置值。
分别配置传输和工件:
```toml
[mcp.github]
artifact = ".agents/mcp/github"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
[mcp.github.env]
GITHUB_TOKEN = "${GITHUB_TOKEN}"
```
创作和验证使用与运行时相同的加载器、编译器、客户端和结果渲染器:
```bash
fiasco mcp capture github
fiasco mcp check github
fiasco mcp check github --live
fiasco mcp compile "github search_code query='McpRuntime'"
fiasco mcp call "github search_code query='McpRuntime'"
```
安装存储库的`register-mcp`技能,以便代理捕获、记录、探索和验证任意配置的stdio MCP:
```bash
npx skills add siriusctrl/fiasco \
--skill register-mcp \
--agent universal
```
技能围绕用户可见的功能组织,并鼓励将共享对象、标识符或工作流的命令分组。它保持原始的每个工具目录精确且在模型上下文之外。
## 多代理编排
`delegate`异步启动作为可重用子代理的唯一面向模型的`general-task`角色;
没有面向模型的配置文件选择。运行时提醒状态为精确的剩余委托深度。默认`max_subagent_depth = 1`,第一个子代理有零剩余深度;`delegate`在那里可见但本地失败。子代理是同一个运行程序的另一个调用,而不是第二个代理类。每个子代理:
- 调用相同的`AgentRunner`和提供者
- 有单独的运行ID、记录、事件和工件
- 记录其父运行ID
- 共享工作项目,因此可以检查和修改相同的文件
- 使用配置的GeneralTask模型和输出配置文件
- 在默认深度限制下无法委托另一个子代理
父和子模型请求共享`runtime.max_parallel_model_calls`,默认为一个以兼容速率限制的端点。委托子代理的能力独立于`runtime.max_parallel_subagents`控制。
每个`delegate`调用启动一个独立的子代理,仅具有其运行时提醒和委托的提示。提示必须包括完整的目标和任何任务特定的上下文;子代理不会继承父对话。完成的活动将使子代理空闲。`send_message`使用普通用户消息恢复相同的子代理,`followup`在不阻塞父的情况下排队该消息,而停止的代理在下一个`send_message`之前保持暂停。`close`是代理生命周期的明确结束。它在需要时取消并等待当前活动,拒绝在关闭开始后新的输入,并丢弃任何仍在排队的后续操作。其轨迹存储在子运行中,因此重用、恢复和历史检索不依赖于活动的父进程。
`runtime.model_stream_idle_timeout_seconds`(默认为300)停止一个模型流,该流在该间隔内未产生有效的SSE事件,而`runtime.model_request_deadline_seconds`(默认为3600)限制完整的模型API调用,即使流继续取得进展。两个限制都不包括工具执行或等待共享模型槽所花费的时间。
只有子活动结果返回到父上下文;完整的子记录保留在其自己的运行目录中。没有父级持久协调记录或恢复状态机。重启时,`list_handles`通过父ID发现直接子运行,并将每个打开的线程显示为空闲状态而无需启动它。第一个显式`send_message`在添加崩溃提醒后重用子代理的完整记录。已关闭的子代理保持关闭状态。工具作业和未交付的活动输出来自前一个进程,已消失;父崩溃提醒让模型决定是否重试。
父代理可以检查子代理的最新消息(默认为六个),按顺序回溯,并控制子代理运行时的操作。控制信息保留在进程本地的邮箱中,直到它作为普通用户消息附加在子代理的当前助手响应和完整的工具调用批处理之后,在下一个模型请求之前。它不会中断或丢弃正在进行的工具。
## 长期记忆
记忆是关于用户和项目的持久性知识,而不是当前对话。它是两个位置的普通Markdown,这两个位置包含在普通代理的初始运行时提醒中:
- `$FIASCO_HOME/memory/user/`用于跨项目用户知识
- `<workspace>/.fiasco/memory/project/`用于项目特定知识
没有特殊的记忆工具。模型使用`read`、`write`和`bash`进行小的聚焦更改。对于大型独立更新,它可以委托普通的`general-task`子代理,继续有用的工作,并在完成前协调子代理结果。
```bash
fiasco memory consolidate
```
使用外部调度器而不是将cron嵌入到支架中:
```cron
15 3 * * * /usr/local/bin/fiasco --workspace /workspace/project memory consolidate
```
参见 [memory.md](docs/memory.md)。
## 架构
```text
CLI/job
-> AgentRunner
-> ModelProvider
-> ToolRegistry
-> local Tool adapters grouped where related
-> one namespaced MCP command adapter
-> RuntimeHandleManager
-> promoted direct Tool future
-> delegated child AgentRunner
-> ArtifactStore
-> RunDirStore
-> EventSink
```
提供者线路格式从不进入循环。MCP命令适配器使用与本地适配器相同的`Tool`合约,而其工件注册表路由到远程MCP客户端。子代理使用相同的运行程序。大结果使用与源无关的相同工件合约。
阅读 [architecture.md](docs/architecture.md) 和 [design-choices.md](docs/design-choices.md) 以获取详细的边界和权衡。
## 开发
```bash
cargo fmt --check
cargo check --all-targets
cargo clippy --all-targets -- -D warnings
cargo test --all-targets
```
运行一个完整的本地烟雾测试任务:
```bash
tmp=$(mktemp -d)
target/debug/fiasco --workspace "$tmp" run --output ndjson "smoke"
find "$tmp/.fiasco/runs" -maxdepth 3 -type f -print
```
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器