Skip to content

refactor(orchestration): consolidate steering and retire task tools - #499

Draft
senamakel wants to merge 181 commits into
tinyhumansai:mainfrom
senamakel:epic-8088-59-steering
Draft

senamakel wants to merge 181 commits into
tinyhumansai:mainfrom
senamakel:epic-8088-59-steering

Conversation

@senamakel

Copy link
Copy Markdown
Member

Consolidate detached child steering under tinyagents_orchestration::steering and expose SteerFallback for host queues. A retained finished child now uses that fallback instead of returning AlreadyDone; live children still receive steering through their registered handle. Ownership, supported lanes, request-ID limits and deduplication continue to apply.

Remove the retired task-tool and restart-recovery APIs and their graph exports. Keep SteeringRegistry in tinyagents-tasks, where DetachedTaskRegistry depends on it. Preserve independent middleware, task-store and completion-router tests.

Refs senamakel#59. Part of tinyhumansai/openhuman#8088.

Draft dependency: canonical PRs #496 and #497 must land first. After they merge, merge canonical main into this branch, verify the resulting diff and gates, and mark this PR ready.

Validation:

  • At the final head 4acd1a578ede5bfde0e22b7866a3f96d4e4b8773, the full workspace all-target check, task-crate all-target Clippy, 115 task tests, and cargo machete crates pass.
  • Before the manifest-only cleanup, full workspace Clippy and tests passed: 5,607 passed, zero failed, 35 ignored, including doctests. Formatting and all-feature rustdoc broken-link checks passed too. The cleanup removes exactly three unused dependency edges and their lockfile entries; source and tests are unchanged.
  • The offline composed test calls public steering and verifies the instruction reaches the child harness model request. All five steering end-to-end tests pass.
  • The terminal-fallback regression failed against the original implementation (AlreadyDone instead of fallback).
  • Current-head CI reruns the full workspace and feature matrix before fork integration.

The wiki is a separate repository. Its reviewed patch is included below for publication after the source change lands; this PR leaves the existing wiki gitlink unchanged.

Wiki follow-up patch
diff --git a/Examples.md b/Examples.md
index 48b9a80..952971c 100644
--- a/Examples.md
+++ b/Examples.md
@@ -377,25 +377,6 @@ let values: Vec<u64> = out.into_successes();
 A total timeout yields `TinyAgentsError::Timeout`; a cancelled token yields
 `TinyAgentsError::Cancelled`.
 
-### List orchestration tasks by kind and creation window
-
-The `orchestrate_list` tool filters spawned tasks by `kind` and a
-creation-time window. *(See `crates/tinyagents-graph/src/orchestration/test.rs`.)*
-
-```rust
-use serde_json::json;
-use tinyagents_graph::{OrchestrationTool, OrchestrationToolKind};
-use tinyagents_harness::tool::Tool;
-use tinyinference::tool::ToolCall;
-
-let list = OrchestrationTool::new(OrchestrationToolKind::List, store);
-let result = list
-    .call(&(), ToolCall::new("l1", "orchestrate_list",
-        json!({ "kind": "sub_agent", "created_after_ms": 0 })))
-    .await?;
-// result.raw is a JSON array of matching task snapshots.
-```
-
 ### Registry introspection
 
 Snapshot the registry (components plus aliases) for audit or UI display, and
diff --git a/Graph-Runtime.md b/Graph-Runtime.md
index d9dd3f5..1d22ae4 100644
--- a/Graph-Runtime.md
+++ b/Graph-Runtime.md
@@ -374,29 +374,21 @@ checkpoint metadata so a UI can render nested runs. The run-id counterpart read
 `ChildRun`s are reported through a `ChildRunSink` and accumulated onto the
 execution.
 
