Skip to content

feat(tools): Jev-ranked tool_search over deferred tools and Composio actions - #6435

Merged
senamakel merged 32 commits into
tinyhumansai:mainfrom
senamakel:jev-tool-search
Sep 22, 2026
Merged

senamakel merged 32 commits into
tinyhumansai:mainfrom
senamakel:jev-tool-search

Conversation

@senamakel

@senamakel senamakel commented Sep 22, 2026

Copy link
Copy Markdown
Member

Summary

Jev-ranked, on-demand tool discovery for the orchestrator: the model keeps a core tool set on the wire, and everything else — rarely used lookups, and now every action of every connected Composio toolkit — is registered as ToolExposure::Deferred and reached through the harness's intrinsic tool_search bridge, ranked by TypeSafe's Jev (BM25 retrieves top-20, one Jev Choice decides) when the process has a TinyHumans credential and by BM25 otherwise. One clear action on a connected service ("ping Alex on Slack that I'm late") becomes a search and a direct call instead of a delegate_to_integrations_agent sub-run.

What changed

  • Retired the host tool_search (tools/impl/meta/tool_search.rs, util/bm25.rs). It shadowed the harness's bridge, and a tool it found could not be called: the turn allowlist registered only advertised names. tools/impl/meta/deferred.rs now only decides what is deferred.
  • Deferred tools are callable. The session host keeps deferred_tool_names beside visible_tool_names: the policy session classifies visible ∪ deferred as Allow (a deferred tool outside the union would be HideFromPrompt, which the direct-call gate refuses), the harness allowlist is the union, the prompt spec list stays the advertised set, and CanonicalSharedToolAdapter forwards exposure() / family() so the harness advertises only Direct and indexes the rest. Both turn loops (session host and runtime session) are wired; the runtime ToolSnapshot carries the deferred specs as the granted declaration set.
  • Belt opt-in. A wildcard belt always reaches deferred tools; a [tools] named belt opts in by listing tool_search (not a registered tool — the builder strips it and treats it as the flag). The orchestrator opts in; every other named belt is unchanged and still cannot reach a deferred tool.
  • Composio actions as deferred tools. collect_orchestrator_tools synthesises one ComposioActionTool::deferred(toolkit, …) per action of each connected toolkit beside delegate_to_integrations_agent; they follow the connected-integration reconcile and resolve the live config per call. Permission level, external_effect classification and the approval gate apply per call exactly as on the sub-agent path.
  • Ranker slot. agent::tinyagents::discovery: process-wide install_tool_ranker, agent.tool_search config (ranker: auto|bm25|jev|compare, top_k, default auto / 3), and the ToolDiscoveryPolicy every turn harness runs with. OverlapRanker wraps the existing rank_tools_by_prompt behind the same trait for comparison.
  • openhuman-tinyhumans jev feature (default, forwarded by the app and CLI): TinyHumansJevRanker resolves the credential and backend URL per search (sign-in/out is honoured, client cached by fingerprint), and install() installs it. No credential → Backend error → harness BM25 fallback, so auto costs nothing signed out.
  • Telemetry. ToolSearched is projected (live bridge + journal replay) as a synthetic tool_search start/complete pair carrying ranker, top_confidence, fallback, shadow_matched, latency_ms, so a Jev-vs-BM25 comparison can be read off traces; ToolsAdvertised / DeferredToolCall are logged.
  • Prompt. Orchestrator: "needs a capability you do not see listed → tool_search first"; the grounding rule now allows what a search returns.
  • Bench. cargo run -p openhuman-cli --bin tool-search-bench -- --ranker all ranks the real orchestrator registry + the recorded Composio catalogues (≈1,000 actions, 9 toolkits) against a labelled intents fixture and reports top-1 / top-3 / recall@20 / needless rate / latency / tokens / USD per ranker.

