feat(skills): add int-aws integration — SNS/SES/S3/CloudWatch#89
Conversation
Provides sns_sms.py for SMS send (single + bulk via CSV), sandbox verification, and account status. Credentials loaded from .env (IAM user evonexus, SNSFullAccess + SESFullAccess). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Reviewer's GuideAdds a new Sequence diagram for sns_sms.py sending an SMS via AWS SNSsequenceDiagram
actor User
participant Script as sns_sms.py
participant Boto3 as boto3_SNS_client
participant SNS as AWS_SNS
User->>Script: invoke main(send, phone, message)
Script->>Script: get_client()
Script->>Boto3: client(region_name, aws_access_key_id, aws_secret_access_key)
Script->>Boto3: publish(PhoneNumber, Message, MessageAttributes)
Boto3->>SNS: Publish
SNS-->>Boto3: MessageId
Boto3-->>Script: publish response
Script-->>User: print(MessageId)
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 2 issues, and left some high level feedback:
- The skill manifest and docs reference different region env vars (
AWS_REGIONvsAWS_DEFAULT_REGION), andsns_sms.pyhardcodesAWS_REGION; it would be good to standardize on a single env var name across code and SKILL.md to avoid subtle misconfigurations. - SKILL.md references
ses_email.pyand SES commands, but that script is not part of this diff or listed underfilesin the manifest; consider either adding the script in this PR or trimming the SES-specific CLI examples to avoid broken instructions. sns_sms.pybuilds the SNS client usingAWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEYdirectly but does not validate their presence, so a quick check with a clear error message when these env vars are missing would make failures easier to debug.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The skill manifest and docs reference different region env vars (`AWS_REGION` vs `AWS_DEFAULT_REGION`), and `sns_sms.py` hardcodes `AWS_REGION`; it would be good to standardize on a single env var name across code and SKILL.md to avoid subtle misconfigurations.
- SKILL.md references `ses_email.py` and SES commands, but that script is not part of this diff or listed under `files` in the manifest; consider either adding the script in this PR or trimming the SES-specific CLI examples to avoid broken instructions.
- `sns_sms.py` builds the SNS client using `AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY` directly but does not validate their presence, so a quick check with a clear error message when these env vars are missing would make failures easier to debug.
## Individual Comments
### Comment 1
<location path=".claude/skills/int-aws/scripts/sns_sms.py" line_range="50-53" />
<code_context>
+ print(f"✅ Enviado! MessageId: {resp['MessageId']}")
+
+
+def cmd_bulk(args):
+ with open(args.file, newline="", encoding="utf-8") as f:
+ reader = csv.DictReader(f)
+ rows = list(reader)
+
+ print(f"Enviando para {len(rows)} números...")
</code_context>
<issue_to_address>
**suggestion (performance):** Avoid loading the entire CSV into memory; iterate over the reader to support large files.
Converting the `DictReader` to a list loads the whole file into memory, which can be a problem for large bulk sends. Instead, iterate over `reader` directly:
```python
def cmd_bulk(args):
with open(args.file, newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
print("Enviando...")
sent, failed = 0, 0
for row in reader:
...
```
If you need the total count, consider a `--dry-run` mode to count first, or otherwise avoid materializing all rows just to print the total up front.
Suggested implementation:
```python
def cmd_bulk(args):
sent, failed = 0, 0
with open(args.file, newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
print("Enviando...")
for row in reader:
phone = row.get("phone") or row.get("telefone") or row.get("celular", "")
message = row.get("message") or row.get("mensagem", "")
if not phone or not message:
print(f" ⚠️ Linha ignorada (phone ou message vazio): {row}")
failed += 1
continue
try:
send_sms(phone, message)
sent += 1
print(f" ✅ {phone}")
except Exception as exc:
failed += 1
print(f" ❌ {phone} - erro ao enviar: {exc}")
print(f"Resumo: {sent} enviados, {failed} falharam")
```
If there is existing error-handling or summary logic for `cmd_bulk` further down in the file (beyond the snippet provided), ensure it is removed or adjusted to avoid duplicate logging or conflicting counters, since this implementation now handles per-row errors and prints a final summary.
</issue_to_address>
### Comment 2
<location path=".claude/skills/int-aws/scripts/sns_sms.py" line_range="14-20" />
<code_context>
+REGION = os.environ.get("AWS_REGION", "us-east-1")
+
+
+def get_client():
+ return boto3.client(
+ "sns",
+ region_name=REGION,
+ aws_access_key_id=os.environ.get("AWS_ACCESS_KEY_ID"),
+ aws_secret_access_key=os.environ.get("AWS_SECRET_ACCESS_KEY"),
+ )
+
+
</code_context>
<issue_to_address>
**suggestion (performance):** Reuse a single SNS client instead of creating a new one for each operation.
Each helper call creates a fresh SNS client, which adds unnecessary overhead and connection churn in bulk usage. Consider caching the client (e.g., module-level singleton or memoizing `get_client()`) so subsequent calls reuse the same instance.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| def cmd_bulk(args): | ||
| with open(args.file, newline="", encoding="utf-8") as f: | ||
| reader = csv.DictReader(f) | ||
| rows = list(reader) |
There was a problem hiding this comment.
suggestion (performance): Avoid loading the entire CSV into memory; iterate over the reader to support large files.
Converting the DictReader to a list loads the whole file into memory, which can be a problem for large bulk sends. Instead, iterate over reader directly:
def cmd_bulk(args):
with open(args.file, newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
print("Enviando...")
sent, failed = 0, 0
for row in reader:
...If you need the total count, consider a --dry-run mode to count first, or otherwise avoid materializing all rows just to print the total up front.
Suggested implementation:
def cmd_bulk(args):
sent, failed = 0, 0
with open(args.file, newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
print("Enviando...")
for row in reader:
phone = row.get("phone") or row.get("telefone") or row.get("celular", "")
message = row.get("message") or row.get("mensagem", "")
if not phone or not message:
print(f" ⚠️ Linha ignorada (phone ou message vazio): {row}")
failed += 1
continue
try:
send_sms(phone, message)
sent += 1
print(f" ✅ {phone}")
except Exception as exc:
failed += 1
print(f" ❌ {phone} - erro ao enviar: {exc}")
print(f"Resumo: {sent} enviados, {failed} falharam")If there is existing error-handling or summary logic for cmd_bulk further down in the file (beyond the snippet provided), ensure it is removed or adjusted to avoid duplicate logging or conflicting counters, since this implementation now handles per-row errors and prints a final summary.
| def get_client(): | ||
| return boto3.client( | ||
| "sns", | ||
| region_name=REGION, | ||
| aws_access_key_id=os.environ.get("AWS_ACCESS_KEY_ID"), | ||
| aws_secret_access_key=os.environ.get("AWS_SECRET_ACCESS_KEY"), | ||
| ) |
There was a problem hiding this comment.
suggestion (performance): Reuse a single SNS client instead of creating a new one for each operation.
Each helper call creates a fresh SNS client, which adds unnecessary overhead and connection churn in bulk usage. Consider caching the client (e.g., module-level singleton or memoizing get_client()) so subsequent calls reuse the same instance.
Summary
Adds a new
int-awsskill that provides EvoNexus agents with access to four core AWS services:Files Added
.claude/skills/int-aws/SKILL.md.claude/skills/int-aws/scripts/sns_sms.pyConfiguration
All credentials are sourced from environment variables — no secrets in code:
Test Plan
/int-awsskill — help text renders correctlysns_sms.pyto a verified numberSummary by Sourcery
Introduce a new int-aws skill that integrates core AWS services into the project and documents how to use them.
New Features:
Documentation: