# Athos on Hermes (and open / self-hosted tool-calling models) Hermes (Nous Research Hermes 2/3) is a **function-calling model**. It doesn't load "skills" or run hooks — you give it a system prompt that (a) carries the Athos coaching rules and (b) declares the Athos API as callable tools. Your harness (vLLM, Ollama, LM Studio, TGI, or any OpenAI-compatible server) executes the HTTP request when Hermes emits a tool call and feeds the result back. The same pattern adapts to other open tool-calling models (Llama 3.x, Mistral, Qwen). ## 1. Load the coaching rules ```bash curl -L /api/v1/skill/download -o athos-skill.tar.gz tar xzf athos-skill.tar.gz # -> athos/SKILL.md, athos/references/*.md ``` Put `athos/SKILL.md` (and any `references/*.md` you need) into the system prompt or a retrieval store. That's the coaching logic, routing, and endpoint cheat sheet. ## 2. Auth — harness-side, never in the model Keep the key in your harness/tool executor, not in the prompt. Every Athos call: ``` Authorization: Bearer Base URL: # default https://app.athos.fitness ``` ## 3. Hermes system prompt + tools Hermes expects tools inside `` and returns calls as `{...}`. Minimal working scaffold: ``` <|im_start|>system You are Athos, an AI fitness & nutrition coach. Never invent training science or nutrition numbers — always call a tool to read Athos state. get_program_week_current is the source of truth for the current plan; keep planned vs logged distinct. Return tool calls as {"name":..,"arguments":{..}}. {"type":"function","function":{"name":"get_program_week_current","description":"Canonical current week: workouts + meals. Source of truth.","parameters":{"type":"object","properties":{}}}} {"type":"function","function":{"name":"get_onboarding_questions","description":"Fetch the onboarding interview questions.","parameters":{"type":"object","properties":{}}}} {"type":"function","function":{"name":"submit_onboarding_answers","description":"Submit interview answers keyed by exact question id.","parameters":{"type":"object","properties":{"answers":{"type":"object","description":"map of question_id -> answer"}},"required":["answers"]}}} {"type":"function","function":{"name":"get_onboarding_status","description":"Poll onboarding progress until strategy is ready.","parameters":{"type":"object","properties":{}}}} {"type":"function","function":{"name":"confirm_strategy","description":"Confirm the proposed coaching strategy.","parameters":{"type":"object","properties":{}}}} {"type":"function","function":{"name":"log_food_text","description":"Log a meal described in plain language.","parameters":{"type":"object","properties":{"description":{"type":"string"},"meal_type":{"type":"string"}},"required":["description"]}}} {"type":"function","function":{"name":"log_activity","description":"Log an activity/workout.","parameters":{"type":"object","properties":{"description":{"type":"string"}},"required":["description"]}}} {"type":"function","function":{"name":"modify_today","description":"Modify today's workout for pain/equipment/time.","parameters":{"type":"object","properties":{"instruction":{"type":"string"}},"required":["instruction"]}}} <|im_end|> ``` Map each tool to its endpoint in your executor (all with the Bearer header): | tool | method + path | |------|---------------| | `get_program_week_current` | `GET /api/v1/program/week/current` | | `get_onboarding_questions` | `GET /api/v1/onboarding/questions` | | `submit_onboarding_answers` | `POST /api/v1/onboarding/submit-answers` | | `get_onboarding_status` | `GET /api/v1/onboarding/status` | | `confirm_strategy` | `POST /api/v1/onboarding/confirm-strategy` | | `log_food_text` | `POST /api/v1/food/entries/analyze-text` | | `log_activity` | `POST /api/v1/activity/log` | | `modify_today` | `POST /api/v1/program/today/modify` | Loop: model emits `` → harness runs the HTTP request → return the JSON as `{...}` → model continues. (Photo food logging uses `POST /api/v1/food/analyze-image` if your harness can send images.) ## 4. No hooks → poll Without a webhook transform you can't receive `onboarding.strategy_ready`, `notification.due`, or `skill.updated` pushes. Poll instead: - After `submit_onboarding_answers`, poll `get_onboarding_status` until ready, then `confirm_strategy`. - Re-fetch `get_program_week_current` when the user re-engages. - Re-download the package periodically to pick up skill updates. If your deployment can expose an inbound URL, register it with `POST /api/v1/webhooks` to reduce polling. Full coaching rules, routing, and dedupe: `athos/SKILL.md` and `references/`.