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:
juanatsap
2026-04-08 00:30:01 +01:00
parent f5276431ea
commit f67126e8c3
3 changed files with 292 additions and 4 deletions
+55 -4
View File
@@ -1,7 +1,9 @@
# CV Site - Go + HTMX # CV Site - Go + HTMX
[![Go Version](https://img.shields.io/badge/Go-1.21%2B-00ADD8?logo=go)](https://go.dev/) [![Go Version](https://img.shields.io/badge/Go-1.25%2B-00ADD8?logo=go)](https://go.dev/)
[![HTMX](https://img.shields.io/badge/HTMX-1.9.10-3366CC)](https://htmx.org/) [![HTMX](https://img.shields.io/badge/HTMX-2.0-3366CC)](https://htmx.org/)
[![ADK Go](https://img.shields.io/badge/ADK_Go-1.0-4285F4?logo=google)](https://github.com/google/adk-go)
[![Gemini](https://img.shields.io/badge/Gemini_2.5_Flash-AI_Chat-8E75B2?logo=google)](https://aistudio.google.com/)
[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) [![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
**Modern, minimal curriculum vitae website** for Juan Andrés Moreno Rubio built with **Go** and **HTMX**. **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 ## 📑 Table of Contents
- [Features](#-features) - [Features](#-features)
- [AI Chat Agent](#-ai-chat-agent)
- [Demo](#-demo) - [Demo](#-demo)
- [Security](#-security) - [Security](#-security)
- [Quick Start](#-quick-start) - [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 -**Zoom Control** - Adjustable zoom (25%-300%) with persistence across sessions
-**Responsive** - Mobile, tablet, and desktop friendly -**Responsive** - Mobile, tablet, and desktop friendly
-**JSON-Based Content** - Easy to update without touching code -**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 -**AI Development Section** - Showcases modern AI-assisted development skills
-**Fast & Lightweight** - Go backend with chromedp for PDF generation -**Fast & Lightweight** - Go backend with chromedp for PDF generation
-**Privacy-Friendly Analytics** - Self-hosted analytics (no third-party data sharing) -**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 -**Production Ready** - Systemd service, CI/CD workflows, deployment guides
-**Developer Friendly** - Hot reload, clear code structure, comprehensive Makefile -**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 ## 📸 Demo
🔗 **Live Demo:** [https://juan.andres.morenorub.io/](https://juan.andres.morenorub.io/) 🔗 **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 ## 🎯 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) - **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 - **Styling:** Custom CSS with Quicksand font from Google Fonts
- **Data:** JSON files for easy content management - **Data:** JSON files for easy content management
- **Deployment:** Systemd service, manual binary, GitHub Actions CI/CD - **Deployment:** Systemd service, manual binary, GitHub Actions CI/CD
@@ -206,6 +255,7 @@ This project includes comprehensive documentation organized by purpose:
### 🔧 Technical Reference ### 🔧 Technical Reference
- **[ARCHITECTURE.md](doc/ARCHITECTURE.md)** - System design, patterns, and technical decisions - **[ARCHITECTURE.md](doc/ARCHITECTURE.md)** - System design, patterns, and technical decisions
- **[API.md](doc/API.md)** - Complete HTTP API reference and HTMX integration - **[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 ### 📋 Policies & Standards
- **[SECURITY.md](doc/9-SECURITY.md)** - Complete security architecture, implementation, and testing guide - **[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 ## 🙏 Acknowledgments
- **HTMX** - For making hypermedia-driven applications enjoyable - **HTMX** - For making hypermedia-driven applications enjoyable
- **Google ADK Go** - For the production-grade agent framework
- **chromedp** - For reliable headless Chrome automation - **chromedp** - For reliable headless Chrome automation
- **Go Community** - For excellent standard library and tooling - **Go Community** - For excellent standard library and tooling
- **AI Assistance** - For accelerating development and documentation - **AI Assistance** - For accelerating development and documentation
+7
View File
@@ -36,6 +36,13 @@ This documentation covers the core Go systems that power the CV site, with a foc
- Coverage gap explanations - Coverage gap explanations
- Best practices and CI/CD integration - 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 ## Quick Navigation
### By Feature ### By Feature
+230
View File
@@ -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