Self-Healing &
Self-Learning

AI Agents

From LLM Chatbots to Autonomous Systems


Syed Umer Hasan — SysDE @ Amazon | IEEE Senior Member | 11x Cloud Certified

About Me

Syed Umer Hasan

Syed Umer Hasan

System Development Engineer @ Amazon

IEEE Senior Member | AWS Book Author

Co-founder: codeforgeeks.com

11x Cloud Certified

AWS Security AWS SA AWS AI AWS Dev AWS CP AWS AI Early CompTIA Terraform Azure GCP Databricks

What We're Building Toward


Agents that detect, diagnose, fix, and learn

— without waking you up at 3am.


Detect Read Logs Root Cause Apply Fix Verify & Learn

Today we'll build every piece of this system from scratch.

LLM vs Agentic AI


LLM (ChatGPT)Agentic AI
InteractionSingle prompt → responseAutonomous loop until task done
ToolsNone (just text)Reads files, runs code, calls APIs
MemoryPer-conversation onlyPersists across sessions
DecisionsYou decide next stepAgent decides next step
CollaborationOne modelMultiple agents coordinating

An agent is an LLM + tools + a loop + memory. It acts, not just responds.

The Agent Loop


User Message LLM Thinks Picks a Tool Executes Tool Observes Result Final Response Loop Done

Lab 01: You build this loop from scratch

The Framework Landscape


FrameworkByStrengthWeakness
LangChainLangChain IncEcosystem, chains, RAGComplex abstractions, heavy
LangGraphLangChain IncStateful graphs, cyclesSteep learning curve
CrewAICommunityMulti-agent rolesLess flexible routing
Strands AgentsAWSSimple, model-agnostic, productionNewer ecosystem

We use Strands Agents SDK — minimal boilerplate, swappable models, built for production.

Why Strands Agents


from strands import Agent from strands_tools import file_read, shell agent = Agent( model=AnthropicModel("claude-haiku-4-5"), tools=[file_read, shell], system_prompt="You are a DevOps assistant." ) result = agent("Find and fix the failing service")

Simple

Agent in 5 lines

Flexible

Swap Ollama/Claude/Bedrock

Production

Sessions, OTEL, multi-agent

What Is a Tool?


A function the LLM can call. The agent decides when to use it.


# Built-in tools (strands_tools) file_read, file_write, shell, http_request, calculator, current_time, editor
# Custom tool from strands import tool @tool def check_service(name: str): """Check if a service is healthy""" result = subprocess.run( ["systemctl", "status", name], capture_output=True ) return result.stdout

Lab 01: file_read, file_write, shell, http_request

What Is MCP?

Model Context Protocol — a universal tool standard


Agent MCP Server (any tool) JSON-RPC / stdio Web Search • Database • Slack GitHub • Custom APIs
  • Tools as external servers — language agnostic
  • Agent discovers tools dynamically at runtime
  • One protocol, infinite integrations

Lab 01 (07_web_fetch): MCP web search server

What Is HITL?

Human-in-the-Loop — safety before dangerous actions


