Files
Eduard van Valkenburg d75f2286f4 Python: Add Telegram channel for agent-framework-hosting (#6698)
* Python: Add Telegram channel for agent-framework-hosting

- Add agent-framework-hosting-telegram package with TelegramChannel
  supporting polling and webhook transports, streaming edits with
  Telegram Bot API rate limiting, per-chat serial workers, and
  multi-modal inbound/outbound (text, photo, document, voice)
- Add local_telegram sample demonstrating multi-channel hosting with
  a TelegramChannel alongside ResponsesChannel, using per-chat
  FileHistoryProvider and a run_hook for Telegram persona temperature
- Fix test layout: move tests to tests/hosting_telegram/ (no __init__.py)
- Remove old [tool.mypy] section and mypy poe task; source type-checking
  is handled by pyright via shared_tasks
- Update uv.lock, pyproject.toml workspace sources, and PACKAGE_STATUS.md

Fixes #6588
Refs #6265

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Python: Address Telegram channel CI failures and review feedback

- Fix webhook secret validation to use constant-time compare_digest
- Harden webhook update parsing: require integer chat IDs and guard slash-only commands
- Fix streaming edge cases in TelegramChannel:
  - prevent edit worker deadlocks when text exceeds 4096 chars
  - prevent deadlock when placeholder send fails (message_id stays None)
  - enforce edit throttling with minimum interval sleep
  - honor send_typing_action=False in streaming mode
  - always forward final multimodal output (e.g. images), while avoiding duplicate text sends
- Expand Telegram tests for slash-only command handling, non-int chat IDs, and streaming behavior (long text, final images, typing toggle)
- Fix sample/docs feedback:
  - rename sample package to agent-framework-hosting-sample-local-telegram
  - switch sample uv.sources from feature branch to main
  - align docs/tool names with lookup_weather
  - fix broken links and server run instructions in README/call_server.py
  - align local_telegram app docstrings with reasoning hook behavior and strip model in responses_hook

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Python: Fix TelegramChannel streaming to iterate contents for multimodal support

- Remove stale PR reference from module docstring
- Add Google-style docstring to TelegramChannel.__init__ documenting all keyword args
- Fix _stream_to_chat to iterate update.contents instead of using
  getattr(update, 'text', None); text chunks are extracted from Content
  items with type='text', non-text content in updates is correctly
  ignored (images etc. are forwarded via the final response)
- Update _FakeStreamUpdate test helper to use contents list matching the
  real AgentResponseUpdate API; add from_text/from_image class methods
- Update _FakeResponseStream to accept _FakeStreamUpdate objects directly
- Add test verifying multimodal stream updates don't corrupt text accumulator

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Python: Split local_telegram into simple Telegram-only and new multi-channel sample

local_telegram is now a focused Telegram-only sample:
- Removes ResponsesChannel and all responses_hook code
- Removes call_server.py (no HTTP endpoint to call)
- Uses a deterministic lookup_weather tool (hash-based, not random)
- Single run_hook that strips model and raises reasoning effort
- Drops agent-framework-hosting-responses dependency

New local_multi_channel sample shows running both channels at once:
- ResponsesChannel + TelegramChannel sharing a FileHistoryProvider
- Cross-channel session resumption via previous_response_id
- call_server.py moved here (the Responses endpoint lives here now)
- Demonstrates the multi-channel coordination story

Update README table to list both samples with clear descriptions.

Also delete personal_assistant/.venv which was not tracked but caused
pyright to crawl the entire installed venv (thousands of files),
making sample pyright checks hang indefinitely.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Python: Fallback when Telegram final edit fails

- only mark final edit as sent after a confirmed 2xx edit response
- fall back to sendMessage when final edit returns a non-success status
- add regression test covering failed final edit fallback behavior

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Python: Fix optional await_args typing in telegram test

- assert await_args is not None before reading kwargs in streaming fallback test
- resolves test-typing failures across mypy/pyright/ty/zuban for hosting-telegram

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-25 11:40:48 +00:00
..

Multi-channel hosting samples

End-to-end samples for serving an agent-framework agent (or workflow) through one or more channels with agent-framework-hosting.

The general hosting plumbing lives in agent-framework-hosting; each channel is its own package. This first sample set includes agent-framework-hosting-responses.

Sample What it shows Packaging
local_responses/ The minimal shape: one agent + one @tool + ResponsesChannel + a single run_hook that strips caller-supplied options and forces a reasoning preset. Local only. Start here to learn the run-hook seam.
local_responses_workflow/ A 4-step Workflow (typed SloganBrief intake → writer → legal → formatter) hosted behind the Responses channel via a run_hook that parses inbound text/JSON into the workflow's typed input. The host writes per-conversation checkpoints via checkpoint_location=…. Demonstrates workflow targets + structured input adaptation + resume-across-turns. Includes a call_server.rest file with REST examples. Local only.
local_telegram/ Telegram bot with @tool, FileHistoryProvider, run_hook, and slash commands (/new, /whoami, /weather). Pure Telegram — no HTTP endpoint. Local only. Start here to learn the Telegram channel.
local_multi_channel/ Same agent behind two channels at once: ResponsesChannel + TelegramChannel. Shared FileHistoryProvider enables cross-channel session resumption (resume a Telegram chat from the Responses endpoint by passing the Telegram isolation key as previous_response_id). Local only.

Each sample is fully self-contained — its own pyproject.toml, uv.lock, server app.py, calling script(s), and storage/ directory. Every sample uses [tool.uv.sources] to wire its agent-framework-hosting* dependencies to the main branch of the upstream repo via git refs, so they install cleanly outside the monorepo while the hosting packages are still pre-PyPI. Once those packages publish, drop the [tool.uv.sources] block and let the declared deps resolve from PyPI.

Relationship to ../foundry-hosted-agents/

The sibling ../foundry-hosted-agents/ directory contains samples for the agent-framework-hosted stack — agents that run inside the Foundry Hosted Agents platform using its built-in protocol surface (Responses, Invocations, conversation store, isolation, identity), with no agent-framework-hosting package involved.

Aspect af-hosting/ (this directory) foundry-hosted-agents/
Server stack agent-framework-hosting + agent-framework-hosting-responses agent-framework-hosted only — the Foundry Hosted Agents runtime owns the HTTP surface
Channels Responses only in this initial sample set The platform exposes Responses + Invocations
Run target Local Hypercorn (local_responses/, local_responses_workflow/) Hosted Agents or local container; targets the Hosted Agents platform contract
When to pick this You want to learn the host/channel seams locally or need custom hosting middleware You want zero hosting boilerplate, leveraging the Foundry-managed surface

The table above summarizes the cross-sample story.