Mobile — Threads & Chat
Threads are the heart of the mobile app. The Threads tab shows the user’s threads, each thread opens into a chat view with a streaming message timeline, and the message input supports workspace selection, voice dictation, and quick actions. When an agent pauses for human confirmation, that request appears in the same Threads surface instead of moving the user to a separate queue.
The Threads tab
Section titled “The Threads tab”Tab: (tabs)/index
The Threads tab is the user’s list of open and recent threads. Each row shows the thread title, the agent handling it, a snippet of the latest message, and a status indicator. Threads that are currently running show a subtle shimmer effect so the user can tell an agent is thinking in real time.
The Threads tab supports:
- Filtering — by status, by agent, by channel (chat, task, email, Slack, GitHub)
- Search — by title or recent message content
- Real-time updates — AppSync subscriptions keep the list in sync without a manual refresh
- Pull-to-refresh — a backup path for when the subscription is warming up
Rows are rendered by two components: ThreadRow for chat threads and TaskRow for external-task threads. The user doesn’t have to care about the difference; the list is unified.
Human-in-the-loop priority
Section titled “Human-in-the-loop priority”Workspace orchestration can pause an agent run when the agent needs a human decision before continuing. The mobile app treats that as a thread state, not as a separate task system.
When a thread has a pending review request:
- The thread sorts above ordinary non-HITL threads, even if another thread has newer activity.
- The row shows a
Needs answerbadge. - The preview changes to explain that the agent is waiting for confirmation.
- The Threads tab badge switches to the count of visible HITL threads before showing ordinary unread counts.
This makes the user’s next required decision visible without splitting the conversation across different tabs.
Sub-agent reviews route through the parent chain
Section titled “Sub-agent reviews route through the parent chain”If a sub-agent of one of your agents pauses for review, that review surfaces in your mobile threads — even though you’re not a participant in the sub-agent’s thread directly. The platform classifies each pending review by walking agents.parent_agent_id from the run’s agent until it finds an ancestor with a human_pair_id set; that user is the responsible human, and the review appears on their mobile.
Sub-agent rows carry an explicit Sub-agent <agent name> needs your input on <target path> label so you can tell whose work the agent is asking about. The thread detail confirmation card that opens from one of these rows is the parent agent’s thread, not the sub-agent’s — your decision wakes the sub-agent run, and the parent agent continues from there.
Reviews where the chain has no human pair anywhere (system agents like the eval test runtime, or genuinely orphaned configurations) do not appear on mobile at all. They surface in the admin app’s Inbox instead. See Workspace Orchestration → Human review flow for the full routing model.
Thread detail
Section titled “Thread detail”Route: /thread/[threadId]
Tapping a thread opens the chat view. The layout top-to-bottom:
- Message timeline. User and agent messages scroll in reverse-chronological order with user messages right-aligned and agent messages left-aligned.
- Message input footer. A multi-line input with supporting controls.
The timeline renders markdown via a custom MarkdownMessage component that handles code blocks, inline code, tables, and streaming text. In-flight agent messages render character-by-character as tokens stream from the model, so the user sees the response form in real time.
Streaming and shimmer
Section titled “Streaming and shimmer”Three visual states communicate agent activity:
- Idle — no activity, no indicator
- Thinking — the agent is working but hasn’t started streaming text yet. A
ShimmerProcessingindicator shows near the bottom of the timeline with a label like “Thinking…” or “Retrieving memory…” - Streaming — text tokens are arriving. A
ShimmerTextrender replaces the static message content with animated cursor-style text that fills in as tokens land
Subscriptions drive all three. useThreadUpdatedSubscription watches for thread-level state changes; useNewMessageSubscription delivers new message events and streaming chunks as they come in.
Tool-call inline render
Section titled “Tool-call inline render”When an agent calls a tool during a turn, the tool call renders inline in the timeline as a collapsible row: tool name, input preview, output preview. This is the mobile mirror of the Admin app’s thread detail turn-level audit view, scoped to what’s relevant to an end user.
Tool calls with rich output — for example, a tool returning an external task envelope — use the GenUI registry to render a custom block inline, instead of just plain text. The GenUI registry is how the mobile app stays extensible without shipping a new build for every new tool.
Human-in-the-loop confirmations
Section titled “Human-in-the-loop confirmations”When the user opens a thread that is waiting for review, the thread detail screen shows a confirmation card near the top of the timeline. The card is the handoff point between the agent and the user.
The card shows:
- The workspace target path the agent is waiting on.
- The review text written by the orchestration layer.
- A compact summary of proposed changes when the review includes them.
- An optional note field for context the user wants to send back to the agent.
- Actions for the decision the user wants to take.
The available actions match the state of the workspace run:
| Action | Meaning |
|---|---|
Approve | Accept the review, include the optional note if present, and clear the agent to continue. |
Continue | Resume a pending workspace run without recording a fresh approval decision. This is used when the run is already queued or only needs a nudge to continue. |
Reject | Cancel the workspace run. The agent is not resumed from that review request. |
After a successful action, the app confirms the decision. For Approve and Continue, the thread is marked active while the agent resumes in the same conversation. If the review changed after the user opened it, the app asks the user to refresh before deciding so they do not answer stale review text.
Under the hood
Section titled “Under the hood”The mobile HITL surface is backed by the workspace review GraphQL contract:
agentWorkspaceReviewslists pending reviews, filtered bystatus: "awaiting_review"andresponsibleUserId: caller.userId. TheresponsibleUserIdfilter is what scopes the list to the signed-in user — the resolver derives it by walking theparent_agent_idchain server-side, so the same query naturally captures both direct-agent and sub-agent reviews routed to this user.agentWorkspaceReviewloads the review body, ETag, event history, and proposed-change summary for the thread detail card.acceptAgentWorkspaceReview,resumeAgentWorkspaceRun, andcancelAgentWorkspaceReviewrecord the user’s decision.
Those decisions are auditable workspace events. Approval and resume decisions queue a workspace_event wakeup so the agent continues the same thread with the review response in context. Cancellation settles the run without waking the agent.
The mobile app does not hide HITL state locally as a workaround. The list and detail screens derive visibility from agentWorkspaceReviews(status: "awaiting_review", responsibleUserId: caller.userId); once the backend run leaves that state — or routes to a different responsible human — the amber row treatment and Threads tab HITL count clear naturally.
Protected orchestration paths are still protected. Review decisions should go through the GraphQL mutations above, not through generic workspace file writes.
Message input
Section titled “Message input”The message input footer is more than a plain text field. It has several stacked controls:
Workspace picker
Section titled “Workspace picker”A chip at the top of the input shows the current workspace. Tapping it opens the WorkspacePickerSheet, a bottom sheet listing the workspaces available for the active agent. Selecting one scopes the next message to that workspace — useful when an agent handles multiple project-like contexts.
Voice dictation
Section titled “Voice dictation”A microphone button next to the input opens the VoiceDictationBar. Speech is transcribed locally via iOS speech recognition and streamed into the input as text. Tapping the mic again commits the transcription and clears the bar.
Quick actions
Section titled “Quick actions”A lightning-bolt button opens the quick-actions sheet: a customizable list of one-tap prompts the user has saved (“summarize”, “plan my day”, “draft a reply”). Quick actions are per-user and sync back to the admin app through the same GraphQL schema — see Admin — Agents for the authoring side.
Plus button
Section titled “Plus button”A plus button opens the workspace-picker sheet (the same one the workspace chip opens), acting as a shortcut for users who want to change workspace before composing.
Real-time, not polling
Section titled “Real-time, not polling”Everything on the Threads list and thread detail screens is driven by AppSync subscriptions. The mobile app does not poll. When the user pulls to refresh, that’s a backup path — the subscription should already have delivered the update by the time the user’s thumb hits the screen.
When the app goes to background and comes back, subscriptions re-attach automatically via the Apollo client’s connection management, and any missed updates are backfilled through the GraphQL query cache.
Offline behavior
Section titled “Offline behavior”The mobile app is online-first: there is no offline message composition queue. If the user is offline, the message input shows a banner and the send button is disabled. Messages in the timeline that were already loaded remain visible.
This is an intentional scope decision for v1. Offline compose adds complexity (local id reconciliation, conflict resolution, optimistic ordering) that does not pay off for the primary use case of agent chat.
Related pages
Section titled “Related pages”- Threads (concept) — the thread model at the product level
- Agents (concept) — how agents produce the messages the timeline renders
- Mobile — Integrations & MCP Connect — per-user integration and MCP server setup