---
description: "Runs an agent from a component, with live status and no chat on the page."
---

# `useWebAgent`

Runs an agent from a component, with live status and no chat on the page. It is the React form of [`agent.invoke`](/docs/reference/chat/define-web-agent#agentinvoke): the page's tools run under the cursor, a confirm-gated tool waits for the person's click (`status` is `"waiting"`), and sub-agents run nested. Reach for it when a button or a form should hand a task to the agent and show how it is going.

## Import

```ts
import { useWebAgent } from "@webmcp-agents/chat";
import type {
  UseWebAgentOptions,
  WebAgentHandle,
  WebAgentStatus,
} from "@webmcp-agents/chat";
```

## Example

A button that runs the agent and lists each step it takes, including a call parked on the person's click.

```tsx title="components/reorder.tsx"
import { useWebAgent } from "@webmcp-agents/chat";

import { shopper } from "@/agents";
import { Button } from "@/components/ui/button";

// Under <WebAgentsProvider>, so the agent's tools are on the page.
export function Reorder() {
  const agent = useWebAgent(shopper);

  return (
    <div className="flex flex-col items-start gap-3">
      <Button
        onClick={() => agent.invoke("Reorder my last purchase.")}
        disabled={agent.status === "running"}
      >
        {agent.status === "running" ? "Working…" : "Reorder"}
      </Button>

      <ul>
        {agent.steps.map((step) => (
          <li key={step.id}>
            {step.tool}: {step.state}
            {step.prompt && ` (${step.prompt})`}
          </li>
        ))}
      </ul>

      {agent.status === "waiting" && <p>Click to confirm.</p>}
      {agent.error && <p role="alert">{agent.error.message}</p>}
      {agent.text && <p>{agent.text}</p>}
    </div>
  );
}
```

## Options

`useWebAgent(agent, options?)`. The first argument is the agent; the second holds the hook's own options.

| Name | Type | Default | Description |
|---|---|---|---|
| `agent` | `WebAgent` | required | The agent, from [`defineWebAgent`](/docs/reference/chat/define-web-agent). The latest render's value is used, so `invoke` stays one function. |
| `adapter` | `AgentAdapter` | one shared `createCloudAdapter()` | What runs the model: the same default as [`<AgentChat>`](/docs/reference/chat/agent-chat) and `agent.invoke`, your `/api/chat`. Create a custom adapter once, at module scope. Passed in the second argument: `useWebAgent(agent, { adapter })`. |

## Returns

A `WebAgentHandle`:

| Name | Type | Description |
|---|---|---|
| `invoke(text)` | `(text: string) => Promise<WebAgentResult \| undefined>` | Run the agent on one message: a fresh conversation each time, and a run in flight is stopped first. Resolves with the result (`text`, `steps`, `messages`), or `undefined` when the run was stopped or failed. It never rejects, so `onClick={() => agent.invoke("…")}` needs no `catch`; a failure is in `error`. An empty message does nothing. |
| `stop()` | `() => void` | Stop the run in flight: the model, the tool running and any sub-agent. `status` goes back to `idle` and the open steps show as `cancelled`. |
| `status` | `WebAgentStatus` | `"idle"` (none yet, finished or stopped), `"running"`, `"waiting"` (a tool is parked on the page until the person clicks; see the steps' `prompt`) or `"error"` (the last run failed). |
| `steps` | `WebAgentStep[]` | The tool calls of the current or last run, live, a sub-agent's included (with `agent` set). See [`WebAgentStep`](/docs/reference/chat/define-web-agent#agentinvoke-result). |
| `text` | `string` | The agent's answer so far, streamed. |
| `error` | `SessionError` | Why the last run failed: `{ message, code? }`, with a code the adapter gave (offline, rate limited…). Cleared by the next `invoke`. |

## Notes

- It aborts the run in flight when the component unmounts.
- The page's tools are read again after each tool call, once they have settled, so a navigation's new tools are there for the next step.
- It needs the page's tools to be registered, so render it under [`<WebAgentsProvider>`](/docs/reference/react/web-agents-provider). The agent's `tools` list picks from them.
- To render a full conversation instead, use [`useAgentChat`](/docs/reference/chat/use-agent-chat) or [`<AgentChat>`](/docs/reference/chat/agent-chat).

## See also

- [Call an agent](/docs/build/call-an-agent), the page that teaches it
- [`defineWebAgent`](/docs/reference/chat/define-web-agent) (`agent.invoke`, `WebAgentStep`, `WebAgentResult`)
- [`useAgentChat`](/docs/reference/chat/use-agent-chat)
- [Adapter types](/docs/reference/chat/adapter-types)
