Microsoft 365 Copilot¶
The most constrained provider in the set.
Setup¶
pip install "anyinfer[azure]"
client = ai.Client(
[
ai.ProviderSettings.of(
"m365-copilot",
options={"tenant_id": "...", "client_id": "..."},
),
]
)
result = client.generate(prompt, target="m365-copilot:m365-copilot")
Alias: m365.
Interactive Authentication¶
There is no client-credential or daemon flow for this API. Sign-in opens a browser. Consequently:
- It cannot run headless, in CI, or in a container without a human present.
- It is exempt from live conformance testing.
health()does not trigger a sign-in: a health probe that opens a browser window would be a hostile surprise, and the router calls it speculatively.
If a token is already held, supply it and skip the interactive flow:
ai.ProviderSettings.of("m365-copilot", api_key="env://M365_TOKEN")
This is the only workable path for automated use.
Supported¶
| Behavior | Support |
|---|---|
| Streaming | No (a whole response, emitted as one delta) |
| Structured output | Prompt-injected only |
| Tools | No |
| Sampling controls | Ignored by the service |
| Usage | Generally absent |
| Schema repair | Capped at one round trip |
Ignored Parameters¶
Temperature, top-p, max tokens, stop sequences, tools, and reasoning effort are declared
on the descriptor as ignored, so requesting them emits a ParameterDropped
telemetry event rather than silently doing nothing:
class Watch:
def on_event(self, event):
if isinstance(event, ai.ParameterDropped):
log.warning("%s ignored %s", event.target, event.parameter)
That event matters: a temperature=0 that had no effect is otherwise
indistinguishable from one that worked.
Schema Repair¶
The descriptor caps schema repair at a single round trip, since every request here is an interactively-authenticated Graph call against service-kept conversation state (the most expensive request shape in the registry). Asking for more is clamped rather than refused, and the clamp is reported the same way an ignored parameter is:
result = client.generate(
prompt,
target="m365-copilot:default",
schema=PERSON,
repair=ai.Repair(max_attempts=3),
)
# ParameterDropped(parameter="repair.max_attempts", reason="... at most 1 ... 3 requested")
Prompt-only schema enforcement plus one repair is a real failure rate. Validate
result.structured defensively, and prefer a provider with a native structured-output
mode when the shape matters more than the M365 grounding does.
Notes¶
- Citations and attributions are retained on
result.rawrather than normalized: build the client withretain_raw=Trueto keep them, since raw payloads are discarded by default. v1 has no typed model for them, and inventing one would freeze a shape before it is understood. - A 401/403 hints at both re-authentication and the tenant licensing and admin-consent requirements, because those are the usual real causes.
- For automation, streaming, tools, or sampling control, use another provider; GitHub Copilot covers the subscription-billed case with fewer constraints. This adapter is for applications with a genuine M365 Copilot requirement.
Wire Contract¶
For the exact request/response fields this adapter depends on, see contracts/m365-copilot.md.