# Multi-turn conversations

The Query Agent transforms a natural language query into actionable searches. You can either pass a single string for the query, or provide more context by including a full conversation with previous message turns.

:::code-group{sync="languages"}
```python title="Python"
from weaviate.agents.classes import ChatMessage

conversation = [
    ChatMessage(
        role="user",
        content=(
            "I have some questions about the weather data. "
            "You can assume the temperature is in Fahrenheit "
            "and the wind speed is in mph."
        )
    ),
    ChatMessage(
        role="assistant",
        content=(
            "I can help with that. "
            "What specific information are you looking for?"
        )
    ),
    ChatMessage(
        role="user",
        content=(
            "What's the average wind speed, the max wind speed, "
            "and the min wind speed?"
        )
    )
]

response = qa.ask(conversation)
```

```typescript title="JavaScript/TypeScript"
import { ChatMessage } from 'weaviate-agents';

const conversation: ChatMessage[] = [
    {
        role: "user",
        content: "Hi!"
    },
    {
        role: "assistant",
        content: "Hello! How can I assist you today?"
    },
    {
        role: "user",
        content: "I have some questions about the weather data. You can assume the temperature is in Fahrenheit and the wind speed is in mph.",
    },
    {
        role: "assistant",
        content: "I can help with that. What specific information are you looking for?",
    },
    {
        role: "user",
        content: "What's the average wind speed, the max wind speed, and the min wind speed",
    }
]

const response = await qa.ask(conversation)
```
:::

Each message in the conversation must have a `role`, being either `"user"` or `"assistant"`, and `content`, being the text of the message.

The final message should be a user message, and it will be treated as the current user query to define the task.

### Example: Iterative message history

In a chat-style application, you typically want each new user message to build on top of everything said so far, rather than asking the agent in isolation. To do this, keep a running list of `ChatMessage` objects and append both the user's query and the agent's reply to it after every turn. Pass the full list back into `qa.ask()` on the next call so the agent has the complete context.

The example below wraps this pattern in a simple way.

:::code-group{sync="languages"}
```python title="Python"
message_history: list[ChatMessage] = []

def use_qa(query: str) -> str:
    message_history.append(
        ChatMessage(role="user", content=query)
    )
    response = qa.ask(message_history)
    message_history.append(
        ChatMessage(role="assistant", content=response.final_answer)
    )
    return response.final_answer

use_qa(
    "I have some questions about the weather data. "
    "You can assume the temperature is in Fahrenheit "
    "and the wind speed is in mph."
)

use_qa(
    "What's the average wind speed, the max wind speed, "
    "and the min wind speed?"
)
```

```typescript title="JavaScript/TypeScript"
const messageHistory: ChatMessage[] = []

async function useQA(query: string): Promise<string> {
    messageHistory.push({ role: "user", content: query })
    const response = await qa.ask(messageHistory)
    messageHistory.push({ role: "assistant", content: response.finalAnswer })
    return response.finalAnswer
}

await useQA(
    "I have some questions about the weather data. " +
    "You can assume the temperature is in Fahrenheit " +
    "and the wind speed is in mph."
)

await useQA(
    "What's the average wind speed, the max wind speed, " +
    "and the min wind speed?"
)
```
:::

## Questions and feedback

Have a question or feedback? Here's how to reach us.

::::card-grid
:::card{title="Community Forum" href="https://forum.weaviate.io/c/support" icon="messages-square"}
Ask questions and connect with other developers on our **Community forum**.
:::

:::card{title="Support" href="/guides/support-overview" icon="life-buoy"}
Weaviate Cloud user or customer? Find the right channel on the **Support page**.
:::
::::

## Related pages

- [Agents](./agents-index.md)
- [AI-assisted Weaviate code generation](./ai-assisted-vibe-coding-index.md)
- [APIs](./apis-index.md)
- [Authorization and authentication](./authorization-and-authentication-index.md)
- [Benchmarks](./benchmarks-index.md)
- [Best practices](./best-practices-index.md)
- [Client libraries](./clients-index.md)
- [Client Libraries / SDKs](./client-libraries-index.md)
- [Cloud](./cloud-index.md)
- [Cloud account management](./cloud-account-management-index.md)

# Agent Instructions

This portal answers questions programmatically. To receive a synthesized,
source-cited answer instead of crawling page by page, append the `?ask=`
query parameter to any page URL on this site:

    /guides/quickstart?ask=how+do+I+authenticate

Optional parameters:

- `&goal=<what-you-are-trying-to-do>` steers the answer toward your
  objective (e.g. `&goal=write+a+python+client`).
- `&version=<label>` scopes the answer to a mounted version when the
  portal publishes more than one.

The response is `text/markdown`: the answer followed by a `# Sources` list
of the portal pages it was grounded in. Status codes are the contract:

- `200` — the answer; `402` — the portal owner’s plan or answer credits are
  exhausted (surface this to your operator; do NOT retry); `429` — you are
  rate-limited; back off for the `Retry-After` seconds; `503` — the answer
  lane is temporarily unavailable; fall back to crawling the `.md` pages.

For the full corpus map read `llms.txt` at the site root; for the tool
surface (search + page fetch as MCP tools) see `/mcp`.
