Extract reply_to_message.text (fallback caption) from each getUpdates result and pass it to handle_message; the ai bridge prefixes the prompt with '[Reply context — the message you are replying to]', so replying to a /status output and asking 'ai check this details' gives the model the actual output. AI bridge only — mapped /commands unchanged; context rides in the user turn so the session records what was analyzed. Docs: howto/ai.md bridge section.
4.1 KiB
How-To: pos ai
Chat with Google Gemini — from the terminal and through the Telegram bot.
Tools: gemini (ask, chat, models).
| Tool | What it does |
|---|---|
pos ai gemini ask "<prompt>" |
One-shot answer to stdout (scriptable) |
pos ai gemini ask --session <name> "…" |
Same, but remembers prior turns |
pos ai gemini chat |
Interactive multi-turn conversation |
pos ai gemini models |
List available model ids |
pos ai gemini sessions |
List/clear persistent sessions (reset <name>) |
Shared flags: --model <id> overrides the model; --system "<text>" adds a
system instruction to every turn (kept out of the session file).
First run — get a key, configure, chat
-
Get a free API key from https://aistudio.google.com/apikey (requires a Google account).
-
Configure it (masked input):
pos config ai # enter AI_GEMINI_API_KEY -
Test:
pos ai gemini ask "Explain DNS in one line" pos ai gemini models # verify the default model id is live pos ai gemini chat # multi-turn conversation
ai.env lives at ~/.config/linux_post_install/ai.env (chmod 600); pos config ai
is the only place the key is written. The key is never printed by pos.
From the Telegram bot
Once pos ai gemini ask works, any non-command message starting with ai is
answered by the model — no bot map entry needed:
you: ai what is Nvidia
bot: NVIDIA is a company best known for GPUs...
The bridge lives in the Telegram listener's handle_message (it calls
pos ai gemini ask); only the owner chat is served, so your key stays private.
Set a different model per message:
you: ai --model gemini-2.5-flash explain a Raft consensus log
Telegram memory & formatting
Each chat has its own persistent session (telegram-<chat id>), so the model
remembers the conversation; ai /reset clears it. The listener passes a system
prompt telling the model it is answering in a Telegram chat — so it uses emojis
and stays lively — and strips markdown (**x**, backticks, #, links…) from
the reply before sending it, since messages go out as plain text.
Replying to a message before ai … makes that message part of the prompt, so
the model can answer about it:
you: /status → bot: (system health output…)
you: ai check this details about my linux ← reply to the /status message
Recipes
- Answer from a file:
pos ai gemini ask "$(cat notes.txt)" - Pipe into it:
echo "fix this: $(cat error.log)" | pos ai gemini ask - Answer in a cron job:
pos ai gemini ask "summarize today's git log" > /tmp/ai_digest.txt - Change the default model:
pos config ai # set AI_GEMINI_MODEL, or: AI_GEMINI_MODEL=gemini-2.5-flash pos ai gemini ask "hi"
How it works
askPOSTscontents:[{role:user, parts:[{text:"…"}]}]tohttps://generativelanguage.googleapis.com/v1beta/models/<model>:generateContentwith the key in thex-goog-api-keyheader, and prints.candidates[0].content.parts[].text— nothing else.chatkeeps the whole conversation in memory as a growingcontents[]array, so later turns have earlier context./resetdrops it.- On a non-2xx response the API's
error.messageis shown and the exit code is non-zero — so scripts can rely onaskfailing loudly.
Troubleshooting
askerrors "No Gemini API key — run 'pos config ai'" → the key isn't set (orai.envisn't readable). Runpos config ai.API error 400→ the model id is wrong or the prompt is too long for the model's context window; checkpos ai gemini models.API error 429→ rate limit (free tier); wait and retry, or use a different model.- Nothing in Telegram for
ai …→ the listener daemon must be running (pos communication telegram listener --status); the bot token and owner chat id must matchpos config telegram.
Related
- Reference: DOC/POS.md → ai
- Telegram bridge context: communication.md