Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ def as_skills_provider(
source_id: str | None = None,
instruction_template: str | None = None,
disable_caching: bool = False,
disable_load_skill_approval: bool = False,
disable_read_skill_resource_approval: bool = False,
disable_run_skill_script_approval: bool = False,
) -> SkillsProvider:
"""Return a :class:`~agent_framework.SkillsProvider` backed by this toolbox.

Expand All @@ -214,6 +217,18 @@ def as_skills_provider(
skills; see :class:`~agent_framework.SkillsProvider`.
disable_caching: Re-query the toolbox on every agent run instead of
caching after the first discovery.
disable_load_skill_approval: When ``True``, register the provider's
``load_skill`` tool with ``approval_mode="never_require"`` so loading
a skill body needs no host approval. Set this for unattended agents
(for example, an agent hosted behind :class:`ResponsesHostServer`,
which runs without an :class:`~agent_framework.AgentSession` and so
cannot satisfy the default approval flow). Defaults to ``False``.
disable_read_skill_resource_approval: When ``True``, register the
provider's ``read_skill_resource`` tool with
``approval_mode="never_require"``. Defaults to ``False``.
disable_run_skill_script_approval: When ``True``, register the provider's
``run_skill_script`` tool with ``approval_mode="never_require"``.
Defaults to ``False``.

Returns:
A :class:`~agent_framework.SkillsProvider` that advertises and loads the
Expand All @@ -228,7 +243,9 @@ def as_skills_provider(
# ``tools=toolbox`` connects the MCP session; ``load_tools=False``
# keeps its tools hidden so only its skills are surfaced.
tools=toolbox,
context_providers=[toolbox.as_skills_provider()],
# ``disable_load_skill_approval`` lets the hosted agent load
# skills without an approval round-trip (no AgentSession needed).
context_providers=[toolbox.as_skills_provider(disable_load_skill_approval=True)],
default_options={"store": False},
)
await ResponsesHostServer(agent).run_async()
Expand All @@ -238,6 +255,9 @@ def as_skills_provider(
source_id=source_id,
instruction_template=instruction_template,
disable_caching=disable_caching,
disable_load_skill_approval=disable_load_skill_approval,
disable_read_skill_resource_approval=disable_read_skill_resource_approval,
disable_run_skill_script_approval=disable_run_skill_script_approval,
)


Expand Down
29 changes: 29 additions & 0 deletions python/packages/foundry_hosting/tests/test_toolbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,35 @@ def test_as_skills_provider_returns_provider() -> None:
assert provider.source_id == "toolbox-skills"


def test_as_skills_provider_requires_approval_by_default() -> None:
toolbox = FoundryToolbox(
_FakeCredential(), # type: ignore
url="https://h/toolboxes/tb/mcp",
)
provider = toolbox.as_skills_provider()
# By default every skill tool keeps its approval requirement.
assert provider._disable_load_skill_approval is False # pyright: ignore[reportPrivateUsage]
assert provider._disable_read_skill_resource_approval is False # pyright: ignore[reportPrivateUsage]
assert provider._disable_run_skill_script_approval is False # pyright: ignore[reportPrivateUsage]


def test_as_skills_provider_forwards_approval_overrides() -> None:
toolbox = FoundryToolbox(
_FakeCredential(), # type: ignore
url="https://h/toolboxes/tb/mcp",
)
provider = toolbox.as_skills_provider(
disable_load_skill_approval=True,
disable_read_skill_resource_approval=True,
disable_run_skill_script_approval=True,
)
# Overrides flow through to the underlying SkillsProvider so an unattended
# host (no AgentSession) can load skills without an approval round-trip.
assert provider._disable_load_skill_approval is True # pyright: ignore[reportPrivateUsage]
assert provider._disable_read_skill_resource_approval is True # pyright: ignore[reportPrivateUsage]
assert provider._disable_run_skill_script_approval is True # pyright: ignore[reportPrivateUsage]


async def test_skills_source_requires_connection() -> None:
toolbox = FoundryToolbox(
_FakeCredential(), # type: ignore
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
agent.manifest.yaml
agent.yaml
.env.example
.env
toolbox.yaml
skills
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ __pycache__
*.pyd
.Python
.env
skills
toolbox.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
FOUNDRY_PROJECT_ENDPOINT="..."
AZURE_AI_MODEL_DEPLOYMENT_NAME="..."
TOOLBOX_NAME="..."
# Full versioned MCP endpoint of the skills toolbox the agent consumes.
# Copy this from the output of `azd ai toolbox create ... --from-file ./toolbox.yaml`.
# Example: https://<account>.services.ai.azure.com/api/projects/<project>/toolboxes/maf-skills-toolbox/versions/1/mcp?api-version=v1
TOOLBOX_ENDPOINT="..."
Loading
Loading