You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
title: "Building Production AI Agents with GAIA SDK"
description: "Medical Intake Agent Demo - From Concept to Production in Minutes"
duration: "15 minutes"
audience: "Technical"
Building Production AI Agents with GAIA SDK
Medical Intake Agent: From Concept to Production in Minutes
The Problem: Manual Data Entry at Scale
The Manual Process Pain Points
Task
Time
Friction
Locate each field on paper
2-3 min
Scanning, cross-referencing
Type patient demographics
3-4 min
Tab between 20+ fields
Transcribe medical history
2-3 min
Handwriting interpretation
Enter insurance details
2-3 min
Policy numbers, group IDs
Total per form
8-12 min
High cognitive load
**Key Insight:** This isn't a technology problem Sarah can solve. She needs the paper forms for compliance. She needs the EMR for billing. The gap is the transcription.
The Solution: Build It in 50 Lines with GAIA SDK
The GAIA SDK makes building production-grade AI agents trivial.
fromgaia.agents.baseimportAgentfromgaia.agents.base.toolsimporttoolfromgaia.databaseimportDatabaseMixinfromgaia.utilsimportFileWatcherMixinclassMedicalIntakeAgent(Agent, DatabaseMixin, FileWatcherMixin):
"""Agent that processes intake forms automatically."""def__init__(self, watch_dir="./intake_forms", db_path="./patients.db"):
super().__init__()
self.init_database(db_path, schema=PATIENT_SCHEMA)
self.start_watching(watch_dir, patterns=["*.png", "*.jpg", "*.pdf"])
def_on_file_created(self, path):
"""Triggered automatically when new file appears."""data=self._extract_with_vlm(path) # VLM extractionself._store_patient(data) # Save to database@tooldefsearch_patients(self, query: str) ->dict:
"""Search patients by name, DOB, allergies, etc."""returnself.query("SELECT * FROM patients WHERE ...")
That's it. GAIA handles file watching, VLM integration, database ops, and tool calling.
@tooldefsearch_patients(self, query: str, limit: int=10) ->dict:
"""Search for patients by name, DOB, or other fields."""results=self.query(
"SELECT * FROM patients WHERE last_name LIKE :q LIMIT :limit",
{"q": f"%{query}%", "limit": limit}
)
return {"count": len(results), "patients": results}
The decorator automatically:
Generates JSON schema from type hints
Registers with agent's tool registry
Validates arguments
Handles errors gracefully
Example natural language query:
User: "Show me patients with penicillin allergies"
LLM: → Calls search_patients(query="penicillin")
Agent: → Returns 3 matching patients
LLM: → "I found 3 patients with penicillin allergies..."
The 7-Step VLM Pipeline
The Code Behind Each Step
def_on_file_created(self, path: Path):
"""FileWatcherMixin auto-calls this when file appears."""# Step 1: Read file (with retry for file locking)file_content=self._read_file_with_retry(path)
# Step 2: Duplicate check via hashfile_hash=compute_file_hash(file_content)
ifself._is_duplicate(file_hash):
return# Skip processing# Step 3: Image optimizationoptimized_image=self._optimize_image(file_content)
# Step 4-5: VLM extraction (lazy loads model on first use)extracted_data=self._extract_with_vlm(optimized_image)
# Step 6: Parse & validate JSONpatient_data=self._parse_and_validate(extracted_data)
# Step 7: Save via DatabaseMixinpatient_id=self._store_patient(patient_data)
self._create_alerts(patient_id, patient_data)
Step
Time
GAIA SDK Component
1-2
~2s
compute_file_hash() util
3
~1s
PIL + image utils
4
0s
Lazy VLMClient init
5
10-15s
Lemonade VLM inference
6-7
~1s
DatabaseMixin.query()
Total
~14-18s
vs. 8-12 min manual
Image Optimization: Why It Matters
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#ED1C24', 'primaryTextColor':'#fff', 'primaryBorderColor':'#C8171E', 'lineColor':'#F4484D', 'fontFamily': 'system-ui, -apple-system, sans-serif'}}}%%
flowchart TD
A[/"Raw Image (4000x3000)"/] --> B(["EXIF Auto-Rotate"])
B --> C(["Resize to 1024px Max"])
C --> D(["Pad to Square"])
D --> E[/"Optimized JPEG (85%)"/]
style A fill:#f8f9fa,stroke:#dee2e6,stroke-width:2px,color:#495057
style B fill:#F4484D,stroke:#ED1C24,stroke-width:2px,color:#fff
style C fill:#ED1C24,stroke:#C8171E,stroke-width:2px,color:#fff
style D fill:#F4484D,stroke:#ED1C24,stroke-width:2px,color:#fff
style E fill:#28a745,stroke:#1e7e34,stroke-width:2px,color:#fff
linkStyle 0,1,2,3 stroke:#ED1C24,stroke-width:2px
Loading
Token Budget
Component
Tokens
Notes
Image (1024x1024)
~5,000
14x14 pixel patches
Extraction prompt
~400
50+ field definitions
JSON output
~800
Filled form data
Total
~6,200
Fits in 8K context
VLM Integration: GAIA's VLMClient
The GAIA SDK provides a unified VLM client abstraction:
fromgaia.llm.vlm_clientimportVLMClientclassMedicalIntakeAgent(Agent):
def__init__(self, vlm_model="Qwen3-VL-4B-Instruct-GGUF"):
super().__init__()
self._vlm_model=vlm_modelself._vlm=None# Lazy load on first usedef_extract_with_vlm(self, image_path: Path) ->dict:
# Lazy initialize VLM (expensive operation)ifself._vlmisNone:
self._vlm=VLMClient(model=self._vlm_model)
# Optimize image (handled by GAIA utils)optimized=self._optimize_image(image_path)
# Call VLM with structured promptresponse=self._vlm.process(
image=optimized,
prompt=EXTRACTION_PROMPT,
max_tokens=2048
)
# Parse JSON from VLM responsereturnextract_json_from_text(response)
What GAIA handles for you:
Model loading and caching
Connection to Lemonade Server
Error recovery and retry logic
Image token counting
JSON extraction from free-form text
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#ED1C24', 'primaryTextColor':'#fff', 'primaryBorderColor':'#C8171E', 'lineColor':'#F4484D', 'fontFamily': 'system-ui, -apple-system, sans-serif'}}}%%
flowchart LR
A[/"Intake Form"/] --> B["VLMClient.process()"]
B <-->|"REST API"| C["Lemonade Server<br/>Qwen3-VL-4B"]
C --> D["Structured JSON"]
style A fill:#f8f9fa,stroke:#dee2e6,stroke-width:2px,color:#495057
style B fill:#ED1C24,stroke:#C8171E,stroke-width:3px,color:#fff
style C fill:#ED1C24,stroke:#C8171E,stroke-width:2px,color:#fff
style D fill:#28a745,stroke:#1e7e34,stroke-width:2px,color:#fff
linkStyle 0,1,2 stroke:#ED1C24,stroke-width:2px
Loading
The Extraction Prompt (Excerpt)
You are a medical data extraction system. Extract ALL patient
information from this intake form image.
Return a JSON object with ALL fields you can extract:
REQUIRED:
- "first_name": patient's first name
- "last_name": patient's last name
PATIENT INFO:
- "date_of_birth": YYYY-MM-DD format
- "gender": Male/Female/Other
- "ssn": Social Security Number (XXX-XX-XXXX)
- "phone", "mobile_phone", "email"
- "address", "city", "state", "zip_code"
EMERGENCY CONTACT:
- "emergency_contact_name"
- "emergency_contact_relationship"
- "emergency_contact_phone"
PRIMARY INSURANCE:
- "insurance_provider": insurance company name
- "insurance_id": policy number
- "insurance_group_number"
MEDICAL HISTORY:
- "reason_for_visit": chief complaint
- "allergies": known allergies
- "medications": current medications
IMPORTANT:
- Return ONLY the JSON object, no other text
- Use null for fields that exist but are blank
- Dates must be in YYYY-MM-DD format
34 fields extracted in 14.2 seconds from a single scanned image.
What Makes VLM Different from OCR?
Traditional OCR
Vision Language Model
Extracts text blobs
Extracts structured data
Needs template zones
Handles any form layout
Fails on handwriting
Interprets context
No semantic understanding
Knows "DOB" = date of birth
Database Schema: Flexible by Design
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#ED1C24', 'primaryTextColor':'#fff', 'primaryBorderColor':'#C8171E', 'lineColor':'#F4484D', 'fontFamily': 'system-ui, -apple-system, sans-serif'}}}%%
erDiagram
PATIENTS ||--o{ ALERTS : has
PATIENTS ||--o{ INTAKE_SESSIONS : has
PATIENTS {
int id PK
text first_name
text last_name
text date_of_birth
text phone
text email
text insurance_provider
text allergies
text medications
text additional_fields
blob file_content
text file_hash UK
}
ALERTS {
int id PK
int patient_id FK
text alert_type
text message
int acknowledged
}
INTAKE_SESSIONS {
int id PK
int patient_id FK
int is_new_patient
real processing_time_seconds
text changes_detected
}
Loading
Returning Patient Detection: Simple SQL
No embeddings needed - straightforward SQL matching works reliably.
def_find_existing_patient(self, data: dict) ->Optional[dict]:
"""Check if patient already exists via DatabaseMixin."""# Strategy 1: Match on name + DOB (most reliable)ifdata.get("date_of_birth"):
results=self.query(
"""SELECT * FROM patients WHERE first_name = :fn AND last_name = :ln AND date_of_birth = :dob ORDER BY created_at DESC LIMIT 1""",
{"fn": data["first_name"],
"ln": data["last_name"],
"dob": data["date_of_birth"]}
)
ifresults:
returnresults[0]
# Strategy 2: Fallback to name-onlyresults=self.query(
"SELECT * FROM patients WHERE first_name = :fn AND last_name = :ln",
{"fn": data["first_name"], "ln": data["last_name"]}
)
returnresults[0] ifresultselseNone
# Mix and match components for your use casefromgaia.agents.baseimportAgentfromgaia.agents.base.toolsimporttool# Mixins (add capabilities via inheritance)fromgaia.databaseimportDatabaseMixinfromgaia.utilsimportFileWatcherMixinfromgaia.ragimportRAGToolsMixinfromgaia.shellimportCLIToolsMixin# Clients (call AI models)fromgaia.llmimportLLMClientfromgaia.llm.vlm_clientimportVLMClientfromgaia.audioimportWhisperASR, KokoroTTS
# Install GAIA SDK
pip install amd-gaia
# Install Lemonade Server
pip install lemonade-server
# Download models for this demo
gaia-emr init
Build Your First Agent (5 Steps)
# 1. Import GAIA componentsfromgaia.agents.baseimportAgentfromgaia.agents.base.toolsimporttoolfromgaia.databaseimportDatabaseMixin# 2. Define your agent classclassMyAgent(Agent, DatabaseMixin):
def__init__(self):
super().__init__()
self.init_database("my_data.db", schema=MY_SCHEMA)
# 3. Add tools with the decorator@tooldefmy_tool(self, param: str) ->dict:
"""Your custom business logic."""returnself.query("SELECT ...")
# 4. Instantiate and runagent=MyAgent()
# 5. Query with natural languageresponse=agent.process_query("Find all records from today")
Q&A
SDK Questions
Q: Can I use other models besides Qwen?
A: Yes - GAIA works with any GGUF model via Lemonade, or cloud APIs (OpenAI, Anthropic, etc.)
Q: Does it work on non-AMD hardware?
A: Yes - CPU-only mode works everywhere. AMD NPU/GPU provides 5-10x speedup.
Q: What's the learning curve?
A: If you know Python and basic SQL, you can build agents in an afternoon.
Q: Can I deploy this in production?
A: Yes - includes Docker support, API server, monitoring, and audit trails.
EMR-Specific Questions
Q: What form layouts does it support?
A: Any medical intake form. VLMs understand context, not templates.
Q: How do I integrate with Epic/Cerner?
A: Use the REST API or sync the SQLite database via your EMR's integration API.
title: "Building Production AI Agents with GAIA SDK"
description: "Medical Intake Agent Demo - From Concept to Production in Minutes"
duration: "15 minutes"
audience: "Technical"
Building Production AI Agents with GAIA SDK
Medical Intake Agent: From Concept to Production in Minutes
The Problem: Manual Data Entry at Scale
The Manual Process Pain Points
The Solution: Build It in 50 Lines with GAIA SDK
The GAIA SDK makes building production-grade AI agents trivial.
That's it. GAIA handles file watching, VLM integration, database ops, and tool calling.
What GAIA SDK Provides
Pre-Built Components
What This Means
Architecture: Agent + Mixins + Tools
Full System Architecture
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#ED1C24', 'primaryTextColor':'#fff', 'primaryBorderColor':'#C8171E', 'lineColor':'#F4484D', 'fontFamily': 'system-ui, -apple-system, sans-serif'}}}%% flowchart TD subgraph Lemonade["Lemonade Server (AMD Ryzen AI NPU/GPU)"] L1(["Qwen3-VL-4B<br/>Vision Model"]) L2(["Qwen3-Coder-30B<br/>Language Model"]) end Lemonade <-.->|"Local REST API"| Pipeline subgraph Pipeline["GAIA Medical Intake Agent"] FW[/"FileWatcherMixin<br/>Monitors ./intake_forms"/] -->|"New file"| P1 P1["1. File Read<br/>(retry logic)"] --> P2["2. Duplicate Check<br/>(SHA-256 hash)"] P2 --> P3["3. Image Optimize<br/>(resize, compress)"] P3 --> P4["4. VLM Extraction<br/>(call Lemonade)"] P4 --> P5["5. JSON Parse<br/>(validate fields)"] P5 --> P6["6. Patient Match<br/>(SQL queries)"] P6 --> P7[("7. Database Save<br/>(SQLite)")] end P7 --> Dashboard[/"Dashboard UI<br/>(Real-time SSE)"/] style FW fill:#F4484D,stroke:#ED1C24,stroke-width:3px,color:#fff style P1 fill:#f8f9fa,stroke:#dee2e6,stroke-width:2px,color:#495057 style P2 fill:#f8f9fa,stroke:#dee2e6,stroke-width:2px,color:#495057 style P3 fill:#F4484D,stroke:#ED1C24,stroke-width:2px,color:#fff style P4 fill:#ED1C24,stroke:#C8171E,stroke-width:2px,color:#fff style P5 fill:#F4484D,stroke:#ED1C24,stroke-width:2px,color:#fff style P6 fill:#F4484D,stroke:#ED1C24,stroke-width:2px,color:#fff style P7 fill:#6c757d,stroke:#495057,stroke-width:2px,color:#fff style Dashboard fill:#28a745,stroke:#1e7e34,stroke-width:2px,color:#fff style L1 fill:#ED1C24,stroke:#C8171E,stroke-width:2px,color:#fff style L2 fill:#ED1C24,stroke:#C8171E,stroke-width:2px,color:#fff style Lemonade fill:none,stroke:#666,stroke-width:2px,stroke-dasharray: 5 5 style Pipeline fill:none,stroke:#ED1C24,stroke-width:3px,stroke-dasharray: 5 5 linkStyle 0,1,2,3,4,5,6,7,8,9 stroke:#ED1C24,stroke-width:2pxThree main components:
GAIA SDK Value Proposition
self._vlm.process(image)FileWatcherMixinDatabaseMixin@tooldecoratorTime to Production: Hours, not weeks.
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#ED1C24', 'primaryTextColor':'#fff', 'primaryBorderColor':'#C8171E', 'lineColor':'#F4484D', 'fontFamily': 'system-ui, -apple-system, sans-serif'}}}%% flowchart LR Form[/"📄 Intake Form"/] --> FW["FileWatcherMixin<br/>Auto-detects file"] FW -->|"Triggers"| Agent["MedicalIntakeAgent"] Agent --> Tools subgraph Tools["Agent Tools"] T1["@tool extract_form()"] T2["@tool save_patient()"] T3["@tool search_patients()"] end T1 <-->|"VLM API"| VLM["Lemonade<br/>Qwen3-VL-4B"] T2 --> DB["DatabaseMixin<br/>SQLite"] T3 --> DB DB --> UI[/"Dashboard"/] style FW fill:#F4484D,stroke:#ED1C24,stroke-width:3px,color:#fff style Agent fill:#ED1C24,stroke:#C8171E,stroke-width:3px,color:#fff style T1 fill:#28a745,stroke:#1e7e34,stroke-width:2px,color:#fff style T2 fill:#28a745,stroke:#1e7e34,stroke-width:2px,color:#fff style T3 fill:#28a745,stroke:#1e7e34,stroke-width:2px,color:#fff style VLM fill:#ED1C24,stroke:#C8171E,stroke-width:2px,color:#fff style DB fill:#6c757d,stroke:#495057,stroke-width:2px,color:#fff style Tools fill:none,stroke:#28a745,stroke-width:2px,stroke-dasharray: 5 5 linkStyle 0,1,2,3,4,5,6,7 stroke:#ED1C24,stroke-width:2pxKey: FileWatcher triggers Agent → Agent calls Tools → Tools use Lemonade VLM & Database
The Agent Pattern: Composition Over Configuration
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#ED1C24', 'primaryTextColor':'#fff', 'primaryBorderColor':'#C8171E', 'lineColor':'#F4484D', 'fontFamily': 'system-ui, -apple-system, sans-serif'}}}%% flowchart TD subgraph AgentClass["MedicalIntakeAgent Class"] Base["Agent (Base Class)"] DB["DatabaseMixin"] FW["FileWatcherMixin"] Base --> Methods DB --> Methods FW --> Methods Methods["Core Methods:<br/>_on_file_created()<br/>_extract_with_vlm()<br/>_find_existing_patient()"] end Methods --> Tools["Registered Tools"] subgraph Tools T1["@tool search_patients()"] T2["@tool get_patient()"] T3["@tool get_intake_stats()"] end FW -->|"File detected"| Trigger["Auto-triggers<br/>_on_file_created()"] Trigger --> VLM["Call Lemonade<br/>VLM API"] VLM --> Parse["Parse JSON<br/>& Validate"] Parse --> DB2["DatabaseMixin<br/>save to SQLite"] Tools --> LLM["Natural Language<br/>Queries via LLM"] style Base fill:#ED1C24,stroke:#C8171E,stroke-width:2px,color:#fff style DB fill:#F4484D,stroke:#ED1C24,stroke-width:2px,color:#fff style FW fill:#F4484D,stroke:#ED1C24,stroke-width:2px,color:#fff style Methods fill:#6c757d,stroke:#495057,stroke-width:2px,color:#fff style T1 fill:#28a745,stroke:#1e7e34,stroke-width:2px,color:#fff style T2 fill:#28a745,stroke:#1e7e34,stroke-width:2px,color:#fff style T3 fill:#28a745,stroke:#1e7e34,stroke-width:2px,color:#fff style AgentClass fill:none,stroke:#ED1C24,stroke-width:3px,stroke-dasharray: 5 5 linkStyle 0,1,2,3,4,5,6,7,8,9 stroke:#ED1C24,stroke-width:2pxKey Architecture Decisions:
@tooldecorator automatically exposes to LLM_on_file_created()automaticallyKey Pattern 1: FileWatcherMixin
Problem: Monitor directories for new files with retry logic and debouncing.
Without GAIA (50+ lines):
With GAIA (3 lines):
Built-in features:
Key Pattern 2: DatabaseMixin
Problem: Persistent storage with connection pooling and SQL safety.
Without GAIA (100+ lines):
With GAIA (5 lines):
Built-in features:
Key Pattern 3: @tool Decorator
Problem: Expose Python functions to LLM for tool calling.
Without GAIA (50+ lines per tool):
With GAIA (decorator magic):
The decorator automatically:
Example natural language query:
The 7-Step VLM Pipeline
The Code Behind Each Step
compute_file_hash()utilDatabaseMixin.query()Image Optimization: Why It Matters
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#ED1C24', 'primaryTextColor':'#fff', 'primaryBorderColor':'#C8171E', 'lineColor':'#F4484D', 'fontFamily': 'system-ui, -apple-system, sans-serif'}}}%% flowchart TD A[/"Raw Image (4000x3000)"/] --> B(["EXIF Auto-Rotate"]) B --> C(["Resize to 1024px Max"]) C --> D(["Pad to Square"]) D --> E[/"Optimized JPEG (85%)"/] style A fill:#f8f9fa,stroke:#dee2e6,stroke-width:2px,color:#495057 style B fill:#F4484D,stroke:#ED1C24,stroke-width:2px,color:#fff style C fill:#ED1C24,stroke:#C8171E,stroke-width:2px,color:#fff style D fill:#F4484D,stroke:#ED1C24,stroke-width:2px,color:#fff style E fill:#28a745,stroke:#1e7e34,stroke-width:2px,color:#fff linkStyle 0,1,2,3 stroke:#ED1C24,stroke-width:2pxToken Budget
VLM Integration: GAIA's VLMClient
The GAIA SDK provides a unified VLM client abstraction:
What GAIA handles for you:
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#ED1C24', 'primaryTextColor':'#fff', 'primaryBorderColor':'#C8171E', 'lineColor':'#F4484D', 'fontFamily': 'system-ui, -apple-system, sans-serif'}}}%% flowchart LR A[/"Intake Form"/] --> B["VLMClient.process()"] B <-->|"REST API"| C["Lemonade Server<br/>Qwen3-VL-4B"] C --> D["Structured JSON"] style A fill:#f8f9fa,stroke:#dee2e6,stroke-width:2px,color:#495057 style B fill:#ED1C24,stroke:#C8171E,stroke-width:3px,color:#fff style C fill:#ED1C24,stroke:#C8171E,stroke-width:2px,color:#fff style D fill:#28a745,stroke:#1e7e34,stroke-width:2px,color:#fff linkStyle 0,1,2 stroke:#ED1C24,stroke-width:2pxThe Extraction Prompt (Excerpt)
Example VLM Output
{ "first_name": "Alice", "last_name": "Williams", "date_of_birth": "1980-04-04", "gender": "Female", "phone": "(411) 413-1234", "mobile_phone": "(411) 555-7890", "email": "alice.williams@hotmail.com", "address": "123 Oak Street", "city": "Springfield", "state": "IL", "zip_code": "62701", "emergency_contact_name": "Robert Williams", "emergency_contact_relationship": "Spouse", "emergency_contact_phone": "(411) 413-5678", "insurance_provider": "Medicaid Demo", "insurance_id": "MCD-2024-87654", "insurance_group_number": "GRP-IL-001", "reason_for_visit": "Lower back pain for 3 weeks", "allergies": "Penicillin, Sulfa drugs", "medications": "Lisinopril 10mg daily, Metformin 500mg", "marital_status": "Married", "employment_status": "Employed", "employer": "Springfield Elementary School", "signature_date": "2024-01-15" }34 fields extracted in 14.2 seconds from a single scanned image.
What Makes VLM Different from OCR?
Database Schema: Flexible by Design
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#ED1C24', 'primaryTextColor':'#fff', 'primaryBorderColor':'#C8171E', 'lineColor':'#F4484D', 'fontFamily': 'system-ui, -apple-system, sans-serif'}}}%% erDiagram PATIENTS ||--o{ ALERTS : has PATIENTS ||--o{ INTAKE_SESSIONS : has PATIENTS { int id PK text first_name text last_name text date_of_birth text phone text email text insurance_provider text allergies text medications text additional_fields blob file_content text file_hash UK } ALERTS { int id PK int patient_id FK text alert_type text message int acknowledged } INTAKE_SESSIONS { int id PK int patient_id FK int is_new_patient real processing_time_seconds text changes_detected }Returning Patient Detection: Simple SQL
No embeddings needed - straightforward SQL matching works reliably.
Detects changes automatically:
Tool Calling: Exposing Agent Functions to LLM
The @tool Decorator Pattern
How It Works
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#ED1C24', 'primaryTextColor':'#fff', 'primaryBorderColor':'#C8171E', 'lineColor':'#F4484D', 'fontFamily': 'system-ui, -apple-system, sans-serif'}}}%% sequenceDiagram participant User participant Agent as MedicalIntakeAgent participant LLM as Lemonade (Qwen3-Coder) participant Tool as @tool search_patients() participant DB as DatabaseMixin User->>Agent: "Which patients have allergies?" Agent->>LLM: Send query + tool schemas LLM->>Agent: tool_call: search_patients(query="allergy") Agent->>Tool: Execute function Tool->>DB: Parameterized SQL query DB-->>Tool: [Alice, Bob, Charlie] Tool-->>Agent: Formatted results Agent->>LLM: Tool results LLM-->>User: "Found 3 patients with allergies..."Safety: LLM never writes raw SQL. It calls predefined tools with validated parameters.
Demo: Live Walkthrough
Step 1: Launch the Dashboard
Step 2: Drop a Form
./intake_forms/)Step 3: Explore the Data
Step 4: Query with Natural Language
Video Demo
Watch the EMR Agent in action - from file drop to extracted patient data in under 20 seconds:
<video
controls
className="w-full aspect-video"
src="https://assets.amd-gaia.ai/videos/gaia-emr-agent-demo.webm"
Full end-to-end demonstration showing real-time processing, dashboard updates, and patient record extraction.
The Complete Agent: Putting It Together
Lines of code comparison:
Time Savings: Development + Operational ROI
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#ED1C24', 'primaryTextColor':'#fff', 'primaryBorderColor':'#C8171E', 'lineColor':'#F4484D', 'fontFamily': 'system-ui, -apple-system, sans-serif'}}}%% pie showData title "Time per Form" "Manual Entry" : 600 "AI Agent" : 15Operational ROI
Development ROI
The GAIA + Lemonade Stack
Why Local AI Matters
The AMD Advantage
Lemonade Server = AMD's local inference engine optimized for Ryzen AI
GAIA SDK = Framework for building agents on top of Lemonade
Beyond EMR: The Same Patterns Apply
GAIA SDK Component Library
Example: Other Agent Patterns
Same SDK, endless applications.
Why Choose GAIA SDK?
The Value Proposition
Rapid Development
Best Practices Built-In
Local-First Architecture
AMD Hardware Optimized
Extensible & Composable
Key Takeaways
What We Demonstrated
Agent Pattern
Agentbase classFileWatcherMixin
DatabaseMixin
@tool Decorator
VLMClient
The GAIA Value Proposition
Build production-grade AI agents in hours, not weeks:
Getting Started with GAIA SDK
Installation
Build Your First Agent (5 Steps)
Q&A
SDK Questions
Q: Can I use other models besides Qwen?
A: Yes - GAIA works with any GGUF model via Lemonade, or cloud APIs (OpenAI, Anthropic, etc.)
Q: Does it work on non-AMD hardware?
A: Yes - CPU-only mode works everywhere. AMD NPU/GPU provides 5-10x speedup.
Q: What's the learning curve?
A: If you know Python and basic SQL, you can build agents in an afternoon.
Q: Can I deploy this in production?
A: Yes - includes Docker support, API server, monitoring, and audit trails.
EMR-Specific Questions
Q: What form layouts does it support?
A: Any medical intake form. VLMs understand context, not templates.
Q: How do I integrate with Epic/Cerner?
A: Use the REST API or sync the SQLite database via your EMR's integration API.
Resources
Get Started with GAIA SDK
EMR Agent Specifics
Installation
Community
License: MIT · Copyright (C) 2024-2025 Advanced Micro Devices, Inc.