AG2B

useAg2bChat

Stateful hook for synchronous chat.

function useAg2bChat(): {
  send: (message: string) => Promise<AgentResponse | undefined>;
  response: AgentResponse | undefined;
  events: AgentEvent[];
  isPending: boolean;
  error: unknown;
  abort: () => void;
};

Usage

Basic chat

Send a message and render the final response.

function Chat() {
  const { send, response, isPending } = useAg2bChat();
  const [input, setInput] = useState('');

  return (
    <>
      <form
        onSubmit={(e) => {
          e.preventDefault();
          send(input);
          setInput('');
        }}
      >
        <input value={input} onChange={(e) => setInput(e.target.value)} />
        <button disabled={isPending}>{isPending ? 'sending…' : 'send'}</button>
      </form>
      {response && <div>{response.content}</div>}
    </>
  );
}

Agent Events

Use events to render progress while a send is in flight — tool calls, iteration boundaries, finish reasons:

function ChatWithIndicators() {
  const { send, events, response } = useAg2bChat();
  const toolCalls = events.filter((e) => e.type === 'agent_tool_call_start').length;

  return (
    <>
      <button onClick={() => send('What is blocked?')}>send</button>
      {toolCalls > 0 && <div>Called {toolCalls} tool(s) so far…</div>}
      {response && <div>{response.content}</div>}
    </>
  );
}

Chat History

useAg2bHistory gives you the live conversation. It updates as the loop pushes messages, so the in-flight send appears as it progresses.

function Chat() {
  const messages = useAg2bHistory();
  const { send, isPending } = useAg2bChat();
  const [input, setInput] = useState('');

  return (
    <>
      {messages.map((m, i) => (
        <div key={i}>{m.role}: {m.content ?? '(no content)'}</div>
      ))}
      <form
        onSubmit={(e) => {
          e.preventDefault();
          send(input);
          setInput('');
        }}
      >
        <input value={input} onChange={(e) => setInput(e.target.value)} />
        <button disabled={isPending}>{isPending ? 'sending…' : 'send'}</button>
      </form>
    </>
  );
}

Errors

send() never throws — it resolves to undefined and stores the failure in error which can hold:

Two exceptions:

  • Tool handler throws don't land here — the LLM can recover from them, so they're emitted as agent_tool_call_error events instead.

  • abort() doesn't land here either — to catch aborts, listen for the agent_chat_abort event.

function Chat() {
  const { send, error, isPending } = useAg2bChat();
  return (
    <>
      {error && <div role="alert">{String(error)}</div>}
      <button disabled={isPending} onClick={() => send('hi')}>send</button>
    </>
  );
}

Aborting

Cancel an in-flight send with abort(). The hook also auto-aborts on unmount and when send() is called while a prior send is still running:

function ChatWithCancel() {
  const { send, abort, isPending } = useAg2bChat();

  return (
    <>
      <button onClick={() => send('Long task')}>send</button>
      {isPending && <button onClick={abort}>cancel</button>}
    </>
  );
}

Returns

send

send: (message: string) => Promise<AgentResponse | undefined>

Calls agent.chat() with the message. Aborts any prior in-flight send and clears error. Resolves with AgentResponse, or undefined if the send was aborted, superseded by a newer send(), or threw a non-abort error.

response

response: AgentResponse | undefined

The last successful AgentResponse. Persists across the start of a new send() — only overwritten when the new send completes.

events

events: AgentEvent[]

Array of AgentEvent emitted during the current send. Resets on every send().

isPending

isPending: boolean

true while a send is in flight.

error

error: unknown

The last non-abort error from a send. Cleared automatically on the next send(). See Errors.

abort

abort: () => void

Cancel the in-flight send. See Aborting.

On this page