Still to do on this branch (why it is a draft)

  • tests/fixtures/tool_search/intents.jsonl (~150 labelled intents) and the bench run
  • Before/after baseline table (docs/plans/jev-tool-search-baseline.md): prompt/schema bytes per agent, advertised vs registered, bench accuracy, and model calls / prompt tokens / sub-agent spawns on 10 scripted live prompts — on main first, then here under jev, bm25 and compare
  • scripts/prompt-budget.limits ratchet (the deferred tail must pay for the bridge; target a net orchestrator decrease)
  • MCP tools, skills and sub-agents as Deferred families (Composio actions and the core Deferred tools are in)
  • x-sdk-name on the Jev request (needs a small tinyjevclient change; every other backend request carries it)
  • Docs: gitbooks/developing/architecture/agent-harness.md, platform/about_app/
  • Decide the auto default from the bench numbers (ships as Jev only if top-3 ≥ +10 pts over BM25 with the needless rate not worse)

Depends on tinyhumansai/tinytools#17 and tinyhumansai/tinyagents#185 — the vendor/tinyagents gitlink points at that branch.

Test plan

  • RUST_MIN_STACK=67108864 cargo test -p openhuman --lib: 10,456 passed; the 77 failures are the same 77 on untouched main (spawn/orchestration suites that need the mock backend) — diffed with comm, zero new
  • New tests: builder exposure (wildcard defers + keeps reachable, named belt opts in via tool_search, named belt without it reaches nothing), tools::implementations::meta::deferred, agent::tinyagents::discovery (policy from settings, overlap ranker), openhuman-tinyhumans::jev (no credential → backend error, fingerprint)
  • cargo clippy -p openhuman -p openhuman-cli -p openhuman-tinyhumans -- -D warnings clean (the --all-targets form fails on pre-existing test files untouched here)
  • cargo check for the core and crates/openhuman-app (feature forwarded)
  • Live: openhuman-core serve with a TinyHumans key and Slack connected → tool.tool_search span (ranker=jev) then the SLACK_SEND_MESSAGE action, no subagent.* span

Co-authored-by: Medulla medulla@tinyhumans.ai

Summary by CodeRabbit

  • New Features
    • Added on-demand tool discovery for capabilities not shown in the standard tool list.
    • Deferred integration actions can now be found and invoked by name when needed.
    • Tool search supports configurable result limits and ranking modes, including BM25 and Jev when credentials are available.
    • Added Jev-backed ranking with automatic fallback to BM25 when unavailable.
  • Observability
    • Tool searches and deferred tool calls now appear in progress and activity reporting.
  • Documentation
    • Updated tool and configuration documentation to describe deferred discovery.

Bump the vendored tinyagents dependency to commit ae48b2c, incorporating upstream fixes and improvements.

Auto-committed-on: macbook
The change consolidates the search logic by moving the BM25 implementation into a shared utility module, removing duplicated code from the skills and tools modules. This simplifies the codebase and ensures consistent search behavior across different components.

Auto-committed-on: macbook
Added a README for the search utility module to explain its purpose and usage, making it easier for developers to understand and maintain the codebase.

Auto-committed-on: macbook
This change adds a README file to the util module, documenting its purpose and usage. The file provides guidance for developers working with the utility functions in this crate.

Auto-committed-on: macbook
Added README files for the tools module and its implementation directory to explain their purpose and structure.

Auto-committed-on: macbook
The tool call state is now restored when a tool execution fails, ensuring that subsequent tool calls in the same turn are not incorrectly blocked. Previously, a failed tool call left the state marked as in-progress, which prevented any further tool calls from being processed.

Auto-committed-on: macbook
Removed unused imports from the tools module to clean up the codebase and avoid compiler warnings.

Auto-committed-on: macbook
The agent configuration schema previously declared several fields with incorrect types, causing validation failures when users provided valid values. This change updates the schema to match the actual data structures used by the agent runtime, ensuring that configuration files with the intended types are accepted without errors.

