Repository navigation
Add optional Copilot SDK completion provider - #2616
Open
Chris Trevino (darthtrevino) wants to merge 2 commits into
Open
Chris Trevino (darthtrevino) wants to merge 2 commits into
Chris Trevino (darthtrevino) wants to merge 2 commits into
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Chris Trevino (darthtrevino)
marked this pull request as ready for review
October 30, 2026 21:06
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Add a built-in
copilotcompletion provider to the standalonegraphrag-llmpackage. Consumers can use models available to their GitHub Copilot account
through the official Python SDK without configuring direct OpenAI/Azure
endpoints.
This adapts the provider idea from BenchmarkQED to GraphRAG's current completion
abstraction and registration mechanism. There are no provider-specific branches
in indexing, querying, or downstream applications. The SDK is an optional
graphrag-llm[copilot]dependency for Python 3.11+; it is also a developmentdependency so CI can exercise real SDK types and signatures.
Related Issues
Prior contribution and motivation:
microsoft/benchmark-qed#141.
This PR does not modify BenchmarkQED or close that contribution.
Proposed Changes
copilotthrough the existing completion factory, retaining customregistration overrides and CLI/library configuration via
completion_models.streaming, typed output-schema requests through the SDK with strict-schema
normalization, and local Pydantic validation of generated responses.
Isolate cache entries by provider/model and restore concrete structured
response types on cache hits.
availability; disable repository discovery, instructions, hooks, skills, memory
and cross-session storage. Abort incomplete work, unsubscribe, disconnect,
delete the request's session and stop the client on failure/cancellation/explicit
stream closure.
without retaining conversations between calls. Reject unsupported arguments
instead of silently ignoring them.
an optional dependency/lock entry, and a minor release note. Existing
dependency versions and lockfile formatting are preserved.
Checklist
Additional Notes
Validation
uv run --no-sync pytest tests\unit\language_model tests\unit\config tests\unit\graphrag_factory -q-- passed, 64 tests.
uv run --no-sync poe check-- passed: formatting, Ruff and whole-repositoryPyright (0 errors).
uv build --package graphrag-llm-- passed for the wheel and sourcedistribution; wheel metadata confirms SDK installation is conditional on the
copilotextra and Python >=3.11.uv lock --check-- passed.git diff --check-- passed.uv run --no-sync python -) with SDK 1.0.26, modelgpt-6.1-sol, and a compatible installed CLI supplied via
cli_path--passed for synchronous typed structured output and asynchronous streaming
with supplied conversation history; the final streaming check also asserted no
event-loop callback errors. The live typed-output test used a simple
Answermodel containing one integer field (answer=42), on one model/CLIcombination. It was not advanced-schema or cross-model compatibility coverage;
nested/nullable/default-field normalization was exercised in unit tests, not
independently verified against the live backend.
configured. CAPI routing is inferred from that default Copilot path; the
underlying HTTP endpoint/backend was not independently traced, and no direct
CAPI HTTP integration test was run.
stricter smoke test failed because the SDK logs an upstream event-decoding
AssertionErrorforsession.indexed_search/disabledReason=server_limit. This is documented, not suppressed or patched.Selecting the compatible installed CLI through
cli_pathavoided that error.run.
JSON output behavior and caveats
There are two distinct output paths; they should not both be described as
native JSON mode:
Typed output:
response_format=SomePydanticModel. The adapter derives themodel's JSON Schema, normalizes it using OpenAI's public
pydantic_function_toolhelper, and sends the resulting output schema throughthe Copilot SDK's
send_and_wait(response_schema=...). This is a constraintrequested for the model's generated response, not validation of the user's input
prompt. Using this schema-conversion helper does not enable tool execution.
The adapter also parses and validates the returned text against the original
Pydantic model before caching a successful response, and restores the
concrete Pydantic response type after cache lookup. Malformed JSON or Pydantic
validation failures raise errors rather than being repaired or cached as
successful structured output.
OpenAI-compatible strict output schemas expect closed objects
(
additionalProperties: false) and all declared object properties to be listedas required. Normalization can therefore make a field required in the generated
output even if the Pydantic model allows it to be omitted because it has a
default. A nullable field (
T | None) can contain JSONnull; nullable doesnot mean omittable in the strict output schema. Pydantic defaults are not a
promise that the backend will fill missing output properties.
The backend/model/runtime supports only its own schema subset. Normalization is
not a guarantee that arbitrary Pydantic models or arbitrary JSON Schema
constructs will be accepted: for example, open-ended object/map shapes or
incompatible schema keywords may be rejected. Unsupported schemas can fail at
the endpoint, and returned content can still fail local validation. Schema
conformance validates output structure/types, not factual correctness.
The live smoke test establishes only the simple-schema case described above.
This adapter rejects
stream=Truetogether with typedresponse_format,consistent with its existing completion interface. This is an adapter
restriction, not a claim that the Copilot SDK universally cannot stream
structured responses.
Unconstrained object output:
response_format_json_object=True. When notyped
response_formatis supplied, the adapter adds a JSON-only instruction tothe system prompt. It does not send a native JSON-object mode or a strict
output schema to the SDK for this path. Non-streaming output is parsed with
json.loadsand must be a JSON object; malformed JSON or a non-object valueraises an error. There is no JSON repair or Markdown-code-fence stripping.
If used with streaming, the JSON instruction still applies, but chunks are
returned without final assembled-JSON parsing or object validation.
Capabilities and limitations
it is in maintenance mode; maintainer acceptance is not assumed.
event-loop isolation straightforward, but adds startup overhead for large
workloads.
prompt-only JSON-object requests, as detailed above. Neither path establishes
factual correctness or universal schema compatibility.
role-separated OpenAI history or resumed SDK sessions.
generation token-limit controls. GraphRAG DRIFT search is currently
incompatible because it injects unsupported sampling parameters internally;
use another provider for DRIFT.
not successful consumption; streaming token usage is available on the final
chunk when requested, and iteration failures are not automatically retried.
Close streams explicitly if stopping early.
Availability, quotas and runtime compatibility depend on the user's Copilot
environment.