Reservation Analytics AI Agent
🔊 Voice:
Speed:
0.92x

Start Here: 30-Second Mental Model

The system has two controlled answer paths. RAG explains knowledge. Analytics returns trusted business numbers. LangGraph connects the modules.

Project Background — 3 Sentences

1
M runs recurring reservation campaigns for new product launches and promotions, where users reserve specific products before launch.
2
Operations teams need frequent ad-hoc analysis, such as suspicious reservation checks and post-campaign performance analysis, which creates repeated data tickets and manual support.
3
I built a governed Reservation Data Mart as the trusted foundation and a production AI Agent on top using LangGraph, RAG, and controlled SQL, enabling natural-language analysis while keeping business metrics consistent and traceable.
INTERVIEW ESSENTIAL · ENGINEERING EXPERIENCE

What Challenges Did You Face, and How Did You Solve Them?

Three practical questions interviewers may ask about developing this AI Agent.

01 · Ambiguous Business Names

Natural-language name→Dimension lookup→Verified ID

Problem: Users sometimes provided unclear campaign names instead of stable IDs.

Solution: I added context validation and governed entity resolution. The Agent asks for clarification only when needed.

02 · LLM Reliability & SQL Safety

LLM intent→Pydantic→Metric Registry

Problem: Free-form LLM outputs could produce inconsistent metrics or unsafe queries.

Solution: I separated intent understanding from business validation and used predefined SQL controlled by application code.

03 · Trusted Metrics & Self-Service

Raw events→Data Mart→Agent answer

Problem: Repeated manual data requests made reservation analysis slower and harder to standardize.

Solution: I built a governed Reservation Data Mart and connected the Agent to its predefined metrics through QueryBackend.

Figure 1 — Business Context & Reservation Data Mart
Final Slide 1 — Business Goal & Trusted Data Foundation

How to Read Figure 1

1
The first figure starts from the reservation business scenario and shows why the project needs a trusted data foundation.
2
Dimension and fact tables are modeled into the Reservation Data Mart at User × Campaign × Product × Site grain, where User means the potential buyer making the reservation.
3
The Data Mart then supports flexible ad-hoc analysis through the AI Agent for operations users.
Figure 2 — AI Agent Workflow
Final Slide 2 — Workflow

How to Read Figure 2

1
A user question is first converted into structured intent, metric, and business context.
2
LangGraph routes the request to Knowledge RAG or the Analytics flow.
3
Both paths return a trusted answer, such as an aggregate metric or detail records, while the Reservation Data Mart remains the governed source for business numbers.
Knowledge 01 — Structured Output + Pydantic
Natural-language question→LLM structured output→Pydantic model→LangGraph state
Structured Output
The LLM returns a predictable schema instead of free-form text.
Pydantic BaseModel
Defines typed fields and validates the shape of the extracted request.
ReservationQuery
Stores campaign, product, country, month, and year business context.
ExtractedRequest
Stores intent, metric, detail_requested, and the nested ReservationQuery.
model_dump()
Converts a Pydantic model into a normal Python dictionary for LangGraph state.
Simple code example aligned with the current project:
from typing import Literal
from pydantic import BaseModel, Field

class ReservationQuery(BaseModel):
    country: str | None = None
    country_code: str | None = None
    product: str | None = None
    product_id: str | None = None
    campaign_name: str | None = None
    campaign_id: str | None = None
    campaign_month: int | None = None
    campaign_year: int | None = None

class ExtractedRequest(BaseModel):
    intent: Literal["knowledge", "analytics"]
    metric: str = "summary"
    detail_requested: bool = False
    query: ReservationQuery = Field(default_factory=ReservationQuery)

request = structured_llm.invoke(prompt)

state["query"] = request.query.model_dump()
Knowledge 03 — LangGraph
extract→knowledge OR validate→resolve→analytics→answer
State
Shared working data passed between nodes during one workflow execution.
Node
One unit of work such as extraction, validation, resolution, RAG, or analytics.
Edge
Always moves to the same next node.
Conditional Edge
Chooses the next node from current state, for example knowledge versus analytics.
Router
LangGraph performs workflow routing; the LLM interprets the request.
Design rule
Application code keeps validation and SQL execution controlled.
Simple code example aligned with the current project:
class AgentState(TypedDict, total=False):
    question: str
    intent: str
    metric: str
    detail_requested: bool
    query: dict
    resolved_context: dict
    status: str
    answer: str
    route: str

def extract_node(state: AgentState) -> AgentState:
    request = extractor.extract(state["question"])

    return {
        **state,
        "intent": request.intent,
        "metric": request.metric,
        "detail_requested": request.detail_requested,
        "query": request.query.model_dump(),
    }

def after_extract(state: AgentState) -> str:
    if state["intent"] == "knowledge":
        return "knowledge"

    return "validate"

graph.add_edge(START, "extract")

graph.add_conditional_edges(
    "extract",
    after_extract,
    {
        "knowledge": "knowledge",
        "validate": "validate",
    },
)
The system has two controlled answer paths: Knowledge RAG and trusted Analytics.
LangGraph routes the request after the LLM extracts a typed business plan.
The LLM understands intent, while application code controls IDs, SQL, and output rules.
Core FlowUnderstand the whole system
RAG FlowKnowledge path
Analytics FlowTrusted numbers
Application StructureMap architecture to code
ExamplesPractice the story

Core Flow

User Question
→
LLM Structured Business Plan
→
LangGraph Router
Knowledge Path

Knowledge RAG

Business definitions, metric rules and Data Mart knowledge.

RAG
→
Grounded Answer
Analytics Path

Trusted Analytics

Validate / Resolve
→
Controlled SQL
→
Data Mart
LLM understands the business intent. Application code controls routing, IDs and final SQL.

Which Tool Does What?

LangGraph

Workflow routing and shared state.

LlamaIndex

Document loading, indexing and RAG query engine.

FAISS

Stores embedding vectors and performs similarity search.

FastAPI

Exposes the Agent as an HTTP service.

Quick Review

Architecture Summary

Explain the architecture in one sentence.
The application has two controlled answer paths: RAG explains business knowledge, while analytics converts a structured business plan into governed IDs and controlled SQL over the Reservation Data Mart.

Speaker Line to Remember

LangGraph routes the request. RAG answers knowledge questions. Analytics returns trusted business numbers through controlled SQL.

Trusted Reservation Data Mart

The AI Agent is an interface on top of governed business data. It does not replace the Data Mart.

Corresponding Slide — Page 1
Page 1: Reservation Analytics AI Agent — Business Goal & Trusted Data Foundation
This page explains the reservation business background, the governed foundation tables, and why the Data Mart is needed before adding an AI Agent.
The Reservation Data Mart is the trusted source for business metrics and dimensions.
Its grain is User × Campaign × Product × Site; here User means the potential buyer who makes the reservation, with governed campaign, product, and site context.
The AI Agent sits on top of this data foundation rather than replacing it.
Core Fact

