Skip to content

Commit e9ee192

Browse files
authored
Merge pull request #24 from boemer00/feature/plan-execute-pattern
fix(calendar): support 'Z' ISO timestamps; preserve fallback formatting - utils/date_parser.iso_to_datetime: - Normalize trailing 'Z' (UTC) to '+00:00' before datetime.fromisoformat - Adds internal _normalize_iso_utc_z helper - tools/tasks.list_calendar_events: - Add _format_calendar_event_fallback to keep formatting when parsing fails - Always include location line (📍 ...) and "(All day)" label in fallback - tests/agent/test_graph.py: - Align with refactor by monkeypatching `tool_node_with_state_injection` instead of removed `create_tool_node` Result: - Previously failing calendar tests now pass (location and "All day" restored)
2 parents bd19190 + cb3a256 commit e9ee192

File tree

14 files changed

+1282
-67
lines changed

14 files changed

+1282
-67
lines changed

README.md

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# AI Task Agent - Production Deployment on Google Cloud Run
22

33
[![CI/CD Pipeline](https://github.com/boemer00/todo-work-agent/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/boemer00/todo-work-agent/actions/workflows/ci-cd.yml)
4-
[![Tests](https://img.shields.io/badge/tests-111%20passing-success)](https://github.com/boemer00/todo-work-agent/actions)
4+
[![Tests](https://img.shields.io/badge/tests-121%20passing-success)](https://github.com/boemer00/todo-work-agent/actions)
55
[![Coverage](https://img.shields.io/badge/coverage-77.3%25-yellow)](https://codecov.io/gh/boemer00/todo-work-agent)
66
[![Python](https://img.shields.io/badge/python-3.11-blue)](https://www.python.org/downloads/)
77
[![Deployed](https://img.shields.io/badge/deployed-Google%20Cloud%20Run-4285F4?logo=google-cloud)](https://ai-task-agent-kbimuakj2a-uc.a.run.app)
88

9-
An intelligent task management agent deployed on **Google Cloud Run** with **WhatsApp interface**, powered by **LangGraph** and **GPT-4o-mini**. Features natural language date parsing, multi-user support, and Google Calendar integration. Built to demonstrate production-ready AI engineering skills.
9+
An intelligent task management agent deployed on **Google Cloud Run** with **WhatsApp interface**, powered by **LangGraph** and **GPT-4o-mini**. Features **Plan-Execute architecture** for complex multi-step requests, natural language date parsing, multi-user support, and Google Calendar integration. Built to demonstrate production-ready Agentic AI engineering skills.
1010

1111
**Live Service**: https://ai-task-agent-kbimuakj2a-uc.a.run.app
1212

@@ -26,9 +26,10 @@ An intelligent task management agent deployed on **Google Cloud Run** with **Wha
2626

2727
## ⚡ Key Features
2828

29+
- **🧠 Plan-Execute Architecture** - Agent breaks down complex requests into multi-step plans (NEW!)
2930
- **🚀 Production Deployment** - Fully deployed on Google Cloud Run with HTTPS endpoints
3031
- **💬 WhatsApp Interface** - Natural conversational UI via Twilio WhatsApp API
31-
- **🧠 LangGraph Agent** - ReAct pattern with state management and checkpointing
32+
- **🔄 Advanced Agent Patterns** - ReAct loop with planning, reflection, and state management
3233
- **🗄️ Cloud-Native Storage** - SQLite databases synced to Cloud Storage
3334
- **🌍 Multi-User Support** - Isolated task lists per user with phone number hashing
3435
- **⏰ Smart Date Parsing** - "tomorrow at 2pm", "next Friday", "in 3 hours"
@@ -134,14 +135,11 @@ ngrok http 8080
134135

135136
---
136137

137-
## 💬 Example Interaction
138+
## 💬 Example Interactions
138139

140+
### Simple Request (Direct Execution)
139141
```
140-
User: Hi!
141-
Agent: 👋 Hi! I'm your task assistant...
142-
143142
User: remind me to buy kombucha tomorrow at 2pm
144-
Agent: Working on it.
145143
Agent: ✓ Reminder set: 'buy kombucha' for Thursday, October 31, 2025 at 02:00 PM
146144
147145
User: show my tasks
@@ -152,11 +150,51 @@ User: mark 1 as done
152150
Agent: ✓ Marked task #1 as done: 'buy kombucha'
153151
```
154152

153+
### Complex Request (Plan-Execute Pattern) 🆕
154+
```
155+
User: organize my tasks for this week
156+
157+
Agent: [Internal] Creating plan...
158+
📋 Plan:
159+
1. List all current tasks
160+
2. Check which tasks have due dates
161+
3. Prioritize tasks by deadline
162+
4. Suggest a schedule for the week
163+
164+
Agent: Let me help organize your week. First, let me see what you have...
165+
[Executes: list_tasks()]
166+
167+
I found 5 tasks:
168+
- Project report (Due: Nov 4, 2pm) 🔴 URGENT
169+
- Review PRs (Due: Nov 4, 4pm)
170+
- Buy groceries (Due: Nov 5, 2pm)
171+
- Call dentist (no deadline)
172+
- Email team (no deadline)
173+
174+
Agent: [Reflection: Step 1 complete → Moving to step 2]
175+
176+
Agent: Now let me prioritize by urgency...
177+
178+
Here's your organized week:
179+
180+
**Monday (Nov 4):**
181+
- 2pm: Finish project report ⚡
182+
- 4pm: Review pull requests
183+
184+
**Tuesday (Nov 5):**
185+
- 2pm: Buy groceries
186+
- Evening: Call dentist, email team
187+
188+
You have 2 urgent tasks today! Would you like me to set reminders?
189+
```
190+
191+
**Key Difference**: Complex requests trigger the Plan-Execute pattern, where the agent creates a multi-step plan and systematically works through it with reflection after each step.
192+
155193
---
156194

157195
## 🧪 Testing
158196

159-
**Test Coverage**: 50 tests | 64% coverage | <3s runtime
197+
**Test Coverage**: 121 tests | 70% coverage | <4s runtime
160198

161199
### Run Tests
162200

@@ -244,9 +282,9 @@ Agent: "✅ Calendar connected! Creating reminder..."
244282
```
245283
my-agent/
246284
├── agent/
247-
│ ├── graph.py # LangGraph workflow definition
248-
│ ├── nodes.py # Agent & tools nodes
249-
│ ├── state.py # State schema (messages, user_id)
285+
│ ├── graph.py # LangGraph workflow with Plan-Execute pattern
286+
│ ├── nodes.py # Agent, planner, reflection, tools nodes
287+
│ ├── state.py # State schema (messages, user_id, plan, plan_step)
250288
│ └── prompts.py # System prompts
251289
├── api/
252290
│ ├── main.py # FastAPI app entry point
@@ -269,7 +307,7 @@ my-agent/
269307
│ └── date_parser.py # Natural language date parsing
270308
├── config/
271309
│ └── settings.py # Environment config
272-
├── tests/ # 50 tests, 64% coverage
310+
├── tests/ # 121 tests, 70% coverage (includes planning tests)
273311
├── docs/ # Setup guides
274312
├── app.py # CLI entry point
275313
├── deploy.sh # Cloud Run deployment script
@@ -281,10 +319,16 @@ my-agent/
281319

282320
## 🎤 Interview Talking Points
283321

322+
**Agent Architecture & Advanced Patterns** 🆕
323+
- **"Explain your Plan-Execute implementation"** → Complex requests trigger planner node → LLM creates numbered plan → agent executes step-by-step → reflection node tracks progress → repeats until plan complete. Simple requests bypass planning for efficiency.
324+
- **"Why Plan-Execute over simple ReAct?"** → Handles multi-step goals (e.g., "organize my week"), improves task decomposition, shows structured thinking. Demonstrates understanding of advanced agentic patterns beyond basic tool calling.
325+
- **"How does reflection work?"** → After each tool execution, reflection node checks: (1) Did we complete current step? (2) Move to next step or finish? (3) Clear plan when done. Keeps agent focused on structured goals.
326+
- **"Show me the agent flow"** → START → should_plan() router → [planner OR agent] → agent → tools → should_reflect() router → [reflection OR agent] → loop until END. Conditional routing based on request complexity and plan state.
327+
284328
**Architecture & Design**
285-
- **"Why LangGraph over pure LLM calls?"** → State persistence, checkpointing for conversation memory, built-in tool calling, conditional routing
286-
- **"Explain the ReAct pattern"** → Reasoning (LLM thinks) → Acting (execute tools) → Observation (tool results) → repeat until done
287-
- **"How does Cloud Run handle statelessness?"** → Databases synced to Cloud Storage on startup/shutdown, ephemeral containers
329+
- **"Why LangGraph over pure LLM calls?"** → State persistence, checkpointing for conversation memory, built-in tool calling, conditional routing, Plan-Execute pattern support
330+
- **"Explain the ReAct pattern"** → Reasoning (LLM thinks) → Acting (execute tools) → Observation (tool results) → repeat until done. Enhanced with planning for complex requests.
331+
- **"How does Cloud Run handle statelessness?"** → Databases synced to Cloud Storage on startup/shutdown, ephemeral containers, checkpointer maintains conversation state
288332

289333
**Production Considerations**
290334
- **"How do you handle Cloud Run cold starts?"** → First message gets "Working on it" acknowledgment within 100ms, then full response after agent processing

agent/graph.py

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,45 @@
77
from langgraph.checkpoint.sqlite import SqliteSaver
88
from langgraph.graph import StateGraph, START, END
99
from .state import State
10-
from .nodes import agent_node, should_continue, create_tool_node
10+
from .nodes import (
11+
agent_node,
12+
should_continue,
13+
tool_node_with_state_injection,
14+
planner_node,
15+
reflection_node,
16+
should_plan,
17+
should_reflect
18+
)
1119
from database.connection import get_db_path
1220

1321

1422
def create_graph():
1523
"""
16-
Construct the agent graph with persistence.
24+
Construct the agent graph with persistence and planning capabilities.
1725
18-
Flow:
19-
START → agent → (decision)
20-
├─→ tools → agent (loop back)
21-
└─→ END (done)
26+
Flow (with planning):
27+
START → (check complexity) → planner OR agent
28+
↓ ↓
29+
agent ← ← ← ┘
30+
31+
(has tools?)
32+
33+
tools
34+
35+
(has plan?)
36+
37+
reflection OR agent
38+
↓ ↓
39+
agent ← ← ← ┘
40+
41+
END
2242
2343
Features:
44+
- Plan-Execute pattern for complex multi-step requests
45+
- Reflection node to track progress through plans
46+
- Simple requests bypass planning for efficiency
2447
- LangGraph checkpointing for conversation memory
2548
- SQLite backend for state persistence
26-
- Supports resume, undo, and time-travel debugging
2749
2850
Returns:
2951
Compiled graph with checkpointing enabled
@@ -50,24 +72,46 @@ def create_graph():
5072
builder = StateGraph(State)
5173

5274
# Add nodes
53-
builder.add_node("agent", agent_node)
54-
builder.add_node("tools", create_tool_node())
75+
builder.add_node("planner", planner_node) # Creates plan for complex requests
76+
builder.add_node("agent", agent_node) # Main reasoning node
77+
builder.add_node("tools", tool_node_with_state_injection) # Tool execution with user_id injection
78+
builder.add_node("reflection", reflection_node) # Progress tracking
5579

56-
# Add edges
57-
builder.add_edge(START, "agent") # Always start with agent
80+
# Entry point: Check if request needs planning
81+
builder.add_conditional_edges(
82+
START,
83+
should_plan,
84+
{
85+
"planner": "planner", # Complex request → create plan first
86+
"agent": "agent" # Simple request → go directly to agent
87+
}
88+
)
89+
90+
# After planning, go to agent
91+
builder.add_edge("planner", "agent")
5892

59-
# Conditional edge: agent decides whether to call tools or finish
93+
# Agent decides whether to call tools or finish
6094
builder.add_conditional_edges(
6195
"agent",
6296
should_continue,
6397
{
64-
"tools": "tools", # If "tools" returned, go to tools node
65-
"end": END # If "end" returned, finish
98+
"tools": "tools", # If agent wants to use tools
99+
"end": END # If agent is done
100+
}
101+
)
102+
103+
# After tools execute, check if we need reflection
104+
builder.add_conditional_edges(
105+
"tools",
106+
should_reflect,
107+
{
108+
"reflection": "reflection", # If following a plan
109+
"agent": "agent" # If no plan, back to agent
66110
}
67111
)
68112

69-
# After tools execute, loop back to agent
70-
builder.add_edge("tools", "agent")
113+
# After reflection, loop back to agent for next step
114+
builder.add_edge("reflection", "agent")
71115

72116
# Compile the graph with checkpointing enabled
73117
# The checkpointer automatically saves state after each node

0 commit comments

Comments
 (0)