Skip to content

feat: dynamic connected integrations in agent system prompts#520

Merged
senamakel merged 10 commits intotinyhumansai:mainfrom
senamakel:fix/prompt-improvements
Apr 13, 2026
Merged

feat: dynamic connected integrations in agent system prompts#520
senamakel merged 10 commits intotinyhumansai:mainfrom
senamakel:fix/prompt-improvements

Conversation

@senamakel
Copy link
Copy Markdown
Member

@senamakel senamakel commented Apr 13, 2026

Summary

  • Connected integrations rendered in system prompts: The orchestrator and all subagents now see which external services the user has connected (e.g. Gmail, Notion, GitHub) with their actual Composio action slugs, so the orchestrator automatically delegates "send an email" to the Skills Agent without the user having to explicitly request a subagent spawn.
  • Single shared fetch function: 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.
  • Process-wide cache with smart invalidation: Connections + tool schemas are fetched once and cached for the process lifetime. Cache is busted on ComposioConnectionCreated events (new OAuth) and on composio_delete_connection (disconnect). No redundant backend calls across agent sessions.
  • Toolkit capability descriptions: Static human-readable summaries for 28+ common toolkits (Gmail, Notion, Slack, GitHub, etc.) with a fallback for unknown slugs.

Changes

File Change
composio/ops.rs Shared fetch_connected_integrations() with RwLock cache, invalidate_connected_integrations_cache(), uncached fetch returning Option to distinguish no-auth from empty
composio/bus.rs Cache invalidation on ComposioConnectionCreated
composio/providers/mod.rs toolkit_description() — 28+ toolkit slug → description map
context/prompt.rs ConnectedIntegration + ConnectedIntegrationTool types, ConnectedIntegrationsSection, wired into both main and subagent prompt renderers
agent/harness/session/turn.rs Fetch integrations on first turn, pass to prompt context
agent/harness/fork_context.rs connected_integrations on ParentExecutionContext
agent/harness/subagent_runner.rs Thread integrations into subagent prompt rendering
context/debug_dump.rs Dump script fetches real connections (with fallback for workspace overrides)

Test plan

  • cargo check --all-targets — clean
  • cargo test -p openhuman --lib — 2398 tests pass
  • cargo run --bin openhuman-core -- agent dump-prompt --agent main — shows Connected Integrations section
  • cargo run --bin openhuman-core -- agent dump-prompt --agent orchestrator — shows Connected Integrations section
  • bash scripts/debug-agent-prompts.sh — all 11 agents dump successfully with integrations visible in orchestrator
  • Workspace override (OPENHUMAN_WORKSPACE=/tmp/...) falls back to real user auth for integration fetch

Summary by CodeRabbit

  • New Features
    • Agent now discovers and references available connected external services (e.g., Gmail, Notion, GitHub, Slack) within system prompts, enabling smarter service awareness
    • Connected integrations are automatically refreshed when connections are created or deleted

- 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.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 13, 2026

Warning

Rate limit exceeded

@senamakel has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 6 minutes and 1 seconds before requesting another review.

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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e04f0b51-6444-4a4b-94d2-bf302fe80048

📥 Commits

Reviewing files that changed from the base of the PR and between 47be111 and 15cb3b8.

📒 Files selected for processing (7)
  • src/openhuman/agent/harness/session/runtime.rs
  • src/openhuman/agent/triage/escalation.rs
  • src/openhuman/composio/bus.rs
  • src/openhuman/composio/ops.rs
  • src/openhuman/config/schema/load.rs
  • src/openhuman/context/debug_dump.rs
  • src/openhuman/context/prompt.rs
📝 Walkthrough

Walkthrough

This 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

