Skip to content

Add a first-party .NET client (proposal)#206

Draft
joshmouch wants to merge 2 commits into
microsoft:mainfrom
joshmouch:pr/dotnet-client
Draft

Add a first-party .NET client (proposal)#206
joshmouch wants to merge 2 commits into
microsoft:mainfrom
joshmouch:pr/dotnet-client

Conversation

@joshmouch

Copy link
Copy Markdown
Contributor

A complete .NET / NuGet client for AHP 0.3.0, at full cross-language parity with the Rust / Kotlin / Swift / TypeScript / Go clients — including the new annotations channel (#195).

Opening as a draft: a 6th first-party client is a maintenance + ownership commitment only you can sign off on, so I'd love a scope decision before you spend review time. I'm happy to keep it updated as the protocol evolves.

What's here

  • Microsoft.AgentHostProtocol.Abstractions (generated wire types + transport/serializer interfaces), Microsoft.AgentHostProtocol (reducers + AhpClient + MultiHostClient), Microsoft.AgentHostProtocol.WebSockets.
  • Codegen-derived from the TS protocol via a new scripts/generate-csharp.ts (wired into generate.ts + the CI generated-source-freshness check) — a protocol change is one regen, not N hand-edits.
  • 332 tests on net8.0 + net9.0, driving the shared cross-language reducer + round-trip fixtures (same vectors as the other clients), incl. the full annotations channel.

Notes for review

Your call: do you want a first-party .NET client? If yes — who owns/maintains it, and should it publish via your ESRP pipeline under Microsoft.AgentHostProtocol.*?

joshmouch added 2 commits June 8, 2026 23:40
Adds a first-party-style `Microsoft.AgentHostProtocol*` client for the Agent
Host Protocol, matching the existing Rust / Kotlin / Swift / TypeScript / Go
clients in layout, generation model, and conformance coverage:

- The wire types are generated from the canonical TypeScript protocol
  definitions by `scripts/generate-csharp.ts` (wired in as `npm run
  generate:dotnet`), so adding a protocol field is one regen, not N
  hand-edits. CI fails if the committed generated sources drift.
- The runtime ships the async JSON-RPC `AhpClient`, the pure state reducers,
  the default System.Text.Json serializer, a `ClientWebSocket` transport, and
  the `MultiHostClient` for talking to two or more hosts at once. The
  `Microsoft.AgentHostProtocol.Abstractions` package carries the wire types +
  transport/serializer interfaces alone.
- The client implements the per-session annotations channel
  (`ahp-session:/<uuid>/annotations`) at full cross-language conformance
  parity. The generator emits the `AnnotationsState`, `Annotation`,
  `AnnotationEntry`, and `AnnotationsSummary` wire types, the four
  `annotations/{set,removed,entrySet,entryRemoved}` actions, the
  `MessageAnnotationsAttachment` attachment variant, and the
  `SessionSummary.annotations` summary; `Reducers.ApplyToAnnotations` is a
  faithful port of the canonical reducer (append-or-replace an annotation by
  id, drop a matching annotation, append-or-replace an entry within an
  annotation, drop a matching entry; unknown target ids are no-ops).
- The shared `types/test-cases/reducers/*` and round-trip fixtures drive the
  .NET implementation through the same fixture-parity theories the other
  clients use. 332 reducer / round-trip / client / transport tests pass on
  net8.0 and net9.0. The client keeps its own test-parity gate
  (`clients/dotnet/scripts/check-test-parity.sh` + `parity-manifest.txt` +
  `MIN_TEST_COUNT`) so coverage can't silently regress.
- `scripts/verify-changelog.ts` now gates `clients/dotnet/CHANGELOG.md` for
  every PR, the same way it does for the other five clients.

Publishing is intentionally left to the maintainers. The package ids use the
`Microsoft.AgentHostProtocol` namespace, but this change wires up no NuGet
publish automation — the maintainers can plug `dotnet pack` + `dotnet nuget
push` into whichever signed release pipeline they already use (the Kotlin and
TypeScript packages publish through Azure DevOps / ESRP rather than a GitHub
Actions registry push). The per-PR CI build/test job validates the code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant