Architecture Overview

Deployment Architecture

flowchart TB
    subgraph Internet
        User[User Browser]
    end

    subgraph AWS["AWS Cloud"]
        subgraph CDN["Content Delivery"]
            CF[CloudFront]
            S3[S3 Bucket<br/>Frontend Assets]
        end

        subgraph Compute["Backend Services"]
            AppRunner[App Runner<br/>Backend Flask API]
        end

        subgraph AI["AI Services"]
            Runtime[AgentCore Runtime<br/>Strands Agent]
            Gateway[AgentCore Gateway<br/>MCP Protocol]
        end

        subgraph API["API Layer"]
            APIGW[API Gateway<br/>HTTP API]
            Lambda[Lambda<br/>Secured API]
        end

        subgraph Auth["Authentication"]
            Okta[Okta<br/>OIDC Provider]
        end
    end

    User --> CF
    CF --> S3
    User --> AppRunner
    AppRunner --> Runtime
    Runtime --> Gateway
    Gateway --> APIGW
    APIGW --> Lambda
    User <--> Okta

CDK Stacks

Stack Resources Description
three-tier-chat-api-dev API Gateway, Lambda Secured REST API
three-tier-chat-agentcore-dev Runtime, Gateway, Interceptor Lambda AI Agent with MCP
three-tier-chat-backend-dev App Runner Service Flask API proxy
three-tier-chat-app-dev S3, CloudFront Frontend static site

User Flow Sequence Diagram

sequenceDiagram
    autonumber
    participant User as User (Browser)
    participant Frontend as Frontend<br/>(React)
    participant Okta as Okta<br/>(IdP)
    participant Backend as Backend<br/>(Flask)
    participant Runtime as AgentCore<br/>Runtime
    participant Gateway as AgentCore<br/>Gateway
    participant Interceptor as Interceptor<br/>Lambda
    participant API as Secured API<br/>Lambda

    %% Authentication Flow
    rect rgb(240, 248, 255)
        Note over User,Okta: Authentication Phase
        User->>Frontend: 1. Access App
        Frontend->>Okta: 2. Redirect to Login
        Okta->>User: 3. Login Form
        User->>Okta: 4. Credentials
        Okta->>Frontend: 5. Authorization Code
        Frontend->>Okta: 6. Exchange Code
        Okta->>Frontend: 7. JWT Tokens (id_token, access_token)
        Note right of Frontend: Stores tokens in memory
    end

    %% Chat Request Flow
    rect rgb(255, 248, 240)
        Note over User,API: Chat Request Phase
        User->>Frontend: 8. Send Message
        Frontend->>Backend: 9. POST /api/agent/invoke
        Note right of Frontend: Headers:<br/>Authorization: Bearer {access_token}<br/>X-ID-Token: {id_token}

        Backend->>Runtime: 10. Invoke Agent
        Note right of Backend: Headers:<br/>Authorization: Bearer {access_token}<br/>X-Amzn-Trace-Id: {trace_id}

        Runtime->>Runtime: 11. Validate JWT (Okta JWKS)
        Runtime->>Gateway: 12. MCP Tool Call
        Note right of Runtime: Headers:<br/>Authorization: Bearer {access_token}
    end

    %% Gateway & Tool Execution
    rect rgb(240, 255, 240)
        Note over Gateway,API: Tool Execution Phase
        Gateway->>Gateway: 13. Validate JWT (CUSTOM_JWT)
        Gateway->>Interceptor: 14. REQUEST Interception
        Note right of Gateway: Passes:<br/>Authorization header<br/>Request context

        Interceptor->>Interceptor: 15. Extract user from JWT
        Interceptor->>Gateway: 16. Return enriched context

        Gateway->>API: 17. HTTP Request
        Note right of Gateway: Headers:<br/>Authorization: Bearer {access_token}<br/>X-Amzn-Trace-Id: {trace_id}

        API->>API: 18. Validate JWT
        API->>API: 19. Get User Profile
        API->>Gateway: 20. User Data Response
    end

    %% Response Flow
    rect rgb(248, 240, 255)
        Note over User,API: Response Phase
        Gateway->>Runtime: 21. Tool Result
        Runtime->>Runtime: 22. Agent Processes
        Runtime->>Backend: 23. Agent Response
        Backend->>Frontend: 24. JSON Response
        Frontend->>User: 25. Display Message
    end

Security Headers Reference

Frontend → Backend

Header Value Purpose
Authorization Bearer {access_token} OAuth2 access token for API authorization
X-ID-Token {id_token} OpenID Connect ID token with user claims
Content-Type application/json Request body format

Backend → AgentCore Runtime

Header Value Purpose
Authorization Bearer {access_token} Forwarded user token for federation
X-Amzn-Trace-Id Root=1-xxx;Parent=yyy X-Ray distributed tracing
Content-Type application/json Request body format

AgentCore Gateway → Secured API

Header Value Purpose
Authorization Bearer {access_token} Federated user token (USER_FEDERATION)
X-Amzn-Trace-Id Root=1-xxx;Parent=yyy Propagated trace context
X-Gateway-Request-Id {request_id} Gateway request tracking

JWT Token Flow

flowchart LR
    subgraph Issuance["Token Issuance"]
        Okta[Okta<br/>Issuer] --> Frontend[Frontend<br/>Stores] --> Backend[Backend<br/>Forwards]
    end

    subgraph Validation["Token Validation"]
        Runtime[AgentCore Runtime<br/>Validates] --> Gateway[AgentCore Gateway<br/>Validates] --> API[Secured API<br/>Validates]
    end

    Backend --> Runtime

Key Points:

  • JWT is validated at each boundary (Runtime, Gateway, API)
  • Token is never modified, only forwarded
  • USER_FEDERATION pattern ensures user context preserved
  • Each service validates against Okta JWKS endpoint

Component Responsibilities

Component Auth Responsibility
Frontend Obtain & store tokens from Okta
Backend Forward tokens, no validation
Runtime Validate JWT, pass to agent context
Gateway Validate JWT (CUSTOM_JWT authorizer)
Interceptor Extract user claims, enrich context
Secured API Final JWT validation, return user data

Traceability and Observability

Distributed Tracing

flowchart LR
    subgraph Request["Request Flow with Trace Context"]
        FE[Frontend] -->|X-Amzn-Trace-Id| BE[Backend]
        BE -->|X-Amzn-Trace-Id| RT[AgentCore Runtime]
        RT -->|X-Amzn-Trace-Id| GW[Gateway]
        GW -->|X-Amzn-Trace-Id| API[Secured API]
    end

    subgraph Observability["AWS Observability"]
        XRay[AWS X-Ray]
        CW[CloudWatch Logs]
    end

    BE -.-> XRay
    RT -.-> XRay
    GW -.-> CW
    API -.-> CW

Trace Header Propagation

Component Action Header
Frontend Generate trace ID X-Amzn-Trace-Id: Root=1-xxx
Backend Propagate trace X-Amzn-Trace-Id: Root=1-xxx;Parent=yyy
AgentCore Runtime Auto-instrumented (ADOT) Propagates trace context
AgentCore Gateway Log with trace X-Gateway-Request-Id
Secured API Log with trace Correlates with trace ID

Observability Stack

  • AWS X-Ray: End-to-end request tracing
  • CloudWatch Logs: Centralized logging with trace correlation
  • ADOT: OpenTelemetry auto-instrumentation on AgentCore Runtime

Best Practices