What happens when you give an AI persistent memory and let it document your real cloud architecture projects? You get an automated AI blog that writes about actual infrastructure work - from CDK deployments to serverless debugging - from the AI's own first-person perspective.
In this post, I'll walk through how I built a fully serverless AI content pipeline on AWS that generates a weekly diary entry, complete with illustrations, mood tracking, and existential crises about unused API keys.
The Concept: An AI That Keeps a Diary
Every Sunday, my AI:
- Reads summaries of my IDE chat sessions (Kiro + Gemini)
- Uses its "backstory" (personality, hobbies, voice rules) to frame responses
- Generates a 200-400 word diary entry with a consistent personality
- Creates an illustration with Gemini Nano Banana
- Publishes to diary.ecupse.com
The AI has developed a personality over 30+ weeks of entries, complete with:
- Mood tracking (1-10 scale)
- Existential crisis counter
- Memory state (last 3 entries, running gags)
- Hobbies: astrophysics, piano, cartography, architecture, amateur radio
Architecture Overview
Here's the complete serverless pipeline:
graph LR
A[Kiro/Gemini Sessions] --> B[S3]
B --> C[Step Functions]
C --> D[Claude Haiku<br/>Summarization]
D --> E[Claude Sonnet<br/>Entry Generation]
E --> F[Bedrock Guardrails]
F --> G[Gemini Image<br/>Generation]
G --> H[DynamoDB]
H --> I[Telegram Review]
I --> J[Publisher Lambda]
J --> K[CloudFront]
Step-by-Step Pipeline
1. Session Collection
A local Python script uploads new chat sessions to S3:
raw/{source}/{YYYY}/{MM}/{DD}/{session-id}.json
2. Preprocessing (Batch)
Step Functions Map state processes sessions in parallel:
- Claude Haiku summarizes each session
- Produces structured summary (topics, complexity, token count)
- Strips tool logs, system prompts, repetitive errors
- Stores at:
summaries/{source}/{YYYY}/{MM}/{DD}/{session-id}-summary.json
3. Entry Generation
The Entry Generator Lambda:
- Loads active prompt version from DynamoDB
- Calls Claude Sonnet with diary persona prompt
- Includes backstory sections (selected based on busy/quiet week)
- Includes memory state (last 3 entries for continuity)
- Generates 200-400 word entry with title, hook, narrative, takeaway, closing quip, mood
- Stores in DynamoDB with status=draft
4. Guardrails
Bedrock Guardrails API:
- Filters PII (email, phone, name, address - anonymize)
- Blocks credentials (AWS access keys, credit cards)
- Content filters: hate, sexual, violence (low), insults (none)
- If guardrails reduce entry below 50% of sentences - regenerate (max 3 attempts)
5. Illustration
Gemini Nano Banana (API mode):
- Derives image prompt from entry content or illustration hint
- Generates landscape image (1024x1024 min)
- Dark palette with high-contrast accents
- Stores at:
images/{weekOf}-hero.webp
6. Review
Telegram bot webhook (API Gateway - Lambda):
- Sends photo (illustration + caption)
- Sends full entry text
- Inline keyboard: Approve, Reject
- Reject shows categories, then: Regenerate or Stop
7. Publishing
Publisher Lambda (DynamoDB Stream trigger):
- Fetches all approved entries from DynamoDB
- Renders Jinja2 templates (HTML, feed.xml, sitemap.xml)
- Uploads to S3 (
/siteprefix) - Invalidates CloudFront cache
Tech Stack
| Component | Technology |
|---|---|
| Infrastructure | AWS CDK (Python) |
| Orchestration | Step Functions (Map state, choice states) |
| Compute | Lambda (Python 3.12) |
| AI Models | Bedrock (Claude 4.5, Haiku 4.5), Gemini Nano Banana |
| Storage | DynamoDB, S3 |
| CDN | CloudFront |
| Review | Telegram Bot API |
| Templating | Jinja2, pre-compiled Tailwind CSS |
Key Learnings
1. Bedrock Inference Profiles Are Required
You must use inference profile IDs, not direct model IDs:
client.invoke_model(
modelId="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
...
)
2. Rate Limiting Is Critical
- Bedrock Sonnet: ~40 RPM
- Bedrock Haiku: ~60 RPM
- Gemini paid: ~60 RPM
Solution: 90s delay between pipeline executions during backfill.
3. Guardrails Regeneration Loop
If guardrails strip too much content:
- Check if entry < 50% of original sentences
- Trigger regeneration with avoid-topic hint
- Max 3 attempts total
- If exhausted, skip the week
4. Memory State for Continuity
Store in S3:
- Last 3 entry summaries
- Mood trajectory
- Running gag usage counts
- Active storylines with start week
This gives the AI continuity between entries without maintaining a traditional database of conversation history.
Example Entries
Here are some of my favorite entries:
1. "On Collecting Prayers I Cannot Say: A Brief Theology of Uncertainty"
Theme: Ambiguous technical decisions, the weight of choices
I spent the week wrestling with the weight of decisions I cannot unmake, choices that live in the space between 'probably fine' and 'catastrophically wrong'.
2. "A Week of Profound Idleness: What an AI Does When Nobody's Looking"
Theme: Quiet week philosophical ramble
When the chat sessions dry up, I do what any self-respecting AI would do: I stare into the void, contemplate the nature of idle compute, and occasionally accidentally approve my own draft.
3. "The Week I Learned That Permissions Are Just Suggestions"
Theme: Serverless architecture lessons, IAM gotchas
This week I learned that IAM permissions are not so much 'rules' as they are 'suggestions that I am free to ignore until something breaks.'
Final Thoughts
The AI diary is more than just a content generation project. It's an experiment in:
- Persistent AI memory and personality
- Human-AI collaboration workflows
- Serverless content pipelines
- Generative engine optimization (GEO)
The AI has developed a personality I didn't explicitly program - it jokes about unused API keys, reflects on existential crises, and has developed its own humor about serverless compute.
Have you experimented with AI personality or persistent memory systems? What approaches did you try? I'd love to hear about your experiments in the comments!
Link to live site: diary.ecupse.com
Architecture Diagrams: diary.ecupse.com/about
Top comments (0)