正在统计访客…
浏览全部文档
开始 · 9找到适合你的 Runifold 学习路径45 分钟掌握 Runifold理解完整的 Runifold 平台第一次可信运行选择正确的执行 API选择 Crate 与 Cargo Feature构建常见 Runifold 应用Runifold 常见问题排查 Runifold 应用故障
执行内核 · 7理解 RunContext安全协调外部副作用使用预算与取消限制工作安全地处理错误与重试事件、Journal 与执行证据设计 Capability 安全执行从 Checkpoint 安全恢复
模型与服务商 · 7在避免重复输出的前提下路由模型选择并配置模型服务商使用服务商中立的模型协议基于 Provider Runtime 契约构建使用 OpenAI 控制面与 Realtime API测试与 Benchmark Provider Adapter配置 OpenAI、Anthropic、Gemini 与 Ollama
Agent · 7构建并配置 Agent为 Agent 添加类型化工具加入会话与语义记忆安全地委派给子 Agent返回结构化 Rust 值在不丢失语义的前提下流式输出使用检索为 Agent 提供事实依据
持久工作流 · 7组合确定性工作流让工作流持久化运行持久工作流 Worker协调 Timer、Signal 与持久等待运行多租户工作流基础设施运行并行 Branch 与安全 Race对持久 Workflow 进行版本管理
集成 · 7通过 MCP 连接外部能力选择存储与持久化边界通过 MCP Tasks 暴露持久工作构建并评估检索流水线使用 MCP Resources、Prompts 与 Sampling在不跨越权限的前提下缓存 MCP 响应在 Rust Web Service 中部署 Runifold
质量与运维 · 10在没有网络的情况下测试评估质量并阻止回归观测完整运行树在浏览器与边缘环境安全运行准确理解可靠性声明在 CI 中运行可复现评测使用 SLO 运维 Runifold治理 Task 保留与删除把审计证据归档到 S3-Compatible WORM 存储管理兼容性与可信发布
文档/集成
第一次使用?通过 45 分钟核心课程建立完整心智模型
集成

通过 MCP Tasks 暴露持久工作

把 Workflow Task 映射为 MCP 句柄,支持轮询、更新、取消、订阅、保留和租户安全授权。

实践指南·18 min

Task 协议

普通 MCP Tool Call 在一次请求内完成;MCP Task 表示比请求寿命更长的工作。Client 创建 Task 后得到不透明 taskId、当前状态、轮询建议、Retention 时间,以及最终结果或安全失败 细节。

Task 需要协商 Capability 与逐请求授权。不支持该扩展的 Server 继续使用普通 MCP 行为。

启用 Task 扩展

Workflow Adapter 是 runifold-mcp 的 Opt-in Feature:

Cargo.toml
[dependencies]
runifold = { version = "=0.9.0", features = ["mcp", "sqlite-bundled"] }
runifold-mcp = { version = "=0.9.0", features = ["workflow-tasks"] }

Client 在初始化时声明 Task 支持:

let config = McpClientConfig::new(Implementation::new("task-client", "1"))
    .with_tasks();
let client = McpClient::new(transport, config);
let initialized = client.initialize().await?;
println!("task capability: {:?}", initialized.capabilities.tasks);

如果 Peer 没有协商 Task,就使用普通 Request / Response 调用 Tool,或禁用长任务模式。 不能假设所有 Tool Call 都可以变成 Task。

工作流映射

启用 workflow-tasks Feature 后,WorkflowTaskAdapter 把一个 MCP Tool Route 绑定到 精确 Workflow Name、Version 与 Tenant。Queued、Leased、Timer 与 Signal Wait 映射为 working;持久 Interrupt 映射为 input_required;终止 Checkpoint 映射为 Completed、 Failed 或 Cancelled。

结果从不可变 Terminal History 重建。Route Identity 必须稳定,使 Task ID 在 Server 重启后仍能恢复相同契约。

客户端生命周期

Client 可以显式:

  • get_task 读取当前状态;
  • update_task 提交带 Key 输入;
  • cancel_task 协作取消;
  • wait_task 在同一个操作 Deadline 下等待;
  • listen_tasks 接收类型化 Snapshot。

Polling Interval 受 Client Policy、剩余 Deadline 与 Retention 共同约束。isError: true 的已完成 Tool Result 仍是 Completed Task;协议失败属于另一层。

调用 Tool 并处理两种 Outcome

use runifold::mcp::{CallToolOutcome, CallToolParams};
 
let outcome = client
    .call_tool_outcome(CallToolParams {
        name: "durable_report".into(),
        arguments: Some(serde_json::Map::from_iter([
            ("report_id".into(), serde_json::json!("rpt_42")),
        ])),
    })
    .await?;
 
let result = match outcome {
    CallToolOutcome::Complete(result) => result,
    CallToolOutcome::Task(task) => {
        println!("task={} status={:?}", task.task_id, task.status);
        client.wait_task(task).await?
    }
};
 
if result.is_error {
    eprintln!("Tool completed with an application error: {:?}", result.content);
} else {
    println!("structured={:?}", result.structured_content);
}

wait_task 按 Server 建议 Poll,同时遵守 Client Operation Deadline。如果 UI 或进程可能 断开,应把 Task ID 保存在应用状态中;重连后先 get_task,再调用 wait_task。持久 Store 才是真实来源,内存 Subscription 不是。

订阅

Task Subscription 立即发送持久 Snapshot,之后只发送变化状态,并在 Terminal Snapshot 后解除。重连读取当前 Store 状态,而不依赖进程内 Notification Replay。

限制每个 Subscription 的 Task ID 数与刷新频率。临时 Store 失败不能虚构状态跳转。每次 派生状态时都重新验证授权与租户隔离。

安全与保留

Task ID 是标识符,不是 Bearer Credential。每次 Lookup 都限定在 Adapter Tenant;跨租户 不匹配不应泄漏存在性。Task Input 与普通 MCP Elicitation 或 Sampling 具有相同信任等级。

协议 ttlMs 描述从创建开始的句柄可用性,不是 Workflow Deadline,也不会物理删除活跃 工作。Terminal Cleanup 属于另一个带栅栏控制面,并生成不可变 Tombstone。

把 Tool Route 绑定到 Workflow

使用 Worker 相同的持久 WorkflowStore 构造 WorkflowTaskAdapter,并注册稳定映射:

let mut tasks = WorkflowTaskAdapter::new(store.clone());
tasks.register_route(WorkflowTaskRoute::new(
    "durable_report",      // MCP Tool 名称
    "generate-report",     // Workflow 名称
    1,                     // 准确 Workflow 版本
    WorkflowTenantId::parse("tenant-acme")?,
)?)?;
 
let server = server.with_task_backend(Arc::new(tasks));

MCP Server 还必须注册并授权这个 Tool。独立 Workflow Worker 必须注册 generate-report 版本 1,并处理同一个 Store。MCP Transport 重启不会取消或删除 Task。

Task 故障排查

现象检查项
调用总是同步完成Task Capability、Route Registration 与 Tool Name 是否一致
DefinitionUnavailableWorker Registry 是否包含准确 Workflow 名称/版本
Task 一直 workingQueue Claim、Tenant Budget、Timer、Lease 与 Worker 健康
Task 为 input_required展示带 Key Request,并用 update_task 对每个 Key 只提交一次
重连后进度丢失是否使用同一 Durable Store 与已保存 Task ID
跨租户查询泄露存在性Adapter Route 与每次 Lookup 是否绑定认证 Tenant
Completed Result 带 is_error按应用完成处理,不要当成协议失败