docs: add AI Chat Agent documentation and update README
- doc/28-AI-CHAT-AGENT.md: comprehensive technical documentation covering architecture, agent design, query_cv tool, HTMX integration, graceful degradation, security, and example conversations - README.md: add AI Chat Agent section with examples, ADK Go badge, updated tech stack and documentation index - doc/00-GO-DOCUMENTATION-INDEX.md: add chat agent to doc index
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
# CV Site - Go + HTMX
|
||||
|
||||
[](https://go.dev/)
|
||||
[](https://htmx.org/)
|
||||
[](https://go.dev/)
|
||||
[](https://htmx.org/)
|
||||
[](https://github.com/google/adk-go)
|
||||
[](https://aistudio.google.com/)
|
||||
[](LICENSE)
|
||||
|
||||
**Modern, minimal curriculum vitae website** for Juan Andrés Moreno Rubio built with **Go** and **HTMX**.
|
||||
@@ -19,6 +21,7 @@ A professional, bilingual CV site with server-side PDF generation, HTMX interact
|
||||
## 📑 Table of Contents
|
||||
|
||||
- [Features](#-features)
|
||||
- [AI Chat Agent](#-ai-chat-agent)
|
||||
- [Demo](#-demo)
|
||||
- [Security](#-security)
|
||||
- [Quick Start](#-quick-start)
|
||||
@@ -43,6 +46,7 @@ A professional, bilingual CV site with server-side PDF generation, HTMX interact
|
||||
- ✅ **Zoom Control** - Adjustable zoom (25%-300%) with persistence across sessions
|
||||
- ✅ **Responsive** - Mobile, tablet, and desktop friendly
|
||||
- ✅ **JSON-Based Content** - Easy to update without touching code
|
||||
- ✅ **AI Chat Agent** - Ask questions about the CV in natural language (powered by ADK Go + Gemini)
|
||||
- ✅ **AI Development Section** - Showcases modern AI-assisted development skills
|
||||
- ✅ **Fast & Lightweight** - Go backend with chromedp for PDF generation
|
||||
- ✅ **Privacy-Friendly Analytics** - Self-hosted analytics (no third-party data sharing)
|
||||
@@ -50,6 +54,50 @@ A professional, bilingual CV site with server-side PDF generation, HTMX interact
|
||||
- ✅ **Production Ready** - Systemd service, CI/CD workflows, deployment guides
|
||||
- ✅ **Developer Friendly** - Hot reload, clear code structure, comprehensive Makefile
|
||||
|
||||
## 🤖 AI Chat Agent
|
||||
|
||||
Visitors can ask questions about the CV through a floating chat widget — powered by [Google ADK Go 1.0](https://github.com/google/adk-go) and Gemini 2.5 Flash.
|
||||
|
||||
### How It Works
|
||||
|
||||
```
|
||||
Visitor types question → HTMX POST /api/chat → ADK Agent runs query_cv tool
|
||||
→ Tool searches cached CV JSON data → Agent formulates answer → HTML response
|
||||
```
|
||||
|
||||
### Example Questions & Answers
|
||||
|
||||
| Question | Answer |
|
||||
|----------|--------|
|
||||
| *"How many Go projects has Juan built?"* | Lists 2 Go projects with descriptions |
|
||||
| *"What companies has he worked at?"* | Lists all 11 companies |
|
||||
| *"Does he have React experience?"* | Shows companies where React was used |
|
||||
| *"¿Qué certificaciones tiene?"* | Lists certifications — answers in Spanish automatically |
|
||||
|
||||
### Key Design Decisions
|
||||
|
||||
- **Single agent, single tool** — the CV data is bounded; multi-agent orchestration would be over-engineering
|
||||
- **Reads from the same data cache** the site uses — zero data duplication, always in sync
|
||||
- **Graceful degradation** — no API key? Chat icon simply doesn't appear. Zero impact on the site
|
||||
- **HTMX-native** — `hx-post` sends messages, responses are HTML fragments, no WebSocket needed
|
||||
- **Language-aware** — the agent responds in whatever language the visitor writes in
|
||||
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
# Get a free API key from https://aistudio.google.com/apikey
|
||||
echo "GOOGLE_API_KEY=your-key" >> .env
|
||||
|
||||
# Chat icon appears automatically on next server start
|
||||
go run .
|
||||
```
|
||||
|
||||
**Free tier:** 15 requests/minute — more than enough for a personal CV site.
|
||||
|
||||
**Full technical documentation:** [doc/28-AI-CHAT-AGENT.md](doc/28-AI-CHAT-AGENT.md)
|
||||
|
||||
---
|
||||
|
||||
## 📸 Demo
|
||||
|
||||
🔗 **Live Demo:** [https://juan.andres.morenorub.io/](https://juan.andres.morenorub.io/)
|
||||
@@ -187,9 +235,10 @@ No code changes needed - just refresh browser!
|
||||
|
||||
## 🎯 Key Technologies
|
||||
|
||||
- **Backend:** Go 1.21+ (stdlib `net/http`, graceful shutdown)
|
||||
- **Backend:** Go 1.25+ (stdlib `net/http`, graceful shutdown)
|
||||
- **AI Agent:** Google ADK Go 1.0 + Gemini 2.5 Flash (conversational CV navigator)
|
||||
- **PDF Generation:** chromedp (headless Chrome automation)
|
||||
- **Frontend:** HTMX 1.9.10 (hypermedia-driven interactions)
|
||||
- **Frontend:** HTMX 2.0 + Hyperscript (hypermedia-driven interactions)
|
||||
- **Styling:** Custom CSS with Quicksand font from Google Fonts
|
||||
- **Data:** JSON files for easy content management
|
||||
- **Deployment:** Systemd service, manual binary, GitHub Actions CI/CD
|
||||
@@ -206,6 +255,7 @@ This project includes comprehensive documentation organized by purpose:
|
||||
### 🔧 Technical Reference
|
||||
- **[ARCHITECTURE.md](doc/ARCHITECTURE.md)** - System design, patterns, and technical decisions
|
||||
- **[API.md](doc/API.md)** - Complete HTTP API reference and HTMX integration
|
||||
- **[AI-CHAT-AGENT.md](doc/28-AI-CHAT-AGENT.md)** - ADK Go agent architecture, tool design, and integration details
|
||||
|
||||
### 📋 Policies & Standards
|
||||
- **[SECURITY.md](doc/9-SECURITY.md)** - Complete security architecture, implementation, and testing guide
|
||||
@@ -323,6 +373,7 @@ This project is licensed under the **MIT License** - see the [LICENSE](LICENSE)
|
||||
## 🙏 Acknowledgments
|
||||
|
||||
- **HTMX** - For making hypermedia-driven applications enjoyable
|
||||
- **Google ADK Go** - For the production-grade agent framework
|
||||
- **chromedp** - For reliable headless Chrome automation
|
||||
- **Go Community** - For excellent standard library and tooling
|
||||
- **AI Assistance** - For accelerating development and documentation
|
||||
|
||||
@@ -36,6 +36,13 @@ This documentation covers the core Go systems that power the CV site, with a foc
|
||||
- Coverage gap explanations
|
||||
- Best practices and CI/CD integration
|
||||
|
||||
5. **[AI Chat Agent](28-AI-CHAT-AGENT.md)** (~280 lines)
|
||||
- ADK Go 1.0 integration architecture
|
||||
- Agent definition with query_cv tool
|
||||
- HTMX chat widget implementation
|
||||
- Graceful degradation pattern
|
||||
- Example conversations and security considerations
|
||||
|
||||
## Quick Navigation
|
||||
|
||||
### By Feature
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
# 28. AI Chat Agent — ADK Go Integration
|
||||
|
||||
## Overview
|
||||
|
||||
The CV site includes an AI-powered conversational assistant that lets visitors ask natural language questions about the CV content. Built with [Google ADK Go 1.0](https://github.com/google/adk-go) (Agent Development Kit), it provides instant answers by querying the same cached JSON data that renders the site.
|
||||
|
||||
**Live example:** A visitor can ask *"How many Go projects has Juan built?"* and get an accurate answer drawn directly from the CV data — no hallucination, no stale data.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ CV Site Server │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌────────────────────────┐ │
|
||||
│ │ Data Cache │────▶│ ADK Go Agent │ │
|
||||
│ │ (cv-en.json) │ │ ┌──────────────────┐ │ │
|
||||
│ │ (cv-es.json) │ │ │ cv_assistant │ │ │
|
||||
│ └─────────────┘ │ │ (LLM Agent) │ │ │
|
||||
│ │ │ │ │ │ │
|
||||
│ │ │ │ Tools: │ │ │
|
||||
│ │ │ │ ├─ query_cv │ │ │
|
||||
│ │ │ │ │ (section+query) │ │ │
|
||||
│ │ │ └──────────────────┘ │ │
|
||||
│ │ └───────────┬────────────┘ │
|
||||
│ │ │ │
|
||||
│ ┌──────▼─────────────────────────▼──────────┐ │
|
||||
│ │ POST /api/chat │ │
|
||||
│ │ (chat.Handler) │ │
|
||||
│ │ ├─ Session management │ │
|
||||
│ │ ├─ ADK Runner execution │ │
|
||||
│ │ └─ HTML fragment response (HTMX) │ │
|
||||
│ └────────────────────────────────────────────┘ │
|
||||
│ ▲ │
|
||||
│ │ hx-post │
|
||||
│ ┌──────────────────────┴─────────────────────┐ │
|
||||
│ │ Chat Widget (HTMX + Hyperscript) │ │
|
||||
│ │ ├─ Floating chat icon │ │
|
||||
│ │ ├─ Expandable panel │ │
|
||||
│ │ ├─ Message history │ │
|
||||
│ │ └─ Session persistence │ │
|
||||
│ └────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Gemini 2.5 Flash │
|
||||
│ (Google AI) │
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
### 1. Agent Definition (`internal/chat/agent.go`)
|
||||
|
||||
A single LLM agent (`cv_assistant`) with one tool (`query_cv`):
|
||||
|
||||
```go
|
||||
llmagent.New(llmagent.Config{
|
||||
Name: "cv_assistant",
|
||||
Model: llm,
|
||||
Instruction: `You answer questions about the CV owner's experience,
|
||||
projects, skills, education, and career.
|
||||
Use the query_cv tool to look up CV data before answering.
|
||||
Answer in the SAME LANGUAGE the user writes in.`,
|
||||
Tools: []tool.Tool{queryTool},
|
||||
})
|
||||
```
|
||||
|
||||
**Why a single agent?** The CV data is structured and bounded — there's no need for multi-agent orchestration. One agent with one tool is the right abstraction: simple, fast, predictable.
|
||||
|
||||
### 2. The `query_cv` Tool
|
||||
|
||||
The tool accepts two parameters:
|
||||
- **`section`** — which CV section to search: `experience`, `projects`, `skills`, `education`, `languages`, `certifications`, `courses`, `awards`, `summary`, or `all`
|
||||
- **`query`** — keyword filter (e.g., "Go", "React", "2019", "Olympic")
|
||||
|
||||
The tool reads from the same `cache.DataCache` that powers the website rendering — zero additional I/O, zero data duplication.
|
||||
|
||||
**Filtering logic:** Case-insensitive keyword matching across all relevant fields in each section (title, company, technologies, descriptions, responsibilities).
|
||||
|
||||
### 3. HTTP Handler (`internal/chat/handler.go`)
|
||||
|
||||
```
|
||||
POST /api/chat
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
message=How many Go projects has Juan built?
|
||||
session_id=<optional, auto-assigned>
|
||||
```
|
||||
|
||||
**Response:** HTML fragment for HTMX swap:
|
||||
```html
|
||||
<div class="chat-message chat-user">How many Go projects has Juan built?</div>
|
||||
<div class="chat-message chat-agent">
|
||||
<p>Juan has built 2 projects that use Go:</p>
|
||||
<ul>
|
||||
<li>Immich Photo Manager - AI-Powered Photo Library MCP Server</li>
|
||||
<li>Cmux Resurrect - Terminal Session Persistence Tool</li>
|
||||
</ul>
|
||||
</div>
|
||||
<input type="hidden" name="session_id" value="c06faf66-..." form="chat-form"/>
|
||||
```
|
||||
|
||||
**Session management:** ADK Go's in-memory session service maintains conversation context. The session ID is preserved via a hidden form input, enabling follow-up questions.
|
||||
|
||||
### 4. Chat Widget (HTMX + Hyperscript)
|
||||
|
||||
The UI is a floating chat panel that follows the site's existing widget pattern:
|
||||
|
||||
```html
|
||||
<!-- Toggle button -->
|
||||
<button class="fixed-btn chat-toggle-btn"
|
||||
_="on click toggle .chat-open on #chat-panel">
|
||||
<iconify-icon icon="mdi:chat-outline"></iconify-icon>
|
||||
</button>
|
||||
|
||||
<!-- Chat panel -->
|
||||
<form hx-post="/api/chat"
|
||||
hx-target="#chat-messages"
|
||||
hx-swap="beforeend scroll:#chat-messages:bottom"
|
||||
hx-indicator="#chat-spinner">
|
||||
<input type="text" name="message" />
|
||||
</form>
|
||||
```
|
||||
|
||||
**Key HTMX attributes:**
|
||||
- `hx-post="/api/chat"` — sends message to the agent
|
||||
- `hx-target="#chat-messages"` — appends response to chat history
|
||||
- `hx-swap="beforeend scroll:bottom"` — auto-scrolls to latest message
|
||||
- `hx-indicator="#chat-spinner"` — shows loading spinner during request
|
||||
|
||||
## Graceful Degradation
|
||||
|
||||
The chat feature is entirely optional. When `GOOGLE_API_KEY` is not set:
|
||||
|
||||
1. `chat.NewHandler()` returns a disabled handler
|
||||
2. `CVHandler` receives `chatEnabled: false`
|
||||
3. Template data includes `ChatEnabled: false`
|
||||
4. The chat widget template renders nothing (`{{if .ChatEnabled}}...{{end}}`)
|
||||
5. No JavaScript errors, no broken UI, no hidden network requests
|
||||
|
||||
**Zero impact on the site when disabled.**
|
||||
|
||||
## Configuration
|
||||
|
||||
### Required
|
||||
|
||||
```bash
|
||||
# .env
|
||||
GOOGLE_API_KEY=your-gemini-api-key # From https://aistudio.google.com/apikey
|
||||
```
|
||||
|
||||
### Optional
|
||||
|
||||
```bash
|
||||
MODEL_NAME=gemini-2.5-flash # Default model (free tier)
|
||||
```
|
||||
|
||||
### Cost
|
||||
|
||||
Gemini 2.5 Flash free tier: **15 requests/minute**, no credit card needed. Each chat message = 1 request. For a personal CV site, this is more than sufficient.
|
||||
|
||||
## Example Conversations
|
||||
|
||||
### English
|
||||
|
||||
| Question | Answer |
|
||||
|----------|--------|
|
||||
| "How many years of experience?" | "Juan has 21 years of professional experience, starting in April 2005." |
|
||||
| "What Go projects has he built?" | Lists Immich Photo Manager and Cmux Resurrect with descriptions |
|
||||
| "Has he worked with React?" | Lists companies where React was used (Olympic Broadcasting, LIV Golf, etc.) |
|
||||
| "Tell me about his time at SAP" | Pulls SAP experience entry with responsibilities and technologies |
|
||||
| "What certifications does he have?" | Lists SAP CDC Full Training, SAP Cloud Platform, GDPR Compliance |
|
||||
|
||||
### Spanish
|
||||
|
||||
| Pregunta | Respuesta |
|
||||
|----------|-----------|
|
||||
| "¿En cuántas empresas ha trabajado?" | Lista las 11 empresas con nombres |
|
||||
| "¿Qué tecnologías domina?" | Categorías de skills con proficiency levels |
|
||||
| "¿Tiene experiencia con autenticación?" | Detalla SAP CDC, Gigya, sistemas de auth |
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
internal/chat/
|
||||
├── agent.go # LLM agent + query_cv tool + filter helpers
|
||||
└── handler.go # HTTP handler + session management + response rendering
|
||||
|
||||
templates/partials/widgets/
|
||||
└── chat-widget.html # HTMX chat panel template
|
||||
|
||||
static/css/04-interactive/
|
||||
└── _chat.css # Chat UI styles (responsive, dark theme)
|
||||
```
|
||||
|
||||
## Dependencies Added
|
||||
|
||||
| Package | Purpose | Size Impact |
|
||||
|---------|---------|-------------|
|
||||
| `google.golang.org/adk` | Agent framework (runner, session, tools) | ~2 MB binary increase |
|
||||
| `google.golang.org/genai` | Gemini API client | Included with ADK |
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- **No personal data exposure:** The agent instruction explicitly prohibits revealing email, phone, or other contact details — it directs visitors to the contact form instead
|
||||
- **Input sanitization:** User messages are HTML-escaped before rendering
|
||||
- **Response sanitization:** Agent responses go through `formatResponse()` which escapes HTML then applies safe markdown-to-HTML conversion
|
||||
- **Rate limiting:** The `/api/chat` endpoint inherits the site's middleware chain (recovery, logging, security headers)
|
||||
- **Session isolation:** Each visitor gets an independent in-memory session; sessions are ephemeral and not persisted to disk
|
||||
|
||||
## ADK Go Concepts Used
|
||||
|
||||
| Concept | Usage |
|
||||
|---------|-------|
|
||||
| `llmagent.New` | Creates the CV assistant agent with instruction and tools |
|
||||
| `functiontool.New` | Wraps the `query_cv` Go function as an agent-callable tool |
|
||||
| `runner.Runner` | Executes the agent within the HTTP handler |
|
||||
| `session.InMemoryService` | Maintains conversation context per visitor |
|
||||
| `genai.NewContentFromText` | Converts user message to ADK content format |
|
||||
| `event.IsFinalResponse()` | Extracts the agent's final answer from the event stream |
|
||||
| `agent.RunConfig{}` | Default run configuration (non-streaming) |
|
||||
|
||||
## Relation to Other Documentation
|
||||
|
||||
- **[01-ARCHITECTURE.md](01-ARCHITECTURE.md)** — Overall system design
|
||||
- **[03-API.md](03-API.md)** — HTTP API reference (includes `/api/chat`)
|
||||
- **[14-BACKEND-HANDLERS.md](14-BACKEND-HANDLERS.md)** — Handler patterns
|
||||
- **[23-DATA-CACHE.md](23-DATA-CACHE.md)** — How CV data is cached and accessed
|
||||
Reference in New Issue
Block a user