Auto-committed-on: macbook
Introduce the tinyagents module with harness assembly and discovery capabilities, along with corresponding configuration schema updates. This establishes the foundational structure for managing tiny agent workflows within the core system.

Auto-committed-on: macbook
The session host builder now applies the `tool_search` settings from its configuration during the build process, ensuring that every subsequent turn is treated as configured even when the turn harness is assembled without a config in hand.

Auto-committed-on: macbook
Add a new `jev` feature gate to openhuman-tinyhumans that enables a Jev-backed `tool_search` ranker, using TypeSafe's Jev through the TinyHumans System One proxy. The feature is on by default and forwarded by the app and CLI crates, while the core falls back to BM25 ranking when disabled.

Auto-committed-on: macbook
The redact_url_for_log function has moved from openhuman_core::api::config to openhuman_core::util::redact, so the ranker now calls the updated path to keep the log redaction working correctly.

Auto-committed-on: macbook
The ranker now accepts a config loader, defaulting to the core's read path, so tests can supply a fixed config instead of relying on process-global state. This makes the no-credential test deterministic by removing its dependency on environment setup.

Auto-committed-on: macbook
Add a `tool_ranker` option to `InstallOptions`, defaulting to true, that installs the Jev-backed ranker as the core's process-wide ranker when the `jev` feature is enabled. This replaces the default BM25 ranking for `tool_search` when permitted by the agent configuration, with the ranker resolving credentials per search so no login is required at install time.

Auto-committed-on: macbook
Replace the let-chain condition with a filter call on the cached option, simplifying the code while preserving the same behavior of returning the cached ranker only when the fingerprint matches.

Auto-committed-on: macbook
Add a test asserting that a wildcard belt withholds every `Deferred` registration from the wire while keeping it reachable: never advertised, always in the deferred set, and classified `Allow` by the policy. Also expose the deferred tool names set for test assertions.

Auto-committed-on: macbook
Added a test-only accessor to expose the tool policy session for verification in unit tests, enabling assertions on its state without altering production behavior.

Auto-committed-on: macbook
Use the fully qualified path for `ToolPolicySession` in the test-only accessor to avoid relying on a local import, making the type unambiguous and the code more robust to future import changes.

Auto-committed-on: macbook
…lder/builder_tests_tool_exposur

Auto-committed-on: macbook
The harness answers `tool_search` without running a tool, so no `ToolStarted`/`ToolCompleted` pair exists for it. Replay the same synthetic pair the live bridge emits, so a replayed trace has the `tool.tool_search` span with the ranking facts. Also emit the corresponding progress events and log lines in the live bridge, keeping the query text out of log lines as it is user content.

Auto-committed-on: macbook
The orchestrator agent's named tool allowlist now includes `tool_search`, enabling on-demand tool discovery for rarely needed lookups. This addition ensures the deferred tool set remains reachable through the harness's intrinsic search mechanism, which ranks results by Jev with a TinyHumans credential or BM25 otherwise, and supports calling tools by name or via `tool_call` after discovery.

Auto-committed-on: macbook
The orchestrator prompt now instructs the agent to call `tool_search` with the user's intent when a needed capability is not in the visible tool list, before delegating or declining. This reflects that the tool list is a core set, with many more registered tools discoverable via search, and clarifies that a single clear action on a connected service is a search-then-call rather than a delegation. The grounding section is updated to match, requiring a search attempt before claiming a capability does not exist.

Auto-committed-on: macbook
…mputation

The deferred tool name set now includes names from both durable and synthesized tools, ensuring per-action integration tools are kept off the wire and in the searchable set. A new `discovery_enabled` flag tracks whether the belt reaches deferred tools at all, and a shared recompute method keeps the deferred set consistent whenever either tool set changes.

Auto-committed-on: macbook
…licy

