AI-powered content summarization agent that processes web articles (HTML), YouTube videos, and PDF documents through Slack, delivering intelligent summaries directly to your channels.
OmniSummary is a production-ready agentic system built on Strands Agents and AWS Bedrock AgentCore. It enables teams to quickly digest technical content by mentioning a Slack bot with a URL, receiving comprehensive summaries with extracted images and reference links.
- Multi-Format Support: HTML articles, YouTube videos, PDF documents
- Intelligent Summarization: Claude Sonnet 4.5 with customizable opening messages
- Image Processing: Automatic extraction and analysis using Claude Haiku 3 VLM
- Metadata Extraction: Authors, affiliations, publication dates, keywords, reference URLs
- Dual Slack Workspace: Support for both personal and business channels
- Production Infrastructure: AWS Bedrock AgentCore with event deduplication and signature verification
- Research teams tracking arxiv papers and technical blogs
- Engineering teams digesting conference talks and tutorials
- Product teams reviewing industry reports and whitepapers
- Knowledge sharing across personal and business Slack workspaces
┌─────────────┐
│ Slack User │ @your-bot https://example.com/article
└──────┬──────┘
│
▼
┌─────────────────────────────────────────────────┐
│ API Gateway → Lambda (Slack Event Handler) │
│ - Signature verification │
│ - Event deduplication (DynamoDB) │
│ - Immediate ACK │
└──────┬──────────────────────────────────────────┘
│ (async invoke)
▼
┌─────────────────────────────────────────────────┐
│ AWS Bedrock AgentCore Runtime │
│ - Docker container (ECS-like) │
│ - Strands Agent orchestration │
└──────┬──────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ Agent Tools │
│ 1. parse_html / parse_pdf / parse_youtube │
│ 2. generate_summary │
│ 3. send_slack_message │
└──────┬──────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ Slack Channels │
│ - Summary with images │
│ - Reference URLs │
└─────────────────────────────────────────────────┘
| Component | Technology |
|---|---|
| Agent Framework | Strands Agents |
| Runtime Platform | AWS Bedrock AgentCore |
| Infrastructure | AWS CDK (Python) |
| LLM | Amazon Bedrock (Claude Sonnet 4.5) |
| VLM | Amazon Bedrock (Claude Haiku 3) |
| PDF Parsing | Unstructured / Upstage Document Parser |
| Messaging | Slack Bot API |
| Package Manager | uv |
Before starting, ensure you have:
- AWS Account with Administrator access
- AWS CLI configured with credentials
- Slack Workspace with Admin permissions to create apps
- Python 3.12+ installed
- uv package manager (installation guide)
- Docker for building AgentCore runtime images
# Clone the repository
git clone <your-repo-url>
cd omnisummary
# Install dependencies using uv
uv sync
# Create environment configuration
cp .env.template .env
# Edit .env with your credentials (see below)
# Create config file
cp config/config-template.yaml config/config.yaml
# Edit config.yaml (see Configuration section)This section provides detailed instructions for creating and configuring your Slack App.
- Go to Slack API
- Click "Create New App" → "From scratch"
- Enter:
- App Name: Choose any name (e.g., "ContentSummary", "DigestBot", "OmniSummary")
- Workspace: Select your workspace
- Click "Create App"
Note: Throughout this README, we use
@omnisummaryas an example. Replace it with your actual bot name.
- Navigate to "OAuth & Permissions" in the sidebar
- Scroll to "Scopes" → "Bot Token Scopes"
- Add the following scopes:
app_mentions:read - Detect when bot is mentioned chat:write - Send messages to channels files:write - Upload images (PDF thumbnails) channels:history - (Optional) Read channel history - Scroll to top and click "Install to Workspace"
- Authorize the app
- Copy the Bot User OAuth Token (starts with
xoxb-)- Save this as
SLACK_PERSONAL_TOKENorSLACK_BUSINESS_TOKENin.env
- Save this as
Important: Complete this step AFTER deploying the AWS infrastructure (Step 3).
- Navigate to "Event Subscriptions"
- Toggle "Enable Events" to ON
- Enter Request URL:
You'll get the API Gateway URL from AWS deployment outputs.
https://<your-api-gateway-url>/slack/events - Under "Subscribe to bot events", add:
app_mention - Click "Save Changes"
Channel IDs are required in your configuration to specify where summaries should be posted.
Method 1: Slack Web/Desktop App
- Right-click the channel name
- Select "View channel details"
- Scroll down and copy the Channel ID (starts with
C)
Method 2: Slack API
curl -H "Authorization: Bearer xoxb-YOUR-TOKEN" \
https://slack.com/api/conversations.listMultiple Channels: Separate with commas (no spaces)
SLACK_PERSONAL_CHANNEL_IDS=C123ABC456,C789DEF012,C345GHI678
- Navigate to "Basic Information"
- Scroll to "App Credentials"
- Copy the Signing Secret
- Save as
SLACK_SIGNING_SECRETin.env
After app installation, invite your bot to channels:
/invite @your-bot-name
The bot must be a member of all channels listed in SLACK_PERSONAL_CHANNEL_IDS and SLACK_BUSINESS_CHANNEL_IDS.
Edit .env with your credentials:
# Slack Configuration
SLACK_PERSONAL_TOKEN=xoxb-your-personal-workspace-token
SLACK_PERSONAL_CHANNEL_IDS=C123ABC456,C789DEF012
SLACK_BUSINESS_TOKEN=xoxb-your-business-workspace-token # Optional
SLACK_BUSINESS_CHANNEL_IDS=C345GHI678 # Optional
SLACK_SIGNING_SECRET=your-signing-secret
# Optional: Upstage Document Parser (for PDF parsing)
UPSTAGE_API_KEY=your-upstage-api-key
# Optional: Langchain Tracing
LANGCHAIN_API_KEY=your-langchain-api-key
LANGCHAIN_TRACING_V2=false
LANGCHAIN_ENDPOINT=https://api.smith.langchain.com
LANGCHAIN_PROJECT=omnisummary
# Logging
LOG_LEVEL=INFOSlack Configuration Notes:
- Personal vs Business Tokens: You can configure separate Slack workspaces
SLACK_PERSONAL_*: Always used for summariesSLACK_BUSINESS_*: Only used when explicitly requested (e.g., "send to business channels")
- Channel IDs: Comma-separated, no spaces
- Signing Secret: Required for request verification and security
Edit config/config.yaml:
resources:
project_name: omnisummary
stage: dev # or prod
profile_name: your-aws-profile # AWS CLI profile name
default_region_name: us-west-2
bedrock_region_name: us-west-2 # Must support Claude models
# Optional: Use existing VPC
vpc_id: vpc-xxxxx
subnet_ids:
- subnet-xxxxx
- subnet-yyyyy
# Enable business Slack workspace
enable_business_slack_channels: true # Set to false to disable
content_parser:
figure_analysis_model_id: anthropic.claude-3-haiku-20240307-v1:0
metadata_extraction_model_id: anthropic.claude-sonnet-4-5-20250929-v1:0
pdf_parser_type: unstructured # or upstage
summarization:
summarization_model_id: anthropic.claude-sonnet-4-5-20250929-v1:0
n_thumbnails: 1 # Number of images to extract
agent:
agent_model_id: anthropic.claude-sonnet-4-5-20250929-v1:0
infrastructure:
lambda_timeout_seconds: 60
lambda_memory_mb: 128
agentcore_image_tag: latestImportant Configuration Notes:
bedrock_region_name: Must be a region where Claude Sonnet 4.5 is available (e.g.,us-west-2,us-east-1)enable_business_slack_channels: Must betruefor business workspace features to workpdf_parser_type:unstructured(free, local) orupstage(API-based, requires key)
# Export AWS profile if using named profile
export AWS_PROFILE=your-aws-profile
# Bootstrap CDK (creates S3 bucket and IAM roles)
uv run cdk bootstrap# Deploys: VPC, ECR, DynamoDB, IAM Roles, CodeBuild
uv run cdk deploy OmniSummaryFoundationStack
# Review changes and confirm with 'y'This stack creates:
- ECR repository for AgentCore Docker images
- DynamoDB table for event deduplication
- CodeBuild project for automatic Docker builds
- IAM roles for Lambda and AgentCore
After Foundation Stack deployment, the CodeBuild project automatically triggers to build and push the Docker image to ECR. You can monitor the build:
# Get build project name from CloudFormation outputs
aws codebuild list-builds-for-project \
--project-name omnisummary-dev-summary-bot-builder
# Check build status
aws codebuild batch-get-builds --ids <build-id>Manual build (if needed):
# Get ECR repository URI from CloudFormation outputs
aws ecr describe-repositories --repository-names omnisummary-dev-summary-bot
# Login to ECR
aws ecr get-login-password --region us-west-2 | \
docker login --username AWS --password-stdin <account-id>.dkr.ecr.us-west-2.amazonaws.com
# Build and push
docker build -t omnisummary-dev-summary-bot:latest .
docker tag omnisummary-dev-summary-bot:latest <ecr-uri>:latest
docker push <ecr-uri>:latest# Deploys: AgentCore Runtime, Lambda, API Gateway, SSM Parameters
uv run cdk deploy OmniSummaryApplicationStack
# Save the API Gateway URL from outputsImportant: Copy the API Gateway URL from deployment outputs. You'll need it for Slack Event Subscriptions (Step 2.3).
Example output:
OmniSummaryApplicationStack.ApiEndpoint = https://abcdef1234.execute-api.us-west-2.amazonaws.com/dev
Now go back to Step 2.3 and configure the Event Subscription URL using the API Gateway endpoint:
https://abcdef1234.execute-api.us-west-2.amazonaws.com/dev/slack/events
# Check AgentCore Runtime status
aws bedrock-agentcore list-agent-runtimes
# Check Lambda function
aws lambda list-functions --query "Functions[?contains(FunctionName, 'slack-event-handler')]"
# Test API Gateway
curl -X POST https://<your-api-gateway-url>/slack/events
# Should return 401 (Unauthorized) without valid Slack signatureOnce deployed and configured, interact with your bot in Slack:
@your-bot-name https://example.com/blog-post
The bot will:
- Parse the HTML content
- Extract metadata (title, authors, date, keywords)
- Generate a summary
- Post to personal Slack channels
@your-bot-name https://youtube.com/watch?v=abcd1234
Extracts transcript and summarizes video content.
@your-bot-name https://arxiv.org/pdf/2301.12345.pdf
Parses PDF, extracts figures, and generates summary with image thumbnails.
Add keywords to send summaries to both personal AND business workspaces:
@your-bot-name https://example.com/article 회사 채널에도 보내줘
@your-bot-name https://example.com/article send to business channels
@your-bot-name https://example.com/article 전체 채널에
Keywords detected:
- Korean:
회사 채널,비즈니스 채널,업무 채널,전체 채널,다 보내 - English:
business channel,work channel,send to all
Requirement: enable_business_slack_channels: true in config.yaml
Start the summary with a specific phrase:
@your-bot-name https://example.com/article AWS 신기능이네요로 시작해줘
The summary will begin with: "AWS 신기능이네요"
Keywords: 로 시작해줘, 로 시작, 부터 시작
@your-bot-name https://example.com/article
흥미로운 아키텍처네요로 시작. 회사 채널에도 공유해줘
This will:
- Generate summary starting with "흥미로운 아키텍처네요"
- Post to both personal and business channels
Summaries include:
🗞️ 2024-01-15에 John Doe, Jane Smith에서 발행한 Article Title의 요약입니다.
[Opening commentary in Gruber-style voice]
📌 왜 여기에 주목해야 하나요?
[Significance and context]
🔄 핵심 아이디어 및 접근 방식
[Key concepts and methodologies]
🛠️ 기술적 심층 분석
[Technical details and implementation]
📊 성과 및 비즈니스 임팩트
[Results and metrics]
📎 참고 링크
- https://github.com/example/repo
- https://arxiv.org/abs/2301.12345
For PDFs, image thumbnails are uploaded separately after the text summary.
omnisummary/
├── agent/ # Strands Agent definition
│ ├── agent.py # summarization_agent
│ ├── agent_tools.py # Tool implementations
│ └── tool_state.py # Stateful tool execution
├── agent_runtime/ # Bedrock AgentCore entrypoint
│ └── app.py # BedrockAgentCoreApp
├── config/ # Configuration files
│ ├── config-template.yaml
│ └── config.yaml # User config (gitignored)
├── infrastructure/ # AWS CDK stacks
│ ├── foundation_stack.py # VPC, ECR, DynamoDB, IAM
│ └── application_stack.py # AgentCore, Lambda, API Gateway
├── lambda_handlers/ # Lambda functions
│ └── slack_event_handler.py # Slack event processing
├── shared/ # Shared utilities
│ ├── config.py # Config models
│ ├── constants.py # Enums and constants
│ ├── formatters.py # Slack message formatting
│ ├── models.py # Data models (Pydantic)
│ └── prompts/ # LLM prompts
│ └── prompts.py
├── tools/ # Content processing tools
│ ├── content_parser/ # HTML, PDF, YouTube parsers
│ ├── output_handler/ # Slack message sender
│ └── summarizer/ # LLM summarization
├── tests/ # Unit and integration tests
├── .env.template # Environment variable template
├── config.yaml # Main configuration
├── pyproject.toml # Python project definition
├── Dockerfile # AgentCore runtime image
└── README.md # This file
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=omnisummary --cov-report=html
# Run specific test file
uv run pytest tests/test_agents.py# Format code
uv run black .
# Lint
uv run ruff check .
# Type checking
uv run mypy .You can test agent logic locally:
from agent import summarization_agent
# Test the agent
response = summarization_agent("https://example.com/article")
print(response)Note: This requires configuring local .env with Slack tokens and setting up AWS credentials for Bedrock access.
-
Define tool function in
agent/agent_tools.py:@tool async def my_new_tool(param: str) -> str: """Tool description for LLM.""" # Implementation return result
-
Add tool to agent in
agent/agent.py:tools = [ generate_summary, parse_html, parse_pdf, parse_youtube, send_slack_message, my_new_tool, # Add here ]
-
Update system prompt to instruct agent when to use the tool
-
Rebuild and redeploy:
# Trigger CodeBuild aws codebuild start-build --project-name omnisummary-dev-summary-bot-builder # After build completes, update AgentCore runtime uv run cdk deploy OmniSummaryApplicationStack
Check 1: Bot is invited to channel
/invite @your-bot-name
Check 2: Event Subscription URL is verified
- Go to Slack App → Event Subscriptions
- URL should show green checkmark
Check 3: Check Lambda logs
aws logs tail /aws/lambda/omnisummary-dev-slack-event-handler-lambda --followCheck 4: Verify app_mention scope
- Slack App → OAuth & Permissions → Scopes
- Ensure
app_mentions:readis added
Check 1: AgentCore Runtime logs
# Get runtime name
aws bedrock-agentcore list-agent-runtimes
# Get log group
aws logs describe-log-groups --query "logGroups[?contains(logGroupName, 'agentcore')]"
# Tail logs
aws logs tail <log-group-name> --followCheck 2: Slack tokens are correct
# Verify token works
curl -H "Authorization: Bearer xoxb-YOUR-TOKEN" \
https://slack.com/api/auth.testCheck 3: Channel IDs are correct
# List channels the bot is member of
curl -H "Authorization: Bearer xoxb-YOUR-TOKEN" \
https://slack.com/api/conversations.listCheck 1: Config setting
# config/config.yaml
resources:
enable_business_slack_channels: true # Must be trueCheck 2: Mention business keywords
@bot https://example.com/article 회사 채널에도 보내줘
Check 3: Business token and channel IDs are set
# .env
SLACK_BUSINESS_TOKEN=xoxb-...
SLACK_BUSINESS_CHANNEL_IDS=C123ABC456Check 1: ECR authentication
aws ecr get-login-password --region us-west-2 | \
docker login --username AWS --password-stdin <account-id>.dkr.ecr.us-west-2.amazonaws.comCheck 2: CodeBuild logs
aws codebuild list-builds-for-project --project-name omnisummary-dev-summary-bot-builder
aws codebuild batch-get-builds --ids <build-id>If you're seeing duplicate events:
# Check DynamoDB table
aws dynamodb scan --table-name omnisummary-dev-event-deduplication
# Verify TTL is enabled
aws dynamodb describe-time-to-live --table-name omnisummary-dev-event-deduplicationApproximate monthly costs for moderate usage (100 summaries/day):
| Service | Usage | Cost |
|---|---|---|
| Bedrock Claude Sonnet 4.5 | ~50K tokens/summary × 100 | ~$15 |
| Bedrock Claude Haiku 3 | ~10K tokens/image × 100 | ~$1 |
| Lambda | 100 invocations/day | ~$0.01 |
| API Gateway | 100 requests/day | ~$0.01 |
| DynamoDB | On-demand, minimal | ~$0.25 |
| AgentCore Runtime | Runtime hours | Variable* |
| ECR | 10 images stored | ~$0.10 |
| Total | ~$16-20/month |
*AgentCore Runtime costs depend on task duration and concurrency. Idle time may incur minimal charges.
Cost Optimization Tips:
- Use
devstage for testing (enables aggressive cleanup) - Set
n_thumbnails: 1to minimize VLM API calls - Configure lifecycle rules on ECR (already included)
- Use Bedrock on-demand pricing for variable workloads
- Slack Request Verification: Always enabled via signing secret
- Secrets Management: All credentials stored in SSM Parameter Store (encrypted)
- Event Deduplication: Prevents replay attacks and duplicate processing
- IAM Least Privilege: Separate roles for Lambda and AgentCore with minimal permissions
- VPC Isolation: Optional VPC deployment for network isolation
- Environment Separation: Use
dev/prodstages with separate AWS accounts
We welcome contributions! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Follow code standards in
CLAUDE.md - Write tests for new functionality
- Run code quality checks (
black,ruff,mypy) - Commit with descriptive messages
- Push and create a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Built on Strands Agents by Anthropic
- Uses AWS Bedrock AgentCore for production deployment
- Inspired by Daring Fireball's analytical writing style
- PDF parsing powered by Unstructured and Upstage
For issues and questions:
- Open an issue on GitHub
- Check existing issues for solutions
- Review CloudWatch Logs for debugging
Note: Replace @your-bot-name with your actual Slack bot display name throughout usage examples.