-## Orchestration tools (`tinyagents_graph::orchestration`)
-
-The orchestration module exposes child-work supervision as ordinary harness
-`Tool` implementations a model can call. An `OrchestrationTool` over a `TaskStore`
-(the `InMemoryTaskStore` ships by default) records and controls managed tasks.
-Each task is an `OrchestrationTaskKind` — `Graph`, `SubAgent`, `Tool`, or a
-policy-gated `ExternalProcess` placeholder — moving through an
-`OrchestrationTaskStatus` lifecycle (`Pending`, `Running`, `Awaiting`,
-`Completed`, `Failed`, `CancelRequested`, `Cancelled`, `TimedOut`, `Abandoned`).
-
-`OrchestrationToolKind` enumerates the ten built-in tools, each with a stable
-model-visible name: `orchestrate_spawn`, `orchestrate_await`,
-`orchestrate_cancel`, `orchestrate_kill`, `orchestrate_status`,
-`orchestrate_list`, `orchestrate_timeout`, `orchestrate_race`,
-`orchestrate_yield` (a durable interrupt), and `orchestrate_steer`. Build a
-`OrchestrationTaskSpec`/`OrchestrationTaskRecord` model and register the whole
-set onto a registry with `register_orchestration_tools` (or build them with
-`orchestration_tools` / inspect schemas via `orchestration_tool_schema(s)`).
-`orchestrate_list` filters through `OrchestrationTaskFilter`: the run-tree
-fields (`parent_run_id`, `root_run_id`, `thread_id`, `node_id`, `status`), a
-`kind` label (`"graph"`, `"sub_agent"`, `"tool"`, `"external_process"`), and an
-inclusive `created_after_ms` / `created_before_ms` window in Unix-epoch
-milliseconds (builders: `with_kind`, `created_between`).
+## Detached subagent steering (`tinyagents_orchestration::steering`)
+
+Host code steers a detached child through `steer_detached` or its
+request-id-idempotent variant, `steer_detached_with_request_id`. These
+functions validate the task owner and lane, then deliver through the child's
+live `SteeringHandle` when available. A retained terminal task or a live task
+without a handle is sent through the host-provided `SteerFallback` seam, which
+lets the host enqueue its own metadata, lane, and message. Unknown or pruned
+tasks remain errors. `cancel_for_thread` cancels registered children owned by a
+parent thread.
+
+`SteeringRegistry` remains in `tinyagents_tasks`; `DetachedTaskRegistry` shares
+it with the executor and removes the live handle when a detached task is
+released. The orchestration steering functions depend on that task contract
+without introducing a tasks-to-orchestration dependency.
 
 ## Per-thread goals and todos (`tinyagents_graph::goals`, `tinyagents_graph::todos`)
 

The expected schema list still contained ledger.entries and its head, index and label tables, which no longer exist. Removing them keeps the assertion aligned with the current schema.

Auto-committed-on: dragonfly
The opt-in entry tree API and its RunLedgerStore entry_* methods have been
dropped, leaving the linear transcript paths as the only conversation shape.
This removes the second, parallel ledger abstraction so the session crate
exposes a single history model.

Auto-committed-on: dragonfly
The entry tree collections and their driver implementations are no longer
needed, so the storage specs, migration steps, and RunLedgerStore methods
that backed them have been dropped. This trims the ledger surface to the
remaining event and tool-effect storage.

Auto-committed-on: dragonfly
The entry tree migration test was dropped along with its now-unused
Entry import, since the migration path it covered is no longer part of
the driver schema.

Auto-committed-on: dragonfly
The historical migration step for the conversation entry tree is now an
empty placeholder and the corresponding row readers were removed, since
the entry tree tables are no longer part of the classic schema. The
classic source check no longer treats entry_tree_entries as a known table.

Auto-committed-on: dragonfly
The legacy import tests no longer seed or verify the entry tree, so the
fixture and the assertions covering entry ids, ordinals and labels were
removed to match the current import surface.

Auto-committed-on: dragonfly
The legacy importer no longer reads or writes the entry-tree collections,
so the entries count and the loaded trees map are gone from the report
and the schema table no longer lists those tables.

Auto-committed-on: dragonfly
Add a regression test asserting that importing a classic database which
still contains retired entry-tree tables leaves those tables and their
rows untouched. The now-obsolete documentation describing the native
entry trees and their schema mapping was removed to match.

Auto-committed-on: dragonfly
Update crate and module documentation to drop mentions of the
conversation entry tree, which is no longer part of the storage ports.
The run ledger test no longer exercises entry tree import and index
rebuild, so its name and body were trimmed to match.

Auto-committed-on: dragonfly
Reworded the CompactionRecord and CompactionSink documentation to describe
persistence in terms of a host-provided store rather than the session crate's
EntryTree, since the harness cannot depend on tinyagents-session. The comments
now describe the coordinate system exposed to a host sink instead of naming a
specific session-backed implementation.

Auto-committed-on: dragonfly
The compaction and summarization docs no longer describe the session-backed
`SessionCompactionSink` implementation. The harness treats `CompactionSink` as a
generic trait with no prescribed persistence backend, so the docs now reflect
that a host may attach any implementation.

