Skip to content

Python: add hosting Channels sample apps - #5645

Merged
Eduard van Valkenburg (eavanvalkenburg) merged 5 commits into
microsoft:feature/python-hostingfrom
eavanvalkenburg:feat/hosting-samples
May 28, 2026
Merged

Python: add hosting Channels sample apps#5645
Eduard van Valkenburg (eavanvalkenburg) merged 5 commits into
microsoft:feature/python-hostingfrom
eavanvalkenburg:feat/hosting-samples

Conversation

@eavanvalkenburg

@eavanvalkenburgEduard van Valkenburg (eavanvalkenburg) commented May 5, 2026

Copy link
Copy Markdown
Member

Motivation and Context

Adds the runnable sample apps for the Python hosting Channels work specified in SPEC-002 (merged via #5549) and the channel packages in PR-1..PR-8.

Description

Adds five sample apps under python/samples/04-hosting/af-hosting/:

SampleChannels exercisedNotes
local_responses/ResponsesSmallest hello-world + run-hook example
local_responses_workflow/Responses3-agent workflow as host target with checkpoint storage
local_telegram/Responses + TelegramSingle-bot variant + multicast variant
local_identity_link/Responses + Invocations + Telegram + Activity Protocol + Entra link sidecarFull surface — uses ActivityProtocolChannel from PR-5a, not the Teams-SDK channel from PR-5b
foundry_hosted_agent/Responses + Invocationsazd-deployable; Dockerfile + azure.yaml for Foundry Hosted Agents

Each sample's pyproject.toml pulls hosting packages directly from this repo's feature/python-hosting branch via [tool.uv.sources] git refs, e.g.:

[tool.uv.sources]
agent-framework-hosting = { git = "https://github.com/microsoft/agent-framework.git", branch = "feature/python-hosting", subdirectory = "python/packages/hosting" }

This pattern lets the samples be tried before any of the channel packages are published to PyPI. The READMEs note the migration path to PyPI deps once the packages are released. uv.lock files are intentionally not committed — generated on the user's first uv sync.

foundry_hosted_agent/ previously bundled a _vendor/ snapshot of the hosting packages so its container could build self-contained; that scaffolding is now removed in favor of the git-ref pattern (no scripts/vendor-packages.sh, no _vendor/COPY in the Dockerfile, no hooks.prepackage in azure.yaml).

Stack

PR-9 of 10 — the last PR. Nothing depends on it. The samples won't uv sync against the feature/python-hosting branch until PR-1..PR-8 land on that branch first; merging this PR earlier is harmless but the samples won't run.

#BranchRequired for samples
PR-1refactor/foundry-hosted-agent-history-providerfoundry_hosted_agent/
PR-2feat/hosting-coreall
PR-3feat/hosting-channel-responsesall
PR-4feat/hosting-channel-invocationsfoundry_hosted_agent/, local_identity_link/
PR-5afeat/hosting-channel-activity-protocollocal_identity_link/
PR-6feat/hosting-channel-telegramlocal_telegram/, local_identity_link/
PR-7feat/hosting-entra-helperslocal_identity_link/
PR-8feat/hosting-channel-discordvalidates channel abstractions; no current sample dependency

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible (samples — manual run validation)
  • Is this a breaking change? No — new samples.

@moonbox3Evan Mattson (moonbox3) added documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python labels May 5, 2026

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Code Review

Reviewers: 4 | Confidence: 93% | Result: All clear

Reviewed: Correctness, Security Reliability, Test Coverage, Design Approach


Automated review by eavanvalkenburg's agents

Comment threadpython/samples/04-hosting/af-hosting/foundry_hosted_agent/call_server.py Outdated
Comment threadpython/samples/04-hosting/af-hosting/foundry_hosted_agent/call_server.py Outdated
Comment threadpython/samples/04-hosting/af-hosting/local_identity_link/app.py Outdated
Comment threadpython/samples/04-hosting/af-hosting/local_identity_link/app.py Outdated
Eduard van Valkenburg (eavanvalkenburg) added a commit to eavanvalkenburg/agent-framework that referenced this pull request May 7, 2026
- foundry_hosted_agent/call_server.py: replace hard-coded
project_endpoint and service_session_id with FOUNDRY_PROJECT_ENDPOINT,
FOUNDRY_HOSTED_AGENT_NAME, and optional FOUNDRY_HOSTED_SESSION_ID
environment variables. Session-id is now optional so the sample
exercises the new-conversation path by default.
- local_identity_link/app.py:
* make_telegram_hook: apply the reasoning bump regardless of
identity-link state (the previous early-return on linked chats
silently dropped the high-effort preset for the very flow the
sample exists to demonstrate).
* make_responses_hook: add a prominent DEV-ONLY warning that the
client-supplied entra_oid shortcut bypasses identity verification
and must be replaced by a JWT validator in production.
* /link command: early-return when chat_id is missing instead of
minting an authorize URL keyed on "telegram:None" (which would
poison the link store with a binding any future chat_id-less
update would collapse onto).
* Switch ENTRA_CERT_PATH / ENTRA_CERT_PASSWORD env vars to the
longer ENTRA_CERTIFICATE_PATH / ENTRA_CERTIFICATE_PASSWORD names
that the README already documents.
* channels: Sequence[Channel] -> list[Channel] (the next line
appends, which a Sequence type doesn't expose).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@eavanvalkenburg
Eduard van Valkenburg (eavanvalkenburg)force-pushed the feature/python-hosting branch 2 times, most recently from 1a4caf6 to 25692a1CompareMay 22, 2026 11:54
Eduard van Valkenburg (eavanvalkenburg) added a commit to eavanvalkenburg/agent-framework that referenced this pull request May 22, 2026
- foundry_hosted_agent/call_server.py: replace hard-coded
project_endpoint and service_session_id with FOUNDRY_PROJECT_ENDPOINT,
FOUNDRY_HOSTED_AGENT_NAME, and optional FOUNDRY_HOSTED_SESSION_ID
environment variables. Session-id is now optional so the sample
exercises the new-conversation path by default.
- local_identity_link/app.py:
* make_telegram_hook: apply the reasoning bump regardless of
identity-link state (the previous early-return on linked chats
silently dropped the high-effort preset for the very flow the
sample exists to demonstrate).
* make_responses_hook: add a prominent DEV-ONLY warning that the
client-supplied entra_oid shortcut bypasses identity verification
and must be replaced by a JWT validator in production.
* /link command: early-return when chat_id is missing instead of
minting an authorize URL keyed on "telegram:None" (which would
poison the link store with a binding any future chat_id-less
update would collapse onto).
* Switch ENTRA_CERT_PATH / ENTRA_CERT_PASSWORD env vars to the
longer ENTRA_CERTIFICATE_PATH / ENTRA_CERTIFICATE_PASSWORD names
that the README already documents.
* channels: Sequence[Channel] -> list[Channel] (the next line
appends, which a Sequence type doesn't expose).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…osting/af-hosting
Adds five end-to-end sample apps under
``python/samples/04-hosting/af-hosting/`` that exercise the
``agent-framework-hosting`` Channels stack from the simplest single-channel
case up to a multi-channel deployment with cross-channel identity linking.
Samples (ordered by complexity)
-------------------------------
* ``foundry_hosted_agent/`` — minimal Responses + Invocations host with a
Foundry-backed agent and ``FoundryHostedAgentHistoryProvider``.
``agd``-deployable; bundles a ``Dockerfile`` and
``scripts/vendor-packages.sh`` that copies workspace packages into
``_vendor/`` for self-contained builds. ``_vendor/`` is gitignored.
* ``local_responses/`` — single-channel Responses host with a
``run_hook`` that strips caller-supplied options and forces a
reasoning preset. Demonstrates the hook seam over the uniform
``ChannelRequest`` envelope.
* ``local_responses_workflow/`` — Responses + Invocations exposing a
three-agent workflow with per-conversation checkpoint storage.
* ``local_telegram/`` — Responses + Telegram with a ``@tool``,
``FileHistoryProvider``, hooks, and a ``ResponseTarget`` multicast
variant (``call_server_multicast.py``) that pushes a single Responses
reply to a separate Telegram chat.
* ``local_identity_link/`` — full surface: Responses + Invocations +
Telegram + Activity Protocol (Teams) + the ``EntraIdentityLinkChannel``
sidecar. Resolves per-channel ids onto a single Entra object id so a
user's history follows them across surfaces.
Notes
-----
* Samples that use Telegram/Teams via Activity Protocol depend on the
renamed ``agent-framework-hosting-activity-protocol`` package (see the
PR-5 series).
* All samples use ``[tool.uv.sources]`` editable workspace deps, except
``foundry_hosted_agent/`` which uses the ``./_vendor/`` self-contained
layout for ``azd`` Docker builds.
* Each sample includes a ``README.md`` with run instructions and an
``app.py`` ASGI entrypoint plus a ``call_server.py`` client harness.
Depends on the prior hosting PRs (foundry-hosted-agent refactor +
hosting-core + the per-channel packages). After those merge, this
branch can be rebased onto ``main`` cleanly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…Hub branch
Switches every sample's ``[tool.uv.sources]`` from in-monorepo
editable path deps (which only resolve when running inside the
agent-framework workspace) to git refs targeting the
``feature/python-hosting`` branch on
``microsoft/agent-framework``. Samples now install standalone outside
the monorepo while the ``agent-framework-hosting*`` packages are still
pre-PyPI; once they publish, the ``[tool.uv.sources]`` block can be
dropped and the declared deps resolve from PyPI.
Cleanup
-------
* Drops ``foundry_hosted_agent/scripts/vendor-packages.sh``,
``_vendor/`` from ``.gitignore``, the ``hooks.prepackage`` block in
``azure.yaml`` and the ``COPY _vendor/`` step in the Dockerfile —
vendoring is no longer needed because git refs make the deps
network-resolvable from any context.
* Drops obsolete ``workspace.pyproject.toml`` reference and ``scripts/``
/ ``workspace.pyproject.toml`` entries from
``Dockerfile.dockerignore``.
* Updates the foundry sample's Dockerfile to ``uv sync --no-dev``
(no ``--frozen``) so it locks fresh against the GitHub-hosted deps
at build time.
* Drops every committed ``uv.lock`` because the resolver needs network
access to ``feature/python-hosting`` to lock — they regenerate the
first time a user runs ``uv sync`` after the branch lands.
* Refreshes the per-sample READMEs to mention the GitHub install path
instead of "in-tree workspace packages".
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- foundry_hosted_agent/call_server.py: replace hard-coded
project_endpoint and service_session_id with FOUNDRY_PROJECT_ENDPOINT,
FOUNDRY_HOSTED_AGENT_NAME, and optional FOUNDRY_HOSTED_SESSION_ID
environment variables. Session-id is now optional so the sample
exercises the new-conversation path by default.
- local_identity_link/app.py:
* make_telegram_hook: apply the reasoning bump regardless of
identity-link state (the previous early-return on linked chats
silently dropped the high-effort preset for the very flow the
sample exists to demonstrate).
* make_responses_hook: add a prominent DEV-ONLY warning that the
client-supplied entra_oid shortcut bypasses identity verification
and must be replaced by a JWT validator in production.
* /link command: early-return when chat_id is missing instead of
minting an authorize URL keyed on "telegram:None" (which would
poison the link store with a binding any future chat_id-less
update would collapse onto).
* Switch ENTRA_CERT_PATH / ENTRA_CERT_PASSWORD env vars to the
longer ENTRA_CERTIFICATE_PATH / ENTRA_CERTIFICATE_PASSWORD names
that the README already documents.
* channels: Sequence[Channel] -> list[Channel] (the next line
appends, which a Sequence type doesn't expose).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@eavanvalkenburg
Eduard van Valkenburg (eavanvalkenburg) merged commit 6b82285 into microsoft:feature/python-hostingMay 28, 2026
2 checks passed
Eduard van Valkenburg (eavanvalkenburg) added a commit that referenced this pull request Jun 17, 2026
* samples(hosting): add hosting Channels sample apps under samples/04-hosting/af-hosting
Adds five end-to-end sample apps under
``python/samples/04-hosting/af-hosting/`` that exercise the
``agent-framework-hosting`` Channels stack from the simplest single-channel
case up to a multi-channel deployment with cross-channel identity linking.
Samples (ordered by complexity)
-------------------------------
* ``foundry_hosted_agent/`` — minimal Responses + Invocations host with a
Foundry-backed agent and ``FoundryHostedAgentHistoryProvider``.
``agd``-deployable; bundles a ``Dockerfile`` and
``scripts/vendor-packages.sh`` that copies workspace packages into
``_vendor/`` for self-contained builds. ``_vendor/`` is gitignored.
* ``local_responses/`` — single-channel Responses host with a
``run_hook`` that strips caller-supplied options and forces a
reasoning preset. Demonstrates the hook seam over the uniform
``ChannelRequest`` envelope.
* ``local_responses_workflow/`` — Responses + Invocations exposing a
three-agent workflow with per-conversation checkpoint storage.
* ``local_telegram/`` — Responses + Telegram with a ``@tool``,
``FileHistoryProvider``, hooks, and a ``ResponseTarget`` multicast
variant (``call_server_multicast.py``) that pushes a single Responses
reply to a separate Telegram chat.
* ``local_identity_link/`` — full surface: Responses + Invocations +
Telegram + Activity Protocol (Teams) + the ``EntraIdentityLinkChannel``
sidecar. Resolves per-channel ids onto a single Entra object id so a
user's history follows them across surfaces.
Notes
-----
* Samples that use Telegram/Teams via Activity Protocol depend on the
renamed ``agent-framework-hosting-activity-protocol`` package (see the
PR-5 series).
* All samples use ``[tool.uv.sources]`` editable workspace deps, except
``foundry_hosted_agent/`` which uses the ``./_vendor/`` self-contained
layout for ``azd`` Docker builds.
* Each sample includes a ``README.md`` with run instructions and an
``app.py`` ASGI entrypoint plus a ``call_server.py`` client harness.
Depends on the prior hosting PRs (foundry-hosted-agent refactor +
hosting-core + the per-channel packages). After those merge, this
branch can be rebased onto ``main`` cleanly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* samples(hosting): point sample deps at the feature/python-hosting GitHub branch
Switches every sample's ``[tool.uv.sources]`` from in-monorepo
editable path deps (which only resolve when running inside the
agent-framework workspace) to git refs targeting the
``feature/python-hosting`` branch on
``microsoft/agent-framework``. Samples now install standalone outside
the monorepo while the ``agent-framework-hosting*`` packages are still
pre-PyPI; once they publish, the ``[tool.uv.sources]`` block can be
dropped and the declared deps resolve from PyPI.
Cleanup
-------
* Drops ``foundry_hosted_agent/scripts/vendor-packages.sh``,
``_vendor/`` from ``.gitignore``, the ``hooks.prepackage`` block in
``azure.yaml`` and the ``COPY _vendor/`` step in the Dockerfile —
vendoring is no longer needed because git refs make the deps
network-resolvable from any context.
* Drops obsolete ``workspace.pyproject.toml`` reference and ``scripts/``
/ ``workspace.pyproject.toml`` entries from
``Dockerfile.dockerignore``.
* Updates the foundry sample's Dockerfile to ``uv sync --no-dev``
(no ``--frozen``) so it locks fresh against the GitHub-hosted deps
at build time.
* Drops every committed ``uv.lock`` because the resolver needs network
access to ``feature/python-hosting`` to lock — they regenerate the
first time a user runs ``uv sync`` after the branch lands.
* Refreshes the per-sample READMEs to mention the GitHub install path
instead of "in-tree workspace packages".
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* samples(hosting): address PR #5645 review comments
- foundry_hosted_agent/call_server.py: replace hard-coded
project_endpoint and service_session_id with FOUNDRY_PROJECT_ENDPOINT,
FOUNDRY_HOSTED_AGENT_NAME, and optional FOUNDRY_HOSTED_SESSION_ID
environment variables. Session-id is now optional so the sample
exercises the new-conversation path by default.
- local_identity_link/app.py:
* make_telegram_hook: apply the reasoning bump regardless of
identity-link state (the previous early-return on linked chats
silently dropped the high-effort preset for the very flow the
sample exists to demonstrate).
* make_responses_hook: add a prominent DEV-ONLY warning that the
client-supplied entra_oid shortcut bypasses identity verification
and must be replaced by a JWT validator in production.
* /link command: early-return when chat_id is missing instead of
minting an authorize URL keyed on "telegram:None" (which would
poison the link store with a binding any future chat_id-less
update would collapse onto).
* Switch ENTRA_CERT_PATH / ENTRA_CERT_PASSWORD env vars to the
longer ENTRA_CERTIFICATE_PATH / ENTRA_CERTIFICATE_PASSWORD names
that the README already documents.
* channels: Sequence[Channel] -> list[Channel] (the next line
appends, which a Sequence type doesn't expose).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore(hosting-samples): apply sample formatting
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(hosting-samples): guard command input text
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@eavanvalkenburg
Eduard van Valkenburg (eavanvalkenburg) deleted the feat/hosting-samples branch June 30, 2026 09:02
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationUsage: [Issues, PRs], Target: documentation in the code base and learn docspythonUsage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@eavanvalkenburg@moonbox3