The runtime session snapshot now carries deferred tool names and a discovery flag, matching the session host's allowlist. This ensures the policy engine classifies deferred tools as reachable, so they remain callable through the tool_search bridge while not being advertised.

Auto-committed-on: macbook
Add a `deferred` constructor that registers Composio actions as searchable, off-wire tools for parent sessions, resolving live config per call instead of anchoring to spawn-time config. This lets one clear action be a search and a call rather than a sub-agent run.

Auto-committed-on: macbook
Register one deferred ComposioActionTool per connected integration action, sorted by toolkit and action name for stable ordering. This lets belts that opted into discovery reach actions through the harness's tool_search, avoiding an integrations_agent run, while non-opted belts never see them due to prompt-hiding and the direct-call gate. Gated actions are excluded, and slug collisions keep the first arrival.

Auto-committed-on: macbook
When a wildcard belt is used, the durable `Hidden` members of the registry (such as collapsed `memory_*` and `todo_*` tools) were not being deferred, causing them to remain visible. This change ensures that for a wildcard belt, these hidden tools are stripped from the visible set and added to the deferred set, while named belts continue to exclude them entirely. The logic now correctly handles both durable and synthesised deferred tools, preserving the intended visibility behaviour.

Auto-committed-on: macbook
…ndency

The new `tool-search-bench` binary compares the `tool_search` rankers (bm25, overlap, and jev) over the real orchestrator registry and recorded Composio catalogues. The `jev` ranker is now compiled in by default via the `jev` feature, which also enables the optional `tinytools-jev` dependency, so the benchmark can measure it without requiring a Jev client at build time.

Auto-committed-on: macbook
The Cargo.lock file has been updated to include the new `tinytools-jev` dependency, which is now required by the project. This change ensures that the lock file reflects the current dependency tree and maintains reproducibility of builds.

Auto-committed-on: macbook
The token-overlap ranker used by the Composio sub-agent has been moved from the benchmark binary into the core discovery module, where it is now publicly exposed and callable. It also gains an explicit empty-intent guard that returns an error, and a test covering both its ranking behavior and kind name.

Auto-committed-on: macbook
The `RankHit` type was no longer used in the benchmark code, so the import has been cleaned up to keep the codebase tidy.

Auto-committed-on: macbook
@coderabbitai

coderabbitai Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 498c311e-53b5-4e30-aabf-cb165119ec8d

📥 Commits