Auto-committed-on: dragonfly
…ion_sink.rs,crates/tinyagents-s

Auto-committed-on: dragonfly
Tool modules for goals, todos, skills, thread locks, time, plan exit, and
ask clarification now live in the dedicated tinyagents-harness-tools crate
instead of being split across tinyagents-harness and tinyagents-graph. This
consolidates tool code in one place so the harness and graph crates no longer
need to own it.

Auto-committed-on: dragonfly
The README listed entry trees among the data covered by the ledger API and
among the things retention does not prune. Entry trees are no longer part of
that scope, so both mentions were dropped to keep the documentation accurate.

Auto-committed-on: dragonfly
The native entry-tree slice documentation and its Mongo integration proof
are dropped, and the feature-gap entry for the conversation entry tree is
marked removed. The run context doc comment now describes persistence as a
host-provided trait object without naming the removed type.

Auto-committed-on: dragonfly
Phase 5 no longer lists EntryTree among the shipped pieces, leaving
compaction, the prepare_for_model handoff transform, the tool-effect
ledger, and Message::Custom as the completed work.

Auto-committed-on: dragonfly
…d types

The crate referenced its own module paths for types that actually live in
tinyagents_harness, so the imports now point at the real crate. The crate is
also added to the workspace default members and a time_parse test module is
registered.

Auto-committed-on: dragonfly
Reword the comparison notes so the linear TinyAgents transcript is
distinguished from pi's conversation entry tree, and attribute the two
coexisting pi session designs to pi rather than to TinyAgents. Also
generalize the compaction sink doc comment to describe a host-provided
store rather than a session entry tree.

Auto-committed-on: dragonfly
The lock map and its constructor and accessor are now public so
downstream crates can share per-thread locks. Documentation comments
were also updated to drop stale references to the removed goal
continuation module.

Auto-committed-on: dragonfly
Test modules now reference types through the tinyagents_harness crate
rather than the local crate root, and the ask_clarification and plan_exit
test modules are no longer registered. This aligns the tests with the
relocated tool and context types.

Auto-committed-on: dragonfly
The per-thread lock helper is now a dedicated execution_locks module
with a RunLockMap type, replacing the previous ThreadLockMap and its
constructor argument. The goals and todos modules and their re-exports
were dropped from the crate root.

Auto-committed-on: dragonfly
…uation.rs,crates/tinyagents-har

Auto-committed-on: dragonfly
Drops the `continuation_suppressed` field and the `GoalProgress` and
`TurnOutcome` re-exports, since goal continuation is now driven by the
host's turn lifecycle rather than an out-of-band heartbeat.

Auto-committed-on: dragonfly
The continuation_suppressed field and its compare-and-set helper are no longer needed, so the field and the set_continuation_suppressed_if function have been removed along with the test covering their behaviour.

Auto-committed-on: dragonfly
Dropped the unused Message and json imports from the run ledger driver
modules to keep the build warning-free.

Auto-committed-on: dragonfly
Introduce a per-call module that records tool invocations so each call
can be tracked and inspected independently. Tests cover the new
tracking behaviour.

Auto-committed-on: dragonfly
… docs

Corrected the module documentation so the parenthetical listing the contents of the SQLite database closes properly and the transcript and snapshot paths read as separate items rather than being nested inside it.

Auto-committed-on: dragonfly
Introduce a goal runtime and observer layer that prepares turns and
charges token and elapsed-time usage under a per-thread lock, so
concurrent turns cannot lose usage or report the same budget transition
twice. Elapsed time now tracks sub-second precision while keeping the
legacy whole-second field intact.

Auto-committed-on: dragonfly
The module documentation referenced `super::discover`, which no longer resolves since the discover module lives in tinyagents_harness. Point the link at the fully qualified path so the doc comment stays accurate.

Auto-committed-on: dragonfly
Removed the anyhow dependency from tinyagents-graph and the uuid
dependency from tinyagents-harness-tools, as neither crate references
them anymore.

Auto-committed-on: dragonfly
Update the detached subagent steering tests to expect the fallback route
and a single fallback call when the task has already failed, and assert
that steering through the live handle injects the user's additional
context into the subagent.

Auto-committed-on: dragonfly
Adds an assertion that the counting callback is never invoked when steering a
detached subagent on an unsupported lane. This guards against the rejection
path silently dispatching work before returning the error.

Auto-committed-on: dragonfly
… module

