Docs / ai / useAgent

useAgent

hooksince 0.1.0

Run AI agent queries with streaming, tool calls, interrupts, status updates, and automatic conversation persistence.

import { useAgent } from 'flowstack-sdk'

useAgent is the primary AI hook: it runs agent queries with token streaming, surfaces active/completed tool calls and connected data sources, and supports mid-execution interrupts.

Template (first arg): 'data-science' | 'marketing' | 'support' | 'custom'. For a persona-backed app (your app's brain is an agent registered via casino_create_agent), the template is just a fallback label — the registered persona overrides it. Use 'custom' (or omit) and select the brain with the persona option. The template does not pick the agent.

Conversation memory (automatic): useAgent persists a stable session ID for each component mount — generated on first use via crypto.randomUUID() (with a timestamp fallback for legacy browsers), stable across turns (every query() passes the same session ID), and reused by Strands' S3SessionManager so the agent remembers prior messages, tool calls, and context across turns. clearMessages() resets the session, generating a fresh session ID on the next query(). The session ID is tied to the component mount: unmounting/remounting (e.g. closing and reopening a modal) starts a new conversation. The simplest path (0.2.1+) for cross-reload persistence is to pass a stable sessionKey per surface; for cross-tab or multi-conversation persistence, manage the session ID at the application level (e.g. in localStorage). Wallet-authenticated users have conversations scoped to their wallet address server-side.

ChatMessage fields (each item in messages): id (string), role ('user' | 'assistant'), content (string), isStreaming (boolean), statusLine (string | undefined — live status text during streaming), toolCalls (ToolCall[]), visualizations (VisualizationData[]), searchResults (SearchResultsData[]).

Signature

const { messages, isStreaming, isLoading, toolCalls, connectedDataSources, error, query, clearMessages, startNewSession, cancelQuery, interruptAgent, respondToInterrupt } = useAgent(template?, options?)

Parameters

ParamTypeNotesDescription
template'data-science' | 'marketing' | 'support' | 'custom'Fallback template label (first arg). For persona-backed apps the registered persona overrides it — use 'custom' (or omit) and pick the brain via persona. The template does NOT select the agent.
options.capabilitiesstring[]Pre-load tool categories the agent may use. The nine categories are data_access, external_integration, site_operations, code_execution, domain_task, workspace_management, agent_management, specialist_agents, automation_managementdata_access covers the MongoDB read/write tools needed for the Reason→Write→Read pattern. Grant only what the task needs; most built-app agents only need data_access. For persona-backed apps the registered definition is authoritative — capabilities passed here are advisory and cannot widen it. Run casino_list_tools for the live category set.
options.personastringsince 0.2.1Target a specific registered persona/subagent by name (maps to target_agents). Without it the backend auto-selects the FIRST registered persona, so multi-persona apps MUST set this to reach the others. (agentName is an alias.)
options.systemPromptstringsince 0.2.1Inline system-prompt override for this hook (maps to system_prompt_override). Use to tune behavior per-surface without registering a separate persona.
options.sessionKeystringsince 0.2.1Namespaces this hook's conversation. Pass a stable, distinct value per surface (e.g. 'chat', 'tasks') so independent useAgent instances don't share one conversation. It also persists that surface's history across reloads (same tab). Omit only for a single-surface app.
options.toolsstring[]Whitelist specific tool names (finer-grained than capabilities).
options.targetAgent(s)string | string[]Deprecated (Strands swarm, removed in P0-73). Use persona instead.

Returns

FieldTypeDescription
messagesChatMessage[]Conversation messages (see ChatMessage fields).
isStreamingbooleanWhether the agent is currently streaming a response.
isLoadingbooleanWhether a query is in flight.
toolCallsToolCall[]Active/completed tool executions.
connectedDataSourcesDataSourceBadgeInfo[]Connected data sources.
errorstring | nullLast error message.
query(prompt: string, attachments?: AttachmentInput[], allowedTerms?: string[]) => Promise<void>Send a prompt to the agent. Optionally pass attachments — images (png/jpeg/webp/gif) ride the /stream wire as vision content blocks the model can SEE (since 0.2.5); non-image files (PDF/CSV/DOCX…) upload before streaming and land as datasets/context. allowedTerms scopes PII unmasking for this turn.
clearMessages() => voidWipe in-memory messages and clear the stored session ID, so the next query() starts a fresh session.
startNewSession() => voidForce a brand-new backend session (fresh conversation), discarding prior context. Stronger than clearMessages(), which only clears the local session id.
cancelQuery() => voidCancel the in-flight query.
interruptAgent() => Promise<void>Pause the agent mid-execution.
respondToInterrupt(response: string) => Promise<void>Resume a paused agent with user input.

Examples

Persona-backed, multi-surface app
// Each surface gets its own brain + isolated conversation.
const chat   = useAgent('custom', { capabilities: ['data_access'], persona: 'assistant', sessionKey: 'chat' });
const worker = useAgent('custom', { capabilities: ['data_access'], persona: 'worker',    sessionKey: 'tasks' });
Multi-turn chat with automatic memory
function AssistantChat() {
  const { query, messages, isStreaming } = useAgent(undefined, {
    persona: 'assistant'  // agent registered via casino_create_agent
  });

  // Turn 1: "summarize this dataset"
  // Turn 2: "now group it by region"      ← agent remembers "this dataset"
  // Turn 3: "which region is the biggest?" ← agent knows the grouping from turn 2

  return (
    <ChatUI messages={messages} onSend={query} isStreaming={isStreaming} />
  );
}
Persist a conversation across reloads (0.2.1+)
const chat = useAgent('custom', { capabilities: ['data_access'], sessionKey: 'support-chat' });
// Reopening/reloading this surface resumes the same conversation; a different sessionKey is a
// different conversation. Call chat.clearMessages() / startNewSession() to start fresh.
WarningMultiple useAgent instances on one page: before 0.2.1 they all SHARED one tenant-wide session, so surfaces bled into each other (a reply from one surface showing up in another). Fix: give each instance a distinct sessionKey (0.2.1+) so conversations stay isolated.
NoteIf a built app appears to "forget" every turn: (1) check your SDK version — apps built before the sessionIdRef fix don't pass a session ID at all, so rebuild via edit_site/build_site; (2) make sure you're not remounting the component between queries (conditional rendering on isStreaming can cause remounts); (3) ensure multiple instances each use a distinct sessionKey; (4) check the console for warnings about crypto.randomUUID not being available (very old browsers).
NoteUse useConversations() to list the user's past conversations and useConversation(id) to restore one (both shipped). For custom multi-conversation UIs you can also manage session IDs at the application level.
NoteImage attachments (0.2.5+): pass Files (or { filename, content_type, data } wire objects) as the 2nd arg to query. Images with a vision-capable mime type (image/png, image/jpeg, image/webp, image/gif) are sent inline as base64 vision blocks on the /stream request, so the model actually sees them. Non-image files continue to upload first and attach as datasets/context.

See also

useCollection · useAuth · useDatasets

Source: README.md#useagent · Also available in llms-full.txt and registry.json.