Reviewing files that changed from the base of the PR and between 6e45c61 and c3a8ed9.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (44)
  • crates/openhuman-app/Cargo.toml
  • crates/openhuman-cli/Cargo.toml
  • crates/openhuman-cli/src/bin/tool_search_bench.rs
  • crates/openhuman-core/src/agent/progress_tracing/journal_projection.rs
  • crates/openhuman-core/src/agent/registry/agents/orchestrator/agent.toml
  • crates/openhuman-core/src/agent/registry/agents/orchestrator/prompt.md
  • crates/openhuman-core/src/agent/session_host/builder/builder_build.rs
  • crates/openhuman-core/src/agent/session_host/builder/builder_tests_tool_exposure_tests.rs
  • crates/openhuman-core/src/agent/session_host/builder/factory.rs
  • crates/openhuman-core/src/agent/session_host/runtime/accessors.rs
  • crates/openhuman-core/src/agent/session_host/runtime_session.rs
  • crates/openhuman-core/src/agent/session_host/turn/tools.rs
  • crates/openhuman-core/src/agent/session_host/types.rs
  • crates/openhuman-core/src/agent/tinyagents/discovery.rs
  • crates/openhuman-core/src/agent/tinyagents/discovery_tests.rs
  • crates/openhuman-core/src/agent/tinyagents/harness_assembly.rs
  • crates/openhuman-core/src/agent/tinyagents/mod.rs
  • crates/openhuman-core/src/agent/tinyagents/observability/event_projection.rs
  • crates/openhuman-core/src/agent/tinyagents/tools.rs
  • crates/openhuman-core/src/config/schema/agent.rs
  • crates/openhuman-core/src/config/schema/mod.rs
  • crates/openhuman-core/src/integrations/composio/action_tool.rs
  • crates/openhuman-core/src/skills/search.rs
  • crates/openhuman-core/src/tools/README.md
  • crates/openhuman-core/src/tools/impl/README.md
  • crates/openhuman-core/src/tools/impl/meta/deferred.rs
  • crates/openhuman-core/src/tools/impl/meta/deferred_tests.rs
  • crates/openhuman-core/src/tools/impl/meta/mod.rs
  • crates/openhuman-core/src/tools/impl/meta/tool_search.rs
  • crates/openhuman-core/src/tools/impl/meta/tool_search_tests.rs
  • crates/openhuman-core/src/tools/ops.rs
  • crates/openhuman-core/src/tools/ops_tests_default_registry_tests.rs
  • crates/openhuman-core/src/tools/orchestrator_tools.rs
  • crates/openhuman-core/src/util/README.md
  • crates/openhuman-core/src/util/bm25.rs
  • crates/openhuman-core/src/util/bm25_tests.rs
  • crates/openhuman-core/src/util/mod.rs
  • crates/openhuman-tinyhumans/Cargo.toml
  • crates/openhuman-tinyhumans/src/install.rs
  • crates/openhuman-tinyhumans/src/jev/mod.rs
  • crates/openhuman-tinyhumans/src/jev/ranker.rs
  • crates/openhuman-tinyhumans/src/jev/ranker_tests.rs
  • crates/openhuman-tinyhumans/src/lib.rs
  • vendor/tinyagents
 ____________________________________________________________
< In God we trust. All others must go through a code review. >
 ------------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).

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

@senamakel
senamakel marked this pull request as ready for review September 22, 2026 02:46
@senamakel
senamakel requested a review from a team September 22, 2026 02:46
@tinysweeper

tinysweeper Bot commented Sep 22, 2026

Copy link
Copy Markdown

Tiny Sweeper review

⚠️ Review failed for 61572b4f9a94. the review of #6435 did not finish within 900s

# Conflicts:
#	crates/openhuman-cli/Cargo.toml
#	crates/openhuman-core/src/agent/tinyagents/harness_assembly.rs
#	vendor/tinyagents
@senamakel
senamakel merged commit 9949e11 into tinyhumansai:main Sep 22, 2026
14 of 17 checks passed
senamakel added a commit to senamakel/openhuman that referenced this pull request Sep 22, 2026
Keeps the hermetic orchestrator prompt and adds the tool_search branch from
tinyhumansai#6435; prompt_cache segments use the harness per-tier ids (system, system.1,
tools) so the sticky prompt_cache_key from tinyhumansai#6434 stays constant across tiers.
vendor/tinyagents -> main (4aeae2b5), nested tinytools -> main (aa811fe).

Co-authored-by: Medulla <medulla@tinyhumans.ai>
senamakel added a commit to senamakel/openhuman that referenced this pull request Sep 22, 2026
vendor/tinyagents is pinned at 0bc4ec44 (tinyagents main tip, PR tinyhumansai#190
merged), while the merge-base pin (eefef72b) was an ad hoc merge commit
made while resolving PR tinyhumansai#6435 locally and was never pushed to
tinyagents main. It sits on a sibling branch, so the monotonicity gate
sees the two as diverged ("sideways") rather than a clean fast-forward.

Diffing eefef72b against 0bc4ec44 confirms no work is lost: content
unique to eefef72b (ToolRanker/BM25 discovery, the claude_code input
builder, dialect docs) is present in 0bc4ec44 too, just reshaped by
later commits on tinyagents main (net +1617/-151 lines across the
submodule, almost entirely superseding rewrites of the same files).
0bc4ec44 is the correct pin to build against; keep it.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
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