> ## Documentation Index
> Fetch the complete documentation index at: https://www.algolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ais-result-card

> Displays an AI Overview card above the results with an Agent Studio recommendation based on the query and the top hits.

This widget is **experimental** and is subject to change in minor versions.

For more information, see [Agent Studio](https://www.algolia.com/doc/guides/algolia-ai/agent-studio).

```vue Signature theme={"system"}
<ais-result-card
  // Required parameter
  agent-id="string"
  // Optional parameters, at most one of
  :transport="object"
  :request-options="object"
  // Optional parameters
  :class-names="object"
  :translations="object"
/>
```

## Import

> [tab] Component
>
> To ensure optimal bundle sizes,
> see [Optimize build size](https://www.algolia.com/doc/guides/building-search-ui/going-further/improve-performance/vue.md#optimize-build-size).
>
> ```js Vue icon=code theme={"system"}
> import { AisResultCard } from "vue-instantsearch";
> // Use "vue-instantsearch/vue3/es" for Vue 3
>
> export default {
>   components: {
>     AisResultCard,
>   },
>   // ...
> };
> ```

> [tab] Plugin
>
> This imports all widgets, even the ones you don't use.
> For more information, see [Get started with Vue InstantSearch](https://www.algolia.com/doc/guides/building-search-ui/getting-started/vue.md).
>
> ```js JavaScript icon="code" theme={"system"} theme={"system"}
> import Vue from "vue";
> import InstantSearch from "vue-instantsearch";
> // Use "vue-instantsearch/vue3/es" for Vue 3
>
> Vue.use(InstantSearch);
> ```

## About this widget

Use `ais-result-card` to display an "AI Overview" card above your results.
The widget sends the query, the active filters, and the first five hits to an Agent Studio agent as [per-turn context](https://www.algolia.com/doc/guides/algolia-ai/agent-studio/how-to/turn-context.md),
and asks the agent which of these results it recommends and why.
The answer streams into the card, and a skeleton placeholder shows until the first text arrives.

The card only shows when the search meets both conditions:

* A [rule](https://www.algolia.com/doc/guides/managing-results/rules/rules-overview) that matches the search sets `renderingContent.widgets.resultCard.enabled` to `true` in the search response. For more information, see [Activate the card with a rule](#activate-the-card-with-a-rule).
* The query has at least two words.

The widget sends a new request only when the query, the filters, or the first five hits change.
Going to another page of results doesn't send a new request.

Users can collapse the card to its header, which hides the answer, the follow-up suggestions, and the **Continue in chat** button.
The answer keeps generating in the meantime, and the card stays collapsed for new searches until users restore it.
The card clips long answers and shows a **Show more** button to reveal the full text.
If the answer completes without any text, the card doesn't render.

When an [`ais-chat`](https://www.algolia.com/doc/api-reference/widgets/chat/vue) widget with the same `agent-id` is on the same index,
the card shows a **Continue in chat** button and up to two follow-up suggestions from the agent.
Both hand the card's conversation to the chat and open it.
A suggestion is also sent to the chat as the next message.
If the chat is generating a response, the handoff doesn't happen.
That makes the widget an entry point for the chat, so a page with both doesn't also need an [`ais-chat-trigger`](https://www.algolia.com/doc/api-reference/widgets/chat-trigger/vue) widget.
Without a matching `ais-chat` widget, the card hides these actions and, in development, logs a warning.

## Activate the card with a rule

The widget adds the [rule context](https://www.algolia.com/doc/api-reference/api-parameters/ruleContexts.md) `agent-studio-result-card-AGENT_ID` to every search,
where `_` replaces any character in the agent ID other than letters, digits, `_`, and `-`.
Use this context as a rule condition to limit the rule to searches that include the widget.

To show the card, add a rule whose consequence sets [`renderingContent`](https://www.algolia.com/doc/api-reference/api-parameters/renderingContent) in its search parameters:

```json JSON icon=braces theme={"system"}
{
  "renderingContent": {
    "widgets": {
      "resultCard": {
        "enabled": true
      }
    }
  }
}
```

## Examples

```vue Vue icon=code expandable theme={"system"}
<template>
  <ais-instant-search index-name="INDEX_NAME" :search-client="searchClient">
    <ais-search-box />
    <ais-result-card agent-id="AGENT_ID" />
    <ais-hits />
    <ais-chat agent-id="AGENT_ID" />
  </ais-instant-search>
</template>

<script>
  import { liteClient as algoliasearch } from "algoliasearch/lite";

  export default {
    data() {
      return {
        searchClient: algoliasearch("ALGOLIA_APPLICATION_ID", "ALGOLIA_SEARCH_API_KEY"),
      };
    },
  };
</script>
```

## Props

**agent-id** `string` *required*

The unique identifier of the agent to connect to.
You can find the agent ID in the [Agent Studio dashboard](https://dashboard.algolia.com/generativeAi/agent-studio/agents).
It's required even with a custom [`transport`](#param-transport), because the widget derives its rule context from it.
The card only hands its conversation to an `ais-chat` widget with the same `agent-id`.

```vue Vue icon=code theme={"system"}
<ais-result-card agent-id="AGENT_ID" />
```

**transport** `object`

A custom transport object to send the card's requests to your own backend instead of Agent Studio.
It has the same shape as the [`transport`](https://www.algolia.com/doc/api-reference/widgets/chat/vue#param-transport) prop of the `ais-chat` widget.
You can't use it together with [`request-options`](#param-request-options).

```vue Vue icon=code theme={"system"}
<ais-result-card
  agent-id="AGENT_ID"
  :transport="{
    api: 'https://chatapi.example.com/api/v1/chat',
  }"
/>
```

**request-options** `object`

Request options to send with the built-in Agent Studio completion requests.
You can't use it together with [`transport`](#param-transport).

The object accepts the following properties:

* `queryParameters` (`Record<string, string | number | boolean>`). Query parameters to append to each completion request.
* `headers` (`Record<string, string> | Headers`). Headers to send with each completion request.

```vue Vue icon=code theme={"system"}
<ais-result-card
  agent-id="AGENT_ID"
  :request-options="{
    headers: {
      'X-Session-Id': 'SESSION_ID',
    },
  }"
/>
```

**class-names** `object` (default: \{})

The [CSS classes you can override](https://www.algolia.com/doc/guides/building-search-ui/widgets/customize-an-existing-widget/vue.md#style-your-widgets):

* `ais-ResultCard`. The root element of the widget.
* `ais-ResultCard-header`. The header element.
* `ais-ResultCard-headerTitle`. The header title element.
* `ais-ResultCard-continueButton`. The **Continue in chat** button.
* `ais-ResultCard-minimizeButton`. The button that minimizes or maximizes the card.
* `ais-ResultCard-body`. The element that holds the answer and clips it.
* `ais-ResultCard-loader`. The skeleton placeholder shown while the answer loads.
* `ais-ResultCard-message`. Each answer message.
* `ais-ResultCard-suggestions`. The follow-up suggestions container.
* `ais-ResultCard-expandButton`. The button that shows or clips a long answer.

```vue Vue icon=code theme={"system"}
<ais-result-card
  agent-id="AGENT_ID"
  :class-names="{
    'ais-ResultCard': 'MyCustomResultCard',
    'ais-ResultCard-body': 'MyCustomResultCardBody',
  }"
/>
```

**translations** `object`

A dictionary of translations to customize the UI text and support internationalization.

* `headerTitle`. The title displayed in the header. Defaults to `"AI Overview"`.
* `continueInChatText`. The text of the button that hands the conversation to the chat. Defaults to `"Continue in chat"`.
* `minimizeLabel`. The accessible label of the button that minimizes the card. Defaults to `"Minimize"`.
* `maximizeLabel`. The accessible label of the button that maximizes a minimized card. Defaults to `"Maximize"`.
* `expandText`. The text of the button that shows a clipped answer in full. Defaults to `"Show more"`.
* `collapseText`. The text of the button that clips an expanded answer. Defaults to `"Show less"`.
* `retryText`. The text of the retry button shown when the request fails. Defaults to `"Retry"`.

```vue Vue icon=code theme={"system"}
<ais-result-card
  agent-id="AGENT_ID"
  :translations="{
    headerTitle: 'Our pick',
    continueInChatText: 'Ask a follow-up question',
  }"
/>
```

## Customize the UI

**layout**

The slot to replace the whole card with custom markup.
The slot owns the full rendering, including every status and the retry and handoff actions.
When you use it, the [`class-names`](#param-class-names) and [`translations`](#param-translations) props don't apply.

**Scope**

* `status: 'hidden' | 'loading' | 'streaming' | 'complete' | 'failed'`.
  The card status.
  It's `hidden` when no rule enables the card or when the query is shorter than two words.
  It's `loading` while the widget waits to send the request and until the response starts streaming.
* `query: string`.
  The query the answer is about.
* `messages: UIMessage[]`.
  The card's conversation: the user message, then the assistant answer as it streams.
  The user message contains the full question that the widget sends to the agent. To display the query, use `query` instead.
* `error: Error | undefined`.
  The error of the latest failed request.
  It's only set when `status` is `failed`.
* `suggestions: string[] | undefined`.
  Follow-up suggestions sent by the agent with the answer.
* `retry: () => void`.
  Sends the request again.
* `canContinueInChat: boolean`.
  Whether an `ais-chat` widget with the same `agent-id` is on the same index.
* `continueInChat: (message?: string) => void`.
  Hands the conversation to the `ais-chat` widget and opens it.
  When you pass `message`, the chat sends it as the next message.
* `expanded: boolean`.
  Whether a long answer shows in full instead of clipped.
* `setExpanded: (expanded: boolean) => void`.
  Shows or clips a long answer.
* `sendEvent: function`.
  Sends an event to the Insights middleware.

```vue Vue icon=code expandable theme={"system"}
<template>
  <ais-result-card agent-id="AGENT_ID">
    <template
      v-slot:layout="{ status, messages, error, retry, canContinueInChat, continueInChat }"
    >
      <div v-if="status === 'failed'">
        <p>{{ error ? error.message : "Something went wrong." }}</p>
        <button @click="retry()">Retry</button>
      </div>
      <section v-else-if="status !== 'hidden'">
        <p>{{ getAnswer(messages) || "Loading..." }}</p>
        <button
          v-if="status === 'complete' && canContinueInChat"
          @click="continueInChat()"
        >
          Continue in chat
        </button>
      </section>
    </template>
  </ais-result-card>
</template>

<script>
  export default {
    methods: {
      getAnswer(messages) {
        return messages
          .filter((message) => message.role === "assistant")
          .flatMap((message) => message.parts)
          .filter((part) => part.type === "text")
          .map((part) => part.text)
          .join("");
      },
    },
  };
</script>
```

## HTML output

```html HTML icon=code-xml theme={"system"}
<section class="ais-ResultCard" data-status="complete" aria-live="polite">
  <div class="ais-ResultCard-header">
    <span class="ais-ResultCard-headerTitle">
      <svg>...</svg>
      AI Overview
    </span>
    <button class="ais-Button ais-Button--outline ais-Button--sm ais-ResultCard-continueButton">
      Continue in chat
    </button>
    <button class="ais-Button ais-Button--ghost ais-Button--sm ais-Button--icon-only ais-ResultCard-minimizeButton" title="Minimize" aria-label="Minimize" aria-expanded="true">
      <svg>...</svg>
    </button>
  </div>
  <div class="ais-ResultCard-body ais-ResultCard-body--clipped">
    <article class="ais-ChatMessage ais-ChatMessage--left ais-ChatMessage--subtle ais-ResultCard-message">...</article>
  </div>
  <button class="ais-Button ais-Button--ghost ais-Button--sm ais-ResultCard-expandButton" aria-expanded="false">
    Show more
    <svg>...</svg>
  </button>
</section>
```

While the answer loads, the body holds a skeleton placeholder instead of the message:

```html HTML icon=code-xml theme={"system"}
<div class="ais-ResultCard-body">
  <div class="ais-ResultCard-loader">
    <div class="ais-ResultCard-loaderLine"></div>
    <div class="ais-ResultCard-loaderLine"></div>
    <div class="ais-ResultCard-loaderLine"></div>
  </div>
</div>
```

When users collapse the card, the `ais-ResultCard-minimizeButton` button has `aria-expanded="false"` and the `Maximize` label, and the body, the expand button, the **Continue in chat** button, and the suggestions don't render.

When users expand a long answer, or when the request fails, the body has the `ais-ResultCard-body--expanded` class.
When the answer is complete and isn't clipped, the follow-up suggestions render after the body in a `div` with the `ais-ChatPromptSuggestions ais-ResultCard-suggestions` classes.