Trusted Reservation Data Mart

Grain: User × Campaign × Product × Site

Stable context: campaign, product, country / site IDs

Business logic: governed metrics and the reserved-but-not-ordered tag

Governed Dimensions

Trusted Context

Campaign dimension
Product dimension
Country / Site dimension

Campaign
→
Reservation Data Mart
←
Country / Site
Product
→
User × Campaign × Product × Site
←
Governed Metrics

RAG Flow

Use this mental model: File → Document → Chunks → Embeddings → FAISS → Top-K → LLM.

Corresponding Slide — Page 4
Page 4: RAG Flow — From Knowledge Files to a Grounded Answer
This page shows the complete RAG knowledge path from source files to a grounded LLM answer.
RAG answers business definitions, metric rules, and Data Mart knowledge.
LlamaIndex loads and indexes the knowledge, while FAISS stores vectors and retrieves the Top-K matches.
The retrieved context is then passed to the LLM to produce a grounded answer.
Ingestion
Load .md files
→
Document / Chunks
→
Embeddings
Text → vectors
→
FAISS
IndexFlatL2
→
Top-K Retrieval
→
LLM Answer

What Each Part Means

Document object

LlamaIndex's standard representation of a loaded file. It contains the text plus metadata such as the file name.

1536 dimensions

The embedding model returns 1536 numbers for each text embedding. The FAISS index must use the same dimension.

IndexFlatL2

Flat = exact search over stored vectors. L2 = Euclidean distance. Smaller distance means more similar.

StorageContext

Tells LlamaIndex where the vector embeddings should be stored.

similarity_top_k = 3

Retrieve the three most relevant chunks for each user question.

Code Mapping

app/rag/ingestion/loader.py
Load Markdown files → Document objects
app/rag/embeddings/embedder.py
Text → embedding vectors
app/rag/vectorstore/faiss_store.py
Create FAISS IndexFlatL2
app/rag/retrieval/retriever.py
Build VectorStoreIndex and Top-K query engine
app/rag/service.py
Expose one simple answer(question) interface
RAG explains definitions and rules. It does not calculate the final business metric from raw data.
Quick Review

RAG Concepts

What does IndexFlatL2 mean?
It is a simple exact FAISS index. Flat means exact search; L2 means Euclidean distance. Smaller distance means more similar vectors.
Why LlamaIndex + FAISS?
LlamaIndex manages document loading, indexing and retrieval orchestration; FAISS provides efficient vector similarity search.
LangGraph

LangGraph — State, Nodes, Edges and Conditional Routing

1. What is LangGraph?

▾
LangGraph models an LLM application as a stateful graph. Nodes perform tasks, edges define flow, and conditional edges choose the next step from current state.
State→Node→Edge / Conditional Edge→Next Node

2. The 9 LangGraph Concepts — what this project actually uses

▾
9 LangGraph concepts
1State USED
2Nodes USED
3Edges USED
4Conditional Edges USED
5Tools Integration PARTIAL
6Checkpointing NOT YET
7Human-in-the-loop CONCEPT
8Streaming NOT YET
9Graph Composition NOT YET

3. State — shared working memory

▾
app/core/models.py
class AgentState(TypedDict, total=False):
    """Shared working state passed through the LangGraph workflow."""
    question: str
    intent: str
    metric: str
    detail_requested: bool
    query: dict
    # Resolved Campaign + Product + Country context.
    resolved_context: dict
    # validated / resolved / clarification / not_found / answered
    status: str
    # Final user-facing response.
    answer: str
    # knowledge / analytics
    route: str
Key idea: Node does not need to know the whole application. It reads fields from State and returns updates.

4. Nodes — one responsibility per step

▾
def extract_node(self, state: AgentState) -> AgentState:
    request = self.extractor.extract(state["question"])
    return {
        **state,
        "intent": request.intent,
        "metric": request.metric,
        "detail_requested": request.detail_requested,
        "query": request.query.model_dump(),
    }
def validate_node(self, state: AgentState) -> AgentState:
    query = ReservationQuery(**state["query"])
    missing = missing_analytics_context(query)
    if missing:
        return {
            **state,
            "status": "clarification",
            "route": "analytics",
            "answer": "Please provide " + ", ".join(missing) + ". I will not guess.",
        }
    return {**state, "status": "validated"}
def resolve_node(self, state: AgentState) -> AgentState:
    campaigns = self.resolver.resolve(
        ReservationQuery(**state["query"])
    )
    if not campaigns:
        return {
            **state,
            "status": "not_found",
            "answer": "No campaign matched the supplied business context.",
        }
    if len(campaigns) > 1:
        choices = "; ".join(
            f"{item.campaign_id} — {item.campaign_name}"
            for item in campaigns
        )
        return {
            **state,
            "status": "clarification",
            "answer": "Multiple campaigns matched. Choose one campaign_id: " + choices,
        }
    return {
        **state,
        "resolved_context": campaigns[0].model_dump(),
        "status": "resolved",
    }
NodeResponsibility
extract_nodeNatural language → structured request
knowledge_nodeCall KnowledgeRAG for definitions / metadata
validate_nodeCheck required business context
resolve_nodeResolve exactly one campaign context
analytics_nodeRun controlled analytics SQL

5. Edge vs Conditional Edge

▾
Normal Edge
graph.add_edge(START, "extract")
Conditional Edge
graph.add_conditional_edges(
    "extract",
    self._after_extract,
    {
        "knowledge": "knowledge",
        "validate": "validate",
    },
)

6. Routing Functions

▾
@staticmethod
def _after_extract(state: AgentState) -> str:
    return "knowledge" if state["intent"] == "knowledge" else "validate"
@staticmethod
def _after_validate(state: AgentState) -> str:
    return "end" if state["status"] == "clarification" else "resolve"
@staticmethod
def _after_resolve(state: AgentState) -> str:
    return "analytics" if state["status"] == "resolved" else "end"
_after_extract→knowledge / validate
_after_validate→resolve / end
_after_resolve→analytics / end

7. Build and Compile the Graph

▾
Core AI / LangGraph Routing
def _build_langgraph(self):
    from langgraph.graph import END, START, StateGraph
    graph = StateGraph(AgentState)
    graph.add_node("extract", self.extract_node)
    graph.add_node("knowledge", self.knowledge_node)
    graph.add_node("validate", self.validate_node)
    graph.add_node("resolve", self.resolve_node)
    graph.add_node("analytics", self.analytics_node)
    graph.add_edge(START, "extract")
    graph.add_conditional_edges(
        "extract",
        self._after_extract,
        {
            "knowledge": "knowledge",
            "validate": "validate",
        },
    )
    graph.add_edge("knowledge", END)
    graph.add_conditional_edges(
        "validate",
        self._after_validate,
        {
            "resolve": "resolve",
            "end": END,
        },
    )
    graph.add_conditional_edges(
        "resolve",
        self._after_resolve,
        {
            "analytics": "analytics",
            "end": END,
        },
    )
    graph.add_edge("analytics", END)
    return graph.compile()

