eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
135 lines (101 loc) • 6.27 kB
text/mdx
---
title: "useEveAgent (Vue)"
description: "Use the eve Vue composable and its Vue-specific reactive interface."
---
`useEveAgent()` from `eve/vue` exposes the shared eve frontend client as Vue computed refs and methods. Read the [frontend overview](./overview) for session behavior, messages, human input, authorization, callbacks, reducers, and persistence. This page covers the Vue-specific interface.
Nuxt users normally receive the composable as an auto-import after registering the [`eve/nuxt` module](./nuxt).
## Basic usage
Import the composable from `eve/vue`. Its state is exposed as `ComputedRef`s, so templates unwrap it automatically:
```vue
<script setup lang="ts">
import { useEveAgent } from "eve/vue";
import { computed, ref } from "vue";
const { data, status, send } = useEveAgent();
const message = ref("");
const isBusy = computed(() => status.value === "submitted" || status.value === "streaming");
const isInputDisabled = computed(() => isBusy.value || status.value === "resuming");
async function handleSubmit() {
const text = message.value.trim();
if (!text || isInputDisabled.value) return;
message.value = "";
await send(text);
}
</script>
<template>
<div v-for="item in data.messages" :key="item.id">
<p>{{ item.role }}: {{ item.parts }}</p>
</div>
<form @submit.prevent="handleSubmit">
<input v-model="message" :disabled="isInputDisabled" />
<button type="submit" :disabled="isInputDisabled">Send</button>
</form>
</template>
```
## What it returns
The state fields are computed refs; the commands are ordinary methods:
| Property | Vue shape |
| ---------------------------------------------- | ---------------------------------------------- |
| `data` | `ComputedRef<TData>` |
| `status` | `ComputedRef<UseEveAgentStatus>` |
| `error` | `ComputedRef<Error \| undefined>` |
| `events` | `ComputedRef<readonly MessageStreamEvent[]>` |
| `session` | `ComputedRef<ClientSessionState \| undefined>` |
| `send`, `respond`, `resume`, `cancel`, `reset` | Methods |
Destructuring preserves reactivity because each state value remains a ref. Read refs with `.value` in `<script>` and without `.value` in a template. The [shared returned-state reference](./overview#returned-state) describes what each value and command does.
## Send a message
Call `send(text)` for text or pass content parts for attachments. The API and transport behavior match the [shared sending guide](./overview#sending-and-streaming); only reactive access differs in Vue.
## Human-in-the-loop prompts
Pending requests appear in `data.value.messages`. Use the Vue exports when narrowing message parts, then answer through `respond()`:
```vue
<script setup lang="ts">
import { computed } from "vue";
import { useEveAgent } from "eve/vue";
const { data, respond } = useEveAgent();
const pendingRequests = computed(() =>
data.value.messages.flatMap((message) =>
message.parts.flatMap((part) => {
if (part.type !== "dynamic-tool" || part.state !== "approval-requested") return [];
const request = part.toolMetadata?.eve?.inputRequest;
return request ? [request] : [];
}),
),
);
</script>
<template>
<fieldset v-for="request in pendingRequests" :key="request.requestId">
<legend>
{{
request.kind === "tool-approval"
? "Approval required"
: request.kind === "question"
? "Question"
: "Session limit"
}}
</legend>
<p>{{ request.prompt }}</p>
<button
v-for="option in request.options ?? []"
:key="option.id"
type="button"
@click="respond([{ requestId: request.requestId, optionId: option.id }])"
>
{{ option.label }}
</button>
</fieldset>
</template>
```
See [Human-in-the-loop prompts](./overview#human-in-the-loop-prompts) for request semantics and rendering guidance.
## Cancel, reset, and resume
Call `cancel()` to stop the durable server-side turn while the composable remains attached through settlement. Disposing the component only disconnects its local stream; it does not cancel server execution. Call `reset()` to clear local state and start a new session. Pass `initialSession`, `initialEvents`, and `resume: true` to restore a saved conversation and follow an in-flight turn. During bounded catch-up, `status.value` is `"resuming"`; keep the hydrated conversation visible, disable submission, and wait for `"ready"`, `"error"`, or `"streaming"`. Use `resume()` directly when restoration is controlled imperatively. See [Resumable sessions](./overview#resumable-sessions) for the persistence contract and [Sending and streaming](./overview#sending-and-streaming) for cancellation behavior.
## Custom host and credentials
Pass `host`, `auth`, or `headers` to the composable using the same options as the other frontend bindings. See [Custom hosts and headers](./overview#custom-hosts-and-headers).
## Attach page context per turn
Pass `clientContext` to `send()` or `respond()`, or use `prepareSend` to add context before every turn. See [Attach page context per turn](./overview#attach-page-context-per-turn).
## Lifecycle callbacks
Pass `onEvent`, `onError`, `onFinish`, or `onSessionChange` when the application needs lifecycle notifications. See [Lifecycle callbacks](./overview#lifecycle-callbacks) for callback timing and optimistic projection behavior.
## Custom reducer
Import `EveAgentReducer` from `eve/vue` when projecting events into application-specific state. The resulting `data` remains a `ComputedRef<TData>`. See [Custom reducer](./overview#custom-reducer) for the reducer contract and client projection events.
## What to read next
- [Nuxt](./nuxt): register the module and mount the eve runtime.
- [Frontend overview](./overview): use the shared frontend API.
- [Sessions, runs, and streaming](../../concepts/sessions-runs-and-streaming): understand the underlying session protocol.