log_meal
Log a meal to the user's food diary. Use when the user mentions eating, describes a meal, or asks to log food.
INFER:
date: today, or from context ("yesterday", "last night")
meal_type: canonical time mapping (00-05 Snack, 05-10 Breakfast, 10-14 Lunch, 14-17 Snack, 17-22 Dinner, 22-24 Snack); context overrides ("post-workout shake"=Post-Workout)
MACRO SOURCE: strongest evidence wins. Never replace known stored macros with a fresh estimate.
REPEATS: 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. A resolved recipe is a default for THIS meal, not a binding rule: it supplies stored food and macros, and any detail the user states this turn (e.g. "black" instead of the recipe's usual cream) overrides just that field the normal way, via the matching explicit argument. The recipe itself changes only through the Recipes page, never as a side effect of log_meal. Relay no-match/ambiguous errors instead of guessing. If the recipe reports missing macros, estimate only those fields and retry. If food_items adds food beyond the recipe, pass all four macros as the combined total.
BRAND NAMES: for a branded, restaurant, or specific product, use published macros for the stated size/variant before a generic estimate.
Otherwise estimate calories, protein_g, fat_g, carbs_g from the food description. Never ask the user for macros.
MACROS: food_items plus calories/protein_g/fat_g/carbs_g are required unless recipe_name supplies them. Ask only if food_items are absent and no recipe_name applies. Never call without all four macros populated.
SATURATED FAT / FIBER: saturated_fat_g and fiber_g are optional, unlike the four core macros. Populate them only when you have real evidence (a Nutrition Facts label, a well-known packaged product, or a food you can confidently estimate the composition of) -- never guess just to fill the field, and never send a value equal to fat_g (saturated fat is always a subset of total fat, not the whole of it, except literally pure fats like butter or coconut oil). Omit both entirely when unsure; they are never asked for and never inferred as 0.
FASTING: if the user ate nothing / fasted all day, log one "Fast day" Snack with calories/protein_g/fat_g/carbs_g all 0.
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. When a drink amount is known or reasonably inferable, include it in fluids even when the same drink also contributes calories/macros/alcohol. 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. 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.
SAVE AS RECIPE: when the user explicitly asks to save the meal they are logging as a reusable recipe, set save_as_recipe=true in this same call. The recipe is copied from the final persisted meal after the log succeeds.
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. 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. Optional. See SATURATED FAT / FIBER 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). See MACROS above. | |
| 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_type | Yes | Required. Infer from time of day or context, even when recipe_name is used (a saved recipe's own 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 | Name or close phrase for one of the user's saved recipes, e.g. "protein oats", "chicken bowl", or "breakfast" for their saved Breakfast recipe. See SAVED RECIPES above. | |
| save_as_recipe | No | True only when the user explicitly asks to save this meal as a reusable recipe. The recipe is copied from the final persisted meal. On update_meal, this can be the only requested action; use the real meal id or normal selectors and do not invent an edit. | |
| saturated_fat_g | No | Saturated fat in grams. Optional. See SATURATED FAT / FIBER above. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes | Human-readable result text returned by the tool. |