---
title: "useEveAgent (Vue)"
description: "Vue composable that drives an Eve agent session from the browser."
---

`useEveAgent()` from `eve/vue` is how a Vue app talks to an Eve session. It opens a long-lived session and sends turns, and it folds every stream event into reactive data you can bind in a template. Nuxt auto-imports it through the [module](./nuxt), and the [frontend overview](./overview) covers the shared model.

## Basic usage

Import the composable from `eve/vue`. Its state is exposed as `ComputedRef`s, so you read it unwrapped in templates:

```vue
<script setup lang="ts">
import { useEveAgent } from "eve/vue";

const { data } = useEveAgent();
</script>

<template>
  <div v-for="message in data.messages" :key="message.id">
    <p>{{ message.role }}: {{ message.parts }}</p>
  </div>
</template>
```

## What it returns

| Property  | Type                              | Description                                                               |
| --------- | --------------------------------- | ------------------------------------------------------------------------- |
| `data`    | `ComputedRef<TData>`              | Projected state. With the default reducer, `EveMessageData` (`messages`). |
| `status`  | `ComputedRef<UseEveAgentStatus>`  | `"ready"`, `"submitted"`, `"streaming"`, or `"error"`.                    |
| `error`   | `ComputedRef<Error \| undefined>` | Last transport-level error.                                               |
| `events`  | `ComputedRef<...>`                | Raw server events for this session.                                       |
| `session` | `ComputedRef<SessionState>`       | Snapshot of session state.                                                |
| `send`    | `(input) => Promise`              | Send text or a full turn (multi-part, attachments, HITL responses).       |
| `stop`    | `() => void`                      | Abort the in-flight request.                                              |
| `reset`   | `() => void`                      | Clear state and start a new session.                                      |

The first five are `ComputedRef`s; the rest are methods. Destructure whatever you need: refs keep their reactivity through destructuring. Read them with `.value` in `<script>`, and unwrapped in `<template>`.

## Send a message

```vue
<script setup lang="ts">
import { ref } from "vue";
import { useEveAgent } from "eve/vue";

const { send } = useEveAgent();
const message = ref("");

async function handleSubmit() {
  const text = message.value.trim();
  if (!text) return;
  message.value = "";
  await send({ message: text });
}
</script>

<template>
  <form @submit.prevent="handleSubmit">
    <input v-model="message" placeholder="Type a message..." />
    <button type="submit">Send</button>
  </form>
</template>
```

For anything beyond plain text, reach for `send()`. Attachments follow the AI SDK `UserContent` format:

```vue
<script setup lang="ts">
import { useEveAgent } from "eve/vue";

const { send } = useEveAgent();

async function onFileChange(event: Event) {
  const file = (event.target as HTMLInputElement).files?.[0];
  if (!file) return;
  await send({
    message: [
      { type: "text", text: "Describe this image." },
      { type: "file", data: new Uint8Array(await file.arrayBuffer()), mediaType: file.type },
    ],
  });
}
</script>
```

## Human-in-the-loop prompts

A tool opts into approval with `needsApproval` ([Tools](../tools)). When it triggers, the pending request shows up as a `dynamic-tool` part on the latest message. Read it and answer with `send({ inputResponses })`. That find-and-answer flow is the same across every framework, so the full example lives in the [Frontend overview](./overview#human-in-the-loop-prompts).

## Stop, reset, and resume

`stop()` aborts the in-flight stream. `reset()` wipes state and starts a fresh session. To survive a reload, pass `initialSession` to restore a saved session and `onSessionChange` to persist the cursor as it moves:

```ts
const agent = useEveAgent({
  initialSession: savedSessionState,
  initialEvents: savedEvents,
  onSessionChange: (session) => {
    localStorage.setItem("eve-session", JSON.stringify(session));
  },
});
```

## Custom host and credentials

When your Eve server lives somewhere other than the same origin, point at it with `host` and attach credentials through `auth` or `headers`. Pass a function and it re-resolves before each request:

```ts
const agent = useEveAgent({
  host: "https://agent.example.com",
  headers: async () => ({
    authorization: `Bearer ${await getAccessToken()}`,
  }),
});
```

## What to read next

- [Nuxt](./nuxt): module setup
- [Frontend overview](./overview): the shared integration model
- [Sessions, runs & streaming](../advanced/sessions-runs-and-streaming)
