An event-driven, serverless security automation system that processes AWS GuardDuty findings, runs them through AI-powered triage and forensics agents on Amazon Bedrock AgentCore, and delivers enriched notifications across multiple channels — SNS, Email, and Google Chat.
The system features:
- AI Triage Agent - Performs deep threat analysis, computes risk levels, maps findings to MITRE ATT&CK
- AI Forensics Agent - Conducts deep investigation for high-risk findings using AWS APIs
- Voice SOC Escalation - Automated phone calls to on-call engineers for critical incidents
- Multi-Channel Notifications - SNS, Email, and Google Chat with rich formatting
⚠️ SECURITY WARNING: This repository contains example configurations. Never commit real AWS credentials, account IDs, or sensitive information. See SECURITY_AUDIT.md for details.
The system follows an event-driven architecture:
- GuardDuty detects security findings in your AWS environment
- EventBridge rule triggers on GuardDuty findings
- Lambda Function processes the finding and orchestrates the workflow
- Bedrock AgentCore runs AI agents for analysis:
- Triage Agent (Required): Analyzes every finding, computes risk levels
- Forensics Agent (Optional): Deep investigation for high-risk findings only
- Multi-Channel Notifications: Sends enriched alerts via SNS, Email, and Google Chat
- CloudWatch: Captures logs and traces for observability
The complete system includes optional voice escalation for critical incidents:
- Step Functions orchestrates the escalation workflow
- DynamoDB stores incident context for interactive queries
- Amazon Polly converts alerts to speech
- Amazon Connect places outbound calls to on-call engineers
- Amazon Lex provides AI-powered Q&A during the call
lambda_function.py— EventBridge trigger handler; invokes the triage agent and fans out notificationsbedrock-agentcore-runtime/triage_agent.py— Strands-based AI agent deployed on AgentCore RuntimeAWSSession.py— Flexible AWS credential managementNotification.py— SMTP email deliverycloudformation-template.yaml— Full infrastructure as codecloudformation_deploy.sh/agent-deploy.sh— Deployment automation
The triage agent runs on Amazon Bedrock AgentCore Runtime using the Strands Agents SDK backed by Claude Haiku. For every GuardDuty finding it produces a structured JSON risk assessment covering:
- One-sentence finding summary
- Threat category classification (Brute Force, Lateral Movement, Data Exfiltration, etc.)
- Base and escalated risk level (Low / Medium / High / Critical)
- MITRE ATT&CK technique mapping
- Immediate containment steps
- Investigation steps and remediation actions
- Long-term prevention controls
- Automation feasibility assessment
- Confidence score
The agent raises the calculated risk one level if any of the following apply:
- Public IP exposure detected
- Process executed as root (UID 0)
- Repeated activity (
service.count > 5) - Privileged IAM role attached
- Resource tagged as
productionorprod - Persistence mechanism detected
- Lateral movement indicators present
- Data exfiltration risk identified
# Authenticate first
aws sso login --profile <your-profile>
export AWS_PROFILE=<your-profile>
# Deploy
chmod +x agent-deploy.sh
./agent-deploy.sh --profile <your-profile> --region ap-south-1The script installs the AgentCore CLI, runs agentcore configure, and launches the agent to the runtime. The agent ARN is output at the end — set it as AGENTCORE_AGENT_ARN in your Lambda environment.
The agent runtime has observability enabled. To see traces and metrics in the CloudWatch GenAI Observability dashboard:
-
Enable CloudWatch Transaction Search (one-time):
- CloudWatch console → Application Signals (APM) → Transaction Search → Enable
-
The
requirements.txtincludesaws-opentelemetry-distroand the entrypoint in.bedrock_agentcore.yamlis wrapped withopentelemetry-instrument, so OTEL spans flow automatically after redeployment. -
View data at: CloudWatch → GenAI Observability (
/aws/bedrock-agentcore/runtimes/<agent-id>)
Required for All Deployments:
- AWS CLI configured with appropriate permissions
- Python 3.13+
- GuardDuty enabled in your account
- AWS account with permissions to create:
- Lambda functions
- EventBridge rules
- IAM roles and policies
- SNS topics (optional)
Required for AI Agents:
- Bedrock model access (request via AWS Console → Bedrock → Model access)
anthropic.claude-haiku-4-5-20251001-v1:0(Triage Agent - Required)anthropic.claude-sonnet-4-5-20250929-v1:0(Forensics Agent - Optional)
Required for Notifications:
- SMTP credentials (Gmail, SendGrid, etc.) for email notifications
- Google Chat webhook URL for Chat notifications
- SNS topic ARN for SNS notifications
You can deploy this system in different configurations based on your needs:
| Component | Required | Purpose |
|---|---|---|
| Lambda + EventBridge | ✅ Yes | Core notification system |
| Triage Agent | ✅ Yes | AI-powered risk assessment |
| Forensics Agent | Deep investigation for high-risk findings | |
| Voice Escalation | Phone calls for critical incidents | |
| Email Notifications | HTML email alerts | |
| SNS Notifications | SNS topic publishing | |
| Google Chat | Chat space notifications |
Before deploying agents, you must request access to Claude models:
- Open AWS Console → Navigate to Amazon Bedrock
- Go to Model Access (left sidebar)
- Request Access for:
- ✅
Anthropic Claude Haiku 4.5(Required for Triage Agent) ⚠️ Anthropic Claude Sonnet 4.5(Optional for Forensics Agent)
- ✅
- Wait for Approval (usually instant, but can take up to 24 hours)
- Verify Access:
aws bedrock list-foundation-models --region ap-south-1 \ --query 'modelSummaries[?contains(modelId, `claude`)].modelId'
⚠️ Important: Without model access, agent deployment will succeed but invocations will fail withAccessDeniedException.
The Triage Agent is required for the system to function. It analyzes every GuardDuty finding.
What it does:
- Analyzes GuardDuty findings
- Computes risk levels (Low/Medium/High/Critical)
- Maps to MITRE ATT&CK techniques
- Provides containment and remediation steps
- Determines if escalation is needed
Deployment:
cd bedrock-agentcore-runtime
# Authenticate
aws sso login --profile <your-profile>
export AWS_PROFILE=<your-profile>
# Deploy the agent
chmod +x ../agent-deploy.sh
../agent-deploy.sh --profile <your-profile> --region ap-south-1Expected Output:
Configuring agent: guardduty_triage_agent
Launching agent to AgentCore Runtime...
Deploy complete. Run 'agentcore status --agent guardduty_triage_agent' to check.
Agent ARN: arn:aws:bedrock-agentcore:ap-south-1:123456789012:runtime/guardduty_triage_agent-xxxxx
Save the Agent ARN - you'll need it in Step 4.
Verify Deployment:
agentcore status --agent guardduty_triage_agentShould show: Status: ACTIVE
Cost: ~$0.25 per 1000 findings (Claude Haiku pricing)
The Forensics Agent is optional and only runs for high-risk findings that require deep investigation.
When it runs:
- Only when Triage Agent sets
requires_escalation = true - AND
calculated_risk >= High - AND
base_severity >= Low
What it does:
- Analyzes process lineage for attack patterns
- Investigates container security posture
- Evaluates IAM blast radius
- Queries CloudTrail for suspicious API calls
- Analyzes VPC flow logs for network activity
- Checks container logs for evidence
- Provides prioritized remediation actions
IAM Permissions Required: The Forensics Agent needs read-only access to:
- EC2 (DescribeInstances, DescribeSecurityGroups, DescribeNetworkInterfaces)
- ECS (DescribeTasks, DescribeTaskDefinition, DescribeClusters)
- IAM (GetRole, GetRolePolicy, ListRolePolicies, ListAttachedRolePolicies, GetInstanceProfile)
- CloudTrail (LookupEvents)
- CloudWatch Logs (DescribeLogGroups, FilterLogEvents)
- VPC (DescribeFlowLogs)
Deployment:
cd bedrock-agentcore-runtime
# Create execution role with forensics permissions
aws iam create-role \
--role-name guardduty-forensics-agent-role \
--assume-role-policy-document file://execution-role-trust.json
aws iam put-role-policy \
--role-name guardduty-forensics-agent-role \
--policy-name ForensicsPolicy \
--policy-document file://execution-role-policy.json
# Get the role ARN
FORENSICS_ROLE_ARN=$(aws iam get-role --role-name guardduty-forensics-agent-role --query 'Role.Arn' --output text)
# Deploy the forensics agent
agentcore configure \
--entrypoint forensics_agent.py \
--name guardduty_forensics_agent \
--runtime PYTHON_3_13 \
--idle-timeout 300 \
--region ap-south-1 \
--execution-role $FORENSICS_ROLE_ARN \
--disable-memory \
--non-interactive
agentcore launchSave the Forensics Agent ARN - you'll need it in Step 4.
Verify Deployment:
agentcore status --agent guardduty_forensics_agentCost: ~$3 per 1000 high-risk findings (Claude Sonnet pricing + API calls)
Skip this step if:
- You don't need deep forensic investigation
- You want to minimize costs
- You don't want to grant read access to multiple AWS services
Choose which notification channels you want to enable:
What you need:
- SMTP server credentials (Gmail, SendGrid, AWS SES, etc.)
- Recipient email addresses
Gmail Setup (Free):
- Enable 2-factor authentication on your Google account
- Go to Google Account → Security → 2-Step Verification → App passwords
- Generate an app password for "Mail"
- Use this 16-character password (not your regular password)
Create input.json:
cp input.json.template input.jsonEdit input.json:
{
"awsCredentials": {
"region_name": "ap-south-1",
"profile_name": "your-aws-profile"
},
"smtpCredentials": {
"host": "smtp.gmail.com",
"port": "587",
"username": "your-email@gmail.com",
"password": "your-16-char-app-password",
"from_email": "alerts@example.com"
},
"emailNotification": {
"email_subject": "GuardDuty Security Alert",
"subject_prefix": "SECURITY",
"to": ["security-team@example.com"],
"cc": ["devops@example.com"],
"bcc": []
}
}Set environment variable for deployment:
export ENABLE_EMAIL="true"What you need:
- Google Chat space
- Incoming webhook URL
Setup:
- Open Google Chat → Create or select a space
- Click space name → Apps & integrations → Webhooks
- Click "Add webhook"
- Name it "GuardDuty Alerts" and save
- Copy the webhook URL
Set environment variable:
export GOOGLE_CHAT_WEBHOOK="https://chat.googleapis.com/v1/spaces/xxx/messages?key=xxx"
export ENABLE_CHAT="true"What you need:
- Existing SNS topic ARN
- Topic must have appropriate subscriptions (email, SMS, Lambda, etc.)
Create SNS topic (if needed):
aws sns create-topic --name guardduty-security-alertsSet environment variable:
export SNS_TOPIC_ARN="arn:aws:sns:ap-south-1:123456789012:guardduty-security-alerts"
export ENABLE_SNS="true"If you just want to test the agents without notifications:
export ENABLE_EMAIL="false"
export ENABLE_CHAT="false"
export ENABLE_SNS="false"Now deploy the Lambda function that ties everything together:
chmod +x cloudformation_deploy.sh lambda_build.sh
# Set required variables (from previous steps)
export AGENTCORE_AGENT_ARN="<TRIAGE_ARN_FROM_STEP_2>"
# Optional: Set forensics agent ARN if you deployed it
export AGENTCORE_FORENSICS_ARN="<FORENSICS_ARN_FROM_STEP_3>"
# Optional: Set voice escalation state machine ARN
# export ESCALATION_STATE_MACHINE_ARN="<STATE_MACHINE_ARN>"
# Deploy
./cloudformation_deploy.shWhat this creates:
- Lambda function with Python 3.13 runtime
- IAM execution role with permissions for:
- Bedrock AgentCore invocation
- SNS publishing (if enabled)
- CloudWatch Logs
- Step Functions execution (if voice escalation enabled)
- EventBridge rule to trigger on GuardDuty findings
- Lambda permissions for EventBridge invocation
Verify Deployment:
# Check CloudFormation stack
aws cloudformation describe-stacks --stack-name guardduty-notifications
# Check Lambda function
aws lambda get-function --function-name guardduty-notifications-guardduty-processor
# Check EventBridge rule
aws events describe-rule --name guardduty-notifications-guardduty-ruleOption 1: Use GuardDuty Sample Findings
Generate a test finding in GuardDuty console:
aws guardduty create-sample-findings \
--detector-id <your-detector-id> \
--finding-types Execution:Runtime/SuspiciousCommandOption 2: Manual Lambda Invocation
Test with the provided example:
aws lambda invoke \
--function-name guardduty-notifications-guardduty-processor \
--payload file://bedrock-agentcore-runtime/examples/guardduty-event-example.json \
response.json
# Check the response
cat response.json | jq .Expected Response:
{
"statusCode": 200,
"body": {
"message": "Notifications processed successfully",
"finding_id": "94ce4bcc9ee7bdf33cb0963e2043127b",
"triage": {
"risk_assessment": {
"calculated_risk": "Medium",
"requires_escalation": true
}
},
"results": {
"email": "Success",
"chat": "Success"
}
}
}Check Logs:
aws logs tail /aws/lambda/guardduty-notifications-guardduty-processor --follow| Variable | Required | Default | Description |
|---|---|---|---|
AGENTCORE_AGENT_ARN |
✅ Yes | - | ARN of the Triage Agent |
AGENTCORE_FORENSICS_ARN |
- | ARN of the Forensics Agent (omit to disable) | |
ESCALATION_STATE_MACHINE_ARN |
- | ARN of Voice Escalation state machine (omit to disable) | |
AWS_REGION_NAME |
ap-south-1 |
Region for AgentCore client | |
ENABLE_EMAIL |
false |
Enable email notifications | |
ENABLE_SNS |
false |
Enable SNS notifications | |
ENABLE_CHAT |
false |
Enable Google Chat notifications | |
SNS_TOPIC_ARN |
- | SNS topic ARN (required if ENABLE_SNS=true) | |
GOOGLE_CHAT_WEBHOOK |
- | Google Chat webhook URL (required if ENABLE_CHAT=true) |
Triage Agent:
- Runs for every GuardDuty finding
- Timeout: 30 seconds
- Model: Claude Haiku 4.5
- Cost: ~$0.25 per 1000 findings
Forensics Agent:
- Runs only when all conditions are met:
requires_escalation = true(from Triage)calculated_risk >= High(from Triage)base_severity >= Low(from GuardDuty)
- Timeout: 5 minutes
- Model: Claude Sonnet 4.5
- Cost: ~$3 per 1000 high-risk findings
Voice Escalation:
- Triggers only when
requires_escalation = true - Requires separate deployment (see
voice-escalation/README.md) - Calls on-call engineer via Amazon Connect
If you don't want deep forensic investigation:
- Don't deploy the Forensics Agent (skip Step 3)
- Don't set
AGENTCORE_FORENSICS_ARNin CloudFormation deployment
The system will work fine with just the Triage Agent.
Voice escalation is disabled by default. To enable it:
- Deploy the voice escalation infrastructure (see
voice-escalation/README.md) - Set
ESCALATION_STATE_MACHINE_ARNenvironment variable
Update Lambda environment variables:
aws lambda update-function-configuration \
--function-name guardduty-notifications-guardduty-processor \
--environment Variables="{
ENABLE_EMAIL=true,
ENABLE_SNS=false,
ENABLE_CHAT=true,
AGENTCORE_AGENT_ARN=<your-arn>,
GOOGLE_CHAT_WEBHOOK=<your-webhook>
}"Edit bedrock-agentcore-runtime/triage_agent.py:
- Modify
SYSTEM_PROMPTto change analysis behavior - Adjust escalation rules in the prompt
- Change severity mapping thresholds
Redeploy:
cd bedrock-agentcore-runtime
agentcore launchAll channels receive the full AI triage output alongside the raw finding details.
- SNS — plain-text summary with top containment steps; suitable for downstream integrations
- Email — full HTML report with all triage sections, risk badges, and MITRE mapping
- Google Chat — concise card with risk level, escalation flag, and top 2 containment steps
.
├── lambda_function.py # Lambda handler + AgentCore invocation
├── AWSSession.py # AWS credential helper
├── Notification.py # SMTP email sender
├── input.json # Runtime configuration
├── requirements.txt # Lambda dependencies
├── cloudformation-template.yaml # Infrastructure as code
├── cloudformation_deploy.sh # Lambda + EventBridge deploy script
├── agent-deploy.sh # AgentCore agent deploy script
└── bedrock-agentcore-runtime/
├── triage_agent.py # Strands agent on AgentCore Runtime
├── requirements.txt # Agent dependencies (incl. ADOT)
├── .bedrock_agentcore.yaml # AgentCore CLI config
└── examples/
├── guardduty-event-example.json
└── triage-agent-example.json
AgentCore returns empty triage / AGENTCORE_AGENT_ARN not set
- Verify the env var is set on the Lambda function
- Check the Lambda IAM role has
bedrock-agentcore:InvokeAgentRuntimeon the agent ARN - Ensure the agent is in
ACTIVEstate:agentcore status --agent guardduty_triage_agent
No traces in CloudWatch GenAI Observability
- Confirm Transaction Search is enabled in CloudWatch
- Redeploy the agent after adding
aws-opentelemetry-distrotorequirements.txt - Check the entrypoint in
.bedrock_agentcore.yamlusesopentelemetry-instrument python triage_agent.py
Email delivery failures
- Check SMTP credentials and app password configuration
- Review Lambda logs:
aws logs tail /aws/lambda/guardduty-notifications-guardduty-processor - Verify firewall/security groups allow outbound SMTP (port 587)
EventBridge rule not triggering
- Verify the rule is
ENABLED:aws events describe-rule --name guardduty-notifications-guardduty-rule - Use GuardDuty sample findings to generate test events
- Check Lambda permissions allow EventBridge invocation
Forensics Agent timeout or errors
- Forensics agent has 5-minute timeout for deep investigation
- Check IAM role has all required read permissions (EC2, ECS, IAM, CloudTrail, VPC, CloudWatch Logs)
- Review agent logs in CloudWatch:
/aws/bedrock-agentcore/runtimes/<agent-id>
-
Credential Management
- Never commit
input.jsonwith real credentials - Use AWS Secrets Manager for production deployments
- Rotate SMTP passwords regularly
- Use IAM roles instead of access keys where possible
- Never commit
-
IAM Least Privilege
- Review and restrict Lambda execution role permissions
- Forensics agent requires read-only access to multiple services
- Use resource-based policies to limit scope
-
Network Security
- Deploy Lambda in VPC for enhanced security
- Use VPC endpoints for AWS service access
- Restrict outbound internet access to required destinations only
-
Monitoring
- Enable CloudWatch Logs for all Lambda functions
- Set up CloudWatch Alarms for Lambda errors
- Monitor AgentCore agent invocation metrics
- Review GuardDuty findings regularly
-
Data Protection
- GuardDuty findings may contain sensitive information
- Ensure notification channels are secured (encrypted email, private Chat spaces)
- Consider data retention policies for logs and notifications
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Run security audit before committing: Review
SECURITY_AUDIT.md - Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with AWS Bedrock AgentCore
- Uses Strands Agents SDK
- Powered by Anthropic Claude models
For issues and questions:
- Open an issue on GitHub
- Review the SECURITY_AUDIT.md for security concerns
- Check AWS documentation for service-specific issues

