Commit Graph

409 Commits

Author SHA1 Message Date
Henry Su acbcdaa086 Python: fix(python): handle callable class middleware safely in _determine_middleware_type (#6697) (#7333)
* fix(python): handle callable class middleware safely in _determine_middleware_type (#6697)

* test(python): type-annotate test middleware lists to pass test-typing checks
2026-07-27 19:39:47 +00:00
Sriraj 5ccd7784a6 Python: Reject Windows junctions in FileSystemAgentFileStore (#7291)
* Python: reject file-store junctions during enumeration

* Python: clarify file-store probe diagnostics
2026-07-27 10:47:57 +00:00
Tao Chen 0df184e7dd Python: Fix sub-workflow checkpoint restore to preserve sub-workflow state (#7097)
* Fix sub-workflow checkpoint restore to preserve sub-workflow state

Add Runner.capture_checkpoint_object/restore_from_checkpoint_object (quiescent-only nested checkpoint) and embed a sub_workflow_checkpoint in WorkflowExecutor.on_checkpoint_save/on_checkpoint_restore so a resumed parent restores each sub-workflow's mid-progress state instead of only replaying pending request-info events. Keeps a backward-compat fallback when sub_workflow_checkpoint is absent.

* Move checkpoint-object construction into the runner context

Add RunnerContext.create_checkpoint_object alongside create_checkpoint (create_checkpoint now delegates to it and persists), so Runner.capture_checkpoint_object builds the snapshot via the context instead of a one-off get_messages peek primitive. In-flight messages are captured non-destructively (per-source lists copied). The checkpoint-less capturing contexts (azurefunctions, durabletask) raise NotImplementedError to match create_checkpoint.

* Remove per-execution bookkeeping from WorkflowExecutor

The sub-workflow is a single shared instance, so per-execution ExecutionContext/request routing never provided real isolation. Delegate request/response tracking to the sub-workflow itself: can_handle accepts targeted propagated responses, _handle_response validates against the sub-workflow's pending requests and forwards responses immediately, and on_checkpoint_save embeds only the sub-workflow checkpoint (on_checkpoint_restore keeps a legacy reader for older checkpoints). Also emit the fresh-message/checkpoint-while-pending warning from FunctionalWorkflow.run to match Workflow.run.

* Drop redundant decode in WorkflowExecutor.on_checkpoint_restore

The storage backend already materializes the full checkpoint on load (FileCheckpointStorage decodes recursively; InMemoryCheckpointStorage deep-copies), so the embedded sub_workflow_checkpoint (and legacy execution_contexts) arrive already decoded - like every other executor's on_checkpoint_restore state. Remove the no-op decode_checkpoint_value calls and the now-unused import.

* Clean up

* Do not allow checkpoint storage in sub workflow

* Address comments

* Fix syntax check

* Add warning

---------

Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
2026-07-24 17:21:41 +00:00
Atharva Vichare d98ac29115 Python: Fix duplicate function call on approval round-trip (#7267) (#7271)
* Python: Fix duplicate function call on approval round-trip (#7267)

`_replace_approval_contents_with_results` deduped restored function calls
against only the message currently being scanned. On an approval round-trip
the hosting layer replays the stored `function_call` item and its
`mcp_approval_request` item as two separate assistant messages, so the
per-message check never fired and the approval request restored a second
copy of the call.

Only one copy received the function result; the orphaned copy was left
unanswered, which the Responses API rejects with
"No tool output found for function call call_<id>".

Collect existing call ids across all messages instead, and add a restored
call to that set so two approval requests for the same call cannot both
expand.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Refactor approval placeholder result handling

Refactor approval handling logic to improve clarity and maintainability.

* Refactor test to support reused call IDs after completion

Updated the test to allow reused call IDs after completion, ensuring that a completed call does not suppress later approval requests with the same ID. Adjusted assertions to reflect the new behavior.

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 21:27:26 +00:00
Eduard van Valkenburg 5147579992 Python: Enforce package coverage by lifecycle (#7261)
* Enforce Python coverage by package lifecycle

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9ae5ad8e-6b66-41b3-a862-4e2a3fae1cd0

* Fix Python CI and deprecation usage

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

Copilot-Session: 9ae5ad8e-6b66-41b3-a862-4e2a3fae1cd0

* Make POSIX kill-tree test portable

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

Copilot-Session: 9ae5ad8e-6b66-41b3-a862-4e2a3fae1cd0

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9ae5ad8e-6b66-41b3-a862-4e2a3fae1cd0
2026-07-23 02:38:28 +00:00
Evan Mattson a2927c1c09 Python: Fix stateless replay of reasoning-paired tool calls (#7233)
* Python: Fix reasoning-paired client tool replay

* Python: Handle middleware-terminated reasoning tool loops

* Python: Replay encrypted reasoning function groups

Key decisions:
- Request encrypted reasoning on client-managed Responses calls while preserving caller include values.
- Store encrypted payloads in Content.protected_data and reconstruct one provider reasoning item per reasoning id.
- Replay active and completed function call/result groups; retain continuation-owned history behavior and the existing orphan-safe MCP path.

Files changed:
- python/packages/openai/agent_framework_openai/_chat_client.py
- python/packages/openai/tests/openai/test_openai_chat_client.py

Next iteration:
- Extend encrypted reasoning preservation to streaming and framework serialization boundaries.

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

* Python: Preserve encrypted reasoning through streaming

Key decisions:
- Capture encrypted reasoning from terminal streamed output items in Content.protected_data.
- Preserve summary and private reasoning as distinct framework contents while reconstructing one provider reasoning item per id.
- Prove replay after Message JSON and workflow checkpoint round trips, including encrypted-only and completed function groups.

Files changed:
- python/packages/core/agent_framework/_types.py
- python/packages/openai/agent_framework_openai/_chat_client.py
- python/packages/openai/tests/openai/test_openai_chat_client.py

Next iteration:
- Extend lossless stateless reasoning replay to hosted MCP call/output groups.

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

* Python: Replay hosted MCP reasoning groups

Key decisions:
- Preserve hosted MCP call/output groups in client-managed history instead of deleting them when reasoning cannot be reconstructed.
- Keep call/result coalescing and orphan-result exclusion intact, while retaining continuation-owned duplicate avoidance.
- Cover completed, active, and multi-call reasoning groups plus the public outgoing request boundary.

Files changed:
- python/packages/openai/agent_framework_openai/_chat_client.py
- python/packages/openai/tests/openai/test_openai_chat_client.py

Next iteration:
- Preserve middleware-terminated and parallel function groups atomically.
- Add preflight rejection for non-replayable reasoning groups in the dedicated validation slice.

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

* Python: Preserve terminated parallel reasoning groups

Key decisions:
- Return ordinary function results when middleware terminates a loop, removing the provider-specific durable marker.
- Preserve every parallel call and available sibling result as one encrypted reasoning group in stateless replay.
- Prove successful and policy-blocked batches through the public two-agent Foundry workflow and outgoing HTTP boundary.

Files changed:
- python/packages/core/agent_framework/_tools.py
- python/packages/core/tests/core/test_function_invocation_logic.py
- python/packages/openai/tests/openai/test_openai_chat_client.py
- python/packages/foundry/tests/foundry/test_foundry_agent.py

Next iteration:
- Add preflight rejection for non-replayable and partially compacted reasoning groups.

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

* Python: Reject unsafe stateless reasoning replay

Key decisions:
- Validate client-managed reasoning groups after compaction and report every affected reasoning and call identifier before transport.
- Permit service-owned continuation and fully excluded atomic groups while rejecting partial compaction projections.
- Surface encrypted-reasoning capability failures without lossy retries.

Files changed:
- python/packages/openai/agent_framework_openai/_chat_client.py
- python/packages/openai/tests/openai/test_openai_chat_client.py

Next iteration:
- Run the resource-specific Foundry proof and finish PR #7233; that live proof remains intentionally local and requires the configured developer resource.

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

* Python: Preserve reasoning metadata in Foundry hosting

* Python: Avoid duplicating reasoning text metadata

* Python: Gate encrypted reasoning for Foundry agents

* Python: Type stateless reasoning integration test

* Python: Narrow Foundry mock call arguments

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-22 23:51:22 +00:00
Giles Odigwe 1466d68cf1 Python: make FoundryToolbox.as_skills_provider() disable_caching effective (#7135)
* Python: make FoundryToolbox.as_skills_provider() disable_caching effective

as_skills_provider() forwarded disable_caching to SkillsProvider, which
ignores it for a caller-supplied SkillsSource, so it was a no-op and the
toolbox re-read skill://index.json on every agent run.

Compose caching in as_skills_provider() instead: wrap the context-independent
_FoundryToolboxSkillsSource in DeduplicatingSkillsSource(CachingSkillsSource(...)).
Add a cache_refresh_interval param, fix the docstring, and add tests covering
cached, disabled, and refresh-interval behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 84150ec4-6f7c-4ef8-b9fb-12fa11652773

* Clarify caller-invariant skill-set wording in as_skills_provider docs

Emphasize that the toolbox advertises the same skill set to every caller (the
per-request call-id governs execution/authorization, not which skills are
listed) rather than leaning on 'ignores SkillsSourceContext'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 84150ec4-6f7c-4ef8-b9fb-12fa11652773

* Make MCP skills reconnect-safe via session_provider

Cached MCPSkill objects captured the MCP ClientSession at construction, so
after a FoundryToolbox reconnect (which replaces its session) load_skill and
read_skill_resource would fail against the closed session. This regressed once
as_skills_provider() started caching discovery by default.

Add an optional session_provider callable to MCPSkillsSource and MCPSkill
(exactly one of client or session_provider). When supplied, the session is
resolved on every fetch, mirroring how MCPTool resolves self.session live at
call time. _FoundryToolboxSkillsSource now passes a provider that returns the
toolbox's current session, so cached skills always use the live session.

The fixed client= path is unchanged and backward-compatible. Update core tests,
foundry_hosting tests, and core AGENTS.md.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 84150ec4-6f7c-4ef8-b9fb-12fa11652773

* Fix ty error: type captured session_provider as Callable in test

ty could not call the provider narrowed from \object\ (Top callable). Type the
captured value as Callable[[], object] and drop the redundant callable() assert.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 84150ec4-6f7c-4ef8-b9fb-12fa11652773

* Simplify _resolve_mcp_session_provider per review

Address review feedback: replace the dense (client is None) == (session_provider
is None) guard with explicit branches, and drop the cast by binding the narrowed
client to a typed local. Keeps strict 'exactly one' semantics (raises on both and
on neither), matching the codebase convention (e.g. security.py mcp_tool/url).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 84150ec4-6f7c-4ef8-b9fb-12fa11652773

* Add PR #7135 entries to the 1.12.0 changelog

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 84150ec4-6f7c-4ef8-b9fb-12fa11652773

* Drop redundant @pytest.mark.asyncio from MCP skills tests

asyncio_mode is 'auto', so the marker is unnecessary. Remove it from the whole
file for consistency with the async-by-default convention. Per review feedback.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 84150ec4-6f7c-4ef8-b9fb-12fa11652773

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-21 18:02:38 +00:00
Eduard van Valkenburg d08200d00e Python: Bump package versions for 1.12.0 release (#7238)
* 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
2026-07-21 15:45:00 +00:00
Robbie Walmsley a4f02aabf0 Python: Fix header_provider headers not reaching streamable HTTP transport requests (#7218)
* Python: fix header_provider headers not reaching streamable HTTP requests

MCPStreamableHTTPTool.call_tool stores header_provider output in a
ContextVar, but the streamable HTTP transport sends requests from tasks
spawned at connect time, whose contexts never observe values set later.
The request hook therefore always read an empty dict on real connections
and the per-call headers (e.g. Authorization) were silently dropped.

Keep the ContextVar for in-context reads and add an instance-level
snapshot of the active call's headers that the request hook falls back
to across tasks.

* Python: serialize header_provider tool calls to prevent cross-call header mixing

Parallel tool invocations run concurrently per function-invocation batch,
so two call_tool invocations on the same MCPStreamableHTTPTool could
overwrite each other's active-header snapshot while requests were still
in flight, attaching the wrong per-call credentials. Hold a per-instance
lock for the duration of a header-bearing call, add a regression test
that fails without the lock, and normalize captured header casing in the
transport-task test.
2026-07-21 13:20:27 +00:00
HaoFeng Zhao afdf8af400 Python: Prevent compaction from emitting empty projections (#7219)
* Python: preserve a non-empty compaction projection

* Python: annotate compaction regression input

* Python: document compaction retention floor
2026-07-21 13:16:43 +00:00
Scarab Systems 9e836f7b42 Python: Return MCP tool-use sampling results (#7189)
* Python: support MCP sampling tool-use results

* Python: align MCP sampling test tool schemas

* Python: centralize MCP sampling content type
2026-07-21 12:27:34 +00:00
Evan Mattson c218067646 Python: Consolidate dependency updates (#7204)
* Bump uv from 0.11.28 to 0.11.29 in /python

Bumps [uv](https://github.com/astral-sh/uv) from 0.11.28 to 0.11.29.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.11.28...0.11.29)

---
updated-dependencies:
- dependency-name: uv
  dependency-version: 0.11.29
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump zuban from 0.8.2 to 0.9.0 in /python

Bumps [zuban](https://github.com/zubanls/zubanls-python) from 0.8.2 to 0.9.0.
- [Release notes](https://github.com/zubanls/zubanls-python/releases)
- [Commits](https://github.com/zubanls/zubanls-python/compare/v0.8.2...v0.9.0)

---
updated-dependencies:
- dependency-name: zuban
  dependency-version: 0.9.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* PR #7146: Bump ty from 0.0.55 to 0.0.60 in /python

* Bump ruff from 0.15.20 to 0.15.22 in /python

Bumps [ruff](https://github.com/astral-sh/ruff) from 0.15.20 to 0.15.22.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.15.20...0.15.22)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.15.21
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump mypy from 2.2.0 to 2.3.0 in /python

Bumps [mypy](https://github.com/python/mypy) from 2.2.0 to 2.3.0.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v2.2.0...v2.3.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-version: 2.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump prek from 0.4.8 to 0.4.10 in /python

Bumps [prek](https://github.com/j178/prek) from 0.4.8 to 0.4.10.
- [Release notes](https://github.com/j178/prek/releases)
- [Changelog](https://github.com/j178/prek/blob/master/CHANGELOG.md)
- [Commits](https://github.com/j178/prek/compare/v0.4.8...v0.4.10)

---
updated-dependencies:
- dependency-name: prek
  dependency-version: 0.4.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump azure-ai-projects from 2.2.0 to 2.3.0 in /python

Bumps azure-ai-projects from 2.2.0 to 2.3.0.

---
updated-dependencies:
- dependency-name: azure-ai-projects
  dependency-version: 2.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump types-python-dateutil in /python

Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.9.0.20260518 to 2.9.0.20260716.
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-python-dateutil
  dependency-version: 2.9.0.20260716
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump mypy from 2.2.0 to 2.3.0 in /python

Bumps [mypy](https://github.com/python/mypy) from 2.2.0 to 2.3.0.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v2.2.0...v2.3.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-version: 2.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump botocore from 1.43.45 to 1.43.49 in /python

Bumps [botocore](https://github.com/boto/botocore) from 1.43.45 to 1.43.49.
- [Commits](https://github.com/boto/botocore/compare/1.43.45...1.43.49)

---
updated-dependencies:
- dependency-name: botocore
  dependency-version: 1.43.49
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* PRs #7144/#7147: Align lab uv and ruff pins

* Regenerate lockfile for Python Dependabot PRs #7144-#7153

* Python: Support azure-ai-projects 2.3 session operations (#7150)

* Python: Apply Ruff 0.15.22 suppression updates (#7147)

* Python: Update tests for ty 0.0.60 (#7146)

* Python: Update Foundry samples for azure-ai-projects 2.3 (#7150)

* Python: Address dependency rollup review comments

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-20 18:01:24 +00:00
westey ac474100ce Python: [BREAKING] Graduate create_harness_agent out of experimental (#7120)
* Graduate harness agent

* Add agents.md update

* Fix build errors

* Address PR comments

* Fix build error
2026-07-20 18:00:28 +00:00
Yufeng He 7c6b1e975f Python: fix compaction token count inflating non-ASCII text (#7124)
TokenBudgetComposedStrategy estimates tokens by feeding a JSON-serialized
message to the tokenizer, but _serialize_message() used ensure_ascii=True.
That escapes non-ASCII text into \uXXXX sequences, so CJK and other
non-Latin content is token-counted as the escape sequences rather than the
characters the model actually sees, inflating the estimate (~1.6x for mixed
Japanese, more for pure CJK) and skewing compaction/token-budget decisions.

Serialize with ensure_ascii=False, matching the ensure_ascii=False already
used elsewhere in this module. Only affects token estimation; the serialized
string is never stored or transmitted.

Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
2026-07-19 12:44:40 +00:00
Yufeng He 0d2925037d Python: preserve explicit null arguments in auto function calling (#7108)
* Python: preserve explicit null arguments in auto function calling

FunctionTool.invoke dumped validated arguments with model_dump(exclude_none=True),
which strips any argument the model set to null. A required nullable parameter
(e.g. unit: Literal["C","F"] | None) that the model deliberately sets to null was
therefore dropped, and the function failed to invoke on the missing argument.

Use exclude_unset instead: keep the arguments the model actually provided (null
included) and omit only the ones it left out, so the function's own defaults still
apply. Because the input model is generated from the function signature, its field
defaults match the signature defaults, so omitted optionals are unchanged.

Fixes #5934

Signed-off-by: Yufeng He <40085740+he-yufeng@users.noreply.github.com>

* Python: extend null-arg fix to the auto function-calling path

The earlier change fixed FunctionTool.invoke, but _auto_invoke_function
(the path a model-emitted function_call actually takes) still ran
model_dump(exclude_none=True), so an explicit null for a required
nullable argument was still dropped and the call failed with a missing
argument. Switch it to exclude_unset to match invoke, and add a
regression test that drives _auto_invoke_function with an explicit null.

---------

Signed-off-by: Yufeng He <40085740+he-yufeng@users.noreply.github.com>
Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
2026-07-19 12:43:41 +00:00
Eduard van Valkenburg 62da382082 Python: Optimize shared serialization paths (#7165)
* Optimize core serialization paths

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

Copilot-Session: cda42f21-2500-4f78-a527-d6eeaeef922b

* Streamline AG-UI serialization

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

Copilot-Session: cda42f21-2500-4f78-a527-d6eeaeef922b

* Document shared serialization guidance

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

Copilot-Session: cda42f21-2500-4f78-a527-d6eeaeef922b

* Bound serialization protocol cache

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

Copilot-Session: cda42f21-2500-4f78-a527-d6eeaeef922b
2026-07-17 22:09:53 +00:00
VectorPeak 6afae2f9b4 Python: raise ValueError for malformed data URIs (#6916)
* Python: raise ValueError for malformed data URIs

* Address malformed data URI review feedback

---------

Co-authored-by: VectorPeak <VectorPeak@users.noreply.github.com>
Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
2026-07-17 11:40:20 +00:00
westey a376577263 Gradudate FileMemoryProvider (#7113) 2026-07-15 22:57:21 +00:00
Tao Chen b2549337ff Python: Best effort to serialize tool def to Json for observability (#7029)
* Best effort to serialize tool def to Json

* Fix formatting

* Fix tests

* Optimize json serialization

* Best effort: Add secret filtering

* Remove frozen set and only convert required fields

* Fix tests

* Address comments

* Fix typing
2026-07-15 20:43:36 +00:00
Evan Mattson c35a63ed8d Python: feat: cross-session origin attribution on context messages (#7041)
* Python: feat: cross-session origin attribution on context messages

Add an optional origin_session_id parameter to SessionContext.extend_messages
that propagates into the existing _attribution payload on
Message.additional_properties. Downstream context observers can use it to
detect when a provider injects content stored under a different session than
the requesting one.

Populate the field from the harness memory consolidation pipeline
(_harness/_memory.py) when injected topics include contributions from
sessions other than the current one. Add a self-contained sample observer
under samples/02-agents/context_providers/cross_session_observer.py
demonstrating how to subscribe to the signal.

Backward-compatible: omitting the parameter preserves the existing
attribution shape exactly. Tests added in test_sessions.py and
test_harness_memory.py cover the new parameter, the harness cross-session
case, and the same-session case.

Motivated by Dai et al., Stateful Agent Backdoor (arXiv:2605.06158, May
2026), which specifically surveys MAF in section 6.1 / Table 10.
See #5914 for design discussion.

Surfaced during independent audit conducted by @finnoybu (Ken Tannenbaum, AEGIS Initiative); [MEDIUM, python/packages/core].

* Address cross-session attribution review feedback

* Address follow-up review feedback

* Address follow-up review comments

* Address origin attribution review feedback

---------

Co-authored-by: finnoybu <21694570+finnoybu@users.noreply.github.com>
2026-07-14 17:34:52 +00:00
t-anjan 1c0082721c Python: Fix structured value parsing for split text chunks (#6990)
* Fix structured value parsing for split text chunks

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Fix structured value parsing for split text chunks

---------

Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-14 08:39:11 +00:00
Syed Osama Ali Shah df198005fd Python: fix: preserve function-call name when merging streaming deltas (#6809)
* fix: preserve function-call name when merging streaming deltas

`Content._add_function_call_content` built the merged name with
`getattr(self, "name", getattr(other, "name", None))`. Because
`Content.__init__` always sets `self.name` (defaulting to `None`), the
attribute is never missing, so the `getattr` default is never consulted
and `other.name` is ignored. When two function_call contents are merged
and only the second carries the name -- e.g. a streaming delta where the
function name arrives after the first chunk -- the name was silently
dropped.

Use the same "either side" pattern already used for the sibling
`exception` field on the next line: `getattr(self, "name", None) or
getattr(other, "name", None)`. Extend the existing merge test to cover
the late-name and both-None cases.

* test: construct nameless function-call deltas via Content(...) directly

Per review (pyright `reportArgumentType`): `Content.from_function_call`
annotates `name: str`, so passing `name=None` to model a streaming delta
with no name yet tripped the typing gate. Build those nameless deltas
with the `Content("function_call", ...)` constructor instead (its `name`
param is `str | None`) — the factory just wraps that same constructor, so
the runtime objects and the merge assertions are unchanged.

---------

Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
2026-07-14 06:36:57 +00:00
Evan Mattson 18b03ea487 Python: adjust checkpoint encoding handling (#6579)
* Adjust checkpoint encoding handling

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

* Refine checkpoint encoding handling

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

* Adjust checkpoint dict encoding

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

* Clarify checkpoint unpickler blocked globals

* Preserve typed HITL requests in durable activities

* test: skip flaky durabletask multi-turn integration test

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-14 15:21:12 +09:00
westey f11cfd9d76 Switch FileAcessProvider on Harness to opt-in (#7094) 2026-07-14 02:26:59 +00:00
westey c9b19e831f Gradudate mode and todo providers (#7053) 2026-07-13 13:47:53 +00:00
westey b3d523ee50 Python: [BREAKING] Fix harness before-strategy compaction under per-service-call persistence (#7055)
* Fix middleware ordering to ensure compaction runs

* Address PR comments

* Fix build issue
2026-07-13 09:51:00 +00:00
ByteWise 7f4cc296fd Python: preserve tool span context for parallel calls (#6512)
* Python: preserve tool span context for parallel calls

* Python: address parallel tool span review feedback

* Python: fix parallel tool span test checks

---------

Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
2026-07-13 00:07:53 +00:00
Benke Qu f3057ef20c Python: fix: clear service_session_id in _agent_wrapper when propagate_session=True (#5875)
* fix: clear service_session_id in _agent_wrapper when propagate_session=True

When propagate_session=True, the child agent inherits the parent's
service_session_id. After the parent's first LLM call, MAF auto-populates
this from the Responses API conversation_id. The child sends it as
previous_response_id which the server rejects because the parent's
tool_call is still pending (400 error).

This fix saves and clears service_session_id before calling the child
agent and restores it in a finally block, preserving session.state
sharing while isolating the server-side conversation pointer.

Fixes #5874

* refactor: use child session copy instead of in-place mutation

Address Copilot review comments:
- Create a child AgentSession with shared state dict but isolated
  service_session_id, avoiding race conditions under concurrent
  asyncio.gather tool invocations.
- Update tests to verify child gets a separate session object and
  that child-set service_session_id does not leak to parent.

* fix: update test_chat_agent_as_tool_propagate_session_true for child session isolation

The existing test asserted captured_session is parent_session, but since
we now create a separate child AgentSession (to avoid racing under concurrent
asyncio.gather), the child is a different object. Updated assertions to verify:
- child is NOT the parent object (isolation)
- child shares the same session_id and state dict (by reference)
- child's service_session_id is None (isolated)

* fix: add type narrowing asserts for captured_session

Add 'assert captured_session is not None' before attribute access to
satisfy mypy/pyright type checking on Optional values.

* Python: Fix test typing checks

---------

Co-authored-by: Benke Qu <bequ@microsoft.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
Co-authored-by: Evan Mattson <evan.mattson@microsoft.com>
2026-07-12 23:37:53 +00:00
Eduard van Valkenburg 68136ee081 Python: Clean up dependency groups and compatibility (#7046)
* Python: Clean up dependency management

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

Copilot-Session: 2f7b1c89-f3ff-418d-ab4e-4f014fda308f

* Python: Harden Mistral SDK import fallback

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

Copilot-Session: 2f7b1c89-f3ff-418d-ab4e-4f014fda308f
2026-07-10 22:40:42 +00:00
westey ce96fd4b72 Python: Integrate message injection into harness agent (#7027)
* Integrate message injection into harness agent and sample console

* Add agents.md update.

* Address PR comments
2026-07-10 00:33:31 +00:00
Sheldon 9f4526a41e fix: parse structured response value from final message (#6383)
Signed-off-by: liuzemei <35027683+liuzemei@users.noreply.github.com>
2026-07-09 11:58:39 +00:00
Roger Barreto 5f9ac6b394 Python: bind policy-enforcement approvals to a single tool invocation (#6966)
* Bind policy-enforcement approvals to a single tool invocation

PolicyEnforcementFunctionMiddleware retained approved call_ids in a set
that was never cleared, so a reused call_id could re-authorize a later
or different tool call without a fresh approval. It also accepted an
approved response as long as the invocation metadata carried a pending
call_id, without checking the response id or embedded function_call.

Bind each approval to the exact invocation shown for review: call_id,
function name, arguments, the security label (integrity/confidentiality),
and the session. Validate that the approval response itself names the
pending request (its id and embedded function_call), and consume the
approval on first use. A reused call_id, a different function, changed
arguments, an escalated label, a different session, or a mismatched
approved response now all require a fresh approval. Adds regression tests
covering each of those cases plus legitimate re-approval.

* Require approval response identifiers to be present and match

Make the policy-enforcement approval-response check reject a response
that omits its id or embedded function_call.call_id: both must now be
present and equal to the pending call_id, closing a None-identifier
bypass. Adds a regression test.

* Disclose all policy violations in a single approval request

PolicyEnforcementFunctionMiddleware computed the approval decision once
and reused it across the integrity and confidentiality checks, so a call
that violated both policies produced an approval request describing only
the untrusted-context violation and then silently waved the undisclosed
confidentiality violation on replay.

Detect every applicable violation up front and surface them together in a
single approval request, so a granted approval waves only what it
disclosed. The binding (call_id, function, arguments, security label,
session) and consume-once behavior are unchanged. Adds a regression test
covering a combined untrusted-context and confidentiality violation.

* Bind policy approval to the disclosed violation set and fingerprint

A pending policy approval was bound to the call body, security label, and
session but not to the violations it disclosed. Because the violation set
depends on the tool's policy metadata (max_allowed_confidentiality,
accepts_untrusted), a replay could compute a different or larger set after
that metadata changed and execute it under the old approval even though the
user never reviewed that risk.

Record the canonical disclosed violation fingerprint (type plus reason) in
the pending record and require the replay to trip the same set, otherwise
re-request approval disclosing the new set. Also require the approval
response's approved flag to be a strict boolean True so a truthy non-boolean
value is not treated as approval. Adds regression tests for a new violation
appearing on replay, a same-type violation whose disclosed risk worsened,
and a non-boolean approved flag.
2026-07-09 10:01:53 +00:00
Eduard van Valkenburg 9a5312b278 Python: Add message injection middleware (#6998)
* Python: Add message injection middleware

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

* Python: Ignore informational tool calls for message injection

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

* Python: Preserve per-service history with message injection

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-09 07:47:39 +00:00
Ethan qu 978cfcd9e4 Python: Fix Foundry reasoning MCP compaction (#6907)
* Fix Foundry reasoning MCP compaction

* Address reasoning MCP review feedback

---------

Co-authored-by: godququ5-code <256881196+godququ5-code@users.noreply.github.com>
Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
2026-07-09 07:10:39 +00:00
Eduard van Valkenburg 346d3f0820 Python: Mark hosted tool calls informational-only (#6997)
* Python: Mark hosted tool calls informational-only

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

* Python: Address informational-only review feedback

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

* Python: Preserve approval responses in tool invocation

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-09 06:07:58 +00:00
Eduard van Valkenburg 0b49609176 Python: Add progressive MCP disclosure (#6850)
* Add progressive MCP disclosure

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

* Address progressive MCP review feedback

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

* Document progressive MCP loader name collisions

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

* Address progressive MCP review feedback

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

* Fix progressive MCP test typing

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

* Track progressive MCP warning feature id

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

* Document internal typing helper guidance

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

* Fix README stars badge link

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

* Support batch progressive MCP load unload

Allow progressive MCP load_tool and unload_tool to accept either a single tool name or a list of tool names, applying successful changes in batches with per-tool model-visible results.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
2026-07-08 18:39:02 +00:00
Giles Odigwe 5adc038b16 Python: Add refresh_interval (TTL) to CachingSkillsSource (#6977)
* Python: Add refresh_interval (TTL) to CachingSkillsSource

Port .NET's CachingAgentSkillsSourceOptions.RefreshInterval to the Python
skills cache. Previously CachingSkillsSource cached a source's skill list
indefinitely (only clearing on a failed fetch), so callers had no built-in
way to periodically re-discover skills whose backing source changes at
runtime (notably MCPSkillsSource over the network).

CachingSkillsSource now accepts an optional refresh_interval (timedelta):
a cached list older than the interval is treated as stale and re-fetched on
the next call. When None (default) the cache never expires, so existing
behavior is unchanged. Freshness is measured with a monotonic clock via a
monkeypatchable _monotonic() helper. SkillsProvider.__init__ and from_paths
expose a cache_refresh_interval kwarg threaded into the built-in cache.

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

* Python: Address review feedback on CachingSkillsSource refresh_interval

- from_paths: do not forward cache_refresh_interval when disable_caching=True,
  matching the docstring and avoiding a TypeError for legacy subclass __init__
  signatures.
- Correct docstring/AGENTS.md wording: a failed fetch does not update the cache
  (initial failure leaves it empty; a refresh failure keeps the prior list),
  rather than "resetting"/"leaving empty" in all cases.
- Fix test typing: narrow provider._source via isinstance before accessing
  inner_source/_refresh_interval so ty/zuban/mypy/pyright all resolve them.
- Add regression tests for disable_caching + interval and legacy-subclass paths.

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

* Python: Do not forward cache_refresh_interval from from_paths into __init__

The refresh interval is already baked into the composed CachingSkillsSource
that from_paths builds, and __init__ leaves a caller-supplied source
un-wrapped, so forwarding cache_refresh_interval into cls(...) was a no-op
for caching behavior while breaking legacy subclasses whose __init__ predates
the kwarg (with caching enabled or disabled). Remove the forwarding entirely.

Strengthen the regression test to cover the real break: a legacy subclass
calling from_paths(paths, cache_refresh_interval=...) with caching enabled
must not raise and the composed source still carries the interval.

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

* Python: Drop _monotonic wrapper; call time.monotonic() directly

Address review feedback: remove the _monotonic() helper that existed only to
aid testing. CachingSkillsSource now calls time.monotonic() inline, and the
refresh-interval tests monkeypatch time.monotonic directly.

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

* Python: Restore main's AGENTS.md sections lost in merge resolution

The merge used 'checkout --ours' for AGENTS.md, which took the whole file
from this branch and inadvertently reverted main's non-conflicting additions
(the __init__.pyi tree entry and the 'Root Public API' section). Restore
main's version and re-apply only the intended SkillsSource decorators change
(refresh_interval docs + reworded cache-failure semantics).

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-08 18:17:16 +00:00
Giles Odigwe 1249275997 Python: Remove experimental marker from Skills API (#6974)
* Python: Remove experimental marker from Skills API

Promote the Skills feature from experimental to stable, mirroring
.NET PR #6861. Removes the @experimental(SKILLS) decorators from the
skills APIs and the SKILLS ExperimentalFeature enum member, updates
tests and samples accordingly. MCP skills (MCP_SKILLS) remain
experimental, matching the .NET change.

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

* Add experimental-stage assertions for MCP skills types

Guard MCPSkill, MCPSkillResource, and MCPSkillsSource against accidental
promotion by asserting their docstring warning block and
__feature_stage__/__feature_id__ metadata remain experimental (MCP_SKILLS).

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

* Remove redundant stable-stage test for Skills API

Drop TestSkillsStableStage: asserting the absence of experimental
markers on a released API is not meaningful, and the feature-stage
decorator machinery is already covered by test_feature_stage.py.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-08 17:34:34 +00:00
Eduard van Valkenburg 094d8d209a Python: Lazy load root agent_framework exports (#6962)
* Lazy load root agent_framework exports

Move the root public API to lazy runtime exports backed by a typed stub, keep Runner deprecation handling in the owning workflow runner module, and document the maintenance pattern.

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

* Tighten harness factory typing

Add a private harness stub so create_harness_agent has a fully known public signature without depending on agent-framework-tools at runtime.

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

* Address lazy root export review comments

Harden the circular import guard and add root export smoke tests covering representative lazy imports, star imports, and root stub export synchronization.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-08 09:20:27 +00:00
Evan Mattson 12b029858e Build(deps): consolidate Dependabot dependency updates (#6984)
* Consolidate Dependabot dependency updates

* Restore method assignment suppression
2026-07-08 09:09:03 +00:00
Eduard van Valkenburg e26c8591ae Python: Fix response metadata construction (#6955)
* Python: Fix response metadata construction

Propagate complete AgentResponse metadata through core response construction and provider finalization paths.

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

* Python: Refine Ollama response metadata parsing

Filter Ollama usage details to real token counts and only propagate streaming finish metadata from final chunks.

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

* Python: Address response metadata review comments

Accumulate Copilot non-streaming usage events and keep structured response value parsing lazy for provider hooks.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-08 09:05:50 +00:00
Kranthi Manchikanti de39be9e58 Python: Improve error message when TypeVar is used in handler registration (#4553)
* Python: Improve error message when TypeVar is used in handler registration

Fixes #4547. Adds early detection of unresolved TypeVar instances in:
- @handler decorator (both explicit and introspected type paths)
- @executor decorator (both explicit and introspected type paths)
- WorkflowContext type argument validation (direct and union members)

When a TypeVar is detected, a clear ValueError is raised with actionable
guidance to use concrete types via @handler(input=ConcreteType, output=ConcreteType).

* Address PR review: runtime-safe TypeVar detection and unit tests

- Add shared is_typevar() helper in _typing_utils.py that safely detects
  TypeVar from both typing and typing_extensions modules
- Replace all isinstance(x, TypeVar) calls with is_typevar() in
  _executor.py, _function_executor.py, and _workflow_context.py
- Add 18 unit tests covering TypeVar validation for @handler, @executor,
  and WorkflowContext[T] (explicit params, introspection, union members)

* Fix pyright error: add type annotation to _TYPEVAR_TYPES

Pyright's reportUnknownVariableType flagged the inferred type as
partially unknown. Adding an explicit `tuple[type, ...]` annotation
resolves the strict-mode check.

* Suppress pyright reportUnknownVariableType for _TYPEVAR_TYPES

Pyright cannot infer the runtime type of TypeVar constructors, so the
tuple elements resolve to type[Unknown]. A type annotation alone does
not satisfy strict mode — add an inline suppression for this specific
diagnostic since the unknown types are intentional (runtime TypeVar
class detection).

* Reject nested TypeVars in workflow annotations

---------

Co-authored-by: Kranthi Kumar Manchikanti <kmanchikanti@microsoft.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
Co-authored-by: Evan Mattson <evan.mattson@microsoft.com>
2026-07-08 07:32:54 +00:00
Giles Odigwe 9c4cd07899 Python: Add SkillsSourceContext to SkillsSource.get_skills (#6895)
* Python: Add SkillsSourceContext to SkillsSource.get_skills

Thread an invocation context (agent + optional session) through the skill
source pipeline so sources and decorators can make context-aware decisions.

- Add frozen, experimental SkillsSourceContext(agent, session).
- Change SkillsSource.get_skills and all sources/decorators to accept and
  forward the context.
- Make FilteringSkillsSource predicate context-aware: (skill, context) -> bool.
- Add optional cache_isolation_key_selector to CachingSkillsSource for
  per-key cache isolation (None keeps the shared-bucket behavior).
- Build the context in SkillsProvider from before_run agent/session.
- Update foundry_hosting toolbox source, exports, tests, and docs.

Python port of .NET PR #6797.

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

* Python: Clarify skills source docstring examples

Address PR review: docstring examples referenced `context` without
constructing it. Add a `SkillsSourceContext` construction line (with a
placeholder agent) to each source example and a note that the provider
normally supplies it. Use `source_context` in the FilteringSkillsSource
example to avoid clashing with the predicate's `context` parameter.

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

* Python: Fix CI type errors and skill_filtering sample predicate

Address CI failures from the SkillsSourceContext change:
- Update the skill_filtering sample to the 2-arg predicate signature
  (skill, context); the old 1-arg lambda would fail at runtime.
- Replace ad-hoc _StubAgent test stubs with the shared MockAgent /
  MockAgentSession from conftest so all type checkers (incl. ty) accept
  the SupportsAgentRun-typed agent. Add a small _NamedMockAgent subclass
  for tests needing distinct agent names, and drop now-unnecessary
  attr-defined ignores.
- Use cast(SupportsAgentRun, ...) in foundry_hosting tests, which have no
  shared mock infrastructure.

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

* Python: Make SkillsProvider caching safe-by-default; clarify context docstrings

Address PR review comments:
- Do not auto-wrap a caller-supplied SkillsSource in the provider's default
  CachingSkillsSource. A shared, unkeyed cache around a context-aware source
  replays the first invocation's skills for later SkillsSourceContexts,
  leaking skills across agents/tenants. Default caching now applies only to
  the built-in, context-independent file/in-memory leaf sources
  (Deduplicating(Caching(leaf))), matching the .NET provider. Callers who
  want caching on a custom pipeline compose CachingSkillsSource (optionally
  with a cache_isolation_key_selector) themselves. disable_caching now only
  affects the built-in leaves. Adds a leak-prevention test.
- Reword the misleading "Unused by this source" context docstrings on the
  File/InMemory/MCP sources: the param is part of the get_skills contract;
  these sources just return the same skills regardless of context.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-07 09:41:45 +00:00
Giles Odigwe bcd2800d4c Python: Allow disabling approval for SkillsProvider tools (#6867)
* Python: Allow disabling approval for SkillsProvider tools

Add disable_load_skill_approval, disable_read_skill_resource_approval, and disable_run_skill_script_approval keyword arguments to SkillsProvider.__init__ and SkillsProvider.from_paths. When set, the corresponding tool is registered with approval_mode=never_require so it runs without approval for trusted-skill scenarios. Approval remains required by default.

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

* Preserve from_paths compatibility for SkillsProvider subclasses

Forward the disable_*_approval kwargs from SkillsProvider.from_paths only when explicitly enabled, so subclasses that override __init__ with the previous signature keep working when the flags are left at their defaults. Add a regression test covering a legacy-signature subclass.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-07 04:25:49 +00:00
Tao Chen 868744aeea Python: Process messages to an executor serially within a superstep (#6776)
* Process messages to an executor serially within a superstep

Add a per-executor asyncio.Lock in Executor.execute so each executor processes its messages one at a time within a superstep, while preserving concurrency across distinct executors. Includes a regression test.

* Create per-executor lock lazily under the running loop

asyncio.Lock created in Executor.__init__ would bind to the first event loop it was awaited under, so reusing an executor/workflow across loops (e.g. successive asyncio.run calls) raised 'bound to a different event loop'. Create the lock lazily via _get_execution_lock(), re-creating it when the running loop changes. Adds a loop-scoped lock test.

* Re-create runner context event queue lazily under the running loop

Like the per-executor lock, the runner context's asyncio.Queue bound to the first event loop it was awaited under, so reusing a workflow across loops (e.g. successive asyncio.run calls) raised 'bound to a different event loop'. Re-create the queue lazily via _get_event_queue() when the running loop changes. Adds an integration test reusing a workflow across event loops.

* Use lazy-None init for the event queue, matching the executor lock

Initialize _event_queue to None and create it on first use in _get_event_queue, mirroring the per-executor lock. Avoids constructing a queue in __init__/reset_for_new_run that is immediately discarded once the running loop is known.

* Improve comments

* Fix formatting
2026-07-06 22:40:48 +00:00
Eduard van Valkenburg 0260ea0e61 Python: implement ADR-0029 service_session_id lifecycle mapping (#6724)
* python: implement ADR-0029 service_session_id lifecycle mapping

- Extend AgentSession service_session_id to support structured values
- Add agent-owned conversation id extraction for chat forwarding and telemetry
- Migrate A2A durable continuation state to A2AServiceSessionId
- Keep A2AAgentSession as compatibility shim and mark it deprecated
- Update core/a2a tests and package guidance

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

* Fix service_session_id type fallout across packages

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

* Fix remaining test typing signatures for service_session_id

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

* Fix hosting test stubs for widened get_session type

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

* Fix remaining test stubs for get_session union type

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

* Simplify A2A session state handling

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

* fix import

* Fix hosting-telegram test get_session typing

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-02 18:36:48 +00:00
westey 24581d6865 Python: Allow devs to opt-out of file-access approvals (#6879) 2026-07-02 18:36:44 +00:00
Eduard van Valkenburg e38592a23c Python: Fix Anthropic messages and function-loop fallback (#6794)
* Fix function loop fallback and Anthropic messages

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

* Address PR feedback for fallback and instructions

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-02 05:37:23 +00:00
Giles Odigwe c41676682e Python: [BREAKING] Extract caching from SkillsProvider into a CachingSkillsSource decorator (#6847)
* Python: [BREAKING] Extract caching from SkillsProvider into CachingSkillsSource decorator

Adds a composable CachingSkillsSource(DelegatingSkillsSource) decorator that caches the inner source's skills list, and rewires SkillsProvider to wrap its resolved source in it by default (skipped when disable_caching=True). Removes the provider's baked-in caching (_cached_context field and _get_or_create_context). Mirrors .NET #6768.

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

* Add ty ignore for dynamic _test_context attribute in skills test helper

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-01 16:21:08 +00:00
Giles Odigwe effbd17325 Python: [BREAKING] Treat nested SKILL.md content as part of the parent skill (#6849)
* Python: Stop skill discovery at skill boundaries

File-based skill discovery kept descending after finding a SKILL.md, which treated content nested beneath a skill boundary as an independent skill root. Return immediately after recording a directory that contains SKILL.md so everything below it stays part of that skill, and add a regression test with a nested SKILL.md.

Fixes #6682

* Python: Attach nested skill content to the parent skill

Removing the SKILL.md subdirectory skip in resource and script scanning so that content beneath a skill boundary is attached to that skill, and update the discovery docstring and the nested-skill test to match. Complements the discovery early-return so a nested SKILL.md is never treated as an independent skill root.
2026-07-01 16:06:56 +00:00