AWS Builder Center
Day 5: Lets Build a Chat App  with Bedrock

Day 5: Lets Build a Chat App with Bedrock

turn our Knowledge Base into a chat app with Python and Streamlit. Follow-up questions, source references, also see new releasees

lets we build a small chat screen with:
  • A text box and chat history
  • Follow-up questions that continue the conversation
  • Source files you can check under every answer
It's a small Python app. No web development experience needed.

Who does what?

Here's what happens when you type a question:
  1. Streamlit shows the chat box and sends your question to Bedrock.
  2. The Knowledge Base searches your notes and finds the most relevant chunks.
  3. The AI model reads those chunks and writes the answer.
  4. The answer comes back to Streamlit along with the source files it used.
PieceIts job
Amazon BedrockProvides the AI model and the Knowledge Base API
Knowledge BaseFinds the relevant parts of your notes
StreamlitDraws the chat page
Conversation sessionLets follow-up questions build on earlier ones
The app runs on your laptop, with your AWS credentials, and calls the Knowledge Base
Which Knowledge Base? This article uses the classic Knowledge Base from Day 4 , where we chose the embedding model and vector store. AWS also launched a Managed Knowledge Base in 2026, covered near the end.

Before you start

  • A working Knowledge Base from Day 4   with a finished sync
  • Python and AWS credentials set up from Day 1 
  • Your Knowledge Base ID and a model ARN or inference profile ARN that worked on Day 4

Step 1: Install Streamlit

Streamlit turns a Python file into a web page.
1
pip install --upgrade streamlit boto3

Step 2: Write the app

Create a file called app.py:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import boto3
import streamlit as st
from botocore.exceptions import ClientError

REGION = "YOUR_AWS_REGION"
KB_ID = "YOUR_KB_ID"
MODEL_ARN = "YOUR_MODEL_OR_INFERENCE_PROFILE_ARN"

client = boto3.client("bedrock-agent-runtime", region_name=REGION)

st.set_page_config(page_title="Chat with my notes")
st.title("Chat with my class notes")

if "messages" not in st.session_state:
st.session_state.messages = []
st.session_state.session_id = None

# Reset button: runs BEFORE the history is drawn
if st.button("Start a new chat"):
st.session_state.messages = []
st.session_state.session_id = None

def show_message(role, content, sources=None):
with st.chat_message(role):
st.markdown(content)
if sources:
with st.expander("View sources"):
for s in sources:
st.write(s)

for m in st.session_state.messages:
show_message(m["role"], m["content"], m.get("sources"))

question = st.chat_input("Ask something from your notes")

if question:
st.session_state.messages.append({"role": "user", "content": question})
show_message("user", question)

params = {
"input": {"text": question},
"retrieveAndGenerateConfiguration": {
"type": "KNOWLEDGE_BASE",
"knowledgeBaseConfiguration": {
"knowledgeBaseId": KB_ID,
"modelArn": MODEL_ARN,
},
},
}
if st.session_state.session_id:
params["sessionId"] = st.session_state.session_id

try:
with st.spinner("Searching your notes..."):
response = client.retrieve_and_generate(**params)
st.session_state.session_id = response["sessionId"]
answer = response["output"]["text"]
sources = sorted({
ref["location"]["s3Location"]["uri"]
for c in response.get("citations", [])
for ref in c.get("retrievedReferences", [])
if "s3Location" in ref.get("location", {})
})
except ClientError as e:
answer = f"Something went wrong: {e.response['Error']['Message']}"
sources = []

show_message("assistant", answer, sources)
st.session_state.messages.append(
{"role": "assistant", "content": answer, "sources": sources}
)
Replace the three placeholders at the top with your own values.

Step 3: Run it

1
streamlit run app.py
Your browser opens a chat page. Ask a question from your notes.

Two kinds of "memory"

Our app remembers things in two different places, and they do different jobs.
1. Streamlit remembers what to show. Every time you send a message, Streamlit reruns the whole script. Without st.session_state, the chat on screen would disappear after each question. This memory lives in your browser session. If you refresh the page, it starts fresh.
2. Bedrock remembers what the conversation is about. Each response includes a sessionId. When we send it back with the next question, Bedrock can understand follow-ups like "explain that in simpler words." It continues the conversation. It isn't a notebook of everything you've ever asked.
MemoryWhat it doesLimit
st.session_stateKeeps the chat messages on screenA page refresh starts a new session
sessionId (Bedrock)Gives the model context for follow-upOnly continues the conversation.

Try this

  1. Ask: "What is a deadlock?"
  2. Then ask: "Explain that in simpler words."
  3. Click Start a new chat. This clears the messages on screen and the Bedrock sessionId, so the next question starts a brand-new conversation.
  4. Ask "Explain that in simpler words." again.
If step 2 makes sense and step 4 doesn't, the session memory is working.

Experiment: is your AI actually using your notes?

A working chat is exciting. But I wanted to know: did the answer come from my notes, or did the model already know it?
  1. Ask a question your notes answer clearly. Open View sources and check the file.
  2. Ask about a topic that isn't in your notes. Compare the answer and the sources.
  3. Create a small test file called test-fact.txt containing only this line.
If the app finds your made-up fact, retrieval is working.
My takeaway: an answer can sound confident without being supported by your documents. A source helps you check, but it doesn't prove every claim is right.
My result: The app answered my questions and showed the source files, making it easier to check where the information came from.

What the errors mean

What you seeWhat it meansWhat to try
AccessDeniedExceptionA permissions problemCheck IAM and model access in your console
ValidationException about the modelA model setup problemCopy the exact model or inference profile ARN
No error, but "no information" answersRetrieval found nothing usefulCheck the sync status and whether the answer is in your notes

What's new in 2026 (Managed Knowledge Base)

AWS launched Amazon Bedrock Managed Knowledge Base, a fully managed option. These updates are for the managed version. Our tutorial uses the classic one.
Classic vs Managed: they aren't interchangeable. Managed uses AWS-managed storage (no vector store choice), and its retrieval calls use a different configuration. Check Region availability and the current docs before switching. I kept this series on the classic version so you can see each building block.

Keep it safe and affordable

  • No access keys in your code. Use aws configure.
  • This app is for local learning. Sharing it with others would need hosting, login protection, and care for your AWS resources.
  • Costs depend on the model you use, the retrievals, and the services behind your Knowledge Base. Check the current AWS pricing and set a budget alert in AWS Budgets before experimenting.

Summary

  • A chat app is a small Streamlit page that calls your Knowledge Base
  • Streamlit session state and Bedrock's sessionId are different kinds of memory
  • Always check the sources, and test with facts you control
  • Classic and Managed Knowledge Bases are different options

Next: Day 6

Our bot will answer almost anything. Tomorrow we add Guardrails: block unsafe or off-topic questions and hide personal information.
What would you add to this chat app? Tell me below.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article