from strands.agent.conversation_manager import SlidingWindowConversationManager from strands.handlers.tool_handler import HumanInTheLoop agent = Agent( tools=[file_read, file_write, shell], callback_handler=callback_handler, # Ask human before write/shell operations tool_handler=HumanInTheLoop(allowed_tools=["file_read"]) )

Allowed

file_read executes freely

Requires Approval

file_write, shell ask the user first

Lab 01: All write operations use HITL

Stateful Agents

Memory that survives restarts


# Session persistence from strands.session import FileSessionManager agent = Agent( session_manager=FileSessionManager( session_id="user-123", storage_dir="./sessions" ) ) # Conversation history persists!
# Key-value state from strands import tool from strands.types.tools import ToolContext @tool(context=True) def save_note(context: ToolContext, key: str, value: str): """Save a note to memory""" context.state[key] = value return f"Saved: {key}"

Sessions = conversation history. State = structured key-value data. Both persist.

Lab 02: Notes, todos, preferences, multi-user isolation

Agent as Tool

One coordinator delegates to specialist sub-agents


researcher = Agent(system_prompt="You research topics deeply", name="researcher") writer = Agent(system_prompt="You write polished content", name="writer") # Coordinator uses sub-agents as tools coordinator = Agent( system_prompt="You manage projects. Delegate research and writing.", tools=[researcher, writer, file_read, file_write] ) coordinator("Write a blog post about AI agents") # → Calls researcher tool → Gets research # → Calls writer tool → Gets draft # → Saves to file

Lab 03: Tech planner, email writer, sprint planner, coding assistant (8 files)

Pattern: Sequential Workflow

Pipeline — output of one feeds into the next


researcher = Agent(system_prompt="Research...", callback_handler=None) writer = Agent(system_prompt="Write...", callback_handler=None) editor = Agent(system_prompt="Edit...", callback_handler=None) def publish_blog(topic): research = researcher(f"Research {topic}") draft = writer(f"Write article using: {research.message}") final = editor(f"Polish this: {draft.message}") return final.message

Research → Write → Edit → Publish

Lab 04 (01_blog_publisher, 02_resume_screener)

Pattern: Graph Routing

Conditional edges — route based on state


from strands.multiagent import GraphBuilder builder = GraphBuilder() builder.add_node(analyzer_agent, "analyze") builder.add_node(fixer_agent, "fix") builder.add_node(approver_agent, "approve") builder.set_entry_point("analyze") builder.add_edge("analyze", "fix", condition=lambda state: "bug" in state) builder.add_edge("analyze", "approve", condition=lambda state: "clean" in state) builder.add_edge("fix", "approve") graph = builder.build() graph("Review this code: ...")

Analyze →[bug?]→ Fix → Approve | Analyze →[clean?]→ Approve

Lab 04 (03_code_reviewer, 04_customer_triage)

Pattern: Swarm

Autonomous handoffs — agents decide who speaks next


from strands.multiagent import Swarm greeter = Agent(system_prompt="Greet and classify the request...") billing = Agent(system_prompt="Handle billing questions...") support = Agent(system_prompt="Handle technical support...") escalation = Agent(system_prompt="Handle escalations to humans...") swarm = Swarm( [greeter, billing, support, escalation], entry_point=greeter, max_handoffs=6 ) swarm("I was double-charged on my last invoice") # greeter → billing (autonomous handoff)

Lab 04 (05_call_center_swarm)

Multi-Agent Patterns


Sequential

A → B → C

Fixed pipeline. Output feeds forward.

Use: ETL, content pipelines

Graph

A → [condition] → B or C

Conditional routing. Cycles allowed.

Use: Review loops, triage

Swarm

A ↔ B ↔ C (autonomous)

Agents hand off to each other.

Use: Support, dynamic routing

Observability

See inside your agents — every decision, every tool call


What Langfuse Captures

  • Every LLM call (tokens, latency)
  • Every tool execution
  • Full trace tree
  • Cost per request
  • Error rates
# Zero code changes needed! # shared/__init__.py auto-inits: import os if os.getenv("LANGFUSE_PUBLIC_KEY"): from langfuse import get_client _langfuse = get_client() # Strands emits OTEL spans # Langfuse captures them # Every lab traces automatically

Lab 05: All labs auto-trace to http://localhost:3000

Putting It Together: Self-Healing


Monitor Agent CloudWatch, http_request Diagnose Agent log_reader, trace_analyzer Remediate Agent shell, rollback, scale Session Memory — what worked last time? Langfuse — full trace of every decision

Graph pattern: Monitor → [issue?] → Diagnose → [known fix?] → Apply → Verify

Putting It Together: Self-Learning


How It Learns

  • Session memory persists solutions
  • State tracks: what fix worked for what symptom
  • Next incident → agent searches past fixes first
  • Langfuse traces show success/failure patterns

The Loop

Incident #1 → Diagnose → Try → Fail → Try → Fix ✓

Incident #2 (same) → Remember → Apply known fix ✓

Result: Faster resolution over time


Stateful agents (Lab 02) + Multi-agent (Lab 04) + Observability (Lab 05) = Self-learning system

Lab Roadmap


Lab 01 First Agent — Agent loop, tools, HITL, MCP (7 files)

Lab 02 Stateful Agent — Sessions, state, multi-user memory (6 files)

Lab 03 Agents as Tools — Sub-agents, coordinator pattern, coding assistant (8 files)

Lab 04 Multi-Agent — Sequential workflow, Graph, Swarm (5 files)

Lab 05 Observability — Langfuse + OTEL, zero-code tracing (auto)


Each lab builds on the previous. By the end you have every building block for self-healing agents.

Demo Time


$ python3 lab_03_agents_as_tools/08_coding_assistant.py > Find the bug in server.py and fix it │ Let me analyze the code... ● file_read — reading server.py │ I found a null pointer on line 42. ● file_write — patching the null check ● shell — running pytest │ All 12 tests pass. The bug is fixed. ────────────────────────────────────────

A Claude Code-like CLI. Built with Strands in ~50 lines.

Try It Now


git clone https://github.com/SyedUmerHasan/ai-summit-labs.git cd ai-summit-labs docker compose up -d python3 -m venv .venv && source .venv/bin/activate pip install -e . && pip install -r requirements.txt # Run your first agent python3 lab_01_first_agent/01_basic_agent.py

github.com/SyedUmerHasan/ai-summit-labs

syedumerhasan.dev

strandsagents.com

Thank You


Syed Umer Hasan

SysDE @ Amazon | IEEE Senior Member | AWS Book Author


LinkedIn: linkedin.com/in/syedumerhasan

GitHub: github.com/SyedUmerHasan

Website: syedumerhasan.dev