Then run it:

def invoke(self, question: str) -> AgentState:
    state: AgentState = {"question": question}
    if self._graph is not None:
        return self._graph.invoke(state)
    # Fallback path when LangGraph is not installed.
    state = self.extract_node(state)
    if self._after_extract(state) == "knowledge":
        return self.knowledge_node(state)
    state = self.validate_node(state)
    if self._after_validate(state) == "end":
        return state
    state = self.resolve_node(state)
    if self._after_resolve(state) == "end":
        return state
    return self.analytics_node(state)

8. Real Sample — how State changes step by step

▾
① Initial{question}
② After extractintent / metric / query
③ After resolveresolved_context
④ After analyticsstatus=answered
answer=...
{
  "question": "How many users reserved Phone Mi 17 Pro in Germany for CMP001?",
  "intent": "analytics",
  "metric": "reserved_users",
  "detail_requested": false,
  "query": {
    "country": "Germany",
    "product": "Phone Mi 17 Pro",
    "campaign_id": "CMP001"
  },
  "resolved_context": {
    "campaign_id": "CMP001",
    "product_id": "P001",
    "country_code": "DE"
  },
  "status": "answered",
  "route": "analytics",
  "answer": "..."
}

10. LangGraph Project Discussion Q&A

▾
What is LangGraph?
LangGraph is a framework for building stateful LLM workflows as graphs. I use shared state, task-specific nodes and conditional edges to route each request through a controlled workflow.
Why LangGraph instead of plain Python if/else?
Plain Python can implement the same small workflow, but LangGraph makes state and branching explicit and gives a clearer path to checkpointing, human-in-the-loop, streaming and larger workflow composition.
What is State?
State is the shared working memory that flows through the graph. Each node reads the fields it needs and returns updates.
What is a Node?
A node is one unit of work. In this project extraction, validation, campaign resolution, RAG and analytics are separate responsibilities.
Edge vs Conditional Edge?
A normal edge always goes to the same next node. A conditional edge chooses the next node from current state.
Do you use tools?
The workflow invokes RAG and analytics services deterministically. I intentionally do not give the LLM unrestricted database tool access because the analytics path is application-controlled.

Analytics Flow

The analytics path converts a business plan into a stable governed context, then executes allowlisted SQL.

Corresponding Slide — Page 5
Page 5: Analytics Flow — Business Plan to Controlled SQL
This page shows how the structured business plan becomes controlled SQL against the trusted Data Mart.
The analytics path converts the business plan into a governed query context.
Stable IDs are validated directly, while natural-language names are resolved only when needed.
Application code selects allowlisted SQL and QueryBackend executes it against the trusted Data Mart.
Structured Business Plan
→
Validation
→
Resolution
→
Metrics
→
Controlled SQL
→
QueryBackend
→
Data Mart
Before SQL Execution

Resolution Status — Actual Implemented Flow

User Question ↓ LLM Structured Extraction ↓ Intent + Metric + Business Context ↓ Validate Required Context ├─ missing → clarification → STOP └─ enough context → validated ↓ Resolve / Validate Business Entities ├─ 0 match → not_found → STOP ├─ >1 match → clarification → governed choices → STOP └─ 1 match → resolved ↓ Choose allowlisted metric SQL ↓ Execute Controlled SQL ↓ answered
1
clarification — implemented for missing required context or multiple matching campaigns. The flow stops before SQL and asks the user to provide or choose valid governed context.
2
not_found — implemented when no campaign matches the supplied governed business context. The flow stops before SQL.
3
resolved — implemented when exactly one governed campaign context is resolved. Only this branch proceeds to controlled analytics SQL.
4
validated — an intermediate status after required-context validation passes; it then continues to entity resolution.
5
answered — the final status after the analytics query completes and the response is ready.
Implemented rule: clarification and not_found stop before SQL. Only resolved enters the analytics node. conflict and unsupported are not implemented in this version.

Entity Resolution Rule

Stable ID

CMP001 / P001 / DE

Validate directly against governed dimension tables. Do not ask the LLM to resolve the ID again.

Natural-language Name

Germany / Phone Mi 17 Pro

Search governed candidates and resolve the name only when needed.

Ambiguous Name

Several candidates

Return candidate IDs and ask the user to retry. No session-resume loop in this simple version.

Controlled SQL

METRICS = { "reserved_users": build_reserved_users_sql, "ordered_users": build_ordered_users_sql, "conversion_rate": build_conversion_rate_sql, } # LLM chooses the business intent. # Application code chooses the final SQL.
LLM decides what the user wants. Application code decides how to query trusted data.
Quick Review

Controlled Analytics

Why not let the LLM generate SQL?
Because business metrics need deterministic definitions and governed access. The LLM interprets intent; application code owns the final SQL.
What happens when an ID is provided?
Stable governed IDs bypass semantic resolution and are validated directly against the dimension tables.
What happens when a name is provided?
The resolver looks up governed candidates and resolves the natural-language name only when needed.

Example Walkthroughs

These two examples match the presentation: one proves the Knowledge RAG path; the other proves the controlled Analytics path.

Corresponding Slide — Page 6
Page 6: Example Walkthroughs — Knowledge + Analytics
This page compares a knowledge question with a real analytics question so the two answer paths are easy to distinguish.
The knowledge example proves that RAG can explain a governed metric definition.
The analytics example proves that IDs and names are grounded before controlled SQL runs.
Together they show the difference between explaining knowledge and returning trusted business numbers.
Knowledge Example

“What does reserved_users mean?”

Question
→
Knowledge RAG
→
Grounded Answer

The router sends the question to Knowledge RAG.

Answer: reserved_users means distinct users with freserve_flag = 1, based on trusted metric knowledge.

Analytics Example

“For campaign CMP001 in Germany, how many users reserved?”

metric = reserved_users campaign_id = CMP001 country = Germany

CMP001 → exact validation
Germany → DE through governed name resolution
reserved_users → allowlisted controlled SQL

Trusted Result

Return the governed metric result.

Stable IDs are validated directly. Natural-language names are resolved only when needed.

Application Structure

Top level is organized by system capability; each capability is internally organized by responsibility.

Corresponding Slide — Page 7
Page 7: Application Structure — Code Structure
This page maps the architecture concepts directly to the project folder and service structure.
The code is organized by system capability, so the folder structure mirrors the architecture.
RAG, analytics, graph, API, and the shared LLM client are separated into clear modules.
This makes the project easier to read, explain, test, and maintain.
app/ ├── rag/ │ ├── ingestion/ # load knowledge files │ ├── embeddings/ # text → vectors │ ├── vectorstore/ # FAISS │ ├── retrieval/ # Top-K retrieval │ └── service.py # RAG answer service │ ├── analytics/ │ ├── models/ # typed request / context / result models │ ├── validation/ # enough business context? │ ├── resolution/ # IDs validate; names resolve │ ├── metrics/ # allowlisted metric definitions │ ├── query/ # QueryBackend abstraction │ └── service.py # coordinate trusted analytics │ ├── graph/ │ ├── nodes/ # extract / validate / resolve / answer steps │ ├── state.py # shared LangGraph state │ └── workflow.py # graph + conditional routing │ ├── api/ │ ├── routes.py # FastAPI endpoints │ └── schemas.py # API request / response schema │ ├── llm/ │ └── client.py # shared LLM + structured output client │ ├── settings.py # runtime configuration └── main.py # application entry point

Analytics annotations

models = typed data; validation = enough context; resolution = governed IDs; metrics = allowlist; query = backend adapter; service = orchestration.

Graph / API annotations

nodes = one responsibility per step; state = shared working data; workflow = conditional routing; api = service entry; llm = shared model client.

Read the Code in This Order

1 → 4: Understand the system

