Skip to main content

Overview

@akapulu/react is the lower-level React package in the Akapulu Web SDK. It gives you the provider, hooks, and media helpers you need to build your own React conversation UI.

Installation

npm install @akapulu/react

Quickstart

AkapuluProvider takes paths to your local API routes:
  • connectPath
  • updatesPath
The browser calls those local routes. Your server routes then call Akapulu APIs through @akapulu/server.
import { AkapuluProvider, useAkapuluSession } from "@akapulu/react";

function ConversationState() {
  const { status, start, end, transcripts, currentNode } = useAkapuluSession();

  return (
    <div>
      <div>Status: {status}</div>
      <div>Current node: {currentNode?.label ?? "none"}</div>
      <button onClick={() => void start()}>Start</button>
      <button onClick={() => void end()}>End</button>
      <div>{transcripts.length} transcript rows</div>
    </div>
  );
}

export function App() {
  return (
    <AkapuluProvider
      config={{
        endpoints: {
          connectPath: "/api/akapulu/connect",
          updatesPath: "/api/akapulu/updates",
        },
      }}
    >
      <ConversationState />
    </AkapuluProvider>
  );
}

Main exports

The public exports currently include:
  • AkapuluProvider
  • useAkapuluSession
  • useAkapuluEvents
  • useAkapuluDailyCall
  • useAkapuluMediaControls
  • AkapuluBotAudio
  • AkapuluConfig
  • AkapuluEvent

Provider

AkapuluProvider wraps your app and creates the conversation session store.
type AkapuluProviderProps = {
  config: AkapuluConfig;
  children: ReactNode;
}
AkapuluConfig includes:
endpoints.connectPath
string
required
Local connect endpoint called by the browser.
endpoints.updatesPath
string
required
Local updates endpoint called by the browser.
connectBody
Record<string, unknown>
Optional JSON payload forwarded to your local connect route.
updatesPollIntervalMs
number
Optional polling interval override for the local updates route.
While status === "connecting", the React SDK waits up to 100 seconds for the backend to report that the call is ready. If the updates route never reports call_is_ready: true within that window, the session transitions to:
  • status: "error"
  • error.code: "UPDATES_TIMEOUT"
  • error.message: "Timed out waiting for assistant to become ready."
transport
AkapuluTransport
Optional custom transport implementation.
Ending a call: When your user ends the call in your app, call end() from useAkapuluSession(). That leaves the Daily room from the browser and runs the SDK teardown so the session is no longer live. If the assistant disconnects from Daily first, AkapuluProvider calls end() for you so status does not stay connected with no assistant in the room.

Hooks

useAkapuluSession()

Call useAkapuluSession() anywhere under AkapuluProvider. It exposes everything in the session store plus start / end:
const {
  status,
  start,
  end,
  error,
  callIsReady,
  conversationSessionId,
  completionPercent,
  latestUpdateText,
  currentNode,
  transcripts,
  botSpeakingState,
} = useAkapuluSession();
Lifecycle & connection
  • status — where the client is in the join/leave flow: "idle""connecting""connected""disconnecting" / "ended", or "error" if something failed.
  • start / end — async actions that begin the conversation (connect + Daily join) or hang up and reset session state.
  • error — when status is "error", structured details (code optional, message required) for your error UI or logging.
Call readiness & updates (from your updates route)
  • callIsReady — whether the backend considers the call ready (often used while status === "connecting" so you are not stuck on a spinner forever).
  • completionPercent — numeric progress through the scenario (0–100).
  • latestUpdateText — short human-readable status line for loading/progress copy.
Scenario / flow
  • currentNode — the active scenario node ({ key, label }) or null if none.
Transcript & bot
  • transcripts — ordered list of rows (id, text, speaker, timestamp, isFinal) for your own transcript UI.
  • botSpeakingState"idle", "speaking", or "listening" for indicators or turn-taking UI.
Correlation
  • conversationSessionId — Akapulu conversation session id from connect (used when polling updates; also useful if your app logs or links out to dashboard/API records).
See Customize Conversation UI for how this fits into a full custom layout with Daily and media helpers.

useAkapuluEvents(listener)

Subscribes to the normalized AkapuluEvent stream. See Callbacks and events.

useAkapuluMediaControls()

Returns media control helpers for the underlying Daily call.
type AkapuluMediaControls = {
  isMicMuted: boolean;
  isCamOff: boolean;
  canControlMedia: boolean;
  setMicMuted: (muted: boolean) => void;
  setCamOff: (off: boolean) => void;
  toggleMic: () => void;
  toggleCam: () => void;
}

useAkapuluDailyCall()

Returns the active Daily call object for the current session—the same DailyCall instance AkapuluProvider wires into Daily’s DailyProvider. Before the client exists, this hook returns null. For most React UI you should use @daily-co/daily-react under AkapuluProvider; useDaily() reads that call object from context and is the usual way to drive video tiles, participants, and tracks. Use useAkapuluDailyCall() when you want the call object reference directly (for example code aligned with Daily call-object methods without importing useDaily).

Main unions and types

SessionStatus

type SessionStatus =
  | "idle"
  | "connecting"
  | "connected"
  | "disconnecting"
  | "ended"
  | "error";
When the session enters status: "error", the SDK disconnects from the active Daily call and clears the active session state before surfacing the error to your UI.

BotSpeakingState

type BotSpeakingState = "idle" | "speaking" | "listening";

AkapuluEvent

The main event union includes:
  • status_changed
  • bot_speaking_state_changed
  • node_changed
  • tool_event
  • transcript_updated
  • call_ready
  • timeout
See Callbacks and events for the full breakdown.

When to use this package

Use @akapulu/react when you want to:
  • build your own layout
  • render your own transcript UI
  • control how tool events appear
  • own your call controls and post-call flow
If you want a prebuilt conversation UI instead, use React UI.