d08200d00e
* Bump Python package versions for 1.12.0 release Bump packages represented in the 1.12.0 changelog, promote Foundry Hosting, Azure Content Understanding, Gemini, Mistral, Monty, and Tools to beta, and apply the requested beta cohort date stamp. Root and core move to 1.12.0, released and RC packages use their selected increments, alpha packages including Hosting MCP use the 260721 stamp, and core floors are raised only for proven consumers. Copilot-Session: 2dd9980a-b869-4c16-8642-75b7a6d6ebdf * fix version in readme * Add Responses conversation ID changes to release notes Include the breaking Hosting Responses conversation ID helper changes from #7234 in the Python 1.12.0 changelog. Copilot-Session: 2dd9980a-b869-4c16-8642-75b7a6d6ebdf
agent-framework-hosting-telegram
Telegram Bot API-shaped helpers for app-owned Agent Framework hosting.
This is an alpha, helper-only package: it converts between Telegram's
Update JSON shape and Agent Framework run values in both directions. It
does not provide a bot client, a hosting/channel registry, or a
long-running service. Your app remains fully responsible for:
- Fetching updates -- long polling (
getUpdates) or registering a webhook -- and for verifying webhook authenticity (e.g. Telegram's secret token header, or an IP allowlist). - The Bot API client -- issuing the actual HTTP calls (
sendMessage,sendPhoto,editMessageText,answerCallbackQuery,getFile, ...) with whatever HTTP library you prefer. - Rate limits and retries -- Telegram enforces per-chat and global rate
limits; back off and retry on
429/5xxyourself. - Command dispatch --
telegram_command(...)only parses and normalizes a leading/command; your app decides what each command does. - Sessions/storage -- pair these helpers with
agent-framework-hosting'sAgentState/SessionStore(or your own) to persistAgentSessions across turns.
Helpers
telegram_chat_id(update)-- the chat id an update belongs to.telegram_session_id(update, bot_id=...)-- a bot-scopedAgentStatesession id. Private chats usetelegram:<bot_id>:<user_id>; other chats usetelegram:<bot_id>:<chat_id>.telegram_command(update)-- a leading slash command, with/name@bot argsnormalized to/name args. ReturnsNoneif there is none.telegram_callback_query_id(update)-- a callback query's id, so you can callanswerCallbackQueryyourself.telegram_media_file_id(update_or_message)-- the(file_id, mime_type)of inbound media (largest photo size, document, voice, audio, or video).telegram_to_run(update, *, resolve_file_url=None, stream=False)-- convert amessage,edited_message, orcallback_queryupdate intoAgent.runarguments. Provideresolve_file_url(typically backed bygetFile) to turn inbound media into content; without it (or when it returnsNone), text/caption is preserved and media is otherwise dropped. Media-only input with no resolvable URL raisesValueError.telegram_from_run(result, *, chat_id, parse_mode=None)-- render a finished run as oneTelegramOperation(sendPhotowhen the response has an image, otherwisesendMessage, falling back to"(no response)").telegram_from_streaming_run(stream, *, chat_id, message_id, initial_text=None, parse_mode=None)-- render a streaming run aseditMessageTextoperations with the cumulative text so far, followed by any images in the final response assendPhotooperations. Pass the app-created placeholder text asinitial_textso an identical first edit is omitted. Image-only responses first emitdeleteMessagefor the placeholder.
TelegramOperation is a minimal TypedDict of {"method": str, "payload": dict}
-- your app is responsible for actually calling the Bot API with it.
from agent_framework_hosting import AgentState
from agent_framework_hosting_telegram import (
telegram_chat_id,
telegram_from_run,
telegram_session_id,
telegram_to_run,
)
state = AgentState(agent)
async def handle_update(update: dict) -> None:
chat_id = telegram_chat_id(update)
if chat_id is None:
return # Not a chat update this bot handles.
session_id = telegram_session_id(update, bot_id=bot.id)
session = await state.get_or_create_session(session_id)
run = await telegram_to_run(update, resolve_file_url=resolve_telegram_file_url)
result = await (await state.get_target()).run(run["messages"], session=session, options=run["options"])
await state.set_session(session_id, session) # type: ignore[arg-type]
operation = telegram_from_run(result, chat_id=chat_id)
await call_bot_api(operation["method"], operation["payload"]) # Your HTTP client.
The base execution-state helpers live in
agent-framework-hosting.