04 - Tools Registry (Qwen orchestrator)¶
Qwen 32B w kony-brain używa --enable-auto-tool-choice --tool-call-parser hermes. Kony ma 26 tools łącznie:
- 12 tools "wewnętrznych" w tools.py (FlexyCRM, Kony Hub, RAG, research)
- 14 tools "bridge" w bridge_tools.py (calendar, gmail, HA, drive - przez n8n Kony Bridge webhook)
Każdy tool ma OpenAI JSON schema definition. Qwen wywołuje tool przez function calling, execute_tool() w tools.py dispatchuje.
Tools w tools.py (wewnętrzne, direct HTTP do FlexyCRM/Kony Hub)¶
FlexyCRM Tasks¶
list_urgent_tasks {limit?: int} - Priorytetowe zadania (high priority + due date wkrótce)
list_client_tasks {client_hint: str, limit?: int} - Zadania dla konkretnego klienta (fuzzy match po nazwie)
Kony Hub captures¶
get_kony_capture {kony_number: int} - Pobierz jeden capture po Kony #N
list_recent_captures {limit?: int, hours?: int} - Ostatnie N capture'ów z ostatnich H godzin
search_captures {query: str, limit?: int} - Full-text search przez original_text, agent_suggestion, llm_analysis
search_captures_semantic {query: str, top_k?: int} - RAG search przez kony-embed. Cosine similarity, próg 0.72. Dodane 2026-08-30 (M5 Kierunek 1).
unresolved_count {} - Ile captures nie ma resolved_at (zaległe do rozwiązania)
mark_capture_done {kony_number: int, note?: str} - Ustaw resolved_at=now, ewentualnie dodaj notatkę
mark_capture_undone {kony_number: int} - Reverse (usuń resolved_at)
save_note {text: str, intent?: str, title?: str} - Zapisz nowy capture do Kony Hub jako "kony-conversation" source_app (używa Qwen gdy user w rozmowie mówi "zapisz to")
Meta tools¶
research {query: str, depth?: 'shallow'|'deep'} - Brave Search + Qwen synthesis. depth=deep = więcej search results + głębszy summary.
execute_capture {kony_number: int} - Uruchom "execute pipeline" na capture (detect tasks w treści → auto-create FlexyCRM tasks). Beta feature.
Bridge tools w bridge_tools.py (via n8n Kony Bridge webhook)¶
Wszystkie te wywoływane przez POST n8n.chcedointernetu.pl/webhook/kony-bridge z body {intent: 'xxx', args: {...}}. n8n workflow 88zekiBO4NPeMpjn dispatchuje.
Calendar (Google Calendar OAuth)¶
calendar_today {} - Wydarzenia z dziś (obydwa kalendarze: primary + ratunku@chcedointernetu.pl, merge append, JS date filter Europe/Warsaw)
calendar_this_week {} - Wydarzenia z tego tygodnia (do +7d)
calendar_next_event {} - Najbliższe wydarzenie od teraz (do +30d)
calendar_find_free_slot {duration_minutes: int, day?: str, earliest?: str} - Znajdź wolne okno w dniu (default: dzisiaj)
calendar_create_event {summary: str, start_iso: str, end_iso: str, description?: str, location?: str, calendar?: 'primary'|'ratunku'}
Gmail¶
mail_unread_count {} - Ile nieprzeczytanych w INBOX
mail_recent {limit?: int, hours?: int} - Ostatnie maile (bez OG spam/promotions)
mail_search {query: str, limit?: int} - Gmail search operator
mail_send {to: str, subject: str, body: str, cc?: str} - Wyślij mail (uwaga: watch out for feedback loops, sprawdź czy adresat nie tworzy triggera dla innego workflow!)
Home Assistant¶
ha_status {entity_id?: str} - Stany urządzeń (all lub konkretny)
ha_turn_on {entity_id: str} - Włącz (np. light.salon_main, switch.kettle)
ha_turn_off {entity_id: str} - Wyłącz
ha_speak {message: str, target?: str} - TTS na Google Home. Default target: media_player.clock (Lenovo Clock w sypialni - jedyny realnie działający speaker w HA, patrz [[project_ha_speakers]])
Google Drive¶
drive_create_doc {title: str, content: str, folder?: str} - Utwórz Google Doc w Drive Konrada
Jak Qwen decyduje który tool wywołać¶
Qwen dostaje w system prompt (QWEN_SYSTEM_PROMPT w app.py) wysokopoziomowy opis Kony + listę tools jako function definitions. Reguły które Qwen intuicyjnie stosuje:
- "co mam dziś w kalendarzu" →
calendar_today - "znajdź wolne okno na 30 min" →
calendar_find_free_slot - "jakie mam pilne zadania" →
list_urgent_tasks - "co pisałem o Aureliuszu" →
search_captures_semantic(niesearch_capturesbo semantic lepiej łapie kontekstualne pytania) - "zapisz notatkę: xxx" →
save_note - "włącz kuchnię" →
ha_turn_on entity_id=switch.kitchen_lights - "sprawdź co Anthropic ma nowego" →
research query="Anthropic latest news" depth=shallow - "powiedz w salonie: mam spotkanie za 15 min" →
ha_speak message="..." target=media_player.clock(bo salon nie ma realnego endpointu)
RAG auto-inject (nie tool, ale kluczowe)¶
Kony automatycznie robi RAG search PRZED wywołaniem Qwen. Jeśli user query jest pytaniem (nie command), kony-brain:
- Embed user query z
kony-embed :8018 - Cosine similarity vs in-memory index (~200 captures)
- Jeśli top-3 sim > 0.72 → wsadzi do system prompt jako
## Kontekst z Twoich notatek:
Efekt: Qwen widzi relevantne notatki bez ręcznego search_captures_semantic. Jeśli user zapyta "co ostatnio mówiłem o Aureliuszu", Qwen dostanie już 3 najbardziej pasujące captures - może odpowiedzieć od razu bez tool call.
Threshold 0.72 dostosowany dla mmlw (roberta-large PL). Za nisko = pollution, za wysoko = zero context.
Dodawanie nowego toola¶
- Definition JSON w
tools.pyTOOL_DEFSlist albobridge_tools.pyBRIDGE_TOOL_DEFS - Implementation function
async def tool_xxx(args: dict) -> dict:wtools.pyalbo add case wexecute_bridge_tool()wbridge_tools.py - Dispatcher w
execute_tool()(tools.py) alboexecute_bridge_tool()(bridge_tools.py) - Restart
docker restart kony-brainżeby Qwen widział nowy tool w schema - Test: postaw pytanie w Conversation apce które powinno wywołać nowy tool, sprawdź logi
docker logs kony-brain --tail 20
Uwaga context window: Qwen 32B ma 16k tokens context. Każdy tool def zjada ~150-300 tokens w schema. Za dużo tools = mniej miejsca na RAG + history. 26 tools = ~5-6k tokens overhead. Docelowe max ~30 tools zanim trzeba splitować na dedykowane sub-agenty.
Pokrewne¶
- 00-overview.md - high level
- 01-modules.md - kony-brain module
- 03-data-flow.md - voice conversation flow (Qwen orchestracja)
../kony-brain/tools.py+../kony-brain/bridge_tools.py- source