Conversations Tutorial
This tutorial demonstrates how to have multi-turn conversations with Knowledge Discovery agents. Unlike single-shot questions, conversations maintain context across multiple questions and answers, allowing for more natural dialogue.
Prerequisites
- Valid access token (see Authentication)
- At least one configured agent with data sources
- Discovery User role or higher
Tutorial Overview
In this tutorial, you'll learn to:
- Start a new conversation with an agent
- Ask follow-up questions within a conversation
- List and retrieve conversation messages
- Provide feedback on conversation messages
- Manage conversations (list, update metadata)
Part 1: Start a Conversation
To start a new conversation, send the first question using the conversation endpoint. The response returns both the new conversationId and the first message (question and answer).
- HTTP
- curl
POST {{baseUrl}}/qna/agents/{{agentId}}/conversations
Authorization: Bearer {{accessToken}}
Hxp-Environment: {{environmentKey}}
Hxp-App: {{appKey}}
Content-Type: application/json
{
"question": "What is the status of the project?",
"contextObjectIds": null,
"dynamicFilter": null
}
AGENT_ID="project-agent-id"
curl -X POST "${DISCOVERY_API_BASE_URL}/qna/agents/${AGENT_ID}/conversations" \
-H "Authorization: Bearer ${DISCOVERY_ACCESS_TOKEN}" \
-H "Hxp-Environment: ${ENVIRONMENT_KEY}" \
-H "Hxp-App: ${APP_KEY}" \
-H "Content-Type: application/json" \
-d '{
"question": "What is the status of the project?",
"contextObjectIds": null,
"dynamicFilter": null
}'
Start Conversation Request Parameters
| Field | Required | Description |
|---|---|---|
question | Yes | Initial natural language question for the conversation |
dynamicFilter | No | Runtime filter expression to narrow search results |
Response Structure
{
"conversation": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"lastModified": "2025-12-02T10:30:00Z"
},
"message": {
"id": "f1e2d3c4-b5a6-7890-1234-567890abcdef",
"answer": "Based on the documents, the project is currently in progress.",
"documentReferences": [
{
"documentId": "doc001",
"references": [
{
"referenceId": "ref001",
"rankScore": 0.95,
"rank": 1
}
]
}
],
"question": "What is the status of the project?",
"feedback": null,
"staticFilter": null,
"dynamicFilter": null,
"dateCreated": "2025-12-02T10:30:00Z",
"dateAnswered": "2025-12-02T10:30:05Z",
"agentVersion": 1
}
}
Understanding the Response
| Field | Type | Description |
|---|---|---|
conversation.id | UUID | Unique identifier for the conversation |
conversation.lastModified | datetime | Timestamp of the last update |
message.id | UUID | Unique identifier for this message |
message.question | string | The question text |
message.answer | string | The generated answer |
message.documentReferences | array | Source documents and chunks used for the answer |
message.dateCreated | datetime | When the question was submitted |
message.dateAnswered | datetime | When the answer was generated |
message.agentVersion | integer | Version of the agent used |
Starting a Conversation with Dynamic Filter
You can apply dynamic filters when starting a conversation to narrow the search scope for all messages in that conversation. This is useful when you want to focus the conversation on specific documents, date ranges, or categories.
- HTTP
- curl
POST {{baseUrl}}/qna/agents/{{agentId}}/conversations
Authorization: Bearer {{accessToken}}
Hxp-Environment: {{environmentKey}}
Hxp-App: {{appKey}}
Content-Type: application/json
{
"question": "What are the latest security policies?",
"dynamicFilter": {
"logicalOperator": "And",
"conditions": [
{
"field": "DocumentType",
"type": "Text",
"operator": "Equals",
"value": "Policy"
},
{
"field": "Department",
"type": "Text",
"operator": "Equals",
"value": "Security"
},
{
"field": "LastModified",
"type": "Date",
"operator": "GreaterThan",
"value": "2024-01-01"
}
]
}
}
curl -X POST "${DISCOVERY_API_BASE_URL}/qna/agents/${AGENT_ID}/conversations" \
-H "Authorization: Bearer ${DISCOVERY_ACCESS_TOKEN}" \
-H "Hxp-Environment: ${ENVIRONMENT_KEY}" \
-H "Hxp-App: ${APP_KEY}" \
-H "Content-Type: application/json" \
-d '{
"question": "What are the latest security policies?",
"dynamicFilter": {
"logicalOperator": "And",
"conditions": [
{
"field": "DocumentType",
"type": "Text",
"operator": "Equals",
"value": "Policy"
},
{
"field": "Department",
"type": "Text",
"operator": "Equals",
"value": "Security"
},
{
"field": "LastModified",
"type": "Date",
"operator": "GreaterThan",
"value": "2024-01-01"
}
]
}
}'
Dynamic filters can also be provided when asking follow-up questions (see Part 2). Each message can have its own filter, or you can omit it to use the agent's default behavior. For more details on filter syntax, see the Single-Shot Questions Tutorial.
Dynamic Filter Template Matching
The dynamicFilter you provide at runtime must match the structure defined in the agent's dynamicFilterTemplate, which is configured during agent creation or update. The template defines which fields can be filtered and their types, while the runtime filter provides the actual values.
Example: Agent Configuration with Dynamic Filter Template
When creating or updating an agent, you define which fields users can filter by:
{
"name": "Document Search Agent",
"description": "Agent that allows users to filter by department, document type, and date",
"modelName": "bedrock-amazon-nova-micro",
"sourceIds": ["your-source-id"],
"dynamicFilterTemplate": {
"logicalOperator": "And",
"conditions": [
{
"field": "Department",
"type": "Text"
},
{
"field": "DocumentType",
"type": "Text"
},
{
"field": "LastModified",
"type": "Date"
}
]
}
}
Corresponding Runtime Dynamic Filter
When starting a conversation or asking questions, provide the operator and value for the fields defined in the template:
{
"dynamicFilter": {
"logicalOperator": "And",
"conditions": [
{
"field": "Department",
"type": "Text",
"operator": "Equals",
"value": "Security"
},
{
"field": "DocumentType",
"type": "Text",
"operator": "Equals",
"value": "Policy"
},
{
"field": "LastModified",
"type": "Date",
"operator": "GreaterThan",
"value": "2024-01-01"
}
]
}
}
The fields in your runtime dynamicFilter must match those defined in the agent's dynamicFilterTemplate. You can provide values for all or a subset of the template fields. For more information on configuring agents with dynamic filter templates, see the Managing Agents Tutorial.
Part 2: Ask Follow-Up Questions
Once you have a conversationId, you can continue the conversation by sending follow-up questions. The agent will use previous messages in the conversation as context.
- HTTP
- curl
POST {{baseUrl}}/qna/agents/{{agentId}}/conversations/{{conversationId}}/messages
Authorization: Bearer {{accessToken}}
Hxp-Environment: {{environmentKey}}
Hxp-App: {{appKey}}
Content-Type: application/json
{
"question": "Can you provide more details about the timeline?",
"contextObjectIds": null,
"dynamicFilter": null
}
AGENT_ID="project-agent-id"
CONVERSATION_ID="a1b2c3d4-e5f6-7890-abcd-ef1234567890"
curl -X POST "${DISCOVERY_API_BASE_URL}/qna/agents/${AGENT_ID}/conversations/${CONVERSATION_ID}/messages" \
-H "Authorization: Bearer ${DISCOVERY_ACCESS_TOKEN}" \
-H "Hxp-Environment: ${ENVIRONMENT_KEY}" \
-H "Hxp-App: ${APP_KEY}" \
-H "Content-Type: application/json" \
-d '{
"question": "Can you provide more details about the timeline?",
"contextObjectIds": null,
"dynamicFilter": null
}'
Response
The response contains a ConversationMessageDto with the new question and answer, similar to the initial message:
{
"id": "b2c3d4e5-f6a7-8901-2345-678901abcdef",
"answer": "The latest update shows the project timeline is on track with an expected completion date of Q2 2026.",
"documentReferences": [
{
"documentId": "doc002",
"references": [
{
"referenceId": "ref002",
"rankScore": 0.92,
"rank": 1
}
]
}
],
"question": "Can you provide more details about the timeline?",
"feedback": null,
"staticFilter": null,
"dynamicFilter": null,
"dateCreated": "2025-12-02T10:35:00Z",
"dateAnswered": "2025-12-02T10:35:03Z",
"agentVersion": 1
}
The agent understands that "the timeline" refers to the project mentioned in the first question, demonstrating context retention across the conversation.
Part 3: List Conversation Messages
You can retrieve the history of messages within a conversation using cursor-based pagination.
- HTTP
- curl
GET {{baseUrl}}/qna/agents/{{agentId}}/conversations/{{conversationId}}/messages?pageSize=50&maxContentLength=500
Authorization: Bearer {{accessToken}}
Hxp-Environment: {{environmentKey}}
Hxp-App: {{appKey}}
AGENT_ID="project-agent-id"
CONVERSATION_ID="a1b2c3d4-e5f6-7890-abcd-ef1234567890"
curl -X GET "${DISCOVERY_API_BASE_URL}/qna/agents/${AGENT_ID}/conversations/${CONVERSATION_ID}/messages?pageSize=50&maxContentLength=500" \
-H "Authorization: Bearer ${DISCOVERY_ACCESS_TOKEN}" \
-H "Hxp-Environment: ${ENVIRONMENT_KEY}" \
-H "Hxp-App: ${APP_KEY}"
Query Parameters
| Parameter | Required | Default | Description |
|---|---|---|---|
cursor | No | null | Cursor token for fetching the next page |
pageSize | No | 100 | Number of items per page (1-100) |
maxContentLength | No | null | Maximum length of question/answer content (10-1000) |
fields | No | null | Comma-separated list of fields to include in response |
Response Structure
{
"data": [
{
"id": "f1e2d3c4-b5a6-7890-1234-567890abcdef",
"answer": "Based on the documents, the project is currently in progress.",
"documentReferences": [
{
"documentId": "doc001",
"references": [
{
"referenceId": "ref001",
"rankScore": 0.95,
"rank": 1
}
]
}
],
"question": "What is the status of the project?",
"feedback": "Good",
"staticFilter": null,
"dynamicFilter": null,
"dateCreated": "2025-12-02T10:30:00Z",
"dateAnswered": "2025-12-02T10:30:05Z",
"agentVersion": 1
},
{
"id": "b2c3d4e5-f6a7-8901-2345-678901abcdef",
"answer": "The latest update shows the project timeline is on track...",
"documentReferences": [
{
"documentId": "doc002",
"references": [
{
"referenceId": "ref002",
"rankScore": 0.92,
"rank": 1
}
]
}
],
"question": "Can you provide more details about the timeline?",
"feedback": null,
"staticFilter": null,
"dynamicFilter": null,
"dateCreated": "2025-12-02T10:35:00Z",
"dateAnswered": "2025-12-02T10:35:03Z",
"agentVersion": 1
}
],
"pagination": {
"nextCursor": null,
"hasMore": false
}
}
Understanding Cursor Pagination
Unlike page-based pagination (used in single-shot question history), conversation messages use cursor-based pagination:
| Field | Type | Description |
|---|---|---|
pagination.nextCursor | string (nullable) | Token to fetch the next page; null if no more pages |
pagination.hasMore | boolean | Indicates whether more messages are available |
To fetch the next page, pass the nextCursor value as the cursor query parameter.
Part 4: Get a Single Message
To retrieve a specific message (for example, when a user opens a detailed view), use the message ID.
- HTTP
- curl
GET {{baseUrl}}/qna/agents/{{agentId}}/conversations/{{conversationId}}/messages/{{messageId}}
Authorization: Bearer {{accessToken}}
Hxp-Environment: {{environmentKey}}
Hxp-App: {{appKey}}
AGENT_ID="project-agent-id"
CONVERSATION_ID="a1b2c3d4-e5f6-7890-abcd-ef1234567890"
MESSAGE_ID="f1e2d3c4-b5a6-7890-1234-567890abcdef"
curl -X GET "${DISCOVERY_API_BASE_URL}/qna/agents/${AGENT_ID}/conversations/${CONVERSATION_ID}/messages/${MESSAGE_ID}" \
-H "Authorization: Bearer ${DISCOVERY_ACCESS_TOKEN}" \
-H "Hxp-Environment: ${ENVIRONMENT_KEY}" \
-H "Hxp-App: ${APP_KEY}"
The response is a single ConversationMessageDto object with full details about the message.
Part 5: Provide Feedback on Messages
Feedback on conversation answers is recorded per message, similar to single-shot questions.
- HTTP
- curl
POST {{baseUrl}}/qna/agents/{{agentId}}/conversations/{{conversationId}}/messages/{{messageId}}/feedback
Authorization: Bearer {{accessToken}}
Hxp-Environment: {{environmentKey}}
Hxp-App: {{appKey}}
Content-Type: application/json
{
"feedback": "Good"
}
AGENT_ID="project-agent-id"
CONVERSATION_ID="a1b2c3d4-e5f6-7890-abcd-ef1234567890"
MESSAGE_ID="f1e2d3c4-b5a6-7890-1234-567890abcdef"
curl -X POST "${DISCOVERY_API_BASE_URL}/qna/agents/${AGENT_ID}/conversations/${CONVERSATION_ID}/messages/${MESSAGE_ID}/feedback" \
-H "Authorization: Bearer ${DISCOVERY_ACCESS_TOKEN}" \
-H "Hxp-Environment: ${ENVIRONMENT_KEY}" \
-H "Hxp-App: ${APP_KEY}" \
-H "Content-Type: application/json" \
-d '{"feedback": "Good"}'
Feedback Values
| Value | Meaning |
|---|---|
"Good" | Answer was helpful and accurate |
"Bad" | Answer was not helpful or contained errors |
"Retry" | Request to regenerate the answer |
Part 6: Manage Conversations
List All Conversations for an Agent
Retrieve all conversations associated with an agent.
- HTTP
- curl
GET {{baseUrl}}/qna/agents/{{agentId}}/conversations?pageSize=20
Authorization: Bearer {{accessToken}}
Hxp-Environment: {{environmentKey}}
Hxp-App: {{appKey}}
AGENT_ID="project-agent-id"
curl -X GET "${DISCOVERY_API_BASE_URL}/qna/agents/${AGENT_ID}/conversations?pageSize=20" \
-H "Authorization: Bearer ${DISCOVERY_ACCESS_TOKEN}" \
-H "Hxp-Environment: ${ENVIRONMENT_KEY}" \
-H "Hxp-App: ${APP_KEY}"
Query Parameters
| Parameter | Required | Default | Description |
|---|---|---|---|
cursor | No | null | Cursor token for fetching the next page |
pageSize | No | 20 | Number of items per page (1-100) |
Response
{
"data": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Project Status Discussion",
"description": "Conversation about current project status",
"lastModified": "2025-12-02T10:35:00Z"
},
{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"name": null,
"description": null,
"lastModified": "2025-12-01T15:20:00Z"
}
],
"pagination": {
"nextCursor": "eyJsYXN0SWQiOiJiMmMzZDRlNS1mNmE3LTg5MDEtYmNkZS1mMTIzNDU2Nzg5MDEiLCJsYXN0TW9kaWZpZWQiOiIyMDI1LTEyLTAxVDE1OjIwOjAwWiJ9",
"hasMore": true
}
}
Get Conversation Details
Retrieve metadata for a specific conversation.
- HTTP
- curl
GET {{baseUrl}}/qna/agents/{{agentId}}/conversations/{{conversationId}}
Authorization: Bearer {{accessToken}}
Hxp-Environment: {{environmentKey}}
Hxp-App: {{appKey}}
AGENT_ID="project-agent-id"
CONVERSATION_ID="a1b2c3d4-e5f6-7890-abcd-ef1234567890"
curl -X GET "${DISCOVERY_API_BASE_URL}/qna/agents/${AGENT_ID}/conversations/${CONVERSATION_ID}" \
-H "Authorization: Bearer ${DISCOVERY_ACCESS_TOKEN}" \
-H "Hxp-Environment: ${ENVIRONMENT_KEY}" \
-H "Hxp-App: ${APP_KEY}"
Update Conversation Metadata
Update the name and description of a conversation for better organization.
- HTTP
- curl
PUT {{baseUrl}}/qna/agents/{{agentId}}/conversations/{{conversationId}}
Authorization: Bearer {{accessToken}}
Hxp-Environment: {{environmentKey}}
Hxp-App: {{appKey}}
Content-Type: application/json
{
"name": "Project Status Q2 2025",
"description": "Discussion about project timeline and deliverables for Q2"
}
AGENT_ID="project-agent-id"
CONVERSATION_ID="a1b2c3d4-e5f6-7890-abcd-ef1234567890"
curl -X PUT "${DISCOVERY_API_BASE_URL}/qna/agents/${AGENT_ID}/conversations/${CONVERSATION_ID}" \
-H "Authorization: Bearer ${DISCOVERY_ACCESS_TOKEN}" \
-H "Hxp-Environment: ${ENVIRONMENT_KEY}" \
-H "Hxp-App: ${APP_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "Project Status Q2 2025",
"description": "Discussion about project timeline and deliverables for Q2"
}'
Update Request Parameters
| Field | Required | Description |
|---|---|---|
name | Yes | Conversation name (for display/organization) |
description | No | Optional longer description of the conversation purpose |
Summary
In this tutorial, you learned how to:
✅ Start multi-turn conversations with agents
✅ Ask follow-up questions that use previous context
✅ List and retrieve conversation messages
✅ Provide feedback on conversation messages
✅ Manage conversation metadata (list, view, update)
Next Steps
- Learn about Single-Shot Questions for one-off queries
- Review the API Reference for complete endpoint documentation