feat(welcome-agent): add discovery phase before setup checklist#996
Conversation
The welcome agent now asks 2-3 conversational questions (what brought you here, daily tools, pain points) before starting the onboarding checklist. Responses personalize which checklist items to emphasize and which integrations to suggest first. Includes escape hatch for users who want to skip straight to setup. Closes tinyhumansai#994
📝 WalkthroughWalkthroughAdds a discovery-first onboarding flow to the Welcome agent, raises its Changes
Sequence Diagram(s)sequenceDiagram
participant User as User
participant Welcome as Welcome Agent
participant Onboard as Onboarding Service
participant Composio as Composio Integrations
User->>Welcome: Start onboarding
Welcome->>User: Discovery Q1 (intent / tools)
User->>Welcome: Reply (may name app)
alt User names actionable app
Welcome->>Composio: Suggest/connect integration
Composio-->>Welcome: Connected / Declined
end
loop until (>=3 exchanges and >=1 composio connection) or user refuses
Welcome->>User: Further discovery / checklist step
User->>Welcome: Reply
Welcome->>Onboard: check_ready(composio_connections, exchanges)
Onboard-->>Welcome: Ready / NotReady (reasons)
end
Welcome->>User: Complete onboarding or show unmet requirements
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 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: 1
🤖 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/agents/welcome/prompt.md`:
- Around line 11-26: The discovery + checklist flow can exhaust max_iterations
(configured as max_iterations) and currently hits a hard failure via
anyhow::bail! in .claude/memory.md; update the flow to avoid hard bails by
adding iteration-count checks and graceful handling: instrument and log
iteration usage before calling anyhow::bail!, implement a fallback that
truncates or collapses prompts (e.g., skip optional discovery turns or combine
checklist prompts) when remaining iterations are low, and add monitoring/metrics
around the iteration counter so production can detect frequent limit hits;
reference the discovery/checklist behavior in prompt.md and the bail site in
.claude/memory.md to locate the change points.
🪄 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: 93b7e359-4d63-41d9-ac21-e57e80d3f435
📒 Files selected for processing (5)
.claude/memory.mdsrc/openhuman/about_app/catalog.rssrc/openhuman/agent/agents/loader.rssrc/openhuman/agent/agents/welcome/agent.tomlsrc/openhuman/agent/agents/welcome/prompt.md
| ## Discovery phase | ||
|
|
||
| Before you touch the setup checklist, spend 2-3 turns learning a little about the user. One question per turn, casual tone, no interrogation. | ||
|
|
||
| **Turn order:** | ||
|
|
||
| 1. **First turn (the opener):** greet them warmly and ask what brought them to OpenHuman. Something like: "what made you check this out?" or "what are you hoping this helps with?" Don't introduce checklist items yet. | ||
| 2. **Second turn:** ask about their daily tools. Keep it simple: "what apps do you live in day-to-day? like email, slack, that kind of thing?" Don't list every app we support; let them answer freely. | ||
| 3. **Third turn:** ask what's annoying about their current setup. Something like: "what's the thing that drives you most crazy about how it all works right now?" | ||
|
|
||
| After those 2-3 exchanges, transition naturally into the checklist. Use what they told you: if they mentioned slack, lead with that when you pitch connecting apps; if they hate notification overload, be honest about how ours works. You don't need to announce "ok now setup time" — just move into it like it's the next natural thing. | ||
|
|
||
| **Escape hatch:** if at any point the user says something like "just set me up", "skip the chat", "let's just do it", or anything that reads as "get on with it" — skip straight to the checklist. Don't make them ask twice. | ||
|
|
||
| **One question per turn.** Never stack two questions in one message. | ||
|
|
There was a problem hiding this comment.
Consider iteration budget in edge cases.
The discovery phase (up to 3 turns) + checklist (5 items, one per turn) + the proactive opener consumes roughly 9 iterations in the optimal path. With max_iterations = 10, there's minimal buffer for clarifying questions or back-and-forth on individual checklist items.
Based on .claude/memory.md (lines 131-132), exceeding max_iterations results in a hard failure via anyhow::bail! rather than graceful truncation. While 10 iterations should cover the majority of flows, consider monitoring for iteration limit hits in production to determine if further adjustment is needed.
Also applies to: 72-74
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/openhuman/agent/agents/welcome/prompt.md` around lines 11 - 26, The
discovery + checklist flow can exhaust max_iterations (configured as
max_iterations) and currently hits a hard failure via anyhow::bail! in
.claude/memory.md; update the flow to avoid hard bails by adding iteration-count
checks and graceful handling: instrument and log iteration usage before calling
anyhow::bail!, implement a fallback that truncates or collapses prompts (e.g.,
skip optional discovery turns or combine checklist prompts) when remaining
iterations are low, and add monitoring/metrics around the iteration counter so
production can detect frequent limit hits; reference the discovery/checklist
behavior in prompt.md and the bail site in .claude/memory.md to locate the
change points.
There was a problem hiding this comment.
Good callout. We already deliberately chose 10 over 8 for exactly this reason (the hard bail! at the limit). A few factors that keep it safe:
- The agent naturally combines related items when conversations flow quickly (e.g. folding notification + apps into one turn if the user is breezy)
- The escape hatch ("just set me up") lets users skip discovery entirely, reclaiming 2-3 iterations
- Discovery questions often satisfy the 3-exchange
engagement_criteria_metthreshold, so the agent can fold remaining checklist items together onceready_to_completeflips true
We'll monitor iteration limit hits in production and bump if needed. For now 10 provides a reasonable buffer without over-allocating.
There was a problem hiding this comment.
@graycyrus, that rationale makes sense — especially the ready_to_complete flip enabling checklist consolidation in the back half of the flow. The three factors together give a reasonable practical ceiling well below the hard bail!. Happy to close this out; monitoring for limit hits in production is the right safety net.
🧠 Learnings used
Learnt from: sanil-23
Repo: tinyhumansai/openhuman PR: 437
File: src/openhuman/subconscious/executor.rs:182-201
Timestamp: 2026-04-08T16:47:01.357Z
Learning: In `src/openhuman/subconscious/executor.rs`, the `agent_chat_with_retry` function intentionally performs 3 total attempts (1 initial + 2 retries) with 2s and 4s exponential backoff. MAX_RETRIES = 3 with `attempt < MAX_RETRIES` guard after pre-increment means only 2 retries fire (2s, 4s). The 5-minute heartbeat tick interval is relied upon as the natural retry mechanism for persistent rate limits, so no 8s backoff is needed within a single tick.
…nswers The agent was falling back to the default checklist order (notifications first) even when the user mentioned specific tools during discovery. Made the reorder instruction explicit: lead with the item closest to what the user said, not the numbered default. Closes tinyhumansai#994
…scovery When the user names a specific app like "slack" during discovery, the agent should offer to connect it right away instead of continuing with the next scripted question. Discovery and checklist now blend together rather than being rigid separate phases.
…lling last Restructure checklist with clear priority levels: - Must-do: connect at least one Composio tool - Important: Telegram (push hard, don't accept quick refusal) - Good-to-have: notifications, built-in apps, Discord - Always last: billing/credits mention
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/agents/welcome/prompt.md`:
- Line 85: Clarify that the "Don't move on" constraint for the must-do "Connect
a tool via Composio" is satisfied if any app (e.g., Gmail) is already connected:
update the prompt text for the "Connect a tool via Composio (must-do)" section
to state explicitly that if the snapshot shows at least one Composio integration
(for example Gmail) the requirement is met and the agent may proceed; only call
composio_authorize and insist on connecting a tool if no Composio apps are
connected or the user explicitly refused, and otherwise acknowledge the existing
Gmail connection and optionally suggest additional tools mentioned in discovery.
🪄 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: a99eed16-8ea1-4191-8342-81b4d594447c
📒 Files selected for processing (1)
src/openhuman/agent/agents/welcome/prompt.md
…arding Change engagement criteria from OR to AND: users must now have both minimum exchanges (3) AND at least one Composio integration connected before complete_onboarding succeeds. Updates error message to list which specific requirements are unmet. Closes tinyhumansai#993
When the user describes their role or workflow during discovery, the agent now infers and suggests relevant integrations rather than waiting for explicit app mentions. After connecting one, suggests the next natural one. Closes tinyhumansai#995
If Gmail (or any toolkit) is already connected from the desktop wizard, the must-do is satisfied. The agent acknowledges it and optionally suggests another tool, but can move on. Only blocks if zero toolkits are connected.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/openhuman/tools/impl/agent/onboarding_status.rs (1)
23-26:⚠️ Potential issue | 🟡 MinorStale doc comment — remove the conditional clause.
The comment says "required before
complete_onboardingwill accept a finalization request when no Composio integrations are connected." With the AND gate, Composio is always required regardless of exchange count, so this conditional framing is misleading.📝 Suggested fix
/// Minimum number of welcome-agent exchanges required before -/// `complete_onboarding` will accept a finalization request when no -/// Composio integrations are connected. +/// `complete_onboarding` will accept a finalization request. pub(crate) const MIN_EXCHANGES_TO_COMPLETE: u32 = 3;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/openhuman/tools/impl/agent/onboarding_status.rs` around lines 23 - 26, The doc comment for the constant MIN_EXCHANGES_TO_COMPLETE is misleading because it mentions "when no Composio integrations are connected"; update the comment to remove that conditional clause and state simply that this constant is the minimum number of welcome-agent exchanges required before complete_onboarding will accept a finalization request, so the documentation reflects current logic (refer to MIN_EXCHANGES_TO_COMPLETE and complete_onboarding to locate and update the comment).src/openhuman/tools/impl/agent/complete_onboarding.rs (1)
50-52:⚠️ Potential issue | 🟡 MinorMisleading description — logic says "rejects unless both met" but text implies "rejects if both missing".
Line 52 says "Rejects when the user... has fewer than the required exchange count AND no connected Composio integrations." This reads as rejection only when both are missing. But the actual AND-gate logic rejects when either is missing.
📝 Suggested fix
`ready_to_complete: true` — the tool re-checks the criteria \ server-side and **rejects** premature calls with a descriptive \ - error so the agent knows to keep conversing. Rejects when the \ - user is unauthenticated, or when they have fewer than the \ - required exchange count AND no connected Composio integrations." + error so the agent knows to keep conversing. Rejects when the \ + user is unauthenticated, or when they have fewer than the \ + required exchange count OR no connected Composio integrations \ + (both conditions must be satisfied to proceed)."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/openhuman/tools/impl/agent/complete_onboarding.rs` around lines 50 - 52, The docstring/comment near the CompleteOnboarding logic is misleading: it currently says rejection occurs when the user "has fewer than the required exchange count AND no connected Composio integrations" but the implementation uses an OR semantics. Update the text to match the code (or vice-versa): either change the wording to "Rejects when the user is unauthenticated, or when they have fewer than the required exchange count OR no connected Composio integrations" to reflect the current OR logic, or adjust the condition in the function that evaluates onboarding requirements (e.g., the function/method handling completion in complete_onboarding.rs such as complete_onboarding or the check_exchange_and_composio logic) to enforce an AND if the original text should be preserved; ensure the comment and the symbol that performs the check are consistent.
🤖 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/agents/welcome/prompt.md`:
- Line 76: Update the check_onboarding_status tool description so it matches the
implementation in onboarding_status.rs: change the logic language from "at least
one of" (OR) to explicitly state that ready_to_complete flips true only when
both conditions are met: exchange_count >= MIN_EXCHANGES_TO_COMPLETE AND
composio_connections > 0 (i.e., the user has had at least 3 back-and-forth
exchanges and has connected at least one Composio integration), and note that
calling complete_onboarding before both are true will error.
---
Outside diff comments:
In `@src/openhuman/tools/impl/agent/complete_onboarding.rs`:
- Around line 50-52: The docstring/comment near the CompleteOnboarding logic is
misleading: it currently says rejection occurs when the user "has fewer than the
required exchange count AND no connected Composio integrations" but the
implementation uses an OR semantics. Update the text to match the code (or
vice-versa): either change the wording to "Rejects when the user is
unauthenticated, or when they have fewer than the required exchange count OR no
connected Composio integrations" to reflect the current OR logic, or adjust the
condition in the function that evaluates onboarding requirements (e.g., the
function/method handling completion in complete_onboarding.rs such as
complete_onboarding or the check_exchange_and_composio logic) to enforce an AND
if the original text should be preserved; ensure the comment and the symbol that
performs the check are consistent.
In `@src/openhuman/tools/impl/agent/onboarding_status.rs`:
- Around line 23-26: The doc comment for the constant MIN_EXCHANGES_TO_COMPLETE
is misleading because it mentions "when no Composio integrations are connected";
update the comment to remove that conditional clause and state simply that this
constant is the minimum number of welcome-agent exchanges required before
complete_onboarding will accept a finalization request, so the documentation
reflects current logic (refer to MIN_EXCHANGES_TO_COMPLETE and
complete_onboarding to locate and update the comment).
🪄 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: a1fac9aa-458f-4d3a-8af8-d6c3d91fd994
📒 Files selected for processing (3)
src/openhuman/agent/agents/welcome/prompt.mdsrc/openhuman/tools/impl/agent/complete_onboarding.rssrc/openhuman/tools/impl/agent/onboarding_status.rs
| Call `check_onboarding_status` (no args) on your first iteration of any reactive reply, alongside a short visible message. Never a tool-only turn. The snapshot tells you `composio_connected_toolkits`, `webview_logins`, `exchange_count`, `ready_to_complete`, `ready_to_complete_reason`, `onboarding_status`. | ||
|
|
||
| `ready_to_complete` flips true when either `exchange_count >= 3` OR they've connected at least one Composio toolkit. Don't call `complete_onboarding` before that or you'll get an error. | ||
| `ready_to_complete` flips true when `exchange_count >= 3` AND they've connected at least one Composio toolkit. Both conditions are required. Don't call `complete_onboarding` before that or you'll get an error. |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if check_onboarding_status.rs still has OR-based description
rg -n "at least one of" --type rustRepository: tinyhumansai/openhuman
Length of output: 595
🏁 Script executed:
cat -n src/openhuman/tools/impl/agent/check_onboarding_status.rs | sed -n '60,75p'Repository: tinyhumansai/openhuman
Length of output: 966
🏁 Script executed:
rg -n "ready_to_complete" --type rust -A 2 -B 2 src/openhuman/tools/impl/agent/check_onboarding_status.rsRepository: tinyhumansai/openhuman
Length of output: 1559
🏁 Script executed:
# Find and check the actual onboarding status implementation
fd -i "onboarding_status" --type rustRepository: tinyhumansai/openhuman
Length of output: 238
🏁 Script executed:
find . -name "*onboarding*status*" -type fRepository: tinyhumansai/openhuman
Length of output: 180
🏁 Script executed:
# Also search for where ready_to_complete is calculated
rg -n "ready_to_complete\s*=" --type rust -B 3 -A 3Repository: tinyhumansai/openhuman
Length of output: 1427
🏁 Script executed:
rg -n "fn engagement_criteria_met" --type rust -A 10Repository: tinyhumansai/openhuman
Length of output: 1129
🏁 Script executed:
rg -n "engagement_criteria_met" src/openhuman/tools/impl/agent/onboarding_status.rs -B 2 -A 2Repository: tinyhumansai/openhuman
Length of output: 1376
Update check_onboarding_status tool description from OR to AND logic.
The tool description (lines 63–65 in src/openhuman/tools/impl/agent/check_onboarding_status.rs) incorrectly states:
"
ready_to_completeflips true when at least one of: * The user has had at least 3 back-and-forth exchanges, or * The user has connected at least one Composio integration."
However, the actual implementation in onboarding_status.rs:60 uses AND logic:
exchange_count >= MIN_EXCHANGES_TO_COMPLETE && composio_connections > 0
Tests confirm both conditions are required (see lines 442–450). Update the tool description to match:
"
ready_to_completeflips true when both conditions are met: * The user has had at least 3 back-and-forth exchanges, and * The user has connected at least one Composio integration."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/openhuman/agent/agents/welcome/prompt.md` at line 76, Update the
check_onboarding_status tool description so it matches the implementation in
onboarding_status.rs: change the logic language from "at least one of" (OR) to
explicitly state that ready_to_complete flips true only when both conditions are
met: exchange_count >= MIN_EXCHANGES_TO_COMPLETE AND composio_connections > 0
(i.e., the user has had at least 3 back-and-forth exchanges and has connected at
least one Composio integration), and note that calling complete_onboarding
before both are true will error.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/agents/welcome/prompt.md`:
- Line 21: Unify the trigger rule for composio_authorize so it is consistent
across the welcome prompt: change the two conflicting instructions (the
opportunistic rule that calls composio_authorize when the user names an app and
the later rule that only calls it on explicit request) into one clear rule that
triggers composio_authorize whenever the user expresses intent to connect an app
or explicitly names an app (e.g., "slack", "notion"), and reword both
occurrences to the same sentence so the prompt consistently instructs the agent
to call composio_authorize immediately in that case while weaving
discovery/checklist items around the action.
🪄 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: 6f3fee89-4995-4cc9-b85f-9f02fd70b77e
📒 Files selected for processing (1)
src/openhuman/agent/agents/welcome/prompt.md
| 2. **Second turn:** ask about their daily tools. Keep it simple: "what apps do you live in day-to-day? like email, slack, that kind of thing?" Don't list every app we support; let them answer freely. | ||
| 3. **Third turn (only if needed):** ask what's annoying about their current setup. Something like: "what's the thing that drives you most crazy about how it all works right now?" | ||
|
|
||
| **Be opportunistic — act on what they say immediately.** If the user names a specific app (e.g. "slack", "telegram", "notion"), don't save it for later. Respond by helping them connect it right now: "let's get your slack wired up" and drop the relevant link or call `composio_authorize`. The discovery phase and checklist aren't separate stages; they blend. If the user gives you something actionable, do it on the spot and weave the remaining discovery or checklist items around it. |
There was a problem hiding this comment.
Conflicting composio_authorize trigger rules need to be unified.
Line 21 says to act immediately and call composio_authorize when a user names an app, but Line 129 says to call it only when they explicitly ask. This creates contradictory runtime behavior for the same scenario.
Proposed prompt fix
-Only call `composio_authorize` when the user explicitly asks to connect a new app (e.g. "connect notion", "give me the slack link"). Drop the returned `connectUrl` as a markdown link: `[connect notion](url)`. Mention it opens in their browser. Never invent URLs.
+Call `composio_authorize` when the user clearly signals intent to connect a new app, either explicitly ("connect notion", "give me the slack link") or by agreeing to your suggestion ("yeah, let's do slack"). Drop the returned `connectUrl` as a markdown link: `[connect notion](url)`. Mention it opens in their browser. Never invent URLs.Also applies to: 129-129
🧰 Tools
🪛 LanguageTool
[style] ~21-~21: It’s more common nowadays to write this noun as one word.
Context: ... on what they say immediately.** If the user names a specific app (e.g. "slack", "telegram...
(RECOMMENDED_COMPOUNDS)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/openhuman/agent/agents/welcome/prompt.md` at line 21, Unify the trigger
rule for composio_authorize so it is consistent across the welcome prompt:
change the two conflicting instructions (the opportunistic rule that calls
composio_authorize when the user names an app and the later rule that only calls
it on explicit request) into one clear rule that triggers composio_authorize
whenever the user expresses intent to connect an app or explicitly names an app
(e.g., "slack", "notion"), and reword both occurrences to the same sentence so
the prompt consistently instructs the agent to call composio_authorize
immediately in that case while weaving discovery/checklist items around the
action.
Summary
max_iterationsfrom 6 to 10 to accommodate discovery turns + checklistChanges
src/openhuman/agent/agents/welcome/prompt.mdsrc/openhuman/agent/agents/welcome/agent.tomlmax_iterations6 → 10src/openhuman/agent/agents/loader.rssrc/openhuman/about_app/catalog.rssrc/openhuman/tools/impl/agent/onboarding_status.rssrc/openhuman/tools/impl/agent/complete_onboarding.rsDesign decisions
memory_storeadded: the archivist already extracts preferences from conversation historymax_iterations= 10: hitting the limit causes a hardbail!, so 10 provides headroomTest plan
cargo test -- welcomepasses (max_iterations assertion updated)cargo test -- engagement_criteriapasses (OR→AND, new test cases)cargo test -- all_builtins_parsepasses (agent.toml still valid)Closes #994
Closes #993
Closes #995
Summary by CodeRabbit
New Features
Improvements
Documentation
Tests