Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions benchmarks/compose-bench/src/scenario.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ mod tests {

fn test_context() -> OwnedToolContext {
OwnedToolContext {
failure_observer: None,
session_id: SessionId::new("s"),
turn_id: TurnId::new("t"),
metadata: MetadataMap::new(),
Expand Down
30 changes: 30 additions & 0 deletions book/src/ch18-task-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,34 @@ Correlate the two events by `call_id`. Hosts that need a fully reconstructable t
└────────────────────────────────┘
```

## Typed failures and cancellation observations

Native failed outcomes emit `TaskEvent::Failed`, not `Completed`. Cancellation
emits `TaskEvent::Cancelled`; its snapshot retains the terminal classification
and any validated diagnostic metadata in `failure`. `ToolError::is_cancelled()`
recognizes both the legacy unit variant and typed diagnostic cancellation.

Each task also owns an isolated observation slot. Host producers can clone
`context.failure_observer()` and publish positive effects observations, a final
retry summary, or a host fatal receipt. The manager seals the slot before aborting
cancelled work. Already-published facts survive cleanup; missing facts remain
unknown. `failure_observations` on the task snapshot is deliberately separate from
the native child's diagnostic metadata: these may describe different scopes.

Foreground results, background loop updates, manual results, and detached
notifications retain these facts in reserved result metadata. Use
`agentkit_task_manager::tool_failure_info` and `task_failure_observations` to read
the typed projections. Request metadata cannot forge these host-owned fields;
successful results have failure-only fields removed. Retry observations never
make a child invocation safe to replay.

When interrupting a turn, the loop drains the manager's real frozen cancellation
results before synthesizing missing results. A custom manager that delegates
interruption must also delegate `take_interrupted_task_updates`.

The complete wire, Runlet catch/rethrow, and downstream compatibility contract is
in [Typed failure transport](https://github.com/danielkov/agentkit/blob/main/docs/typed-failure-transport.md).

## Choosing a routing strategy

| Scenario | Recommended routing | Why |
Expand All @@ -199,3 +227,5 @@ Correlate the two events by `call_id`. Hosts that need a fully reconstructable t
> **Example:** [`openrouter-parallel-agent`](https://github.com/danielkov/agentkit/tree/main/examples/openrouter-parallel-agent) uses `AsyncTaskManager` with `ForegroundThenDetachAfter` routing for shell tools and foreground routing for filesystem tools. The `TaskManagerHandle` event stream is printed to stderr.
>
> **Crate:** [`agentkit-task-manager`](https://github.com/danielkov/agentkit/tree/main/crates/agentkit-task-manager) — depends on [`agentkit-tools-core`](https://github.com/danielkov/agentkit/tree/main/crates/agentkit-tools-core), [`agentkit-core`](https://github.com/danielkov/agentkit/tree/main/crates/agentkit-core), and [tokio](https://tokio.rs).

Individual approval closure awaits `TaskManager::close_suspended_task` and delivers its frozen terminal result without a duplicate queue entry. `LoopDriver::cancel_pending_approval_for` is therefore async; callers must await it. Retained-task manager wrappers must delegate this method, `take_terminal_task_result`, and the scoped interruption drain. Approved continuation start failure consumes an already-selected terminal winner before synthesizing an error; terminal-result transfer never closes a suspended task. Queued updates preserve originating session/task identity, and unsurfaced background approval cancellation preserves its loop/manual delivery policy.
Loading
Loading