[agentserver-invocations] Serve AsyncAPI docs at /invocations/docs/asyncapi.{json,yaml}#47829
[agentserver-invocations] Serve AsyncAPI docs at /invocations/docs/asyncapi.{json,yaml}#47829ZhaoChaoqun wants to merge 2 commits into
Conversation
|
Thank you for your contribution @ZhaoChaoqun! We will review the pull request and get back to you soon. |
There was a problem hiding this comment.
Pull request overview
This PR adds two AsyncAPI discovery endpoints to InvocationAgentServerHost in the azure-ai-agentserver-invocations package, mirroring the existing OpenAPI endpoint. AsyncAPI complements OpenAPI for the streaming/WebSocket (invocations_ws) surface. Two optional constructor args (asyncapi_spec_json, asyncapi_spec_yaml) enable each endpoint independently, with path-extension-authoritative content types and no server-side format conversion (keeping the package free of a YAML dependency). Constructor type validation raises TypeError early, and startup logging is extended.
Changes:
- New routes
GET /invocations/docs/asyncapi.json(JSON) andGET /invocations/docs/asyncapi.yaml(raw YAML), each returning404via the upstream error-source path when unregistered. - New public constructor args + accessors (
get_asyncapi_spec_json/get_asyncapi_spec_yaml) with upfront type validation. - Documentation updates in README and CHANGELOG plus new route/type-validation tests.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
azure/ai/agentserver/invocations/_invocation.py |
Adds AsyncAPI constructor args, type validation, two routes, two accessors, two endpoints, and extended startup logging (new public API not reflected in api.md). |
tests/test_server_routes.py |
Adds tests for JSON/YAML 404, success, independence, and constructor type validation. |
README.md |
Documents the new AsyncAPI endpoints and registration model. |
CHANGELOG.md |
Adds an 1.0.0b7 (Unreleased) Features entry (but _version.py still says 1.0.0b6). |
| asyncapi_spec_json: Optional[dict[str, Any]] = None, | ||
| asyncapi_spec_yaml: Optional[str] = None, |
| @@ -1,5 +1,15 @@ | |||
| # Release History | |||
|
|
|||
| ## 1.0.0b7 (Unreleased) | |||
…yncapi.{json,yaml}
InvocationAgentServerHost now accepts optional `asyncapi_spec_json` (dict) and/or
`asyncapi_spec_yaml` (raw YAML str) constructor args. When set, they are served
at GET /invocations/docs/asyncapi.json and GET /invocations/docs/asyncapi.yaml
respectively — the AsyncAPI companion to the existing openapi.json endpoint for
streaming/bidirectional surfaces (e.g. the invocations_ws WebSocket protocol)
that OpenAPI cannot express.
Path extension is authoritative for the returned content type — no Accept
negotiation, no format conversion between the two representations. Either
returns 404 if not registered; users may register only one, only the other,
or both.
Constructor rejects wrong-typed args (dict/str) with TypeError to prevent
misuse from silently leaking a stringified dict to clients as YAML.
Startup log extended to record which specs are configured.
Bumps version to 1.0.0b7 and syncs api.md with the new public surface.
Companion to TypeSpec PR Azure/azure-rest-api-specs#44416.
Fixes: AB#5407709
818269b to
cc2b944
Compare
…alidation - _invocation.py: set media_type to "application/yaml; charset=utf-8". RFC 9512 mandates UTF-8 for application/yaml, but clients don't universally assume it; declaring the charset avoids downstream mis-decoding of non-ASCII content in the raw YAML string. - _invocation.py: add a comment on the asyncapi_spec_* isinstance guards explaining why openapi_spec is intentionally left unchecked (backward-compat with dict-like Mapping subclasses), so future readers don't file the inconsistency as a bug. - test_server_routes.py: drop @pytest.mark.asyncio + async on the two TypeError-raising tests. Their bodies are purely synchronous (constructor call inside pytest.raises); the async wrapping was spurious.
Summary
Adds two AsyncAPI discovery endpoints to
InvocationAgentServerHost, mirroring the existingopenapi.jsonendpoint:GET /invocations/docs/asyncapi.json→application/jsonGET /invocations/docs/asyncapi.yaml→application/yamlOptional constructor args
asyncapi_spec_json(dict) and/orasyncapi_spec_yaml(raw YAML str) enable each endpoint independently. Path extension is authoritative for the returned content type — noAcceptnegotiation, no format conversion between the two representations. Either representation returns404if not registered; users may register only one, only the other, or both.Rationale: AsyncAPI is the companion to OpenAPI for streaming/bidirectional surfaces (e.g. the
invocations_wsWebSocket protocol) that OpenAPI cannot express. Serving both formats natively (rather than converting server-side) matches typical AsyncAPI tooling expectations and keeps the SDK dependency-free of a YAML library.Constructor validates arg types up front (
TypeError) to prevent a stringifieddictleaking to clients as YAML.Startup log extended to record which specs are configured.
Rollout & compatibility
Backward compatible: both constructor args default to
None; existing hosts are unaffected, and each endpoint returns404until registered. Python SDK is independently mergeable and safe to ship ahead of the others.Part of a 5-repo change adding AsyncAPI discovery to Agent Server:
Test plan
pytest tests/test_server_routes.py -v— 14/14 pass (5 new asyncapi tests + 2 type-validation tests)Files changed
azure/ai/agentserver/invocations/_invocation.py— 2 constructor args, 2 routes, 2 handlers, 2 getters, type validation, startup logtests/test_server_routes.py— 7 new testsREADME.md— endpoint table + "Serving an AsyncAPI spec" sectionCHANGELOG.md—1.0.0b7 (Unreleased)entryapi.md— API surface snapshot synchronized_version.py— bumped1.0.0b6→1.0.0b7Fixes: AB#5407709