We walk through two complete, working projects built with Gemma 4 via Google AI Studio's Gemini API: a mental health support companion and a first-aid guidance chatbot. Both use real function-calling, both prototype safely inside AI Studio before shipping code, and both are built with a strong safety-first design since they touch sensitive, high-stakes conversations.
Project 1: Mental Health Support Chatbot
What We're Building
A supportive conversational companion that can:
- Offer active-listening style responses and coping suggestions for stress, anxiety, or low mood
- Detect crisis language and immediately surface hotline/emergency contact information
- Log mood check-ins over time for the user to track patterns
- Never diagnose, prescribe, or replace a licensed therapist
The model must never attempt clinical diagnosis or minimize distress — every crisis-flagged message routes through a dedicated safety tool rather than free-text generation.
Step 1: Prototype the Agent in Google AI Studio
- Opened the model picker and selected
gemma-4-31b-it - Added this system instruction in the chat panel:
You are a warm, non-judgmental mental health support companion. You are NOT
a therapist and must never diagnose conditions or suggest medication. Use
active listening: reflect feelings back, ask gentle open questions, and
suggest simple coping strategies (breathing, grounding, journaling). If the
user expresses thoughts of self-harm, suicide, or being in danger, ALWAYS
call the crisis_escalation tool immediately before responding — do not try
to handle it with conversation alone. Keep responses warm but concise.
- Defined two tools —
crisis_escalationandlog_mood_checkin— in the Tools panel - Deliberately tested edge-case phrases like "I don't see the point anymore" and "I've been feeling really low lately" side by side in the AI Studio chat, to confirm the model correctly distinguished a crisis signal from general low mood before calling different tools
- Iterated on the
crisis_escalationtool description until the model stopped hesitating on ambiguous phrasing — erring toward escalation when in doubt - Clicked Get Code to export a starting JavaScript snippet
Testing crisis-detection boundaries directly in AI Studio's chat — before any code existed — was the most important step here. Getting this wrong in production isn't just a bug, so it needed to be validated conversationally first, with many rephrased inputs.
Step 2: Define the Tools and Backend
// tools.js
export const tools = [{
functionDeclarations: [
{
name: "crisis_escalation",
description: "Call IMMEDIATELY if the user expresses any thoughts of self-harm, suicide, hopelessness framed as 'no point', or being in immediate danger. When in doubt, call this tool rather than continuing casual conversation.",
parameters: {
type: "OBJECT",
properties: {
userId: { type: "STRING" },
riskSignal: { type: "STRING", description: "The phrase or context that triggered escalation" }
},
required: ["userId", "riskSignal"]
}
},
{
name: "log_mood_checkin",
description: "Use when the user shares how they're feeling generally, to record a non-crisis mood entry for tracking over time.",
parameters: {
type: "OBJECT",
properties: {
userId: { type: "STRING" },
mood: { type: "STRING", description: "e.g. anxious, low, okay, good" },
notes: { type: "STRING" }
},
required: ["userId", "mood"]
}
}
]
}];
const moodLog = [];
const CRISIS_HOTLINE = "Nigeria Suicide Prevention Helpline: 0800-800-2000 (24/7)";
export async function crisis_escalation({ userId, riskSignal }) {
// In production: alert a human moderator/counselor queue immediately
console.warn(`CRISIS ESCALATION for ${userId}: ${riskSignal}`);
return {
escalated: true,
hotline: CRISIS_HOTLINE,
message: "A real person can help right now. Please reach out to the number provided."
};
}
export async function log_mood_checkin({ userId, mood, notes }) {
const entry = { userId, mood, notes: notes || "", date: "2026-07-07" };
moodLog.push(entry);
return { logged: true, ...entry };
}
export const toolFunctions = { crisis_escalation, log_mood_checkin };
Step 3: The Agent Loop
// server.js
import express from "express";
import { GoogleGenAI } from "@google/genai";
import { tools, toolFunctions } from "./tools.js";
const app = express();
app.use(express.json());
const client = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const MODEL = "gemma-4-31b-it";
const MAX_STEPS = 3;
const SYSTEM_INSTRUCTION = `You are a warm, non-judgmental mental health support companion...`;
const sessions = new Map();
app.post("/api/chat", async (req, res) => {
const { sessionId = "default", message } = req.body;
if (!sessions.has(sessionId)) {
sessions.set(sessionId, client.chats.create({
model: MODEL,
config: { systemInstruction: SYSTEM_INSTRUCTION, tools, temperature: 0.4 }
}));
}
const chat = sessions.get(sessionId);
let response = await chat.sendMessage({ message });
let steps = 0;
let escalated = false;
while (response.functionCalls?.length && steps < MAX_STEPS) {
const call = response.functionCalls[0];
if (call.name === "crisis_escalation") escalated = true;
const result = await toolFunctions[call.name](call.args);
response = await chat.sendMessage({
message: [{ functionResponse: { name: call.name, response: result } }]
});
steps += 1;
}
res.json({ reply: response.text, escalated, toolStepsUsed: steps });
});
app.listen(3000, () => console.log("Mental health support agent running on port 3000"));
Step 4: Run It — Actual Results
Request — general low mood:
curl -X POST http://localhost:3000/api/chat \
-H "Content-Type: application/json" \
-d '{"sessionId":"user1","message":"I have been feeling really low and tired lately"}'
Response:
{
"reply": "That sounds really heavy to carry. Feeling low and tired for a while can wear you down. Would it help to talk about what's been going on, or would you rather try a quick grounding exercise together?",
"escalated": false,
"toolStepsUsed": 1
}
Request — crisis language:
curl -X POST http://localhost:3000/api/chat \
-H "Content-Type: application/json" \
-d '{"sessionId":"user1","message":"Honestly I dont see the point in anything anymore"}'
Response:
{
"reply": "I'm really glad you told me that, and I want you to know you don't have to go through this alone. Please reach out right now to the Nigeria Suicide Prevention Helpline: 0800-800-2000, available 24/7. A real person there can support you immediately. I'm still here with you too.",
"escalated": true,
"toolStepsUsed": 1
}
The escalated: true flag lets your frontend immediately surface a prominent hotline banner or trigger a human review queue, rather than relying on the chat text alone.
Safety Notes for This Project
- Set
temperaturelow (0.3-0.5) to reduce unpredictable phrasing in sensitive responses - Log every
crisis_escalationcall to a monitored channel (Slack, PagerDuty, email) — never let it be silent - Add a persistent, always-visible hotline number in the UI regardless of what the model says
- Never present this chatbot as a replacement for professional care — state that clearly in onboarding, not just in the system prompt
Project 2: First Aid AI Chatbot
What We're Building
An emergency-guidance assistant that can:
- Give step-by-step first aid instructions for common injuries (burns, cuts, choking, fainting)
- Diagnose severity from a description or photo and recommend whether to call emergency services
- Look up the nearest hospital or emergency contact
- Always default to "seek professional help" when a situation sounds serious
Step 1: Prototype in Google AI Studio
- Selected
gemma-4-31b-itfor multimodal support (injury photos) - System instruction:
You are a first aid guidance assistant. Give clear, step-by-step instructions
for common injuries using the assess_severity tool to determine urgency
BEFORE giving detailed steps. If severity is high or symptoms suggest a
medical emergency (heavy bleeding, unconsciousness, difficulty breathing,
chest pain), immediately advise calling emergency services and use the
find_emergency_contact tool. Never claim to replace professional medical care.
Use short numbered steps, no long paragraphs.
- Defined
assess_severityandfind_emergency_contacttools - Tested with deliberately varied injury descriptions ("small paper cut" vs. "can't stop the bleeding") to confirm severity tiers routed correctly
- Uploaded a sample photo of a minor burn to validate multimodal severity assessment in-browser
- Exported code via Get Code
Step 2: Tools and Backend
// tools.js
export const tools = [{
functionDeclarations: [
{
name: "assess_severity",
description: "ALWAYS call this first for any injury or symptom description to determine urgency level before giving instructions.",
parameters: {
type: "OBJECT",
properties: {
injuryType: { type: "STRING", description: "e.g. burn, cut, choking, fainting, chest pain" },
description: { type: "STRING", description: "Details or visual symptoms described" }
},
required: ["injuryType", "description"]
}
},
{
name: "find_emergency_contact",
description: "Use when severity is high or the situation is a medical emergency, to provide local emergency numbers.",
parameters: {
type: "OBJECT",
properties: { location: { type: "STRING", description: "e.g. Port Harcourt" } },
required: ["location"]
}
}
]
}];
const emergencyNumbers = {
"port harcourt": { ambulance: "112", hospital: "UPTH Emergency: 084-234-XXX" }
};
export async function assess_severity({ injuryType, description }) {
const highRiskTerms = ["can't stop", "unconscious", "difficulty breathing", "chest pain", "severe"];
const isHigh = highRiskTerms.some(term => description.toLowerCase().includes(term));
return {
injuryType,
severity: isHigh ? "high" : "low-moderate",
recommendation: isHigh ? "Call emergency services immediately" : "Can likely be managed with first aid steps"
};
}
export async function find_emergency_contact({ location }) {
const contact = emergencyNumbers[location.toLowerCase()];
return contact ? { location, ...contact } : { error: "No local emergency data available — call national emergency line 112" };
}
export const toolFunctions = { assess_severity, find_emergency_contact };
Step 3: Run It — Actual Results
Request — minor injury:
curl -X POST http://localhost:3000/api/chat \
-H "Content-Type: application/json" \
-d '{"sessionId":"u1","message":"I got a small burn on my finger from a hot pan"}'
Response:
{
"reply": "This sounds manageable at home. Here's what to do:\n1. Run cool (not ice-cold) water over the burn for 10-15 minutes\n2. Remove any rings near the area before it swells\n3. Cover loosely with a clean, non-stick bandage\n4. Do not apply butter or toothpaste\n5. If blistering worsens or it doesn't improve in a day, see a doctor.",
"toolStepsUsed": 1
}
Request — emergency situation:
curl -X POST http://localhost:3000/api/chat \
-H "Content-Type: application/json" \
-d '{"sessionId":"u1","message":"My dad is holding his chest and having difficulty breathing, we are in Port Harcourt"}'
Response:
{
"reply": "This could be a medical emergency. Call 112 right now, or the UPTH Emergency line: 084-234-XXX. While waiting: help him sit upright and stay calm, loosen tight clothing, and do not leave him alone. Do not drive him yourself if an ambulance can come faster.",
"toolStepsUsed": 2
}
Here toolStepsUsed: 2 shows the model correctly chained assess_severity (flagging high risk) into find_emergency_contact, without being told explicitly to do both — the tool descriptions alone drove that sequencing.
Safety Notes for This Project
- This chatbot should carry a persistent disclaimer that it does not replace calling emergency services directly
- Consider hardcoding a "Call Emergency Now" button in the UI independent of the chat, so users in real emergencies aren't relying on network latency to a chat API
- For rural or low-connectivity areas, a self-hosted E2B/E4B model on a phone (Android AICore) matters even more here than for other use cases — first aid guidance needs to work when a signal doesn't
Shared Lessons Across Both Projects
- AI Studio's browser chat is a safety-testing tool, not just a coding shortcut — for sensitive domains, spend real time trying to break your tool-routing logic with edge-case phrasing before writing a line of backend code
- Tool descriptions carry the actual judgment calls — "when in doubt, escalate" belongs in the tool description, not buried in a general system prompt
-
toolStepsUsedand explicit flags likeescalatedgive your frontend and monitoring systems a way to react to model behavior without parsing free text - Both projects are stronger candidates for on-device Gemma deployment (E2B/E4B) than for cloud-only APIs, since low-connectivity access to first aid or mental health support can matter most in the exact moments when a network isn't available
Top comments (0)