I built an agent with Claude Code that’s hosted on AgentCore and connected to a local Telegram bot. It has memory, CloudWatch, X-ray tracing, search tools, email sending, and scheduled task execution.

I wanted to connect it to AWS via Lambda so it wouldn’t depend on running locally. I talked to Claude Code and it explained what needed to be done. It’s not complicated, but I wanted to understand the system first.


Event Delivery Patterns

When System A needs to know something happened in System B, how does it find out?

There are several approaches to event delivery:

  • Polling - constantly asking “anything new?” - inefficient
  • Long polling - keeping the request open until there’s a response - less wasteful
  • Webhook - one side notifies when something happens - efficient, one-way
  • WebSocket - open connection - efficient, bidirectional
  • Server-Sent Events (SSE) - server-to-client only (news feeds, live updates)
  • Message Queues - Service A drops a message, Service B picks it up when ready. Good for async processing.
  • gRPC streaming - bidirectional over HTTP/2, popular for microservices

For web applications, Webhook, WebSocket, and SSE are most common.


Deep Dive: Webhook vs WebSocket

WebSocket: Always-on bidirectional connection

Think phone call - both sides stay connected and can talk whenever they want without dialing again.

Example: Google Docs. When multiple people edit a document, everyone sees changes in real-time. The server maintains an open connection per user and pushes updates instantly. 100 editors = 100 open connections.

Another example: Slack. Messages appear immediately without refreshing. The server pushes new messages through the open connection.

WebSocket requires a server running continuously - someone needs to “hold the line open” and track who’s connected. It’s stateful: the server remembers “I have 50 users connected right now.”

Webhook: One-time “knock on the door”

Think SMS - someone sends you a message, there’s no connection between you, they don’t know if you read it.

Example: GitHub webhooks. When you push to a repo, GitHub sends a POST request to your configured URL. It sends the message and moves on - doesn’t wait for a response, doesn’t care what you do with it.

Another example: Stripe payments. When a payment succeeds, Stripe POSTs transaction details to your server.

Webhooks are stateless: each request stands alone. If you need memory, store it elsewhere (database, AgentCore memory, etc.).

Bottom line:

  • Webhook = “call me when there’s news”
  • WebSocket = “let’s stay on the line together”

For a Telegram bot, webhook fits perfectly - POST when someone messages the bot, Lambda wakes up, handles it, goes back to sleep.


Why Webhook Works for Cloud-Based Telegram Bots

A Telegram bot doesn’t need to send messages proactively - it just responds to users. Why pay for a server running 24/7 waiting? Better to let Telegram “wake up” the Lambda only when needed.

The practical difference:

With WebSocket (Gmail): Connection stays open, so incoming emails trigger notifications instantly. Google’s servers maintain millions of open connections.

With Webhook (Telegram bot): Telegram knocks on the door only when there’s a new message. Lambda can sleep in between - no cost.


Case Study: AI Agent on AgentCore with Telegram Bot

How it works:

  1. User messages the Telegram bot
  2. Request goes through API Gateway to Lambda
  3. Lambda forwards to the agent running on AgentCore
  4. Agent responds back through Lambda to Telegram

Key components:

Lambda - Cloud function. Code that runs only when called, no server management.

Traditional model: Server (EC2/VPS) runs 24/7. Even at 3 AM with zero users, it’s on and someone’s paying. Cost: ~$10-30/month even with no usage.

Lambda model: Code “sleeps” somewhere in AWS. When a request arrives (HTTP, EventBridge trigger, Telegram message) - AWS wakes the code, runs it, returns a response. You pay only for actual execution time. Cost: pennies for low usage.

API Gateway - The gatekeeper. Every external request (from Telegram, apps, websites) passes through it first.

What it does:

  • Provides a fixed public URL
  • Routes requests to the right Lambda
  • Basic security (rate limiting, authentication)
  • Logging

