Skip to content

Add human handoff, CSAT capture, and escalation-aware chat state - #18

Merged
nedasvi merged 6 commits into
mainfrom
feature/human-handoff-csat
Jul 27, 2026
Merged

Add human handoff, CSAT capture, and escalation-aware chat state#18
nedasvi merged 6 commits into
mainfrom
feature/human-handoff-csat

Conversation

@nedasvi

@nedasvi nedasvi commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Client-side support for the backend's new human-handoff/CSAT features, mirroring the iOS SDK:

  • New SSE event handling: SessionEscalated, HumanMessage, FeedbackRequested (with an immediate flag distinguishing an AI-turn-triggered CSAT prompt from a definitive human-resolve trigger).
  • CSAT prompt debounces 15s after an AI turn (cancels if the user keeps chatting), shows immediately when a human resolves the session, and is suppressed entirely while an escalation/handoff is in progress.
  • ChatMessageRole.HUMAN_AGENT message bubble, escalated-state banner, ResolveKitRuntime.submitFeedback/dismissFeedbackRequest.
  • Fixed the sample app's build entirely: it never actually compiled in a clean environment due to a Kotlin/Compose-Compiler/KSP version mismatch plus API drift against current :core/:ui (missing import, renamed interface members, wrong rememberSaveable package) and a missing usesCleartextTraffic manifest exception needed to reach the staging backend over plain HTTP.

Test plan

  • :networking module compiles and its unit tests pass
  • Full clean :sample:assembleDebug build succeeds (previously never worked in this repo)
  • Manually verified end-to-end against staging on an emulator: session creation, message history, SSE reconnect — after the cleartext-traffic fix

nedasvi and others added 6 commits July 21, 2026 10:05
Handles the three new backend SSE event types (session_escalated,
human_message, feedback_requested) and the new HUMAN_AGENT message role:
renders an escalated-state banner, a distinct human-agent message bubble,
and a post-turn CSAT prompt. Adds ResolveKitAPIClient.submitFeedback for
POST /v1/sessions/{id}/feedback.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
feedback_requested fired the rating prompt the moment the event arrived,
even mid-conversation. Wait a few seconds before showing it, and cancel
if the user sends another message in the meantime.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
session_escalated now cancels any CSAT prompt still pending from the
AI's last reply -- it shouldn't surface while the user is waiting on a
human handoff. feedback_requested's new "immediate" flag (true only for
the human-resolve trigger) skips the debounce and shows the prompt
right away, since that signal means the conversation is definitively
over.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Give the user more room to keep chatting before the rating prompt
interrupts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The sample module (and therefore :ui, which it depends on) has never
actually compiled in a clean environment:

- kotlinCompilerExtensionVersion 1.5.8 (in :ui and :sample) is only
  certified for Kotlin 1.9.22, but gradle/libs.versions.toml pins
  Kotlin 1.9.25. Bumped to 1.5.15, the compatible Compose Compiler for
  that Kotlin version.
- ksp was pinned to 1.9.22-1.0.17, incompatible with Kotlin 1.9.25 for
  the same reason. Bumped to 1.9.25-1.0.20.
- Sample source had drifted from current :core/:ui APIs:
  ResolveKitFunctionPack.id -> packName (+ missing supportedPlatforms),
  a missing ResolveKitChatActivity import, rememberSaveable imported
  from the wrong package, and a resolveKitParametersSchema type
  mismatch (Map<String, Any> vs the JSONObject typealias).
- AndroidManifest.xml was missing usesCleartextTraffic="true", so
  every plain-HTTP request (used for staging/local dev, same as the
  iOS sample's NSAllowsArbitraryLoads) was silently blocked by Android.

Verified via a full clean build + running on an emulator against the
staging backend: session creation, message history, and SSE reconnect
all work correctly end to end.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
scripts/check_agent_docs.sh requires AGENTS.md to reference both
docs/INDEX.md and docs/agent-first/README.md -- neither was linked,
which was failing the required build check on main itself, independent
of this branch's actual changes. Also corrected the documented Kotlin
version (1.9.22 -> 1.9.25) to match gradle/libs.versions.toml.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@nedasvi
nedasvi merged commit d80c284 into main Jul 27, 2026
1 check passed
@nedasvi
nedasvi deleted the feature/human-handoff-csat branch July 27, 2026 06:59
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