Cohort / File(s) Summary
Prompt Context & Integration Section Types
src/openhuman/context/prompt.rs
Added ConnectedIntegration and ConnectedIntegrationTool structs to represent external services and their tools. Extended PromptContext with connected_integrations field. Introduced ConnectedIntegrationsSection for rendering integrations in system prompts, and updated render_subagent_system_prompt* functions to accept and render connected integrations.
Composio Backend Integration & Caching
src/openhuman/composio/ops.rs, src/openhuman/composio/mod.rs, src/openhuman/composio/providers/mod.rs, src/openhuman/composio/bus.rs
Implemented process-wide integration cache with fetch_connected_integrations() and invalidate_connected_integrations_cache() functions. Added toolkit_description() for human-readable service descriptions. Cache is invalidated on connection deletion and after connection-created events. Backend discovery lists active Composio connections and batches toolkit tools.
Agent Session Field & Accessor Management
src/openhuman/agent/harness/session/types.rs, src/openhuman/agent/harness/session/builder.rs, src/openhuman/agent/harness/session/runtime.rs
Added connected_integrations field to Agent struct. AgentBuilder::build() initializes field with empty vector. Added public accessor method Agent::connected_integrations() returning borrowed slice.
Agent Turn Lifecycle & Integration Fetching
src/openhuman/agent/harness/session/turn.rs
Added fetch_connected_integrations() method called on first turn before system prompt construction. Loads config and populates integrations from backend. Extended build_parent_execution_context() and system prompt context to include connected_integrations.
Context & Parent Execution Propagation
src/openhuman/agent/harness/fork_context.rs, src/openhuman/agent/harness/subagent_runner.rs, src/openhuman/agent/triage/escalation.rs
Extended ParentExecutionContext with connected_integrations field. Updated subagent runner to thread integrations into prompt rendering. Updated escalation dispatcher to populate connected_integrations when constructing parent context for subagents.
Prompt Rendering & Debug Integration
src/openhuman/context/debug_dump.rs, src/openhuman/learning/prompt_sections.rs
Updated debug dump to fetch and thread connected integrations through main and subagent prompt rendering. Updated render_main_agent_dump and render_subagent_dump signatures. Test helper updated to provide empty integrations slice.
Test Fixtures & Stubs
tests/agent_harness_public.rs
Updated stub_parent_context() test helper to initialize connected_integrations with empty vector to match updated struct.

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Poem

🐰 Integrations flow like carrots through the warren!
Fetch from backend, cache with care and keen eye,
Thread through prompts so agents know what tools to try,
From Composio's garden to the agent's delight!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding dynamic connected integrations visibility to agent system prompts, which is the primary feature across all modified files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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 | 🟠 Major

Connected integrations go stale after the first turn.

Lines 79-87 only load self.connected_integrations for brand-new sessions, and Lines 100-112 intentionally freeze the system prompt after that. So the cache invalidation you added in src/openhuman/composio/ops.rs / src/openhuman/composio/bus.rs never 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_WORKSPACE around 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 to Config (e.g., load_from_default_paths()) that explicitly bypasses OPENHUMAN_WORKSPACE without 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

📥 Commits

Reviewing files that changed from the base of the PR and between 172cd0d and 47be111.

📒 Files selected for processing (15)
  • src/openhuman/agent/harness/fork_context.rs
  • src/openhuman/agent/harness/session/builder.rs
  • src/openhuman/agent/harness/session/runtime.rs
  • src/openhuman/agent/harness/session/turn.rs
  • src/openhuman/agent/harness/session/types.rs
  • src/openhuman/agent/harness/subagent_runner.rs
  • src/openhuman/agent/triage/escalation.rs
  • src/openhuman/composio/bus.rs
  • src/openhuman/composio/mod.rs
  • src/openhuman/composio/ops.rs
  • src/openhuman/composio/providers/mod.rs
  • src/openhuman/context/debug_dump.rs
  • src/openhuman/context/prompt.rs
  • src/openhuman/learning/prompt_sections.rs
  • tests/agent_harness_public.rs

Comment thread src/openhuman/agent/triage/escalation.rs
Comment thread src/openhuman/composio/bus.rs Outdated
Comment thread src/openhuman/composio/ops.rs Outdated
Comment thread src/openhuman/context/prompt.rs Outdated
- 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.
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