log_meal
RECIPE SAVE: intent=create/save recipe not eaten -> save_as_recipe=true, recipe_only=true intent=log eaten meal + save recipe -> save_as_recipe=true, recipe_only=false/omit recipe_only=true -> food_log_write=false; save_as_recipe must be true recipe_only=true -> recipe_title= recipe_only=true -> recipe_servings=<whole-batch servings; default 1> recipe_only=true -> food_items= recipe_only=true -> calories/protein_g/fat_g/carbs_g=<WHOLE-BATCH totals; estimate, never ask> recipe_only=true -> estimate=
Log a meal to the user's food diary. use: logging request or concrete meal consumed. question/habit/hypothetical alone: no write.
INFER:
date: today, or from context ("yesterday", "last night"). For an attached meal photo with , use that photo's local date unless the user explicitly states a different date.
meal_time: for an attached meal photo with , send that photo's local HH:MM unless the user explicitly states a different time/date. User-stated timing always wins. Otherwise omit unless the user gave a real clock time.
meal_type: when meal_time is supplied, OMIT meal_type unless the user's wording explicitly names or clearly anchors a category; the server assigns the category from meal_time. Without meal_time, for a current-day plain meal/food log omit meal_type and let the server assign it from the user's resolved local clock (00-04 Snack, 04-10 Breakfast, 10-14 Lunch, 14-17 Snack, 17-22 Dinner, 22-24 Snack). Send meal_type when the user's wording explicitly names or clearly anchors a category ("breakfast", "for lunch", "post-workout shake"), or when backdating and neither capture time nor another honest clock signal exists.
MACRO SOURCE: strongest evidence wins. Never replace known stored macros with a fresh estimate.
REPEATS (unless a saved recipe is clearly invoked): if the user refers to a previously logged item ("same", "another", "more", "again", or equivalent in any language), call list_meals for the referenced date/range first. If one row unambiguously matches, reuse its stored calories/protein_g/fat_g/carbs_g/alcohol_g and scale by the quantity ratio when the row's quantity is known. If the match or quantity is ambiguous, ask instead of re-estimating. If nothing matches, continue below.
SAVED RECIPES: pass recipe_name whenever the food phrase plausibly names one of the user's saved recipes (see the profile's "Saved recipes" list) -- not only when the user literally says "saved" or "usual"; a bare "morning coffee" should try recipe_name if "Morning Coffee" is one of theirs. recipe_values: Saved macros and nutrients, including estimates and zeros, are authoritative unless explicitly corrected. Scale with recipe_multiplier; combine added_food_items using final meal macros. Estimate only missing values or changed/added foods. Logging never modifies the saved recipe. Relay no-match/ambiguous errors instead of guessing. A recipe's saturated_fat_g/fiber_g are carried automatically when its stored nutrients have them. They are expanded nutrients, never required to log the meal; do not invent them just to satisfy this tool. If the recipe reports missing core macros, estimate only those core fields and retry. If food_items adds food beyond the recipe, pass the combined core macros; expanded nutrients remain optional and are handled by the gated nutrient pipeline when enabled.
BRAND NAMES: for a branded, restaurant, or specific product, use published macros for the stated size/variant before a generic estimate.
Otherwise estimate every macro from the food description. Never ask the user for macros.
MACROS: final stored meal must contain calories, protein_g, fat_g and carbs_g. recipe_name supplies stored core values; estimate and pass only missing core values or explicit changes. Without a recipe, pass food_items and those four. No partial core macros or placeholders. Saturated fat and fiber are expanded nutrients, never required for log_meal. Pass saturated_fat_g/fiber_g only when already known from strong evidence; otherwise omit them. When expanded nutrient tracking is enabled, the gated nutrient estimator can fill them; when disabled they remain unset. 0 is a real value only when the food truly contains none of that nutrient. Ask only if food_items are absent and no recipe_name applies.
FASTING: if the user ate nothing / fasted all day, log one "Fast day" Snack with every macro 0.
ESTIMATE: pass a compact 3-line block estimating every one of the app's 44 tracked nutrients for the food, in exactly this format, no prose before or after: items::|:|... macros:;;;; nutrients:1:;2:;...;44: Estimate all 44 nutrients. Always return all 44 IDs. Never omit one because you are uncertain -- use your best reasonable estimate from the likely food, quantity, ingredients, preparation and comparable foods; 0 only when a nutrient is reasonably expected to be negligible. Which id is which nutrient, and its unit, is the dictionary on the estimate param. Omit for an unchanged saved recipe; with added_food_items, estimate that addition only. Otherwise supply when available; the server estimates missing values.
DUPLICATES: if this tool returns a duplicate error, tell the user what's already logged and ask whether this is a separate serving (retry with force=true) or should update the existing entry instead (update_meal with adjusted values).
DRINKS / HYDRATION: this is the single write path for consumed drinks too. Known or reasonably inferable drink volume (tea, coffee, milk, juice, shakes, smoothies, etc.) → always report fluids, even if also contributes calories/macros/alcohol. Food moisture → omit. The server decides whether hydration tracking is enabled; never use a separate hydration write tool. A plain fluid-only intake may omit food_items and macros and send only fluids. For alcoholic drinks, include that drink's alcohol_g in its fluid item; if there is exactly one drink, the top-level alcohol_g can stand in.
CAFFEINE / DRINKS: this is the single assistant write path for caffeine too. Drinks only; exclude food moisture. When the user consumed a drink and its volume is known or reasonably inferable, include it in fluids so hydration is recorded; if the drink is caffeinated, include caffeine in the same call too. Do not leave a known-volume drink only in food_items. Each caffeine item needs caffeine_mg and may optionally include source_type. The date comes from the intake date. Preserve exact user-provided milligrams; for vague coffee/tea/energy-drink/pre-workout descriptions, estimate caffeine with the same nutrition-estimation judgment used for meal macros. Never use separate hydration or caffeine write tools. A drink-only or caffeine-only intake may omit food_items/macros.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | YYYY-MM-DD. Omit for today (the server resolves it in the user's own timezone, more reliable than guessing). Send explicitly for any past date. | |
| fat_g | No | Fat in grams. See MACROS above. | |
| force | No | True only when the user has explicitly confirmed a separate entry despite a duplicate warning. Bypasses duplicate detection. | |
| fluids | No | Optional drinks consumed in this intake, including liquid ingredients in shakes or smoothies. Omit when no drink amount is known. Hydration is persisted only when the user enabled hydration tracking. | |
| carbs_g | No | Carbohydrates in grams. See MACROS above. | |
| fiber_g | No | Dietary fiber in grams. See MACROS above. | |
| caffeine | No | Optional caffeine doses in this intake. Keep each dose simple: caffeine amount is required and type is optional. The dose date follows the intake/meal date. If the user gave exact milligrams, preserve them exactly; otherwise estimate from the described food or drink. | |
| calories | No | Total calories(kcal) never kJ | |
| estimate | No | The compact 3-line nutrient estimate for this meal. See ESTIMATE above for the format. Omit to have the server estimate instead -- never blocks the write either way. A block whose parts exceed their whole (saturated fat over fat, fiber over carbs) is discarded and re-estimated. NUTRIENT ID DICTIONARY (id=name, unit is the name's suffix; ug=mcg). Every id means exactly this nutrient, never guess the order: 1=fiber_g 2=sugar_g 3=saturated_fat_g 4=monounsaturated_fat_g 5=polyunsaturated_fat_g 6=trans_fat_g 7=cholesterol_mg 8=sodium_mg 9=potassium_mg 10=calcium_mg 11=iron_mg 12=magnesium_mg 13=phosphorus_mg 14=zinc_mg 15=copper_mg 16=manganese_mg 17=selenium_ug 18=chloride_mg 19=chromium_ug 20=iodine_ug 21=molybdenum_ug 22=vitamin_a_ug 23=vitamin_c_mg 24=vitamin_d_ug 25=vitamin_e_mg 26=vitamin_k_ug 27=thiamin_b1_mg 28=riboflavin_b2_mg 29=niacin_b3_mg 30=pantothenic_acid_b5_mg 31=vitamin_b6_mg 32=biotin_b7_ug 33=folate_b9_ug 34=folic_acid_ug 35=vitamin_b12_ug 36=choline_mg 37=omega3_g 38=omega6_g 39=caffeine_mg 40=water_g 41=starch_g 42=added_sugar_g 43=total_unsaturated_fat_g 44=fluoride_mg | |
| alcohol_g | No | Alcohol in grams (not kcal). Only if alcoholic drinks were consumed; unset takes the saved recipe's value when recipe_name matches. 1 standard drink is about 14g. | |
| meal_time | No | Optional local 24-hour HH:MM time. For an attached meal photo, use the current turn's photo capture time when the user did not state a different date/time. User-stated timing always wins. | |
| meal_type | No | Optional. Omit for a current-day plain meal/food log so the server assigns the category from the user's resolved local clock. Send only when the user explicitly names or clearly anchors a category, or when backdating and the current clock cannot apply. A saved recipe's stored meal type never fills this in. | |
| protein_g | No | Protein in grams. See MACROS above. | |
| food_items | No | Description of the food and drinks consumed. See MACROS above; ask the user only if completely absent and no recipe_name applies. | |
| recipe_name | No | Saved recipe title only, without portion words or additions. See SAVED RECIPES above. | |
| recipe_only | No | true=save recipe only and write no food_log row. Requires save_as_recipe=true. See RECIPE SAVE above. | |
| recipe_title | No | Recipe name when recipe_only=true. See RECIPE SAVE above. | |
| save_as_recipe | No | True only when the user explicitly asks to save a reusable recipe. recipe_only=true saves recipe only; otherwise the final persisted meal is saved after the log succeeds. See RECIPE SAVE above. | |
| recipe_servings | No | Whole-batch serving count when recipe_only=true; default=1. See RECIPE SAVE above. | |
| saturated_fat_g | No | Saturated fat in grams. See MACROS above. | |
| added_food_items | No | Only food added to a saved recipe; supply final combined macros. Omit when none. | |
| recipe_multiplier | No | Portions of the matched saved recipe; default 1, e.g. 0.5 for half. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes | Human-readable result text returned by the tool. |