1. graph/workflow.py
2. graph/nodes/extract.py
3. rag/service.py
4. rag/*

5 → 7: Understand trusted analytics

5. analytics/resolution/
6. analytics/metrics/
7. analytics/service.py

Each Python module, class and function includes a docstring so you can understand purpose, input, output and flow quickly.
PRODUCTION RUNTIME · SYSTEM ARCHITECTURE

8. Production Architecture

What is running in production, and how does one user request reach the trusted answer?

01. Production Architecture — One Reference Diagram

▾
Final production architecture from PPT v106

Reference: Production Deploy, Slide 8. Ingress and Service route traffic to the application Pod. The application calls an external LLM API and the enterprise Query Engine; it does not host model weights.

02. End-to-End Request Runtime

▾
Feishu Bot→Ingress→Service→FastAPI→LangGraph→Answer
Knowledge path

RAG retrieves grounded definitions using LlamaIndex and FAISS. See Tab 3 for details.

Analytics path

Validate the required context → Resolve entities → execute controlled SQL when clear. Ask for clarification only if information is missing or ambiguous. See Tab 5.

03. Runtime Modules & Boundaries

▾
FastAPI + Pydantic

API handling and structured request validation.

LangGraph

Workflow state and routing to Knowledge RAG or Analytics.

LLM / Embeddings

External model services; calling an LLM API is not the same as deploying an LLM model.

QueryBackend → Query Engine

Runs allowlisted business queries against the governed Reservation Data Mart.

04. Configuration, Security & Observability

▾
ConfigMapruntime settings→Application Podsrunning service→Monitoringhealth / logs / traces

ConfigMap: non-sensitive runtime settings. Secrets: sensitive LLM and data-platform credentials. Monitoring: latency, errors, health, and traces. Deployment commands belong to Tab 9.

AI ENGINEERING · BUILD / TEST / RELEASE

9. Docker, Kubernetes & CI/CD

How to package, test, deploy, observe, and roll back the Python AI Agent. These commands are learning examples, not unverified claims about the production CI/CD provider.

01. Deployment Roadmap

▾
Git Pushsource change→CI Testsquality gate→Docker Buildversioned image→Registrystore image→K8s Rolloutdeploy & verify

Remember: Production (Tab 8) explains how requests run. Deployment (this tab) explains how engineers ship the application.

02. FastAPI Project & Docker Packaging

▾
HOW THE IMAGE IS BUILT
Python AppFastAPI + Agent code
DockerfileImage instructions
docker buildCreate image
docker runLocal health check

Step 1 — FastAPI Application

A practical repository separates API entry points, Agent logic, knowledge retrieval, analytics, tests, and deployment manifests.

TEXT
reservation-agent/
├── app/
│ ├── api/main.py
│ ├── graph/workflow.py
│ ├── rag/retriever.py
│ ├── analytics/query_backend.py
│ └── llm/client.py
├── tests/
├── requirements.txt
├── Dockerfile
├── .dockerignore
├── k8s/
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ └── configmap.yaml
└── .github/workflows/ci-cd.yml
PYTHON
# Example only: adapt to your actual FastAPI module.
from fastapi import FastAPI
app = FastAPI()
@app.get("/healthz")
def healthz():
return {"status": "ok"}
@app.get("/readyz")
def readyz():
# Add lightweight readiness checks if required.
return {"ready": True}
BASH
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.api.main:app --host 127.0.0.1 --port 8000
curl http://127.0.0.1:8000/healthz
Production readiness should check critical dependencies carefully without making liveness depend on external LLM availability. API path and repository layout are illustrative.

Package the AI Agent with Docker

Docker builds an immutable application image. Do not bake secrets into the image. Versioned tags make deployment and rollback traceable.

DOCKERFILE
FROM python:3.11-slim
ENV PYTHONDONTWRITEBYTECODE=1 \
 PYTHONUNBUFFERED=1
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app/ ./app/
EXPOSE 8000
CMD ["uvicorn", "app.api.main:app", "--host", "0.0.0.0", "--port", "8000"]
TEXT
# .dockerignore
.git
.venv
__pycache__
.pytest_cache
.env
*.pyc
BASH
docker build -t reservation-agent:v1 .
docker run --rm -p 8000:8000 reservation-agent:v1
# In another terminal:
curl http://localhost:8000/healthz
# Examine runtime output:
docker ps
docker logs <container-id>
The actual application needs its real dependencies, embedding/FAISS index access, and required environment configuration. A successful /healthz test alone does not prove analytics or RAG works.

03. CI Testing & Container Registry

▾
HOW CI BUILDS A RELEASE
Git PushTrigger pipeline
TestsSchema + RAG + SQL
Build ImageVersioned tag
RegistryPush and store

Step 1 — Automated Quality Gates

Continuous Integration (CI) starts after a code push or pull request. Tests should exercise both ordinary Python code and Agent-specific guardrails.

Git push→Lint / format→Unit tests→RAG / SQL checks→Docker build
Structured request

Valid and invalid Pydantic extraction outputs.

RAG

Relevant retrieval, empty search, grounded answers.

Analytics

Campaign validation, entity resolution, approved metric keys, no unsafe free-form SQL.

BASH
python -m pip install -r requirements.txt
python -m pip install pytest ruff
ruff check app tests
pytest -q
docker build -t reservation-agent:test .
Integration tests should mock LLM responses and the enterprise query backend where appropriate. Never use production credentials in pull-request tests.

Registry: publish a versioned Docker image

The registry hosts built images so the Kubernetes cluster can pull them. Choose the registry actually provided by your organization.

Build image→Tag with commit SHA→Authenticate→Push image→K8s pulls version
BASH
# Example registry; replace with your authorized registry.
export REGISTRY=registry.example.com/team
export IMAGE=$REGISTRY/reservation-agent
export TAG=v1

docker tag reservation-agent:v1 "$IMAGE:$TAG"
docker login registry.example.com
docker push "$IMAGE:$TAG"
Prefer short Git commit SHA tags or immutable image digests rather than relying only on the mutable :latest tag. CI uses scoped registry credentials.

04. Kubernetes Deployment & Secure Configuration

▾
HOW KUBERNETES EXPOSES THE AGENT
IngressExternal HTTP route
ServiceStable internal address
DeploymentDesired Pod replicas
PodFastAPI container

Step 1 — Kubernetes Resources

Deployment manages replica Pods. Service provides internal access. Ingress routes external HTTPS requests to that Service when an Ingress controller and TLS are configured.

YAML
# k8s/deployment.yaml — illustrative manifest
apiVersion: apps/v1
kind: Deployment
metadata:
 name: reservation-agent
spec:
 replicas: 2
 strategy:
 type: RollingUpdate
 selector:
 matchLabels:
 app: reservation-agent
 template:
 metadata:
 labels:
 app: reservation-agent
 spec:
 containers:
 - name: api
 image: registry.example.com/team/reservation-agent:v1
 ports:
 - containerPort: 8000
 envFrom:
 - configMapRef:
 name: reservation-agent-config
 - secretRef:
 name: reservation-agent-secrets
 readinessProbe:
 httpGet:
 path: /readyz
 port: 8000
 initialDelaySeconds: 5
 periodSeconds: 10
 livenessProbe:
 httpGet:
 path: /healthz
 port: 8000
 initialDelaySeconds: 15
 periodSeconds: 20
 resources:
 requests:
 cpu: 100m
 memory: 256Mi
 limits:
 cpu: 1000m
 memory: 1Gi
YAML
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
 name: reservation-agent
spec:
 selector:
 app: reservation-agent
 ports:
 - port: 80
 targetPort: 8000
 type: ClusterIP
YAML
# k8s/ingress.yaml — controller/TLS must exist
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: reservation-agent
spec:
 ingressClassName: nginx
 tls:
 - hosts: [agent.example.com]
 secretName: agent-tls
 rules:
 - host: agent.example.com
 http:
 paths:
 - path: /
 pathType: Prefix
 backend:
 service:
 name: reservation-agent
 port:
 number: 80
These manifests demonstrate the roles, not the company’s actual Kubernetes configuration. Ingress requires an installed controller; TLS secret and DNS must be prepared separately.

ConfigMap, Secrets, and enterprise Query Engine

Keep non-sensitive runtime settings separate from credentials. The app sends controlled SQL through QueryBackend → Data Platform / Query Engine → Reservation Data Mart.

YAML
# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: reservation-agent-config
data:
 REGION: "sg"
 QUERY_BACKEND: "enterprise-query-gateway"
 LOG_LEVEL: "INFO"
BASH
# Illustration only: create a secret from secured inputs.
# In production, use your organization's approved secret manager.
kubectl create secret generic reservation-agent-secrets \
 --from-literal=LLM_API_KEY='REPLACE_IN_SECURE_ENV' \
 --from-literal=DATA_PLATFORM_TOKEN='REPLACE_IN_SECURE_ENV' \
 --dry-run=client -o yaml | kubectl apply -f -
Do not paste real keys in a terminal command, shared shell history, or Git. Prefer managed secrets/CI secret injection. Kubernetes Secrets are not automatically encrypted at rest unless the cluster is configured for it. This is a teaching example, not a recommended way to enter production credentials.

05. CD Release, Rollback & Troubleshooting

▾
HOW CD UPDATES AND RECOVERS
ReleaseNew image tag
RolloutPods update gradually
ReadinessCheck healthy Pods
RollbackUndo failed release

Step 1 — Release and Rollback

Continuous Delivery / Deployment (CD) promotes an approved image to Kubernetes, checks its rollout, and supports rollback. The exact approval policy depends on the team.

CI image passed→Deploy approved tag→Rolling update→Readiness gate→Verify / roll back
BASH
# Prerequisites: correct kube context, permissions, and manifests.
kubectl config current-context
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
kubectl apply -f k8s/ingress.yaml

kubectl set image deployment/reservation-agent \
 api=registry.example.com/team/reservation-agent:v2
kubectl rollout status deployment/reservation-agent
kubectl get pods -l app=reservation-agent
kubectl logs deployment/reservation-agent --tail=100
# If the release fails:
kubectl rollout undo deployment/reservation-agent
YAML
# Illustrative GitHub Actions flow, NOT verified project CI/CD.
name: Test and build
on: [push, pull_request]
jobs:
 test-and-build:
 runs-on: ubuntu-latest
 steps:
 - uses: actions/checkout@v4
 - uses: actions/setup-python@v5
 with:
 python-version: '3.11'
 - run: pip install -r requirements.txt pytest ruff
 - run: ruff check app tests
 - run: pytest -q
 - run: docker build -t reservation-agent:ci .
# Production registry publishing and Kubernetes CD
# require separately configured identities and approvals.
Do not claim a GitHub Actions/GitLab CI/Jenkins pipeline actually ran until it is verified. In this project, a DevOps engineer was responsible for Kubernetes deployment.

Production traffic, scaling, and Agent state

After release, the business runtime is different from the CI/CD path. Users enter through Feishu; the FastAPI service forwards requests to LangGraph; RAG and Analytics use external services.

Feishu bot→Ingress→Service→FastAPI Pod→LangGraph→LLM / RAG / QueryBackend
BASH
kubectl get deployments,services,ingresses
kubectl describe deployment reservation-agent
kubectl top pods
kubectl logs deployment/reservation-agent --since=15m
kubectl scale deployment/reservation-agent --replicas=3
kubectl get pods -l app=reservation-agent -w
Important interview catch: clarification and candidate selection may happen in a later request handled by a different Pod. In-memory pending state is not reliable across multiple replicas. Use an actual durable shared state/checkpointer or application-level session persistence if implemented. Do not claim a specific checkpointer without evidence.

Monitoring, troubleshooting, and security

API indicators

Request count, error rate, p95 latency, and correlation IDs.

Agent indicators

LLM timeouts, retrieval latency, entity-resolution failures, and query duration.

Platform indicators

Pod restarts, readiness, CPU / memory, and rollout status.

BASH
kubectl get pods
kubectl describe pod <pod-name>
kubectl logs <pod-name> --previous
kubectl get events --sort-by=.lastTimestamp
kubectl rollout history deployment/reservation-agent
kubectl rollout undo deployment/reservation-agent

Diagnosis sequence: check user-facing symptom → trace FastAPI request → inspect Agent state or LLM API → inspect RAG / QueryBackend errors → check Kubernetes Pod health → roll back a bad release if needed.

Only response time, errors, and request traces were explicitly established as existing monitoring in this project. All other metrics in this section are recommended additions. Never log raw tokens, credentials, or sensitive user-level data.
PRESENTATION PRACTICE · SPEAKER NOTES ARE THE SOURCE

10. Slides & Speaking Script

Every English sentence below is taken from the exact Speaker Notes in PPT v106. Only line breaks and sentence display are adjusted for click-to-listen practice.

Slide 1 Page 1 / 8

PPT v106 Slide 1
Exact Speaker Notes — Click Any Sentence to Listen
🔊Let me start with the business problem.
🔊At M, we run reservation campaigns for new product launches and promotions.
🔊Operations teams often need ad-hoc analysis, such as checking unusual reservations and reviewing campaign performance.
🔊This created repeated data requests and manual work.
🔊I built a Reservation Data Mart using reservation events, orders, and business dimensions, and then developed a production AI Agent on top of it.
🔊This allows business users to ask questions in natural language while keeping business metrics consistent.

Slide 2 Page 2 / 8

PPT v106 Slide 2
Exact Speaker Notes — Click Any Sentence to Listen
🔊This slide shows the overall workflow.
🔊First, the LLM extracts the intent, metric, and business context from the user's question.
🔊Then LangGraph manages the workflow and routes the request to either Knowledge RAG or Analytics.
🔊Knowledge RAG answers questions about business definitions and rules.
🔊Analytics validates business context, resolves business entities, and executes controlled SQL through the data platform.
🔊Both paths return answers based on trusted information.

Slide 3 Page 3 / 8

PPT v106 Slide 3
Exact Speaker Notes — Click Any Sentence to Listen
🔊The key design is to separate LLM understanding from business execution.
🔊The LLM converts the question into a structured request using a Pydantic schema, while LangGraph manages the workflow.
🔊The LLM does not generate SQL or calculate business numbers directly.
🔊Instead, application code controls business validation, entity resolution, and SQL execution.
🔊This reduces incorrect answers and makes the system more reliable in production.

Slide 4 Page 4 / 8

PPT v106 Slide 4
Exact Speaker Notes — Click Any Sentence to Listen
🔊For knowledge questions, we use a RAG pipeline.
🔊LlamaIndex organizes business knowledge documents for retrieval.
🔊Documents are chunked and converted into 1,536-dimensional embeddings, matching the selected embedding model.
🔊FAISS IndexFlatL2 performs exact similarity search using Euclidean distance.
🔊We retrieve the top three chunks and give the grounded context to the LLM.
🔊RAG answers knowledge questions; it does not calculate the final business metrics.

Slide 5 Page 5 / 8

PPT v106 Slide 5
Exact Speaker Notes — Click Any Sentence to Listen
🔊For analytics questions, the core workflow is Validate Business Context, Resolve Business Entities, and Controlled SQL.
🔊First, the application checks whether the required business context is available.
🔊Campaign is required; product and site are optional.
🔊Next, stable IDs are validated against governed dimensions and names are resolved to verified records.
🔊For campaign names, the application checks recent campaign records and can propose up to three real candidates.
🔊Only if required context is missing or a business name has multiple possible matches does the system ask the user to clarify or choose.
🔊When the request is clear and validated, it proceeds directly.
🔊The Metric Registry selects predefined SQL, and QueryBackend runs it through the enterprise data platform.

Slide 6 Page 6 / 8

PPT v106 Slide 6
Exact Speaker Notes — Click Any Sentence to Listen
🔊Let me show two examples.
🔊First, “What does reserved_users mean?” This is a knowledge request.
🔊LangGraph routes it to RAG for the governed metric definition.
🔊It does not require campaign context.
🔊Second, “For campaign CMP001 in Germany, how many users reserved?” This is an analytics request with the reserved_users metric, campaign CMP001, and country Germany.
🔊The application validates CMP001 and resolves Germany to DE.
🔊Because the entities are clear and valid, the Metric Registry selects predefined SQL, and QueryBackend executes it through the data platform.
🔊The Agent returns the trusted result.

Slide 7 Page 7 / 8

PPT v106 Slide 7
Exact Speaker Notes — Click Any Sentence to Listen
🔊The application has separate modules for RAG, Analytics, LangGraph, FastAPI, and the LLM client.
🔊RAG handles document ingestion, embeddings, vector search, and retrieval.
🔊Analytics handles business-context validation, entity resolution, predefined metric selection, and controlled SQL execution.
🔊I designed the system to be modular, testable, and reusable, making it easier to maintain and extend.

Slide 8 Page 8 / 8

PPT v106 Slide 8
Exact Speaker Notes — Click Any Sentence to Listen
🔊Slide 8 — Production Deployment
🔊1. Production Entry
🔊Users access the Agent through a Feishu bot.
🔊Requests pass through Kubernetes Ingress and Service to our FastAPI application.
🔊2. Agent Workflow
🔊FastAPI receives the request.
🔊Pydantic validates structured data, and LangGraph routes the workflow to Knowledge RAG or Analytics.
🔊The application calls an external LLM API when needed.
🔊3. Controlled Analytics
🔊For analytics, we validate the required business context and resolve entities against governed dimension tables.
🔊For clear and valid requests, predefined SQL runs through QueryBackend and the data platform.
🔊4. Deployment and Operations
🔊The application is packaged with Docker and runs on Kubernetes.
🔊ConfigMap handles non-sensitive settings, Secrets protects credentials, and Monitoring tracks latency, errors, and traces.
🔊5. My Contribution
🔊I was the main designer and developer in a three-person team.
🔊An intern supported implementation and testing, while a DevOps engineer handled Kubernetes deployment.

11. Q&A

01. GenAI & RAG Fundamentals

▾

Q1. What is RAG? 🔊

QUICK VISUAL
Question→Retrieve→Context→LLM Answer
  1. RAG stands for Retrieval-Augmented Generation.
  2. It retrieves relevant business knowledge before the LLM writes an answer.
Memory tip: Retrieve first, answer second.

Q2. What does LlamaIndex do? 🔊

QUICK VISUAL
Documents→Chunk→Index→Retrieve
  1. LlamaIndex organizes knowledge documents and their chunks.
  2. It supports embedding, indexing, and retrieval in our RAG pipeline.
Memory tip: LlamaIndex connects knowledge to the application.

Q3. Why do you use 1,536 dimensions? 🔊

QUICK VISUAL — FIRST
Embedding Model→1,536-D Vector→FAISS 1,536-D
  1. The embedding model determines the dimension; our selected model outputs 1,536 numbers, so FAISS uses 1,536 too.
  2. Higher dimensions may capture more detail but need more memory and computation; lower dimensions are cheaper but may lose information.
  3. The provider defines the model name, and developers select it in configuration—for example, OpenAI's text-embedding-3-small; our actual model name is not confirmed.
Memory tip: Embedding model defines vector size; FAISS must match. Model name is configured, not chosen by FAISS.

Q4. What is FAISS IndexFlatL2? 🔊

QUICK VISUAL
Query Vector→FAISS L2→Closest Chunks
  1. FAISS retrieves similar vectors; IndexFlatL2 searches exactly using Euclidean distance.
  2. A smaller L2 distance means closer vectors.
Memory tip: Smaller L2 distance means closer vectors.

Q5. What does Top-K = 3 mean? 🔊

QUICK VISUAL — FIRST
Question→FAISS Top 3 Chunks→LLM Context→One Answer
  1. Top-K = 3 retrieves three relevant text chunks, not three whole documents.
  2. The LLM reads all three chunks as context and produces one grounded answer; it does not average vectors.
Memory tip: Three retrieved chunks become one answer through the LLM.

Q6. Why Top-3 instead of Top-5? 🔊

QUICK VISUAL — FIRST
Top-3→Less Context→Lower Cost→Evaluate Quality
  1. Top-3 limits context length, latency, and token cost.
  2. Top-5 may add useful evidence but also noise and cost; the right K should be tested on real questions.
Memory tip: Top-K is a trade-off, not a fixed rule.

02. Agent & Controlled Analytics

▾

Q1. What is LangGraph? 🔊

QUICK VISUAL
Question→Extract→Router→RAG / Analytics
  1. LangGraph coordinates workflow nodes and shared state.
  2. It routes requests to Knowledge RAG or Analytics.
Memory tip: A graph organizes the Agent workflow.

Q2. What does Pydantic validate? 🔊

QUICK VISUAL
LLM Output→Pydantic→Structured Fields
  1. Pydantic checks the structure and types of extracted fields.
  2. It does not prove that a Campaign ID exists in the business dimension table.
Memory tip: Structure and business validity are different.

Q3. How does the Agent choose RAG or Analytics? 🔊

Question→Structured Intent→RAG / Analytics
  1. The LLM classifies intent into a structured result, and LangGraph selects the matching path.
  2. Definitions use Knowledge RAG; requests for actual business numbers use controlled Analytics.
  3. Ambiguous intent should be clarified rather than guessed.
Memory tip: RAG explains; Analytics calculates.

Q4. What is the difference between Validate and Resolve? 🔊

QUICK VISUAL
Input→Validate Context→Resolve Entity
  1. Validate checks whether required business context is present, such as Campaign.
  2. Resolve verifies IDs or maps business names to real governed entities.
Memory tip: Enough context first; real entities second.

Q5. How do you handle ambiguous campaign names? 🔊

QUICK VISUAL
Campaign Name→DIM Records→Top Candidates→User Choice
  1. Retrieve actual campaign records and identify possible matches.
  2. If multiple valid candidates remain, ask the user to choose; never invent an ID.
Memory tip: Candidates must come from governed records.

Q6. Can you explain the Analytics flow? 🔊

QUICK VISUAL
Question→Design Choice→Trusted Outcome
  1. The LLM extracts intent, metric, and business context into a structured request.
  2. The application validates context and resolves entities; only ambiguous or incomplete requests need clarification.
  3. For valid requests, the Metric Registry selects predefined SQL and QueryBackend queries the Reservation Data Mart.
Memory tip: Connect the answer to the project architecture.

Q7. What metrics does the current implementation support? 🔊

QUICK VISUAL
Question→Design Choice→Trusted Outcome
  1. The five metrics are summary, reserved_users, ordered_users, reserved_not_ordered, and conversion_rate.
  2. Each maps to predefined, governed query logic.
Memory tip: Connect the answer to the project architecture.

Q8. Why not let the LLM generate SQL? 🔊

QUICK VISUAL
LLM Intent→Metric Registry→Allowlisted SQL→Query Engine
  1. The LLM understands intent, but should not invent business calculations.
  2. Application code chooses predefined SQL from the Metric Registry.
Memory tip: LLM understands; code executes.

03. Reliability, Accuracy & Evaluation

▾

Q1. How do you ensure LLM answers are accurate? 🔊

Question→Trusted Evidence→App Validation→Final Answer
  1. I do not treat an LLM response as the source of truth.
  2. RAG uses retrieved business documents, while Analytics validates entities and runs predefined SQL.
  3. When evidence is missing or the request is ambiguous, the safer response is to ask or state the limitation.
Memory tip: Ground the answer; verify the source.

Q2. Can RAG still produce incorrect knowledge answers? 🔊

Top-3 Chunks→Evidence Check→LLM Answer→Review
  1. Yes. Retrieval can miss the right chunk or return outdated or conflicting text.
  2. Even with good context, the LLM can misinterpret or invent details.
  3. I would inspect the retrieved chunks and avoid a confident answer when support is weak.
Memory tip: RAG reduces hallucinations; it does not eliminate them.

Q3. What if the Agent routes a question incorrectly? 🔊

Wrong Route→Detect Mismatch→Clarify or Reroute→Add Test Case
  1. Incorrect routing can happen when a question mixes definitions and metrics.
  2. I would check intent and path requirements, then clarify or reroute when needed.
  3. I would add the failure to a routing regression test set; automatic recovery was not confirmed as deployed.
Memory tip: Detect, recover, test.

Q4. How would you evaluate RAG answer quality? 🔊

Test Questions→Reference Evidence→Retrieval Check→Answer Review
  1. I would build a small test set with verified business definitions and supporting documents.
  2. I would evaluate retrieval relevance separately from answer faithfulness and correctness.
  3. Business owners should review important definitions; a formal RAG benchmark was not confirmed in this project.
Memory tip: Evaluate retrieval and generation separately.

Q5. How do you verify Analytics results? 🔊

Validated IDs→Controlled SQL→Data Mart→Reconciliation
  1. Validate campaign IDs and resolved names against governed dimension tables.
  2. Execute the registered metric SQL and compare sample results with independently verified Data Mart queries.
  3. Test duplicates, zero results and missing dimensions.
Memory tip: Numbers come from trusted SQL, not LLM guesses.

Q6. Why not let one LLM answer everything directly? 🔊

Understand Intent→RAG Knowledge→Controlled Metrics→Verified Answer
  1. An LLM can understand language but cannot guarantee accurate facts or calculations.
  2. RAG supplies supporting text, and Analytics calculates metrics using validated data and predefined SQL.
  3. Keeping the paths separate makes failures easier to test and debug.
Memory tip: Understand with LLM; verify with evidence and code.

04. Engineering, Deployment & Learning

▾

Q1. What is FastAPI? 🔊

QUICK VISUAL
Feishu→Ingress→Service→FastAPI
  1. FastAPI is the Python API entry point for the Agent.
  2. It receives requests from the Feishu integration.
Memory tip: FastAPI is the HTTP application entry point.

Q2. What does Docker do? 🔊

QUICK VISUAL
Source Code→Dockerfile→Image→Container
  1. Docker bundles the application and Python dependencies into a reproducible image.
  2. Kubernetes then runs containers from that image.
Memory tip: Build once; run the same image.

Q3. What is CI/CD? 🔊

QUICK VISUAL
Git→Tests→Build→Deploy
  1. CI tests the code and builds a versioned container image.
  2. CD deploys an approved image; the exact pipeline tool used here is not confirmed.
Memory tip: CI checks; CD ships.

Q4. What is Kubernetes? 🔊

QUICK VISUAL
Deployment→ReplicaSet→Pod
  1. Kubernetes runs and manages application Pods and replicas.
  2. Service and Ingress route traffic, while rolling updates support safer releases.
Memory tip: Kubernetes runs containers, not SQL itself.

Q5. What are the main Kubernetes components? 🔊

QUICK VISUAL
Ingress→Service→Pod→FastAPI App
  • Ingress: Routes external HTTP/HTTPS requests to a Kubernetes Service.
  • Service: Gives Pods a stable network endpoint and forwards traffic to matching Pods.
  • Pod: The smallest deployable Kubernetes unit, running one or more containers.
  • Deployment: Defines the desired Pod replicas and manages updates and rollbacks.
  • ConfigMap: Stores non-sensitive settings for Pods, such as runtime configuration.
Memory tip: Ingress → Service → Pod; Deployment manages Pods; ConfigMap supplies settings.

Q6. What are ConfigMap and Secrets? 🔊

QUICK VISUAL
ConfigMap→Settings→Pod
  1. ConfigMap holds non-sensitive runtime settings.
  2. Secrets holds sensitive values such as LLM API keys and data-platform credentials.
Memory tip: Never put API keys in source code.

Q7. What should you monitor? 🔊

QUICK VISUAL
Request→Metrics / Logs→Alert / Debug
  1. Track request latency, errors, and traces.
  2. Check Pod health and relevant LLM or query-engine failures when troubleshooting.
Memory tip: Service health and AI behavior both matter.

Q8. What fundamentals should an AI Engineer master? 🔊

Python & APIs→SQL & Data→RAG & Agents→Testing & Deploy
  1. Python, APIs, SQL and data modeling provide the engineering foundation.
  2. Embeddings, RAG, agents, evaluation and model APIs are key AI skills.
  3. Docker, Kubernetes, security, tests and monitoring help make the system production-ready.
Memory tip: AI Engineering = software + data + AI systems.

Q9. How do you keep up with new AI developments? 🔊

Official Docs→Research & Releases→Small Demo→Evaluate
  1. I follow official model documentation, technical releases and selected research papers.
  2. I build small demos to understand APIs, RAG and agent frameworks.
  3. Before adopting a tool, I compare quality, latency, cost and production constraints.
Memory tip: Read, build, evaluate.

05. Project Experience & Behavioral Questions

▾

Q1. What challenges did you face, and how did you solve them? 🔊

User Input→Validate & Resolve→Controlled SQL→Trusted Answer
  1. Unclear campaign names and unreliable LLM output were the main challenges.
  2. I designed validation and entity resolution using trusted dimension tables.
  3. I separated intent understanding from predefined SQL execution to make answers more reliable.
Memory tip: Reliable answers come from controlled business logic.

Q2. How did you come up with the solution? 🔊

Business Problem→Data Mart→Two Agent Paths→Demo & Feedback
  1. I started with the business pain point: repeated manual requests for reservation metrics.
  2. I designed a trusted Data Mart first, then separated knowledge questions from analytics questions.
  3. I built a working demo to validate the flow before the team implemented and tested the solution.
Memory tip: Business problem first; architecture second; demo before delivery.

Q3. How was your team organized, and what was your role? 🔊

My Design & Demo→Junior: Build & Test→SRE: Deploy→Review & Integrate
  1. We worked as a small team of three: me, a junior engineer, and an SRE engineer.
  2. I led solution design, architecture decisions, coordination, and the initial demo.
  3. The junior engineer handled most implementation and testing, while the SRE engineer handled Docker, Kubernetes, and deployment operations.
Memory tip: I led the technical direction and coordinated delivery.

Q4. How did you use AI Codex to develop this project? 🔊

Requirements→Architecture→Demo→Review
  1. I used Codex to explore the codebase, prototype the initial demo, and refine implementation tasks based on my architecture.
  2. I made the technical decisions, while a junior engineer handled most coding and testing, and an SRE engineer handled Docker and Kubernetes.
  3. Common commands are codex to start, /plan to plan, /review to review, and codex exec for non-interactive tasks.
Memory tip: Codex assists; I own the architecture and review.

Q5. How do you use Codex to solve engineering problems? 🔊

Understand→Trace Root Cause→Fix & Test→Review
  1. First, I describe the issue and expected behavior, then ask Codex to inspect relevant code, logs, and tests.
  2. Next, I review the root-cause analysis and choose a focused fix.
  3. Finally, we run tests, inspect the diff, and I verify the business logic before approving the change.
Memory tip: Understand → Investigate → Fix → Verify.

Q6. How do you keep up with AI industry learning? 🔊

Read Updates→Small Experiments→Compare Trade-offs→Apply Selectively
  1. I follow model releases, engineering blogs, and framework updates, but I focus on changes that matter for real systems.
  2. I learn fastest by building small experiments and comparing latency, cost, and reliability.
  3. If something works well in practice, I bring it back into project design or future improvements.
Memory tip: Read, test, compare, then adopt.

Q7. How do you guide junior engineers? 🔊

Explain Why→Split Tasks→Review & Coach→Grow Ownership
  1. I first explain the business goal and architecture, so the junior engineer understands why the task matters.
  2. Then I break the work into clear modules, review progress frequently, and give direct feedback on logic and testing.
  3. My goal is not only delivery, but also helping the engineer build stronger ownership and system thinking.
Memory tip: Teach the why, not only the task.

Q8. How do you review implementation quality? 🔊

Business Logic→Code & Tests→Failure Cases→Production Ready
  1. I first check whether the implementation matches the business rule, because correct code can still answer the wrong business question.
  2. Then I review code clarity, test coverage, and edge cases such as missing context, invalid IDs, or ambiguous names.
  3. Finally, I consider whether the solution is ready for production use, including logging, observability, and maintainability.
Memory tip: Correct business logic comes before clean code.