1
0
mirror of synced 2026-05-22 22:53:35 +00:00

Add local streamlit app for agentcore gateway testing (#339)

* Add local streamlit app for agentcore gateway testing

* Update contributors

* Remove example for simplicity

* Add example agent back in

* Add architecture diagram
This commit is contained in:
Brian Loyal
2025-09-09 08:59:03 -05:00
committed by GitHub
parent 57c46d1b80
commit d7ca11f76d
19 changed files with 2731 additions and 0 deletions
@@ -0,0 +1,16 @@
# Python-generated files
__pycache__/
*.py[oc]
build/
dist/
wheels/
*.egg-info
# Virtual environments
.venv
# Other
.DS_Store
.bedrock_agentcore.yaml
.dockerignore
Dockerfile
@@ -0,0 +1 @@
3.11
@@ -0,0 +1,33 @@
[server]
enableStaticServing = true
[theme]
primaryColor = "#5C7FFF"
textColor = "#232F3E"
font = "amazon-ember, sans-serif"
headingFont = "amazon-ember-heading, sans-serif"
codeFont = "amazon-ember-mono, monospace"
showSidebarBorder = true
[[theme.fontFaces]]
family = "amazon-ember"
url = "app/static/Amazon-Ember-Medium.ttf"
style = "normal"
[[theme.fontFaces]]
family = "amazon-ember"
url = "app/static/Amazon-Ember-MediumItalic.ttf"
style = "italic"
[[theme.fontFaces]]
family = "amazon-ember-mono"
url = "app/static/AmazonEmberMono_Rg.ttf"
style = "normal"
[[theme.fontFaces]]
family = "amazon-ember-heading"
url = "app/static/AmazonEmber_He.ttf"
style = "normal"
[theme.sidebar]
primaryColor = "#962EFF"
@@ -0,0 +1,164 @@
# Bedrock AgentCore Chat Interface
A Streamlit web application for interacting with AI agents deployed on Amazon Bedrock AgentCore Runtime. This application provides an intuitive chat interface to communicate with your deployed agents in real-time.
## About Amazon Bedrock AgentCore
Amazon Bedrock AgentCore is a comprehensive service that enables you to deploy and operate highly effective AI agents securely at scale using any framework and model. AgentCore Runtime is a secure, serverless runtime purpose-built for deploying and scaling dynamic AI agents and tools using popular open-source frameworks like LangGraph, CrewAI, and Strands Agents.
## Features
- **Real-time Chat Interface**: Interactive chat with deployed AgentCore agents
- **Agent Discovery**: Automatically discover and select from available agents in your AWS account
- **Version Management**: Choose specific versions of your deployed agents
- **Multi-Region Support**: Connect to agents deployed in different AWS regions
- **Streaming Responses**: Real-time streaming of agent responses
- **Response Formatting**: Auto-format responses with options to view raw output
- **Session Management**: Maintain conversation context with unique session IDs
- **Tool Visibility**: Optional display of tools used by agents during execution
- **Thinking Process**: Optional display of agent reasoning (when available)
## Architecture
![Architecture diagram](static/arch.png)
## Prerequisites
- Python 3.11 or higher
- [uv package manager](https://docs.astral.sh/uv/getting-started/installation/)
- AWS CLI configured with appropriate credentials
- Access to Amazon Bedrock AgentCore service
- Deployed agents on Bedrock AgentCore Runtime
### Required AWS Permissions
Your AWS credentials need the following permissions:
- `bedrock-agentcore-control:ListAgentRuntimes`
- `bedrock-agentcore-control:ListAgentRuntimeVersions`
- `bedrock-agentcore:InvokeAgentRuntime`
## Installation
1. **Clone the repository**:
```bash
git clone https://github.com/awslabs/amazon-bedrock-agentcore-samples.git
cd amazon-bedrock-agentcore-samples/03-integrations/ux-examples/streamlit-chat
```
2. **Install dependencies using uv**:
```bash
uv sync
```
## (Optional) Deploy the Example Agent
1. **Install dev dependencies using uv** (recommended):
```bash
uv sync --dev
```
2. **Configure the agent**:
```bash
cd example
uv run agentcore configure -e agent.py
```
3. **Deploy to AgentCore Runtime**:
```bash
uv run agentcore launch
cd ..
```
## Running the Application
### Using uv (recommended)
```bash
uv run streamlit run app.py
```
The application will start and be available at `http://localhost:8501`.
## Usage
1. **Configure AWS Region**: Select your preferred AWS region from the sidebar
2. **Select Agent**: Choose from automatically discovered agents in your account
3. **Choose Version**: Select the specific version of your agent to use
4. **Start Chatting**: Type your message in the chat input and press Enter
### Configuration Options
- **Auto-format responses**: Clean and format agent responses for better readability
- **Show raw response**: Display the unprocessed response from the agent
- **Show tools**: Display when agents use tools during execution
- **Show thinking**: Display agent reasoning process (when available)
- **Session Management**: Generate new session IDs to start fresh conversations
## Project Structure
```
streamlit-chat/
├── app.py # Main Streamlit application
├── example.py # Example agent
├── static/ # UI assets (fonts, icons, logos)
├── pyproject.toml # Project dependencies
└── README.md # This file
```
## Configuration Files
- **`pyproject.toml`**: Defines project dependencies and metadata
- **`.streamlit/config.toml`**: Streamlit-specific configuration
## Troubleshooting
### Common Issues
1. **No agents found**: Ensure you have deployed agents in the selected region and have proper AWS permissions
2. **Connection errors**: Verify your AWS credentials and network connectivity
3. **Permission denied**: Check that your IAM user/role has the required Bedrock AgentCore permissions
### Debug Mode
Enable debug logging by setting the Streamlit logger level in the application or check the browser console for additional error information.
## Development
### Adding New Features
The application is built with modularity in mind. Key areas for extension:
- **Response Processing**: Modify `clean_response_text()` for custom formatting
- **Agent Selection**: Extend `fetch_agent_runtimes()` for custom filtering
- **UI Components**: Add new Streamlit components in the sidebar or main area
### Dependencies
- **boto3**: AWS SDK for Python
- **streamlit**: Web application framework
- **uv**: Fast Python package installer and resolver
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Test thoroughly
5. Submit a pull request
## License
This project is licensed under the terms specified in the repository license file.
## Resources
- [Amazon Bedrock AgentCore Documentation](https://docs.aws.amazon.com/bedrock-agentcore/)
- [Bedrock AgentCore Samples](https://github.com/awslabs/amazon-bedrock-agentcore-samples/)
- [Streamlit Documentation](https://docs.streamlit.io/)
- [Strands Agents Framework](https://github.com/awslabs/strands-agents)
@@ -0,0 +1,627 @@
import json
import re
import time
import uuid
from typing import Dict, Iterator, List
import boto3
import streamlit as st
from streamlit.logger import get_logger
logger = get_logger(__name__)
logger.setLevel("INFO")
# Page config
st.set_page_config(
page_title="Bedrock AgentCore Chat",
page_icon="static/gen-ai-dark.svg",
layout="wide",
initial_sidebar_state="expanded",
)
# Remove Streamlit deployment components
st.markdown(
"""
<style>
.stAppDeployButton {display:none;}
#MainMenu {visibility: hidden;}
</style>
""",
unsafe_allow_html=True,
)
HUMAN_AVATAR = "static/user-profile.svg"
AI_AVATAR = "static/gen-ai-dark.svg"
def fetch_agent_runtimes(region: str = "us-east-1") -> List[Dict]:
"""Fetch available agent runtimes from bedrock-agentcore-control"""
try:
client = boto3.client("bedrock-agentcore-control", region_name=region)
response = client.list_agent_runtimes(maxResults=100)
# Filter only READY agents and sort by name
ready_agents = [
agent
for agent in response.get("agentRuntimes", [])
if agent.get("status") == "READY"
]
# Sort by most recent update time (newest first)
ready_agents.sort(key=lambda x: x.get("lastUpdatedAt", ""), reverse=True)
return ready_agents
except Exception as e:
st.error(f"Error fetching agent runtimes: {e}")
return []
def fetch_agent_runtime_versions(
agent_runtime_id: str, region: str = "us-east-1"
) -> List[Dict]:
"""Fetch versions for a specific agent runtime"""
try:
client = boto3.client("bedrock-agentcore-control", region_name=region)
response = client.list_agent_runtime_versions(agentRuntimeId=agent_runtime_id)
# Filter only READY versions
ready_versions = [
version
for version in response.get("agentRuntimes", [])
if version.get("status") == "READY"
]
# Sort by most recent update time (newest first)
ready_versions.sort(key=lambda x: x.get("lastUpdatedAt", ""), reverse=True)
return ready_versions
except Exception as e:
st.error(f"Error fetching agent runtime versions: {e}")
return []
def clean_response_text(text: str, show_thinking: bool = True) -> str:
"""Clean and format response text for better presentation"""
if not text:
return text
# Handle the consecutive quoted chunks pattern
# Pattern: "word1" "word2" "word3" -> word1 word2 word3
text = re.sub(r'"\s*"', "", text)
text = re.sub(r'^"', "", text)
text = re.sub(r'"$', "", text)
# Replace literal \n with actual newlines
text = text.replace("\\n", "\n")
# Replace literal \t with actual tabs
text = text.replace("\\t", "\t")
# Clean up multiple spaces
text = re.sub(r" {3,}", " ", text)
# Fix newlines that got converted to spaces
text = text.replace(" \n ", "\n")
text = text.replace("\n ", "\n")
text = text.replace(" \n", "\n")
# Handle numbered lists
text = re.sub(r"\n(\d+)\.\s+", r"\n\1. ", text)
text = re.sub(r"^(\d+)\.\s+", r"\1. ", text)
# Handle bullet points
text = re.sub(r"\n-\s+", r"\n- ", text)
text = re.sub(r"^-\s+", r"- ", text)
# Handle section headers
text = re.sub(r"\n([A-Za-z][A-Za-z\s]{2,30}):\s*\n", r"\n**\1:**\n\n", text)
# Clean up multiple newlines
text = re.sub(r"\n{3,}", "\n\n", text)
# Clean up thinking
if not show_thinking:
text = re.sub(r"<thinking>.*?</thinking>", "", text)
return text.strip()
def extract_text_from_response(data) -> str:
"""Extract text content from response data in various formats"""
if isinstance(data, dict):
# Handle format: {'role': 'assistant', 'content': [{'text': 'Hello!'}]}
if "role" in data and "content" in data:
content = data["content"]
if isinstance(content, list) and len(content) > 0:
if isinstance(content[0], dict) and "text" in content[0]:
return str(content[0]["text"])
else:
return str(content[0])
elif isinstance(content, str):
return content
else:
return str(content)
# Handle other common formats
if "text" in data:
return str(data["text"])
elif "content" in data:
content = data["content"]
if isinstance(content, str):
return content
else:
return str(content)
elif "message" in data:
return str(data["message"])
elif "response" in data:
return str(data["response"])
elif "result" in data:
return str(data["result"])
return str(data)
def parse_streaming_chunk(chunk: str) -> str:
"""Parse individual streaming chunk and extract meaningful content"""
logger.debug(f"parse_streaming_chunk: received chunk: {chunk}")
logger.debug(f"parse_streaming_chunk: chunk type: {type(chunk)}")
try:
# Try to parse as JSON first
if chunk.strip().startswith("{"):
logger.debug("parse_streaming_chunk: Attempting JSON parse")
data = json.loads(chunk)
logger.debug(f"parse_streaming_chunk: Successfully parsed JSON: {data}")
# Handle the specific format: {'role': 'assistant', 'content': [{'text': '...'}]}
if isinstance(data, dict) and "role" in data and "content" in data:
content = data["content"]
if isinstance(content, list) and len(content) > 0:
first_item = content[0]
if isinstance(first_item, dict) and "text" in first_item:
extracted_text = first_item["text"]
logger.debug(
f"parse_streaming_chunk: Extracted text: {extracted_text}"
)
return extracted_text
else:
return str(first_item)
else:
return str(content)
else:
# Use the general extraction function for other formats
return extract_text_from_response(data)
# If not JSON, return the chunk as-is
logger.debug("parse_streaming_chunk: Not JSON, returning as-is")
return chunk
except json.JSONDecodeError as e:
logger.error(f"parse_streaming_chunk: JSON decode error: {e}")
# Try to handle Python dict string representation (with single quotes)
if chunk.strip().startswith("{") and "'" in chunk:
logger.debug(
"parse_streaming_chunk: Attempting to handle Python dict string"
)
try:
# Try to convert single quotes to double quotes for JSON parsing
# This is a simple approach - might need refinement for complex cases
json_chunk = chunk.replace("'", '"')
data = json.loads(json_chunk)
logger.debug(
f"parse_streaming_chunk: Successfully converted and parsed: {data}"
)
# Handle the specific format
if isinstance(data, dict) and "role" in data and "content" in data:
content = data["content"]
if isinstance(content, list) and len(content) > 0:
first_item = content[0]
if isinstance(first_item, dict) and "text" in first_item:
extracted_text = first_item["text"]
logger.debug(
f"parse_streaming_chunk: Extracted text from converted dict: {extracted_text}"
)
return extracted_text
else:
return str(first_item)
else:
return str(content)
else:
return extract_text_from_response(data)
except json.JSONDecodeError:
logger.debug(
"parse_streaming_chunk: Failed to convert Python dict string"
)
pass
# If all parsing fails, return the chunk as-is
logger.debug("parse_streaming_chunk: All parsing failed, returning chunk as-is")
return chunk
def invoke_agent_streaming(
prompt: str,
agent_arn: str,
runtime_session_id: str,
region: str = "us-east-1",
show_tool: bool = True,
) -> Iterator[str]:
"""Invoke agent and yield streaming response chunks"""
try:
agentcore_client = boto3.client("bedrock-agentcore", region_name=region)
boto3_response = agentcore_client.invoke_agent_runtime(
agentRuntimeArn=agent_arn,
qualifier="DEFAULT",
runtimeSessionId=runtime_session_id,
payload=json.dumps({"prompt": prompt}),
)
logger.debug(f"contentType: {boto3_response.get('contentType', 'NOT_FOUND')}")
if "text/event-stream" in boto3_response.get("contentType", ""):
logger.debug("Using streaming response path")
# Handle streaming response
for line in boto3_response["response"].iter_lines(chunk_size=1):
if line:
line = line.decode("utf-8")
logger.debug(f"Raw line: {line}")
if line.startswith("data: "):
line = line[6:]
logger.debug(f"Line after removing 'data: ': {line}")
# Parse and clean each chunk
parsed_chunk = parse_streaming_chunk(line)
if parsed_chunk.strip(): # Only yield non-empty chunks
if "🔧 Using tool:" in parsed_chunk and not show_tool:
yield ""
else:
yield parsed_chunk
else:
logger.debug(
f"Line doesn't start with 'data: ', skipping: {line}"
)
else:
logger.debug("Using non-streaming response path")
# Handle non-streaming JSON response
try:
response_obj = boto3_response.get("response")
logger.debug(f"response_obj type: {type(response_obj)}")
if hasattr(response_obj, "read"):
# Read the response content
content = response_obj.read()
if isinstance(content, bytes):
content = content.decode("utf-8")
logger.debug(f"Raw content: {content}")
try:
# Try to parse as JSON and extract text
response_data = json.loads(content)
logger.debug(f"Parsed JSON: {response_data}")
# Handle the specific format we're seeing
if isinstance(response_data, dict):
# Check for 'result' wrapper first
if "result" in response_data:
actual_data = response_data["result"]
else:
actual_data = response_data
# Extract text from the nested structure
if "role" in actual_data and "content" in actual_data:
content_list = actual_data["content"]
if (
isinstance(content_list, list)
and len(content_list) > 0
):
first_item = content_list[0]
if (
isinstance(first_item, dict)
and "text" in first_item
):
extracted_text = first_item["text"]
logger.debug(
f"Extracted text: {extracted_text}"
)
yield extracted_text
else:
yield str(first_item)
else:
yield str(content_list)
else:
# Use general extraction
text = extract_text_from_response(actual_data)
yield text
else:
yield str(response_data)
except json.JSONDecodeError as e:
logger.error(f"JSON decode error: {e}")
# If not JSON, yield raw content
yield content
elif isinstance(response_obj, dict):
# Direct dict response
text = extract_text_from_response(response_obj)
yield text
else:
logger.debug(f"Unexpected response_obj type: {type(response_obj)}")
yield "No response content"
except Exception as e:
logger.error(f"Exception in non-streaming: {e}")
yield f"Error reading response: {e}"
except Exception as e:
yield f"Error invoking agent: {e}"
def main():
st.logo("static/agentcore-service-icon.png", size="large")
st.title("Amazon Bedrock AgentCore Chat")
# Sidebar for settings
with st.sidebar:
st.header("Settings")
# Region selection (moved up since it affects agent fetching)
region = st.selectbox(
"AWS Region",
["us-east-1", "us-west-2", "eu-west-1", "ap-southeast-1"],
index=0,
)
# Agent selection
st.subheader("Agent Selection")
# Fetch available agents
with st.spinner("Loading available agents..."):
available_agents = fetch_agent_runtimes(region)
if available_agents:
# Get unique agent names and their runtime IDs
unique_agents = {}
for agent in available_agents:
name = agent.get("agentRuntimeName", "Unknown")
runtime_id = agent.get("agentRuntimeId", "")
if name not in unique_agents:
unique_agents[name] = runtime_id
# Create agent name options
agent_names = list(unique_agents.keys())
# Agent name selection dropdown
col1, col2 = st.columns([2, 1])
with col1:
selected_agent_name = st.selectbox(
"Agent Name",
options=agent_names,
help="Choose an agent to chat with",
)
# Get versions for the selected agent using the specific API
if selected_agent_name and selected_agent_name in unique_agents:
agent_runtime_id = unique_agents[selected_agent_name]
with st.spinner("Loading versions..."):
agent_versions = fetch_agent_runtime_versions(
agent_runtime_id, region
)
if agent_versions:
version_options = []
version_arn_map = {}
for version in agent_versions:
version_num = version.get("agentRuntimeVersion", "Unknown")
arn = version.get("agentRuntimeArn", "")
updated = version.get("lastUpdatedAt", "")
description = version.get("description", "")
# Format version display with update time
version_display = f"v{version_num}"
if updated:
try:
if hasattr(updated, "strftime"):
updated_str = updated.strftime("%m/%d %H:%M")
version_display += f" ({updated_str})"
except:
pass
version_options.append(version_display)
version_arn_map[version_display] = {
"arn": arn,
"description": description,
}
with col2:
selected_version = st.selectbox(
"Version",
options=version_options,
help="Choose the version to use",
)
# Get the ARN for the selected agent and version
version_info = version_arn_map.get(selected_version, {})
agent_arn = version_info.get("arn", "")
description = version_info.get("description", "")
# Show selected agent info
if agent_arn:
st.info(f"Selected: {selected_agent_name} {selected_version}")
if description:
st.caption(f"Description: {description}")
with st.expander("View ARN"):
st.code(agent_arn)
else:
st.warning(f"No versions found for {selected_agent_name}")
agent_arn = ""
else:
agent_arn = ""
else:
st.error("No agent runtimes found or error loading agents")
agent_arn = ""
# Fallback manual input
st.subheader("Manual ARN Input")
agent_arn = st.text_input(
"Agent ARN", value="", help="Enter your Bedrock AgentCore ARN manually"
)
if st.button("Refresh", key="refresh_agents", help="Refresh agent list"):
st.rerun()
# Runtime Session ID
st.subheader("Session Configuration")
# Initialize session ID in session state if not exists
if "runtime_session_id" not in st.session_state:
st.session_state.runtime_session_id = str(uuid.uuid4())
# Session ID input with generate button
runtime_session_id = st.text_input(
"Runtime Session ID",
value=st.session_state.runtime_session_id,
help="Unique identifier for this runtime session",
)
if st.button("Refresh", help="Generate new session ID and clear chat"):
st.session_state.runtime_session_id = str(uuid.uuid4())
st.session_state.messages = [] # Clear chat messages when resetting session
st.rerun()
# Update session state if user manually changed the ID
if runtime_session_id != st.session_state.runtime_session_id:
st.session_state.runtime_session_id = runtime_session_id
# Response formatting options
st.subheader("Display Options")
auto_format = st.checkbox(
"Auto-format responses",
value=True,
help="Automatically clean and format responses",
)
show_raw = st.checkbox(
"Show raw response",
value=False,
help="Display the raw unprocessed response",
)
show_tools = st.checkbox(
"Show tools",
value=True,
help="Display tools used",
)
show_thinking = st.checkbox(
"Show thinking",
value=False,
help="Display the AI thinking text",
)
# Clear chat button
if st.button("🗑️ Clear Chat"):
st.session_state.messages = []
st.rerun()
# Connection status
st.divider()
if agent_arn:
st.success("✅ Agent selected and ready")
else:
st.error("❌ Please select an agent")
# Initialize chat history
if "messages" not in st.session_state:
st.session_state.messages = []
# Display chat messages
for message in st.session_state.messages:
with st.chat_message(message["role"], avatar=message["avatar"]):
st.markdown(message["content"])
# Chat input
if prompt := st.chat_input("Type your message here..."):
if not agent_arn:
st.error("Please select an agent in the sidebar first.")
return
# Add user message to chat history
st.session_state.messages.append(
{"role": "user", "content": prompt, "avatar": HUMAN_AVATAR}
)
with st.chat_message("user", avatar=HUMAN_AVATAR):
st.markdown(prompt)
# Generate assistant response
with st.chat_message("assistant", avatar=AI_AVATAR):
message_placeholder = st.empty()
chunk_buffer = ""
try:
# Stream the response
for chunk in invoke_agent_streaming(
prompt,
agent_arn,
st.session_state.runtime_session_id,
region,
show_tools,
):
# Let's see what we get
logger.debug(f"MAIN LOOP: chunk type: {type(chunk)}")
logger.debug(f"MAIN LOOP: chunk content: {chunk}")
# Ensure chunk is a string before concatenating
if not isinstance(chunk, str):
logger.debug(
f"MAIN LOOP: Converting non-string chunk to string"
)
chunk = str(chunk)
# Add chunk to buffer
chunk_buffer += chunk
# Only update display every few chunks or when we hit certain characters
if (
len(chunk_buffer) % 3 == 0
or chunk.endswith(" ")
or chunk.endswith("\n")
):
if auto_format:
# Clean the accumulated response
cleaned_response = clean_response_text(
chunk_buffer, show_thinking
)
message_placeholder.markdown(cleaned_response + "")
else:
# Show raw response
message_placeholder.markdown(chunk_buffer + "")
time.sleep(0.01) # Reduced delay since we're batching updates
# Final response without cursor
if auto_format:
full_response = clean_response_text(chunk_buffer, show_thinking)
else:
full_response = chunk_buffer
message_placeholder.markdown(full_response)
# Show raw response in expander if requested
if show_raw and auto_format:
with st.expander("View raw response"):
st.text(chunk_buffer)
except Exception as e:
error_msg = f"❌ **Error:** {str(e)}"
message_placeholder.markdown(error_msg)
full_response = error_msg
# Add assistant response to chat history
st.session_state.messages.append(
{"role": "assistant", "content": full_response, "avatar": AI_AVATAR}
)
if __name__ == "__main__":
main()
@@ -0,0 +1,61 @@
# Basic strands agent streaming example.
# To test locally, run `uv run agent.py` and then
# curl -X POST http://localhost:8080/invocations -H "Content-Type: application/json" -d '{"prompt": "Hello!"}'
import argparse
import asyncio
import datetime
import json
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from strands import Agent, tool
from strands.models import BedrockModel
from strands_tools import calculator
app = BedrockAgentCoreApp()
@tool
def weather():
"""Get weather"""
return "sunny"
model_id = "us.amazon.nova-pro-v1:0"
model = BedrockModel(
model_id=model_id,
)
agent = Agent(
model=model,
tools=[calculator, weather],
system_prompt="You're a helpful assistant. You can do simple math calculation, and tell the weather.",
)
@app.entrypoint
async def strands_agent_bedrock(payload):
"""
Invoke the agent with a payload
"""
user_input = payload.get("prompt")
agent_stream = agent.stream_async(user_input)
tool_name = None
try:
async for event in agent_stream:
if (
"current_tool_use" in event
and event["current_tool_use"].get("name") != tool_name
):
tool_name = event["current_tool_use"]["name"]
yield f"\n\n🔧 Using tool: {tool_name}\n\n"
if "data" in event:
tool_name = None
yield event["data"]
except Exception as e:
yield f"Error: {str(e)}"
if __name__ == "__main__":
app.run()
@@ -0,0 +1,5 @@
bedrock-agentcore
boto3
strands-agents
strands-agents-tools
uv
@@ -0,0 +1,18 @@
[project]
name = "streamlit-chat"
version = "0.1.0"
description = "Simple Streamlit application for chatting with AI agents deployed to Amazon Bedrock AgentCore Runtime."
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"boto3>=1.40.23",
"streamlit>=1.49.1",
"uv>=0.8.15",
]
[dependency-groups]
dev = [
"bedrock-agentcore>=0.1.3",
"bedrock-agentcore-starter-toolkit>=0.1.8",
"strands-agents>=1.7.1",
]
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

@@ -0,0 +1,4 @@
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path class="stroke-linejoin-round" fill="#962EFF" d="M6.15 10.3649L8 15.0049L9.86 10.3649L14.5 8.50488L9.86 6.65488L8 2.00488L6.15 6.65488L1.5 8.50488L6.15 10.3649Z" />
<path class="filled no-stroke" fill="#962EFF" d="M2.38 4.915C2.4 4.965 2.45 4.995 2.5 4.995C2.55 4.995 2.62 4.915 2.62 4.915L3.28 3.275L4.92 2.615C4.97 2.595 5 2.545 5 2.495C5 2.445 4.92 2.375 4.92 2.375L3.28 1.715L2.62 0.075C2.58 -0.025 2.42 -0.025 2.38 0.075L1.72 1.715L0.0799942 2.375C0.0299942 2.395 0 2.445 0 2.495C0 2.545 0.0799942 2.615 0.0799942 2.615L1.72 3.275L2.38 4.915Z" />
</svg>

After

Width:  |  Height:  |  Size: 625 B

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.91802 2.37562L3.27534 1.71766L2.61948 0.072746C2.57948 -0.0242487 2.41952 -0.0242487 2.37952 0.072746L1.72266 1.71766L0.0809838 2.37562C0.0329934 2.39562 0 2.44361 0 2.49561C0 2.54761 0.0319936 2.59561 0.0809838 2.61561L0.130974 2.6356L1.72266 3.27257L2.37952 4.91748C2.39952 4.96548 2.44751 4.99847 2.4995 4.99847C2.55149 4.99847 2.59948 4.96648 2.61948 4.91748L3.27634 3.27257L4.91902 2.61461C4.96701 2.59461 5 2.54661 5 2.49461C5 2.44262 4.96801 2.39462 4.91902 2.37462L4.91802 2.37562Z" fill="#FAF5FF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.99907 1.00458C8.40831 1.0042 8.77649 1.25314 8.92848 1.63299L10.6291 5.88317L14.8704 7.57368C15.2502 7.7251 15.4996 8.09251 15.5 8.50136C15.5004 8.91021 15.2517 9.27808 14.8721 9.43021L10.6291 11.1306L8.9282 15.3723C8.77603 15.7518 8.40804 16.0004 7.99907 16C7.5901 15.9996 7.22257 15.7503 7.07111 15.3705L5.38008 11.1305L1.12861 9.43048C0.748637 9.27854 0.499621 8.91048 0.5 8.50136C0.50038 8.09224 0.750079 7.72465 1.13033 7.57341L5.38008 5.88316L7.07084 1.63472C7.22212 1.25458 7.58983 1.00496 7.99907 1.00458ZM8.0025 4.70229L7.07917 7.02241C6.97752 7.27782 6.77516 7.48012 6.51967 7.58173L4.19884 8.50479L6.52139 9.43353C6.77585 9.53528 6.97739 9.73698 7.07889 9.99148L8.0025 12.3073L8.9318 9.98975C9.03344 9.73628 9.23437 9.53541 9.48792 9.4338L11.8062 8.50479L9.48965 7.58146C9.23507 7.47999 9.03331 7.27851 8.93152 7.02413L8.0025 4.70229Z" fill="#FAF5FF"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@@ -0,0 +1,4 @@
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path fill="#5C7FFF" d="M8 7C9.66 7 11 5.66 11 4C11 2.34 9.66 1 8 1C6.34 1 5 2.34 5 4C5 5.66 6.34 7 8 7Z" />
<path fill="#5C7FFF" d="M2 16V13C2 11.34 3.34 10 5 10H11C12.66 10 14 11.34 14 13V16" class="stroke-linejoin-round"/>
</svg>

After

Width:  |  Height:  |  Size: 294 B

File diff suppressed because it is too large Load Diff
+1
View File
@@ -29,3 +29,4 @@
- w601sxs
- erezweinstein5
- HardikThakkar94
- brianloyal