Skip to content

Host fibey agent in Foundry; load skills via toolbox MCP#2

Open
lindazqli wants to merge 1 commit into
dbarkol:mainfrom
lindazqli:feat/hosted-agent-and-mcp-skills
Open

Host fibey agent in Foundry; load skills via toolbox MCP#2
lindazqli wants to merge 1 commit into
dbarkol:mainfrom
lindazqli:feat/hosted-agent-and-mcp-skills

Conversation

@lindazqli

Copy link
Copy Markdown

Summary

This PR makes the fibey agent deployable as a Foundry hosted agent in the same project and consolidates the agent's skills behind the Foundry Toolbox so they are served via MCP resources (SEP-2640 skills extension) instead of being bundled into each deployable.

It also fixes a real streaming-termination bug in the gateway's hosted proxy.

Changes

Hosted agent (Foundry-hosted entrypoint)

  • src/fibey/agent/hosted.py rewritten to follow the foundry-samples 04-foundry-toolbox pattern.
    • Toolbox MCP URL is resolved from FOUNDRY_PROJECT_ENDPOINT + TOOLBOX_NAME (no hard-coded URL).
    • Skills are pre-loaded synchronously at startup via the new MCPSkillsSource, so they are ready before the first request.
    • default_options={"store": False} per the sample.
    • _ResilientResponsesHostServer now overrides the correct parent method (_handle_inner, not _handle_inner_agent); the previous override was dead code and the context.get_history fallback never ran.
    • OpenTelemetry instrumentation enabled via configure_otel_providers(enable_sensitive_data=True) so traces flow to the project's Application Insights and show in the portal's Tracing tab.
  • Dockerfile.agent: run as module (python -m fibey.agent.hosted) and set PYTHONPATH=/app/user_agent/src so package-relative imports resolve.
  • azure.yaml: matching startupCommand: python -m fibey.agent.hosted.
  • agent.yaml: replace TOOLBOX_MCP_URL with TOOLBOX_NAME (URL is now resolved from the auto-injected project endpoint).
  • requirements.txt: pin agent-framework[foundry]>=1.4.0. Without the [foundry] extra, from agent_framework.foundry import FoundryChatClient fails at import and the container never passes its readiness probe.

MCP-published skills

  • New src/fibey/agent/mcp_skills_source.py implements SkillsSource against any MCP server publishing skill://*/SKILL.md resources. Tolerant of the toolbox's double-frontmatter quirk; works with bearer or API-key auth; sends the Foundry-Features: Toolboxes=V1Preview header.
  • src/fibey/agent/agent.py:
    • _build_skills_provider: prefer MCP skills when TOOLBOX_MCP_URL is set; fall back to FileSkillsSource otherwise. SKILLS_SOURCE=mcp|file|auto to force.
    • create_agent is now async (needed for MCP skill loading); run_agent awaits it.
    • Minor: explicit UTF-8 when reading the system prompt to avoid Windows code-page issues.

Gateway streaming fix

  • src/fibey/gateway/api_server.py _run_hosted: when the upstream Responses SSE stream emits data: [DONE], the previous code only breaked the inner buffer loop and kept awaiting more bytes on the outer aiter_text() loop — so the gateway never reached its own yield _sse("done", "[DONE]") and the UI spinner hung. Added a stream_done flag that propagates the termination to the outer loop.
  • Added logging.basicConfig(level=logging.INFO) so gateway INFO logs are visible during local dev.

Tooling

  • scripts/smoke_mcp_skills.py — exercises MCPSkillsSource against the live toolbox.
  • scripts/probe_toolbox_resources.py — lists raw MCP resources for debugging.

Validation

  • Local mode (AGENT_MODE=local): UI streams correctly; gateway logs show 5 skills loaded from the toolbox; load_skilltool_searchcall_tool chain completes and rendered output matches expectations (e.g. WO-007 briefing, OTDR stock lookup).
  • Hosted mode: agent deployed to fibey-project-westus2 (version 3) via azd deploy; azd ai agent invoke "Do we have OTDR test equipment in stock?" returns a fully formatted markdown response. App Insights confirms Inbound POST /responses completed with status 200 for streaming requests.

Notes for reviewers

  • The OTel exporter currently logs 403 insufficient_scope for the Agent365.Observability.OtelWrite app role — this is a workspace-level RBAC config (not in this PR's scope) and only affects whether GenAI spans show in the portal Tracing tab.

- Add MCPSkillsSource adapter that loads skills published by the Foundry
  Toolbox (SEP-2640 skills extension) as InlineSkill instances usable by
  the existing SkillsProvider, no framework changes required.
- agent.py: prefer MCP-published skills when TOOLBOX_MCP_URL is set, with
  graceful fallback to FileSkillsSource via SKILLS_SOURCE env var.
- hosted.py: rewrite to follow the foundry-samples 04-foundry-toolbox
  pattern. Resolves the toolbox MCP URL from FOUNDRY_PROJECT_ENDPOINT +
  TOOLBOX_NAME, pre-loads skills synchronously at startup, sets
  default_options={store: False}, and enables OpenTelemetry instrumentation
  so traces flow to the project Application Insights.
- _ResilientResponsesHostServer: override the correct parent method
  (_handle_inner, not _handle_inner_agent) so the get_history fallback
  actually runs.
- agent.yaml: switch from TOOLBOX_MCP_URL to TOOLBOX_NAME.
- Dockerfile.agent / azure.yaml: run hosted entrypoint as a module
  (python -m fibey.agent.hosted) and set PYTHONPATH so package-relative
  imports resolve.
- requirements.txt: require agent-framework[foundry] extras; without
  them FoundryChatClient is unimportable and the container fails its
  readiness probe.
- Gateway _run_hosted: fix [DONE] handling so the outer aiter_text loop
  actually terminates (previously only the inner buffer loop broke,
  leaving the upstream connection open after [DONE]).
- Add scripts/smoke_mcp_skills.py and scripts/probe_toolbox_resources.py
  for local validation of the toolbox MCP skills path.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant