Skip to content

fix(agent): reuse cached Composio toolkit actions#4358

Open
YOMXXX wants to merge 13 commits into
tinyhumansai:mainfrom
YOMXXX:fix/GH-4317-composio-cached-actions
Open

fix(agent): reuse cached Composio toolkit actions#4358
YOMXXX wants to merge 13 commits into
tinyhumansai:mainfrom
YOMXXX:fix/GH-4317-composio-cached-actions

Conversation

@YOMXXX

@YOMXXX YOMXXX commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Reuses the parent ConnectedIntegration.tools catalogue for integrations_agent toolkit delegation when action schemas are already cached.
  • Falls back to backend list_tools only when the cached toolkit catalogue is empty.
  • Adds a fake-Composio-backend regression test proving delegation no longer issues an extra /tools request.
  • Re-applies current user scopes to cached catalogues and keeps an execute-time scope gate in action_tool.rs, so stale cached actions cannot run after a scope is narrowed.

Problem

Solution

  • Treat non-empty cached_integration.tools as the primary action source for toolkit overrides.
  • Preserve the existing backend refresh fallback for empty cached catalogues and keep direct/no-client behavior unchanged.
  • Cover the behavior with a regression test that warms the integration cache, runs integrations_agent, and asserts the fake backend /tools call count does not increase.

Submission Checklist

If a section does not apply to this change, mark the item as N/A with a one-line reason. Do not delete items.

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy
  • Diff coverage gate acknowledged — full merged lcov/diff-cover was not run locally; CI enforces the changed-line threshold. Targeted Rust regression covers the changed branch.
  • N/A: Coverage matrix unchanged; this is a behavior/performance fix for existing agent delegation behavior.
  • N/A: No coverage matrix feature IDs changed.
  • No new external network dependencies introduced (mock backend used per Testing Strategy)
  • N/A: Manual smoke checklist unchanged; this does not touch release-cut surfaces.
  • N/A: This fixes only Meet response-latency audit — 9 findings across simple queries and integration queries #4317 Finding 6, so the audit issue should remain open for the other findings.

Impact

  • Runtime impact is limited to Rust core agent harness delegation.
  • Expected effect is lower integration delegation latency and less backend load when parent context already loaded toolkit actions.
  • Cached catalogue freshness follows the existing connected-integrations cache lifecycle: explicit invalidation on scope updates and connection sync events, plus the in-process cache TTL. Newly added backend actions may wait for that refresh window; execution remains guarded by the current persisted scope at action time.
  • No migration, security, CLI, desktop shell, or frontend compatibility impact.

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Keep this section for AI-authored PRs. For human-only PRs, mark each field N/A.

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: fix/GH-4317-composio-cached-actions
  • Commit SHA: 388795706869c18872bb60fc2f2a736265ac59d7

Validation Run

  • N/A: pnpm --filter openhuman-app format:check (no frontend changes)
  • N/A: pnpm typecheck (no TypeScript changes)
  • Focused tests: GGML_NATIVE=OFF cargo test --manifest-path Cargo.toml --lib integrations_agent_reuses_cached_toolkit_actions_without_refetching_list_tools -- --nocapture
  • Focused tests: GGML_NATIVE=OFF cargo test --manifest-path Cargo.toml --lib agent::harness::subagent_runner::ops::tests::
  • Rust fmt/check: cargo fmt --manifest-path Cargo.toml --check
  • Rust fmt/check: git diff --check
  • Rust fmt/check: GGML_NATIVE=OFF cargo check --manifest-path Cargo.toml
  • N/A: Tauri fmt/check (no Tauri changes)

Validation Blocked

  • command: N/A
  • error: N/A
  • impact: N/A

Behavior Changes

  • Intended behavior change: integrations_agent now reuses cached Composio action schemas when available instead of refetching list_tools on every delegation.
  • User-visible effect: integration delegation should spend less time waiting on repeated action catalogue fetches.

Parity Contract

  • Legacy behavior preserved: empty cache still falls back to backend list_tools; direct mode and unavailable-client fallbacks continue to use the cached catalogue.
  • Guard/fallback/dispatch parity checks: fake backend regression verifies cached delegation does not issue an additional /tools request.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): N/A
  • Canonical PR: This PR
  • Resolution (closed/superseded/updated): N/A

Summary by CodeRabbit

  • Bug Fixes
    • Improved integrations toolkit caching: cached toolkit actions are re-filtered to the current user scope without redundant backend refetches.
    • Preserved correct refresh/fallback behavior when cached data is incomplete or when the backend is unavailable.
    • Added earlier enforcement of user scope preferences, preventing blocked actions from executing.
    • Connected-integrations cache is now refreshed after scope preference updates.
  • New Features
    • Unified user-facing messaging for why an action is blocked or unavailable (including curated-whitelist guidance).
  • Tests
    • Added end-to-end and behavior tests covering cache refiltering and early scope-blocking.

@YOMXXX
YOMXXX requested a review from a team June 30, 2026 17:08
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Changes

Scope-Aware Action Execution

Layer / File(s) Summary
Block disallowed actions early
src/openhuman/composio/tools.rs, src/openhuman/composio/action_tool.rs
Scope and whitelist violations now produce centralized messages, and blocked actions return errors before dispatch. Tests cover blocked write actions.
Invalidate cache after scope changes
src/openhuman/composio/schemas.rs
Saving toolkit scope preferences now invalidates the connected-integrations cache.
Align test and CI safeguards
src/openhuman/composio/mod.rs, src/openhuman/composio/ops_tests.rs, .github/workflows/*
Tests serialize shared environment and cache access, CI acknowledges the gated test file, and link checking excludes shields.io URLs.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested labels: agent, bug

Suggested reviewers: oxoxdev

Poem

A rabbit checks each tool with care,
Blocks forbidden calls mid-air.
Fresh scopes clear the cached trail,
Tests guard env vars without fail.
Hop, hop—safer actions bloom!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: reusing cached Composio toolkit actions in the agent.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 30, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3887957068

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/openhuman/agent/harness/subagent_runner/ops/runner.rs Outdated
@coderabbitai coderabbitai Bot added agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. bug rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. labels Jun 30, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 30, 2026
@coderabbitai coderabbitai Bot removed the rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. label Jun 30, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/openhuman/agent/harness/test_support_tests.rs (1)

30-53: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

WorkspaceEnvGuard is duplicated here and in subagent_runner/ops_tests.rs with divergent unsafe usage.

This copy wraps set_var/remove_var in unsafe, while the copy in src/openhuman/agent/harness/subagent_runner/ops_tests.rs (Lines 211-225) does not. Only one can be correct for the crate edition: under edition 2024 these calls are unsafe (the other copy won't compile), and under 2021 this unsafe block is unused_unsafe. Consider extracting a single shared guard into test_support to keep them in sync. See the companion comment on the other file for the compile-risk detail.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/agent/harness/test_support_tests.rs` around lines 30 - 53,
`WorkspaceEnvGuard` is duplicated with inconsistent
`std::env::set_var`/`remove_var` handling, so unify the implementation to avoid
edition-dependent compile issues. Move the guard into a single shared
test-support location and have both `test_support_tests` and
`subagent_runner::ops_tests` use that shared `WorkspaceEnvGuard` instead of
maintaining separate copies; ensure the chosen implementation matches the crate
edition’s safety requirements and removes the divergent `unsafe` usage.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/openhuman/agent/harness/test_support_tests.rs`:
- Around line 30-53: `WorkspaceEnvGuard` is duplicated with inconsistent
`std::env::set_var`/`remove_var` handling, so unify the implementation to avoid
edition-dependent compile issues. Move the guard into a single shared
test-support location and have both `test_support_tests` and
`subagent_runner::ops_tests` use that shared `WorkspaceEnvGuard` instead of
maintaining separate copies; ensure the chosen implementation matches the crate
edition’s safety requirements and removes the divergent `unsafe` usage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5f02a027-3542-4329-b300-9afe4cf0ddee

📥 Commits

Reviewing files that changed from the base of the PR and between 92ea283 and df41f74.

📒 Files selected for processing (5)
  • src/openhuman/agent/harness/subagent_runner/ops_tests.rs
  • src/openhuman/agent/harness/test_support_tests.rs
  • src/openhuman/composio/action_tool.rs
  • src/openhuman/composio/mod.rs
  • src/openhuman/composio/ops_tests.rs
✅ Files skipped from review due to trivial changes (1)
  • src/openhuman/composio/mod.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/openhuman/composio/action_tool.rs

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 30, 2026
…4317-composio-cached-actions

# Conflicts:
#	src/openhuman/agent/harness/test_support_tests.rs
@coderabbitai coderabbitai Bot removed agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. bug labels Jul 2, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 2, 2026
@YellowSnnowmann

Copy link
Copy Markdown
Contributor

Review — not an approval

The core change is sound: reuse a non-empty cached_integration.tools for backend-mode toolkit delegation and only fall back to list_tools when the cached catalogue is empty; direct / no-client paths are unchanged. That directly kills the redundant /tools round-trip from #4317 Finding 6, and the fake-backend test asserting the /tools call count doesn't increase is exactly the right guard.

I especially like that filter_cached_toolkit_actions_with_current_scope re-applies the current user scope to the cached catalogue — that closes the correctness hole the cache-reuse opens (a cached write action surviving after the user disabled write), and the second test (GMAIL_SEND_EMAIL hidden after write is disabled, GMAIL_FETCH_EMAILS still visible) proves it without re-fetching. Good.

Two things to address before this is ready:

  1. Catalogue staleness — please confirm the refresh path. Reusing the cached snapshot means a newly added backend action for an already-connected toolkit won't surface until the connected-integrations cache is invalidated. The old code refetched every delegation and picked it up immediately. You added invalidation on set_user_scopes, but what else refreshes it (TTL? connect/disconnect? explicit invalidate_connected_integrations_cache)? A one-line note in the PR on the acceptable staleness window would settle it.

  2. Scope creep in the description. The per-action execute-time gate in action_tool.rs (action_execution_block_message) is a new execution-time security check, not "reuse cached actions." It's justified here — it's the belt-and-suspenders that stops a stale cached action from actually executing outside the current scope — but it deserves an explicit line in the summary (and its own test is there, good), so a reviewer isn't surprised that a perf PR adds an execution gate.

Minor: filter_...with_current_scope does a load_user_scope_or_default(toolkit).await memory read per delegation — cheap relative to the HTTP call it replaces, just flagging it's not free. CI is green.

@M3gA-Mind

Copy link
Copy Markdown
Collaborator

Maintainer review changes: merged current upstream/main into the PR branch to resolve a merge conflict.

  • src/openhuman/agent/harness/subagent_runner/ops/runner.rs — an add/add conflict at the block between tier_gate_decision and run_subagent. This PR added filter_cached_toolkit_actions_with_current_scope there, while upstream/main added the deterministic memory fast-path helpers (AGENT_MEMORY_ID, memory_fast_path_enabled/parse_memory_fast_path_enabled, format_deterministic_memory_hits, apply_max_result_chars, try_deterministic_memory_retrieval, [memory][perf] retrieve_memory takes ~30–40s per call even with data — dominates agent-turn latency #4677). These are independent additions to the same region, so I kept both — closed this PR's new fn with its own } and preserved the full memory fast-path block after it. Both sides remain referenced (the cached-catalogue call site at the integrations toolkit override, and the AGENT_MEMORY_ID short-circuit / test imports respectively).

No behavioral changes to the PR's own logic. Letting PR CI verify.

@YOMXXX

YOMXXX commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Updated the PR description to cover both review items.

  • Catalogue freshness now explicitly points at the existing connected-integrations cache lifecycle: explicit invalidation on scope updates / connection sync events, plus the in-process TTL. Newly added backend actions can wait for that refresh window instead of being refetched on every delegation.
  • The summary now calls out the execute-time action_tool.rs scope gate as a deliberate safety check, not just part of the cache reuse optimization. That gate is what prevents a stale cached action from executing after the persisted scope has been narrowed.

@coderabbitai coderabbitai Bot added agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. bug labels Jul 19, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/ci-lite.yml (1)

902-914: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Prevent code injection via template expansion.

GitHub context variables and step outputs that contain branch names are interpolated directly into bash scripts. This exposes the workflow to code injection if a branch name is maliciously crafted. Pass these values securely via step env variables instead.

  • .github/workflows/ci-lite.yml#L902-L914: Map github.event_name, github.base_ref, and github.event.before into env variables, and use standard shell variables (e.g., "${BASE_REF}") in the script.
  • .github/workflows/ci-lite.yml#L939-L952: Map steps.coverage-compare.outputs.ref into an env variable and use it in the diff-cover command instead of ${{ ... }}.
🔒️ Proposed fixes

For coverage-compare (Lines 902-914):

       - name: Resolve coverage compare ref
         if: needs.changes.outputs.coverage == 'true'
         id: coverage-compare
+        env:
+          EVENT_NAME: ${{ github.event_name }}
+          BASE_REF: ${{ github.base_ref }}
+          EVENT_BEFORE: ${{ github.event.before }}
         run: |
           set -euo pipefail
-          if [ "${{ github.event_name }}" = "pull_request" ]; then
-            git fetch origin "${{ github.base_ref }}" --depth=200
-            echo "ref=origin/${{ github.base_ref }}" >> "$GITHUB_OUTPUT"
-          elif [ -n "${{ github.event.before }}" ] && [ "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ]; then
-            echo "ref=${{ github.event.before }}" >> "$GITHUB_OUTPUT"
+          if [ "${EVENT_NAME}" = "pull_request" ]; then
+            git fetch origin "${BASE_REF}" --depth=200
+            echo "ref=origin/${BASE_REF}" >> "$GITHUB_OUTPUT"
+          elif [ -n "${EVENT_BEFORE}" ] && [ "${EVENT_BEFORE}" != "0000000000000000000000000000000000000000" ]; then
+            echo "ref=${EVENT_BEFORE}" >> "$GITHUB_OUTPUT"
           else
             echo "ref=HEAD^" >> "$GITHUB_OUTPUT"
           fi

For the coverage enforcement step (Lines 939-952):

       - name: Enforce >= 80% coverage on changed lines
         if: needs.changes.outputs.coverage == 'true'
+        env:
+          COMPARE_REF: ${{ steps.coverage-compare.outputs.ref }}
         run: |
           set -euo pipefail
           mapfile -t LCOV_FILES < <(find lcov-artifacts -type f -name '*.info' | sort)
           if [ "${`#LCOV_FILES`[@]}" -eq 0 ]; then
             echo "::error::No lcov files found; coverage gate cannot run"
             exit 1
           fi
           diff-cover "${LCOV_FILES[@]}" \
-            --compare-branch="${{ steps.coverage-compare.outputs.ref }}" \
+            --compare-branch="${COMPARE_REF}" \
             --fail-under=80 \
             --html-report diff-coverage.html \
             --markdown-report diff-coverage.md
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci-lite.yml around lines 902 - 914, Prevent shell
injection in both coverage workflow steps: in the coverage-compare step
(.github/workflows/ci-lite.yml lines 902-914), map github.event_name,
github.base_ref, and github.event.before to env variables and reference those
quoted shell variables in the script; in the coverage enforcement step
(.github/workflows/ci-lite.yml lines 939-952), map
steps.coverage-compare.outputs.ref to an env variable and pass the quoted shell
variable to diff-cover instead of directly interpolating the GitHub expression.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In @.github/workflows/ci-lite.yml:
- Around line 902-914: Prevent shell injection in both coverage workflow steps:
in the coverage-compare step (.github/workflows/ci-lite.yml lines 902-914), map
github.event_name, github.base_ref, and github.event.before to env variables and
reference those quoted shell variables in the script; in the coverage
enforcement step (.github/workflows/ci-lite.yml lines 939-952), map
steps.coverage-compare.outputs.ref to an env variable and pass the quoted shell
variable to diff-cover instead of directly interpolating the GitHub expression.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8be86fd7-4ce7-448e-a1ab-68e6f166b254

📥 Commits

Reviewing files that changed from the base of the PR and between 43979a7 and b648370.

📒 Files selected for processing (2)
  • .github/workflows/ci-lite.yml
  • .github/workflows/pr-quality.yml

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. bug

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

4 participants