6 Commits

  • Python: Add AgentLoopMiddleware for re-running agents in a loop (#6174)
    * Python: Add AgentLoopMiddleware for re-running agents in a loop
    
    Add `AgentLoopMiddleware`, an `AgentMiddleware` that re-runs the wrapped
    agent in a loop. A single configurable class covers three common patterns,
    each with a convenience classmethod factory:
    
    - Ralph loop (`.ralph(...)`): no exit criteria, with feedback tracking
      (`record_feedback`/`progress`), progress injection (`inject_progress`),
      optional fresh context per iteration (`fresh_context`), and an early-stop
      completion signal (`is_complete`).
    - Predicate (`.with_predicate(...)`): loop while a `should_continue` callable
      returns True (e.g. paired with `todos_remaining`/`background_tasks_running`).
    - Judge (`.with_judge(...)`): a second chat client decides whether the original
      request was answered, using a `JudgeVerdict` structured-output response.
    
    The loop also auto-resolves pending function-approval / user-input requests via
    an `on_approval_request` callable (bounded by `max_approval_rounds`), and the
    next iteration's input is controlled by `next_message`. Supports both streaming
    and non-streaming runs.
    
    Exports `AgentLoopMiddleware`, `JudgeVerdict`, `todos_remaining`, and
    `background_tasks_running`. Adds tests, a sample, and docs.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: Refine AgentLoopMiddleware API and sample
    
    - with_judge: add criteria list with {{criteria}} templating into judge
      instructions plus an agent-side instruction; add fresh_context, additional
      judge feedback relay; default judge max_iterations.
    - should_continue is now required and positional; supports (bool, str|None)
      feedback tuples surfaced to next_message/record_feedback via feedback kwarg.
    - Judge forwards full multi-modal request and response messages.
    - Default max_iterations=10 (explicit None = unbounded); removed is_complete and
      Ralph terminology; ShouldContinueResult is a real TypeAlias.
    - Sample: stream all loops, print iteration counts via injected user-block
      boundaries (robust to function calling), <role>: content formatting, per-method
      expected output, and a looping todo sample.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: Fix CI checks for AgentLoopMiddleware
    
    - Resolve pyright errors in _loop.py: drop the always-true final_result None
      check (the while loop always assigns it) and cast finish_reason to the
      AgentResponse constructor's expected type.
    - Apply pyupgrade --py310-plus: import TypeAlias from typing.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: Resolve mypy/pyright disagreement on finish_reason
    
    pyright infers AgentResponse.finish_reason as including str and rejects the
    direct assignment, while mypy considers a cast redundant. Drop the cast and
    suppress only pyright with a targeted reportArgumentType ignore, satisfying
    both type checkers.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: Add todo+judge AgentLoopMiddleware sample
    
    Add a second AgentLoopMiddleware sample that composes two criteria in one
    should_continue predicate: a TodoProvider check (evaluated first) and a
    report-style judge chat client (evaluated once todos are complete) that grades
    the assembled report against shared requirements. Register it in the middleware
    samples README.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: Compose todo+judge loops as two middleware
    
    Rework the todo+judge sample to compose two AgentLoopMiddleware on the agent
    itself (middleware=[judge_loop, todo_loop]) instead of a single hand-written
    predicate. The inner todos_remaining loop drafts the report todo-by-todo and the
    outer with_judge loop re-runs it until an editor chat client judges the report
    publication-ready, reusing the built-in helpers.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Reset session for fresh_context loops via snapshot/restore
    
    AgentLoopMiddleware.fresh_context previously only reset context.messages,
    so with an attached session each iteration still reloaded the local
    transcript or re-threaded the service-side conversation id and the model
    saw the accumulated history. Snapshot the session once before the loop
    (via to_dict) and restore it (from_dict + field copy) between iterations,
    so every pass starts from the pre-loop baseline. The final iteration's
    pass is persisted (no restore after the terminating iteration), so a
    subsequent agent.run continues from there.
    
    Removed the obsolete warning, updated docstrings and core AGENTS.md, and
    added tests: a snapshot/restore round-trip, a session-reset
    streaming x fresh_context x inject_progress x store matrix across multiple
    runs and loop iterations, and response_format parsing across the loop.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Updated samples and docstrings
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: [BREAKING] Python: move Azure AI embeddings to Foundry (#5056)
    * renamed AzureAIINferenceEmbeddings and lazy load azure-cosmos and env var rename
    
    * updated coverage
    
    * fix readme
  • Python: fixed middleware samples (#5026)
    * fixed samples
    
    * small update to explanation
    
    * add snippet fix on root readme
  • Python: [BREAKING] Remove deprecated Python OpenAI/Azure AI surfaces (#4990)
    * [BREAKING] Remove deprecated Python OpenAI/Azure AI surfaces
    
    Also clean up follow-on docs, environment guidance, package metadata, and lab test stability.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix deleted semantic-kernel sample links
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address PR review feedback
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * improve foundry language
    
    * Fix A2A Foundry sample regression
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • [BREAKING] Python: fix OpenAI Azure routing and provider samples (#4925)
    * Python: fix OpenAI Azure routing and provider samples
    
    Prefer OpenAI when OPENAI_API_KEY is present unless Azure is explicitly requested. Clarify constructor docs, keep deprecated Azure wrappers compatible with stricter settings validation, and refresh the provider samples and tests to use the current client patterns.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix bandit
    
    * Python: align OpenAI embedding Azure routing
    
    Extend the shared OpenAI-vs-Azure routing and credential behavior to the embedding client, add Azure embedding regression coverage, and refresh the embedding samples to use the generic client path.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: fix embedding client pyright check
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: thin OpenAI embedding wrapper
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: document embedding overload routing
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: fix callable OpenAI key routing
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: fix Azure credential routing tests
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: address OpenAI review feedback
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: narrow Azure routing markers
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: refine OpenAI model fallback order
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: narrow Azure deployment docs
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: remove embedding routing wording
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: run embedding Azure integration tests
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * changed variable name
    
    * Python: expand OpenAI package README
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * clarified readme
    
    * Python: fix Azure OpenAI integration setup
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: correct Azure integration env mapping
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * updated code to fix int tests
    
    * test updates
    
    * test fix
    
    * fix test setup
    
    * updates to tests and setup
    
    * remove openai assistants int tests
    
    * improvements in int tests
    
    * fix env var
    
    * fix env vars
    
    * fix azure responses test
    
    * trigger actions
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: [BREAKING] Refactor middleware layering and split Anthropic raw client (#4746)
    * [BREAKING] Refactor middleware layering and raw clients
    
    Reorder chat client layers so function invocation wraps chat middleware, and chat middleware stays outside telemetry while still running for each inner model call. Add middleware pipeline caching, refresh docs and samples, and split Anthropic into raw and public clients to match the standard layering model.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Tighten typing ignores in ancillary modules
    
    Add targeted typing ignores in workflow visualization and lab modules so pyright stays clean alongside the middleware refactor work.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix categorize_middleware to unpack tuple/Sequence and use relative MRO assertions
    
    - Broaden isinstance check in categorize_middleware from list to Sequence
      so tuples and other Sequence types are properly unpacked instead of
      being appended as a single item.
    - Replace fragile hardcoded MRO index assertions in anthropic test with
      relative ordering via mro.index().
    - Add regression tests for categorize_middleware with tuple, list, and
      None inputs.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix middleware string decomposition, add middleware param to FunctionInvocationLayer, and add tests (#4710)
    
    - Guard categorize_middleware Sequence check against str/bytes to prevent
      character-by-character decomposition of accidentally passed strings
    - Add explicit middleware parameter to FunctionInvocationLayer.get_response
      and merge it into client_kwargs before categorization, fixing the
      inconsistency where only OpenAIChatClient supported this parameter
    - Add assertions that RawAnthropicClient does not inherit convenience layers
    - Add chat middleware cache test with non-empty base middleware
    - Add tests for single unwrapped middleware item and string input
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    * Apply pre-commit auto-fixes
    
    * Address review feedback for #4710: review comment fixes
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    Co-authored-by: Copilot <copilot@github.com>