Without it, Lambda isn’t accessible from outside - it has no public address.

SSM Parameter - AWS service for storing configs and secrets. Instead of putting Telegram tokens in code or .env files, store them encrypted in AWS. Lambda reads them at runtime. Benefits: security, central management, no secrets in code.

Polling vs Webhook comparison:

Polling:

  • Bot runs constantly asking Telegram “any new messages?”
  • Requires 24/7 process
  • Doesn’t fit Lambda (Lambda only runs when called)

Webhook:

  • Telegram sends messages when something’s new
  • Lambda sleeps until a message arrives
  • Pay only for actual use

This is the standard way to run bots in the cloud.


Telegram Bot: From Local to Cloud

Initially the bot ran locally - I had to start it from the terminal. I connected it to AWS via Lambda so it wouldn’t depend on running locally.

The bot itself isn’t hosted in the cloud - it lives on Telegram’s servers. What runs on Lambda is the code that handles messages (the webhook handler). Bot lives in Telegram, logic lives in Lambda.

What this includes:

  • Webhook handler in Lambda
  • API Gateway
  • SSM Parameter - AWS service for storing configs and secrets. Instead of putting the Telegram token in code or .env, it’s stored encrypted in AWS. Lambda reads it at runtime. Benefits: security, central management, no secrets in code.

How the agent communicates through Telegram:

Incoming message (webhook): User sends to Telegram → API Gateway → Lambda → AgentCore

Outgoing message (HTTP call): AgentCore → Lambda → Telegram

Agent’s tools: search, send email, send Telegram message.

What was missing: ability for the agent to schedule on its own - a tool to create EventBridge rules or DynamoDB entries.


Adding Scheduling: EventBridge vs DynamoDB

The agent needed to schedule reminders on its own.

DynamoDB: Regular database table, flexible, needs a Lambda scanning every minute, pay per read.

EventBridge: Built-in AWS scheduler, more rigid, cheaper.

For dynamic reminders, DynamoDB is simpler - save a row, Lambda checks every minute what’s due, sends and deletes.

You can create EventBridge rules dynamically via AWS SDK, but:

  • Default limit of 300 rules
  • Need to clean up rules after they run
  • Additional IAM permissions

For small scale - EventBridge works great. For many reminders - DynamoDB is better.

Why does DynamoDB need Lambda running every minute? Isn’t polling inefficient?

DynamoDB is just a database - it can’t “wake something up” at a specific time. So you need a Lambda checking every minute “is anything due now?” It’s polling, but internal to AWS (cheap and reasonable).

EventBridge, on the other hand, is a scheduler - it knows how to say “run this at X.”


What I Built

I chose EventBridge and added:

  • schedule_reminder tool for one-time reminders
  • schedule_recurring tool for recurring ones
  • Reminder Lambda triggered by EventBridge
  • IAM permissions for managing EventBridge rules

Now the agent can:

  1. Receive a request like “remind me tomorrow at 10 to check emails”
  2. Parse the time to ISO format
  3. Create a one-time or recurring EventBridge rule
  4. When the time comes - send a Telegram message and delete the rule if needed

Two Lambdas:

  1. EventBridge wakes the reminder Lambda on schedule, which calls the agent to execute actions
  2. Webhook Lambda passes incoming Telegram messages to the agent

Summary

  • Agent is hosted on AgentCore runtime
  • Telegram bot is a communication layer - a pipe passing messages to/from the agent. The same agent could receive messages from Web UI, Slack, WhatsApp - doesn’t matter. Logic and memory live in AgentCore, not the bot.
  • Scheduling is handled by EventBridge
  • Two Lambdas: one for scheduling, one for the Telegram webhook
  • AgentCore responds to Telegram via regular API calls

Before: User messages via Telegram, local machine constantly polls for requests and forwards to AgentCore.

After: User messages via Telegram, request goes through API Gateway via webhook to Lambda only when needed, then to AgentCore.