Skip to content

Instantly share code, notes, and snippets.

@fmquaglia
Created November 12, 2025 09:10
Show Gist options
  • Select an option

  • Save fmquaglia/c75f64a9253b845fd4221d9868ddb5ab to your computer and use it in GitHub Desktop.

Select an option

Save fmquaglia/c75f64a9253b845fd4221d9868ddb5ab to your computer and use it in GitHub Desktop.
Google 5 Day Intensive Agent Course - Exercise Day 2
sequenceDiagram
    actor User as User
    participant UI as 🖥️ Frontend (React)
    participant API as 🔧 FastAPI Backend
    participant Redis as 💾 Redis
    participant ADK as 🤖 Google ADK
    participant Agent as 🧠 Agent
    participant Tool as 🔨 request_image_generation

    Note over User,Tool: Phase 1: Request start

    User->>UI: "Genera 10 imágenes"
    UI->>API: POST /api/agent/start<br/>{query: "Generate 10 images", user_id: "fabricio"}
    
    API->>ADK: create_session(session_id="abc123")
    API->>ADK: [runner.run](http://runner.run)_async(session_id, query)
    
    ADK->>Agent: new_message: "Generate 10 images"
    Agent->>Tool: request_image_generation(num_images=10)
    
    Note over Tool: num_images (10) > THRESHOLD (1)<br/>tool_context.tool_confirmation es None
    
    Tool->>Tool: tool_context.request_confirmation(<br/>hint="⚠️ Large request: 10 images"<br/>)
    Tool-->>Agent: return {status: "pending", ...}
    
    Agent->>ADK: Generate event adk_request_confirmation<br/>with invocation_id="inv_xyz"
    
    Note over API: Detects special event in events[]
    
    API->>Redis: SETEX paused_session:abc123 3600<br/>{<br/>  approval_info: {...},<br/>  invocation_id: "inv_xyz",<br/>  user_id: "fabricio",<br/>  hint: "⚠️ Large request: 10 images"<br/>}
    
    API-->>UI: 200 OK<br/>{<br/>  status: "pending_approval",<br/>  session_id: "abc123",<br/>  message: "⚠️ Large request: 10 images"<br/>}
    
    UI->>UI: Display approval modal
    UI-->>User: "Approve 10 images?"<br/>[✅ Approve] [❌ Reject]

    Note over User,Tool: Phase 2: Wait for human (could be seconds or even minutes)

    User->>UI: Click en "✅ Approve"

    Note over User,Tool: Phase 3: Resume with Decision

    UI->>API: POST /api/agent/resume<br/>{<br/>  session_id: "abc123",<br/>  approved: true<br/>}
    
    API->>Redis: GET paused_session:abc123
    Redis-->>API: {<br/>  approval_info: {...},<br/>  invocation_id: "inv_xyz",<br/>  user_id: "fabricio"<br/>}
    
    Note over API: create_approval_response(<br/>approval_info, approved=true<br/>)
    
    API->>ADK: [runner.run](http://runner.run)_async(<br/>  session_id="abc123",<br/>  new_message=FunctionResponse(confirmed=true),<br/>  invocation_id="inv_xyz" ⬅️ KEY<br/>)
    
    Note over ADK: ADK detects invocation_id="inv_xyz"<br/>→ RESUME (does not restart)
    
    ADK->>Agent: Loads saved state
    Agent->>Tool: request_image_generation(num_images=10)<br/>tool_context.tool_confirmation.confirmed=True
    
    Tool-->>Agent: return {<br/>  status: "approved",<br/>  order_id: "REQ-10-HUMAN",<br/>  num_images: 10<br/>}
    
    Agent->>Agent: Calls getTinyImage() 10 times
    Agent-->>ADK: "Here are the 10 images"
    ADK-->>API: events[] with final result
    
    API->>Redis: DEL paused_session:abc123
    
    API-->>UI: 200 OK<br/>{<br/>  status: "completed",<br/>  result: "10 images generated"<br/>}
    
    UI->>UI: Hides modal, display result
    UI-->>User: ✅ "10 images generated succesfully"
Loading

Key Points of the Diagram

PHASE 1 - Start and Pause:

  1. The user makes the request
  2. The backend detects that it requires approval
  3. The state is saved in Redis with a TTL of 1 hour
  4. The frontend displays the approval modal

PHASE 2 - Wait:

  • The time between pause and decision can be seconds, minutes, or even hours
  • Redis persists the state even if the backend restarts

PHASE 3 - Resumption:

  1. The user approves or rejects
  2. The backend retrieves the invocation_id from Redis
  3. The agent resumes with the same invocation_id → this is critical
  4. The agent completes the task and returns the final result

Advantages of Using Redis

Feature Benefit
Persistence State survives backend restarts
Automatic TTL Abandoned sessions expire automatically
High speed Read/write in microseconds
Scalability Multiple backend instances can share state
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment