feat: dynamic connected integrations in agent system prompts#520
feat: dynamic connected integrations in agent system prompts#520senamakel merged 10 commits intotinyhumansai:mainfrom
Conversation
- Introduced a new `fetch_connected_integrations` method to retrieve and populate active Composio integrations for the agent. - Updated the `Agent` struct to include a `connected_integrations` field, allowing the system prompt to display available external services. - Enhanced the `build_system_prompt` method to incorporate connected integrations, improving the context provided to users during interactions. - Added a `ConnectedIntegrationsSection` to the prompt rendering, ensuring visibility of active integrations in the system prompt output. - Overall, these changes enhance the agent's ability to leverage connected services, improving user experience and interaction capabilities.
…dumps - Added a new `fetch_connected_integrations_for_dump` function to retrieve active integrations for the agent during prompt dumps. - Updated the `render_main_agent_dump` function to include connected integrations, enhancing the context provided in the debug output. - Improved the overall structure and clarity of the debug dump process, ensuring that connected integrations are accurately represented in the agent's prompt context.
- Refactored the `fetch_connected_integrations` method in the `Agent` struct to delegate integration fetching to a new centralized function in the `composio` module, enhancing code clarity and maintainability. - Updated the `fetch_connected_integrations_for_dump` function to utilize the new centralized fetching logic, ensuring consistent integration retrieval across different contexts. - Improved the overall structure of integration handling, allowing for better error management and logging during the fetching process.
…ontext - Introduced a new field `connected_integrations` in the `ParentExecutionContext` struct to store active Composio integrations. - Updated relevant functions to utilize the new `connected_integrations` field, ensuring that system prompts and agent dumps reflect the current integrations. - Enhanced the integration cache management by implementing cache invalidation logic when connections are created or deleted, improving the accuracy of integration data across sessions. - Overall, these changes enhance the agent's ability to leverage connected services, providing users with better context during interactions.
- Added a `connected_integrations` field to the `ParentExecutionContext` and `Agent` struct, allowing for the storage and retrieval of active Composio integrations. - Updated the `dispatch_target_agent` function to populate the `connected_integrations` field when creating a new sub-agent context. - Enhanced the `fetch_connected_integrations` method to return an `Option<Vec<ConnectedIntegration>>`, improving error handling and caching logic. - These changes improve the agent's ability to manage and utilize connected integrations, enhancing user interactions and context awareness.
- Updated the `fetch_connected_integrations` function to handle caching more effectively by using a match statement. - The function now caches results only when the backend is reachable, preventing unnecessary caching when the client is unavailable. - This change enhances error handling and ensures that subsequent calls with different configurations can retry without stale data.
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 6 minutes and 1 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughThis PR introduces connected integrations support by adding data structures to represent external services, implementing a caching mechanism for integration discovery from the backend, and threading this information throughout the agent execution and prompt rendering pipeline to expose available integrations to the system prompt. Changes
Sequence DiagramsequenceDiagram
participant Agent
participant Config
participant ComposioBackend as Composio Backend
participant Cache
participant PromptRenderer as Prompt Renderer
Agent->>Agent: turn() starts (first iteration)
Agent->>Config: Config::load_or_init()
Config-->>Agent: config
Agent->>ComposioBackend: fetch_connected_integrations_uncached(config)
ComposioBackend->>ComposioBackend: list connections (ACTIVE/CONNECTED)
ComposioBackend->>ComposioBackend: batch toolkit tools
ComposioBackend-->>Agent: Vec<ConnectedIntegration>
Agent->>Cache: store in INTEGRATIONS_CACHE
Agent->>PromptRenderer: build_system_prompt(connected_integrations)
PromptRenderer->>PromptRenderer: render ConnectedIntegrationsSection
PromptRenderer-->>Agent: system prompt with integrations
Agent-->>Agent: turn() continues with enriched context
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/openhuman/agent/harness/session/turn.rs (1)
79-87:⚠️ Potential issue | 🟠 MajorConnected integrations go stale after the first turn.
Lines 79-87 only load
self.connected_integrationsfor brand-new sessions, and Lines 100-112 intentionally freeze the system prompt after that. So the cache invalidation you added insrc/openhuman/composio/ops.rs/src/openhuman/composio/bus.rsnever helps an active chat: if the user connects or deletes Gmail/Notion mid-session, the orchestrator keeps the old integration list until a new session starts.Also applies to: 100-112
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/openhuman/agent/harness/session/turn.rs` around lines 79 - 87, The code only calls fetch_connected_integrations() when self.history.is_empty(), which freezes connected_integrations into the system prompt for the whole session and ignores cache invalidations from your composio ops/bus changes; to fix, always ensure connected_integrations is refreshed before building the system prompt by calling fetch_connected_integrations() (or checking a “connected integrations stale” flag set by the composio cache invalidation) prior to calling build_system_prompt(learned) — update the logic that currently gates fetch_connected_integrations() on history.is_empty() (and mirror the same change for the prompt-freezing block around build_system_prompt in the later section) so mid-session Gmail/Notion connect/delete events cause a refetch and re-render of the system prompt.
🧹 Nitpick comments (1)
src/openhuman/context/debug_dump.rs (1)
320-327: Refactor to use an explicit default-paths config loader instead of env mutation.The fallback at lines 322–326 mutates process-global
OPENHUMAN_WORKSPACEaround an async boundary. While this works in the current CLI-only context, the pattern is fragile: if this logic were ever called concurrently or exposed to JSON-RPC in the future, other tasks could observe the cleared env and load the wrong workspace. Instead, add a new method toConfig(e.g.,load_from_default_paths()) that explicitly bypassesOPENHUMAN_WORKSPACEwithout global mutation, and call that directly in the fallback path.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/openhuman/context/debug_dump.rs` around lines 320 - 327, The fallback currently mutates the process-global OPENHUMAN_WORKSPACE around an await (the block using std::env::remove_var / set_var and calling Config::load_or_init()), which is unsafe for concurrent use; add a new Config method (e.g., Config::load_from_default_paths() or Config::load_without_workspace_env()) that loads config explicitly from the default user paths bypassing the OPENHUMAN_WORKSPACE check, implement it alongside existing Config::load_or_init(), and replace the env mutation block in debug_dump.rs with a direct call to this new loader (remove the std::env::remove_var / set_var logic and call the new method instead).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/openhuman/agent/triage/escalation.rs`:
- Line 153: dispatch_target_agent currently constructs a fresh Agent which ends
up with an empty in-memory connected_integrations, so sub-agent escalation can
forward an empty list; update dispatch_target_agent (or the Agent constructor it
calls) to accept and copy the origin agent's connected_integrations (use
agent.connected_integrations().to_vec()) when building the new Agent, or fetch
the real integrations from the persistent store and assign them to the new
Agent.connected_integrations field so triage-triggered sub-agents receive the
actual connected integrations.
In `@src/openhuman/composio/bus.rs`:
- Around line 266-268: The cache is being invalidated too early by calling
super::ops::invalidate_connected_integrations_cache() immediately after
initiating a connect; move the invalidation to run only after the integration
reaches an ACTIVE/CONNECTED state (i.e., after OAuth flow/handshake completes)
so the recache sees the fully established connection; locate the call to
invalidate_connected_integrations_cache in bus.rs (and any surrounding
connect/authorize handlers) and change it to be invoked from the completion
callback/state-transition handler that marks the integration as
connected/active.
In `@src/openhuman/composio/ops.rs`:
- Around line 333-387: The process-wide INTEGRATIONS_CACHE is unkeyed so
different callers with different Configs can get the wrong integrations; change
the cache to be keyed by the active auth/config identity (e.g., a String key
derived from Config such as workspace_id, user_id, or a stable fingerprint)
instead of a single Option<Vec<...>>. Update INTEGRATIONS_CACHE to
RwLock<HashMap<String, Vec<ConnectedIntegration>>> and in
fetch_connected_integrations compute the config key, read the map entry for that
key, and return/clone it if present; when storing after
fetch_connected_integrations_uncached, insert into the map under that key (still
cache empty vec for reachable backend). Change
invalidate_connected_integrations_cache to accept an Option<&Config> (or a
specific config key) so callers can invalidate a single config entry (and keep
an option to clear the whole map when None). Ensure references to
INTEGRATIONS_CACHE, fetch_connected_integrations,
invalidate_connected_integrations_cache, and
fetch_connected_integrations_uncached are updated accordingly.
In `@src/openhuman/context/prompt.rs`:
- Around line 888-916: The connected_integrations block must use role-aware
wording instead of always instructing to "delegate to the **Skills Agent**
(`skills_agent`) via `spawn_subagent`": update the code that renders
connected_integrations to branch on the current agent identity (use the variable
or context that identifies the running agent), so that if the current agent is
the orchestrator it keeps the existing phrasing about delegating to skills_agent
via spawn_subagent, if the current agent is skills_agent it instead instructs to
call the available Composio tools directly (no spawn_subagent recursion), and if
the current agent is any other sub-agent it should advise delegating to
skills_agent when spawn_subagent is exposed or fallback to using
`composio_list_tools`/local tools if not; reference the connected_integrations
rendering code and the symbols skills_agent, spawn_subagent, and
composio_list_tools when implementing the conditional text.
---
Outside diff comments:
In `@src/openhuman/agent/harness/session/turn.rs`:
- Around line 79-87: The code only calls fetch_connected_integrations() when
self.history.is_empty(), which freezes connected_integrations into the system
prompt for the whole session and ignores cache invalidations from your composio
ops/bus changes; to fix, always ensure connected_integrations is refreshed
before building the system prompt by calling fetch_connected_integrations() (or
checking a “connected integrations stale” flag set by the composio cache
invalidation) prior to calling build_system_prompt(learned) — update the logic
that currently gates fetch_connected_integrations() on history.is_empty() (and
mirror the same change for the prompt-freezing block around build_system_prompt
in the later section) so mid-session Gmail/Notion connect/delete events cause a
refetch and re-render of the system prompt.
---
Nitpick comments:
In `@src/openhuman/context/debug_dump.rs`:
- Around line 320-327: The fallback currently mutates the process-global
OPENHUMAN_WORKSPACE around an await (the block using std::env::remove_var /
set_var and calling Config::load_or_init()), which is unsafe for concurrent use;
add a new Config method (e.g., Config::load_from_default_paths() or
Config::load_without_workspace_env()) that loads config explicitly from the
default user paths bypassing the OPENHUMAN_WORKSPACE check, implement it
alongside existing Config::load_or_init(), and replace the env mutation block in
debug_dump.rs with a direct call to this new loader (remove the
std::env::remove_var / set_var logic and call the new method instead).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 7102eb0a-e2e5-40f4-8dd4-6a6678bb6e98
📒 Files selected for processing (15)
src/openhuman/agent/harness/fork_context.rssrc/openhuman/agent/harness/session/builder.rssrc/openhuman/agent/harness/session/runtime.rssrc/openhuman/agent/harness/session/turn.rssrc/openhuman/agent/harness/session/types.rssrc/openhuman/agent/harness/subagent_runner.rssrc/openhuman/agent/triage/escalation.rssrc/openhuman/composio/bus.rssrc/openhuman/composio/mod.rssrc/openhuman/composio/ops.rssrc/openhuman/composio/providers/mod.rssrc/openhuman/context/debug_dump.rssrc/openhuman/context/prompt.rssrc/openhuman/learning/prompt_sections.rstests/agent_harness_public.rs
- Updated the `dispatch_target_agent` function to initialize connected integrations for sub-agents, ensuring they have access to the latest integrations. - Improved the caching mechanism for connected integrations by using a `HashMap` keyed by configuration identity, allowing for user-specific caching and better isolation of integration data. - Refactored the `invalidate_connected_integrations_cache` function to clear the entire cache instead of setting it to `None`, enhancing cache management. - Added a new method `load_from_default_paths` in the `Config` struct to reliably load user configurations without being affected by environment variable overrides, improving the debug dump process. - Enhanced the rendering of connected integrations in system prompts to provide clearer instructions based on available tools, improving user interaction clarity.
- Introduced a new `set_connected_integrations` method in the `Agent` struct to allow for replacing the agent's connected integrations from external sources, enhancing flexibility in integration management. - Updated the caching mechanism for connected integrations to utilize `LazyLock`, improving initialization efficiency and thread safety.
Summary
composio::fetch_connected_integrations()is the one source of truth — called by both the agent turn loop and the debug dump CLI. No duplicated fetch logic.ComposioConnectionCreatedevents (new OAuth) and oncomposio_delete_connection(disconnect). No redundant backend calls across agent sessions.Changes
composio/ops.rsfetch_connected_integrations()withRwLockcache,invalidate_connected_integrations_cache(), uncached fetch returningOptionto distinguish no-auth from emptycomposio/bus.rsComposioConnectionCreatedcomposio/providers/mod.rstoolkit_description()— 28+ toolkit slug → description mapcontext/prompt.rsConnectedIntegration+ConnectedIntegrationTooltypes,ConnectedIntegrationsSection, wired into both main and subagent prompt renderersagent/harness/session/turn.rsagent/harness/fork_context.rsconnected_integrationsonParentExecutionContextagent/harness/subagent_runner.rscontext/debug_dump.rsTest plan
cargo check --all-targets— cleancargo test -p openhuman --lib— 2398 tests passcargo run --bin openhuman-core -- agent dump-prompt --agent main— shows Connected Integrations sectioncargo run --bin openhuman-core -- agent dump-prompt --agent orchestrator— shows Connected Integrations sectionbash scripts/debug-agent-prompts.sh— all 11 agents dump successfully with integrations visible in orchestratorOPENHUMAN_WORKSPACE=/tmp/...) falls back to real user auth for integration fetchSummary by CodeRabbit