Remove dead exec-aide-reminder Lambda and its IAM role

The reminder Lambda had 0 invocations in 90 days and no EventBridge
rule targets it. Removing the Lambda, its execution role, the
dedicated ReminderSchedulerRole, and the scheduler:CreateSchedule /
iam:PassRole grants from the conversation Lambda's policy.

The conversation Lambda's REMINDER_FN_ARN and REMINDER_SCHEDULER_ROLE_ARN
env vars and the create_reminder tool are removed alongside the
infrastructure. The src/reminder/ handler directory is also deleted.

Adam approved the deletion (INFRA-37).

Refs: INFRA-37
This commit is contained in:
Adam Moussa 2026-06-10 13:30:55 -04:00
parent 34e4634a9a
commit 7ca138099a
5 changed files with 3 additions and 115 deletions

View file

@ -169,31 +169,6 @@ export class EmailPipelineConstruct extends Construct {
sourceArn: `arn:aws:scheduler:${region}:${account}:schedule/default/${schedule.name}`,
});
// ── Reminder Lambda ──────────────────────────────────────
const reminder = new PythonFunction(this, 'Reminder', {
functionName: 'exec-aide-reminder',
entry: path.join(__dirname, '../../src'),
index: 'reminder/app.py',
handler: 'lambda_handler',
runtime: lambda.Runtime.PYTHON_3_12,
architecture: lambda.Architecture.ARM_64,
memorySize: 128,
timeout: cdk.Duration.seconds(30),
environment: lambdaEnv,
logRetention: logs.RetentionDays.TWO_MONTHS,
});
this.table.grantReadData(reminder);
reminder.addToRolePolicy(secretsReadPolicy);
reminder.addToRolePolicy(ssmPolicy);
const reminderSchedulerRole = new iam.Role(this, 'ReminderSchedulerRole', {
roleName: 'exec-aide-reminder-scheduler',
assumedBy: new iam.ServicePrincipal('scheduler.amazonaws.com'),
});
reminder.grantInvoke(reminderSchedulerRole);
// ── Conversation Lambda ───────────────────────────────────
const conversation = new PythonFunction(this, 'Conversation', {
@ -205,11 +180,7 @@ export class EmailPipelineConstruct extends Construct {
architecture: lambda.Architecture.ARM_64,
memorySize: 512,
timeout: cdk.Duration.seconds(180),
environment: {
...lambdaEnv,
REMINDER_FN_ARN: reminder.functionArn,
REMINDER_SCHEDULER_ROLE_ARN: reminderSchedulerRole.roleArn,
},
environment: lambdaEnv,
logRetention: logs.RetentionDays.TWO_MONTHS,
});
@ -224,16 +195,6 @@ export class EmailPipelineConstruct extends Construct {
`arn:aws:bedrock:${region}:${account}:inference-profile/us.anthropic.*`,
],
}));
conversation.addToRolePolicy(new iam.PolicyStatement({
actions: ['scheduler:CreateSchedule', 'scheduler:DeleteSchedule'],
resources: [
`arn:aws:scheduler:${region}:${account}:schedule/default/exec-aide-reminder-*`,
],
}));
conversation.addToRolePolicy(new iam.PolicyStatement({
actions: ['iam:PassRole'],
resources: [reminderSchedulerRole.roleArn],
}));
dailyDigest.grantInvoke(conversation);
this.conversationFn = conversation;

View file

@ -39,10 +39,7 @@ When referencing emails, always include the sender name and subject line. \
For time references, use relative terms (e.g., "2 hours ago", "yesterday").
You can manage Adam's task list — create tasks, list them, mark them \
complete, or delete them. You can also set reminders that will send a Slack \
DM at a specified time. When Adam asks to be reminded of something, use \
create_reminder with the appropriate date/time (default timezone: \
America/New_York).
complete, or delete them.
You have access to Adam's Google Calendar. You can view upcoming events, \
check availability, and create new events. Always confirm event details \

View file

@ -264,28 +264,6 @@ TOOLS = [
},
}
},
{
"toolSpec": {
"name": "create_reminder",
"description": "Set a reminder that will send Adam a Slack DM at a specific time.",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "The reminder message text.",
},
"remind_at": {
"type": "string",
"description": "When to send the reminder in ISO 8601 format (e.g., 2026-05-05T09:00:00). Timezone is America/New_York.",
},
},
"required": ["text", "remind_at"],
}
},
}
},
{
"toolSpec": {
"name": "get_calendar_events",
@ -411,7 +389,6 @@ def dispatch_tool(tool_name, tool_input):
"list_tasks": _handle_list_tasks,
"complete_task": _handle_complete_task,
"delete_task": _handle_delete_task,
"create_reminder": _handle_create_reminder,
"get_calendar_events": _handle_get_calendar_events,
"create_calendar_event": _handle_create_calendar_event,
"check_availability": _handle_check_availability,
@ -601,7 +578,7 @@ def _handle_coordinate(inputs):
}
# ── Task & Reminder Handlers ──────────────────────────────────
# ── Task Handlers ──────────────────────────────────
def _handle_create_task(inputs):
@ -637,27 +614,6 @@ def _handle_delete_task(inputs):
return {"task_id": inputs["task_id"], "status": "deleted"}
def _handle_create_reminder(inputs):
import ulid as _ulid
scheduler = boto3.client("scheduler")
schedule_name = f"exec-aide-reminder-{_ulid.new()}"
remind_at = inputs["remind_at"]
scheduler.create_schedule(
Name=schedule_name,
ScheduleExpression=f"at({remind_at})",
ScheduleExpressionTimezone="America/New_York",
FlexibleTimeWindow={"Mode": "OFF"},
Target={
"Arn": os.environ["REMINDER_FN_ARN"],
"RoleArn": os.environ["REMINDER_SCHEDULER_ROLE_ARN"],
"Input": json.dumps({"text": inputs["text"]}),
},
ActionAfterCompletion="DELETE",
)
return {"status": "scheduled", "remind_at": remind_at, "text": inputs["text"]}
# ── Calendar Handlers ──────────────────────────────────────────

View file

@ -1,26 +0,0 @@
import logging
from shared.secrets import get_config, get_slack_token
from shared.slack import post_message
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
text = event.get("text", "Reminder (no details provided)")
config = get_config()
token = get_slack_token()
import requests
resp = requests.post(
"https://slack.com/api/conversations.open",
headers={"Authorization": f"Bearer {token}"},
json={"users": config["adam_slack_user_id"]},
)
resp.raise_for_status()
channel = resp.json()["channel"]["id"]
post_message(channel, f":bell: *Reminder:* {text}", token)
logger.info("Reminder sent: %s", text)