food-tracker
Food Tracker
ติดตามฟอสฟอรัสและโพแทสเซียมจากอาหาร สำหรับผู้ที่ต้องควบคุมแร่ธาตุ (เช่น ผู้ป่วยโรคไต)
For state management, read and follow the protocol in skills/state-db/SKILL.md
State Schema (via state-db)
skill_name: food-tracker
| key1 | key2 | key3 | purpose | data fields |
|---|---|---|---|---|
| entry | date (YYYY-MM-DD) | meal_period | individual food log | {food_name, meal_time, phosphorus_mg, potassium_mg, serving_size, source, notes} |
- key2 = date (
2026-03-14) — enables daily/monthly queries via index - key3 = meal_period (
เช้า/กลางวัน/เย็น/ก่อนนอน) — enables per-meal filtering via index
Each food item the user eats becomes one entry row. Reports are generated by querying entries and aggregating in-memory.
Data Field Reference
| Field | Type | Example | Note |
|---|---|---|---|
| food_name | string | "ข้าวมันไก่" | required |
| meal_time | string | "2026-03-14T12:00:00" | ISO datetime, Asia/Bangkok |
| phosphorus_mg | number | 250 | required |
| potassium_mg | number | 300 | required |
| serving_size | string | "1 จาน" | optional |
| source | string | "web" | "web" or "ai_estimate" |
| notes | string | null | optional |
Operations
Log a food entry
curl -s -X POST "$DB_URL" "${DB_AUTH[@]}" "${DB_JSON[@]}" "${DB_RETURN[@]}" \
-d '{
"skill_name": "food-tracker",
"key1": "entry",
"key2": "2026-03-14",
"key3": "กลางวัน",
"data": {
"food_name": "ข้าวมันไก่",
"meal_time": "2026-03-14T12:00:00",
"phosphorus_mg": 280,
"potassium_mg": 350,
"serving_size": "1 จาน",
"source": "web",
"notes": null
}
}'
Search for similar food (duplicate check)
Use ilike to search food names:
curl -s "$DB_URL?skill_name=eq.food-tracker&key1=eq.entry&data->>food_name=ilike.*ข้าวมัน*&order=key2.desc&limit=5" \
"${DB_AUTH[@]}"
Query entries for a date (daily report data)
curl -s "$DB_URL?skill_name=eq.food-tracker&key1=eq.entry&key2=eq.2026-03-14&order=created_at.asc" \
"${DB_AUTH[@]}"
Query entries for a month (monthly report data)
Use like to match year-month prefix in key2:
curl -s "$DB_URL?skill_name=eq.food-tracker&key1=eq.entry&key2=like.2026-03*&order=created_at.asc" \
"${DB_AUTH[@]}"
Delete entry by id
curl -s -X DELETE "$DB_URL?id=eq.42" "${DB_AUTH[@]}" "${DB_RETURN[@]}"
List entries for a date (with id for deletion)
curl -s "$DB_URL?skill_name=eq.food-tracker&key1=eq.entry&key2=eq.2026-03-14&select=id,key2,key3,data,created_at&order=created_at.asc" \
"${DB_AUTH[@]}"
Workflow A: Log Food
When the user mentions food they ate (e.g. "กินข้าวมันไก่ มื้อเที่ยง") or sends a food photo:
Step 1 - Parse input
If the user sends an image/photo:
- Analyze the image to identify all food items visible in the photo
- Estimate the serving size of each item from visual cues (plate size, portion)
- List what you see and confirm with the user before proceeding, e.g.: "จากรูปเห็น: ข้าวสวย 1 จาน, แกงเขียวหวานไก่ 1 ชาม, ไข่เจียว 1 ชิ้น — ถูกต้องไหมครับ?"
- Once confirmed (or corrected), continue to Step 2 with the identified food names
If the user sends text:
Extract from the user's message:
- Food name(s) — there may be multiple items
- Meal period — เช้า / กลางวัน / เย็น / ก่อนนอน
- Meal time — if user specifies a time, use it. Otherwise use current time (Asia/Bangkok, UTC+7)
- Serving size — if mentioned (e.g. "2 ถ้วย", "1 จาน")
Step 2 - Look up nutrients
For each food item, use WebSearch:
Search: "{food_name} phosphorus potassium mg per serving nutrition facts"
Also try: "{food_name} ฟอสฟอรัส โพแทสเซียม ต่อหน่วย"
Extract phosphorus_mg and potassium_mg per serving. Prefer Thai food databases or credible sources (USDA, Thai nutrition databases).
If WebSearch returns no usable data, read references/nutrients.md for common Thai food values. If still not found, estimate using AI knowledge and mark source as ai_estimate.
Step 3 - Check for duplicates
Before inserting, search for similar food names using the search operation above. If a match is found with different nutrient values, inform the user but still proceed with the new entry.
Step 4 - Store the entry
Insert using the log operation above. Set key2 to date (YYYY-MM-DD), key3 to meal_period, and meal_time in data to full ISO datetime, all in Asia/Bangkok timezone.
Step 5 - Show running total
Query today's entries using the daily query operation. Sum up phosphorus_mg and potassium_mg from all entries' data field, then calculate percentages against daily limits.
Step 6 - Reply in Thai
Confirm what was logged and show today's running totals using the daily report format below.
Workflow B: Reports
Daily Report
- Query all entries for the date
- Sum
phosphorus_mgandpotassium_mgacross all entries - Calculate percentage against daily limits
- Format output as:
## รายงานประจำวัน - {date}
| # | อาหาร | มื้อ | ฟอสฟอรัส | โพแทสเซียม | ปริมาณ |
|---|-------|------|----------|-----------|--------|
| 1 | ข้าวสวย | เช้า | 68 mg | 55 mg | 1 ถ้วย |
### สรุปรวม
| แร่ธาตุ | รับไปแล้ว | เกณฑ์/วัน | สถานะ |
|---------|----------|----------|-------|
| ฟอสฟอรัส | 310 mg | 1,000 mg | 31% ✅ |
| โพแทสเซียม | 737 mg | 3,000 mg | 25% ✅ |
Monthly Report
- Query all entries for the month
- Group by date to get daily breakdown
- Group by food_name to get top foods and frequency
- Identify exceeded days and foods to avoid
- Format output as:
## รายงานประจำเดือน - {month}
### ภาพรวม
| แร่ธาตุ | รวมทั้งเดือน | เฉลี่ย/วัน | วันที่บันทึก |
|---------|------------|----------|------------|
| ฟอสฟอรัส | 8,432 mg | 843 mg | 10 วัน |
| โพแทสเซียม | 19,540 mg | 1,954 mg | 10 วัน |
### อาหารที่เป็นแหล่งฟอสฟอรัสสูงสุด
| อันดับ | อาหาร | รวม | ทานกี่ครั้ง | เฉลี่ย/ครั้ง |
|-------|-------|-----|----------|------------|
| 1 | นมวัว | 1,220 mg | 5 ครั้ง | 244 mg |
### อาหารที่เป็นแหล่งโพแทสเซียมสูงสุด
(same format)
### วันที่กินเกินเกณฑ์ต่อวัน
| วันที่ | ฟอสฟอรัส | สถานะ | โพแทสเซียม | สถานะ |
|-------|----------|-------|-----------|-------|
| 6 มี.ค. | 1,050 mg | 🔴 เกิน | 2,200 mg | ✅ |
(ถ้าไม่มีวันที่เกินเกณฑ์ แสดง "ไม่มีวันที่เกินเกณฑ์ในเดือนนี้ ✅")
### เมนูที่ควรหลีกเลี่ยง
อาหารที่ค่าต่อครั้งสูงกว่า 20% ของเกณฑ์ต่อวัน (P >200mg หรือ K >600mg):
| อาหาร | ค่าเฉลี่ย/ครั้ง | ทานกี่ครั้ง | รวมทั้งเดือน | ควรเลี่ยงเพราะ |
|-------|---------------|----------|------------|--------------|
| ไก่ทอด Bonchon | P: 300 mg | 3 ครั้ง | 900 mg | ฟอสฟอรัสสูง |
Aggregation Logic for Monthly Report
From the raw entries array, compute:
- Daily breakdown: group by
key2(date), sumdata.phosphorus_mganddata.potassium_mgper day, count entries per day - Top phosphorus foods (top 10): group by
data.food_name, sum phosphorus_mg, count frequency, calculate avg = total / frequency - Top potassium foods (top 10): same logic with potassium_mg
- Exceeded days: days where total phosphorus > 1000 or total potassium > 3000
- Foods to avoid: foods where avg per serving > 20% of daily limit (P >200mg or K >600mg)
Status Indicators
- ✅ = < 70% of daily limit
- ⚠️ = 70-90% of daily limit
- 🔴 = > 90% of daily limit
Nutrient Thresholds (CKD Reference)
| Mineral | Daily Limit |
|---|---|
| Phosphorus (ฟอสฟอรัส) | 800-1,000 mg |
| Potassium (โพแทสเซียม) | 2,000-3,000 mg |
These are general reference values. Always defer to the user's doctor.
Important Notes
- All timestamps displayed as Asia/Bangkok (UTC+7)
- Nutrient values from web search are preferred over AI estimates
- When searching for duplicates, check both exact and similar names because Thai food names can vary (e.g. "ข้าวผัดกะเพรา" vs "ข้าวกะเพรา")
- This skill does NOT provide medical advice — data is for personal tracking only
- Always add the disclaimer in reports: "ข้อมูลนี้เป็นเพียงการติดตามส่วนตัว ไม่ใช่คำแนะนำทางการแพทย์"