The steering logic for detached subagents now lives in a dedicated
steering module rather than under the detached subagent tree. The
behaviour is unchanged; the move gives the lane rules and idempotency
handling a clearer home as more control surfaces adopt them.

Auto-committed-on: dragonfly
Moves the detached subagent steering API out of the subagent module and into its own top-level steering module so it can be reused independently. Introduces a SteerFallback trait to describe the host-provided delivery path, and steering now falls back to the host when the child is finished or has no live handle instead of rejecting the steer outright.

Auto-committed-on: dragonfly
SteeringRegistry now lives in a dedicated steering_registry module and is
re-exported from the crate root. The graph crate's re-exports were trimmed to
match, dropping the orchestration tool helpers it no longer needs to surface.

Auto-committed-on: dragonfly
The crate no longer exposes the orchestration control tools or the
restart-recovery helpers, leaving it as the graph-independent task model,
store implementations and detached task registry. The documentation was
trimmed to match the reduced surface.

Auto-committed-on: dragonfly
…ntrol_and_steer.rs,crates/tinya

Auto-committed-on: dragonfly
The router no longer builds restart recovery notes, dropping the
restart_recovery_note method and its supporting tests. The recovery note
logic now lives elsewhere, so the router keeps only its completion
bookkeeping responsibilities.

Auto-committed-on: dragonfly
Introduces a small helper that builds a graph-kind OrchestrationTaskSpec so tests can construct graph tasks without repeating the boilerplate. Also trims the module doc comment to match the tests it actually describes.

Auto-committed-on: dragonfly
This change refactors the public API exports in `subagent` and `tinyagents-tasks` to better reflect the current structure and responsibilities of the modules. It also updates documentation across several crates to clarify the role of the task store and steering mechanisms.

Auto-committed-on: dragonfly
…back

Documentation now states that lane and ownership validation runs before the request id is consumed, and that a terminal task with retained metadata is delivered through the host fallback. The test name and store doc comments were updated to match the current behaviour.

Auto-committed-on: dragonfly
The steering path previously filtered out registry lookup failures and fell
through to the fallback queue, silently swallowing real errors. The lookup
result is now matched explicitly so that "no handle" and "already done" fall
back as before while any other registry error is propagated to the caller.

Auto-committed-on: dragonfly
The steering fallback bound now requires a callable returning a future
instead of only the SteerFallback trait, so callers can pass async
closures directly. The trait bound is kept alongside the new Future
associated type to preserve existing behaviour.

Auto-committed-on: dragonfly
The two steer_detached functions now take a single F: SteerFallback<M>
bound instead of a separate FnOnce plus Future parameter, letting the
trait own its future type. Tests were updated to use a named
RecordingFallback struct and explicit closure parameter types.

Auto-committed-on: dragonfly
Adds an end-to-end test exercising the control and steer paths so the
interrupt and redirection behaviour is verified against a running agent.

Auto-committed-on: dragonfly
The end-to-end suite now only covers middleware lifecycle controls and a
preloaded steering cancellation delivered to a real run. The steering
registry bridge and orchestrate_list filtering tests were dropped along
with their helpers and now-unused imports.

Auto-committed-on: dragonfly
Adds a README section describing the steering module's detached steering
entry points and how they fall back to the host's SteerFallback when no
live child handle is available. Also notes where SteeringRegistry lives
and that cancel_for_thread cancels registered children by parent thread.

Auto-committed-on: dragonfly
Reformatted several expressions and import lists to satisfy rustfmt,
including the steering registry accessors and the subagent re-exports.
Also removed stray blank lines and reordered module declarations and
re-exports for consistency. No behaviour changes.

Auto-committed-on: dragonfly
Move the `use super::*;` import to the top of the file so it precedes the
external crate imports. This is a purely cosmetic reordering with no
behavioural change.

Auto-committed-on: dragonfly
Adds an end-to-end test that registers a running detached subagent and verifies steer_detached routes through the registry rather than the fallback path. The child harness is then invoked with the resolved steering handle to confirm the delivered instruction appears in the next model request.

Auto-committed-on: dragonfly
Reformatted the detached child harness test to satisfy rustfmt,
collapsing the RunContext construction onto one line and rewrapping the
assertion on the delivered instruction. No behaviour changed.

Auto-committed-on: dragonfly
Removed anyhow, async-trait and tinytools from the crate's dependency
list since nothing in it references them anymore.

Auto-committed-on: dragonfly
@coderabbitai

coderabbitai Bot commented Oct 18, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant