{"owner":"ag-ui-protocol","repo":"ag-ui","hasSkills":true,"totalSkillsCount":63,"totalTokensCount":33637,"categories":["anthropic-skill","root-instruction","claude-rule","marketplace","plugin-manifest","cursor-rule"],"hasMcp":false,"mcpConfig":null,"found":[".github/skills/agui-dotnet-cross-language-tests/SKILL.md",".github/skills/agui-cross-sdk-parity/SKILL.md",".github/skills/agui-dojo/SKILL.md","skills/ag-ui-a2ui-integration/SKILL.md",".github/skills/agui-dotnet-code-review/SKILL.md",".github/skills/agui-dotnet-agents-sync/SKILL.md",".github/skills/agui-dotnet-transport/SKILL.md",".github/skills/agui-dotnet-feature-workflow/SKILL.md",".github/skills/agui-dotnet-wire-types/SKILL.md",".github/skills/agui-playwright-validate/SKILL.md","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-client-tools/SKILL.md","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-human-in-the-loop/SKILL.md","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-multimodal/SKILL.md","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-protobuf/SKILL.md","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-reasoning/SKILL.md","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-server-tools/SKILL.md","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-shared-state/SKILL.md","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-streaming-chat/SKILL.md","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-troubleshoot/SKILL.md","AGENTS.md","CLAUDE.md",".claude-plugin/marketplace.json","skills/ag-ui-a2ui-integration/sources.md","skills/ag-ui-a2ui-integration/references/a2ui-runtime-and-renderer.md","skills/ag-ui-a2ui-integration/references/framework-adapters.md","skills/ag-ui-a2ui-integration/references/verification.md",".github/skills/agui-dotnet-code-review/references/rules.md",".github/skills/agui-dotnet-transport/references/wire-format.md","sdks/dotnet/plugins/ag-ui-dotnet/README.md","sdks/dotnet/plugins/ag-ui-dotnet/plugin.json","sdks/typescript/.cursor/rules/project-rules.mdc","sdks/typescript/packages/a2ui-toolkit/CHANGELOG.md","sdks/typescript/packages/a2ui-toolkit/README.md","sdks/typescript/packages/a2ui-toolkit/package.json","sdks/typescript/packages/a2ui-toolkit/tsconfig.json","sdks/typescript/packages/cli/CHANGELOG.md","sdks/typescript/packages/cli/README.md","sdks/typescript/packages/cli/package.json","sdks/typescript/packages/cli/tsconfig.json","sdks/typescript/packages/client/CHANGELOG.md","sdks/typescript/packages/client/DEPRECATIONS.md","sdks/typescript/packages/client/README.md","sdks/typescript/packages/client/package.json","sdks/typescript/packages/client/tsconfig.json","sdks/typescript/packages/core/CHANGELOG.md","sdks/typescript/packages/core/README.md","sdks/typescript/packages/core/package.json","sdks/typescript/packages/core/tsconfig.json","sdks/typescript/packages/encoder/CHANGELOG.md","sdks/typescript/packages/encoder/README.md","sdks/typescript/packages/encoder/package.json","sdks/typescript/packages/encoder/tsconfig.json","sdks/typescript/packages/proto/CHANGELOG.md","sdks/typescript/packages/proto/README.md","sdks/typescript/packages/proto/package.json","sdks/typescript/packages/proto/tsconfig.json","sdks/typescript/packages/proto/tsconfig.typecheck.json","sdks/dotnet/plugins/ag-ui-dotnet/.claude-plugin/plugin.json","integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/flight_schema.json","integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/hotel_schema.json","integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/flight_schema.json","integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/hotel_schema.json","sdks/typescript/packages/client/src/apply/__tests__/fixtures/strands-native-resume.json"],"skills":{".github/skills/agui-dotnet-cross-language-tests/SKILL.md":"---\nname: agui-dotnet-cross-language-tests\ndescription: >\n  Author cross-language interop tests that verify the AG-UI .NET SDK is\n  wire-compatible with the TypeScript SDK — a Vitest TS client driving a C#\n  CrossLanguage.TestServer over HTTP, both directions, including protobuf\n  byte-parity against @ag-ui/proto. USE FOR: adding or modifying cross-language\n  interop coverage, CrossLanguage.TestServer routes, the CrossLanguage.Vitest\n  suite, protobuf wire parity tests, TS-client-to-C#-server or\n  C#-client-to-TS-server scenarios. DO NOT USE FOR: .NET-only unit tests (use\n  agui-dotnet-unit-tests), ASP.NET Core hosting integration tests (use\n  agui-dotnet-integration-tests).\n---\n\n# AG-UI .NET Cross-Language Interop Tests\n\nHow to add tests proving the .NET AG-UI SDK interoperates with the TypeScript\nSDK on the wire. The harness lives under `sdks/dotnet/tests/`. Read\n`sdks/dotnet/docs/cross-language-testing.md` (design plus the \"Harness reference\"\nsection) for full background.\n\n## Interop philosophy\n\n- **The TypeScript SDK is the reference (oracle).** A round-trip through the TS\n  codec — `proto.decode(proto.encode(event))` — is the canonical normalised form\n  both SDKs must agree on. Assert .NET output against *that*, not against the raw\n  fixture object.\n- **Round-trip semantic equivalence is the real guarantee**, in both directions\n  (TS→.NET and .NET→TS). Byte-for-byte parity is a stronger claim asserted only\n  where deterministic.\n- Tests exercise *our* code via project references (`AGUI.Abstractions`,\n  `AGUI.Server`, `AGUI.Protobuf`), never the published NuGet packages.\n\n## Harness architecture\n\nTwo directions, two server processes (see the \"Harness reference\" section of\n`sdks/dotnet/docs/cross-language-testing.md`):\n\n| Direction | Driver | Target server | Runner |\n|---|---|---|---|\n| TS → .NET (Phase 1) | TS `HttpAgent` (`@ag-ui/client`) | C# `CrossLanguage.TestServer` on :8091 | Vitest |\n| .NET → TS (Phase 2) | C# `AGUIChatClient` | TS fake-agent server (`server/main.ts`) on :8092 | xUnit |\n\nPhase 1 mechanism: Vitest `globalSetup`\n(`CrossLanguage.Vitest/helpers/global-setup.ts`) starts LLMock\n(`@copilotkit/aimock`, deterministic LLM responses), then\n`helpers/dotnet-server.ts` runs `dotnet build` and spawns the produced\n`CrossLanguage.TestServer.exe` (not `dotnet run` — single PID for clean Windows\nteardown) with `OPENAI_BASE_URL` pointed at LLMock. It waits for the HTTP\nlistener, then test files `fetch` the routes. Both server and LLMock stay alive\nacross the whole run; `vitest.config.ts` sets `fileParallelism: false` so\nconcurrent SDK builds don't contend for artifact locks.\n\nPhase 2 mechanism: `TsServerFixture` (`IAsyncLifetime`, shared via\n`[Collection(nameof(TsServerCollection))]`) shells out `pnpm run server`\n(`tsx server/main.ts`) which emits canned AG-UI events via `@ag-ui/encoder`;\n`AGUIChatClient` consumes them.\n\n## Adding a TS → .NET scenario (Phase 1)\n\n1. **Add a server-side route** under `CrossLanguage.TestServer/` following the\n   endpoint pattern (`MapPost` → `input.ToChatRequestContext(...)` →\n   `GetStreamingResponseAsync` → `.AsAGUIEventStreamAsync(ctx)` →\n   `TypedResults.ServerSentEvents(AgenticChatRoute.WrapAsSseItems(...))`). See\n   `ParallelToolCallsRoute.cs`. For a route that must **negotiate the transport**\n   (SSE *or* protobuf from the `Accept` header), end with\n   `AGUIResults.Events(events, httpContext, cancellationToken)` instead and make\n   sure `Program.cs` registers `ProtobufEventStreamFormatter` as an `IAGUIEventStreamFormatter` — see `AgenticChatRoute.cs`.\n2. **Register it in `Program.cs`** (e.g. `app.MapParallelToolCalls(\"/parallel_tool_calls\")`).\n3. **Register any new payload types in `CrossLanguageJsonSerializerContext.cs`**\n   (`[JsonSerializable(typeof(YourReport))]`). This context is snake_case to\n   match the TS wire shape.\n4. **Add an aimock fixture** in `fixtures/*.json` keyed by `userMessage` /\n   `toolCallId` so LLM responses are deterministic (see\n   `fixtures/parallel-tool-calls.json`).\n5. **Add a `tests/<scenario>.test.ts`** that drives the route with `HttpAgent`\n   and asserts on the collected event stream (see `parallel-tool-calls.test.ts`).\n\n## Adding a .NET → TS scenario (Phase 2)\n\n1. Add a fake agent (`(RunAgentInput) => BaseEvent[]`) in `server/fakeAgents.ts`.\n2. Mount its route in `server/main.ts`.\n3. Add a `*.cs` test in `AGUI.CrossLanguage.IntegrationTests/`, decorated\n   `[Collection(nameof(TsServerCollection))]`, driving it with `AGUIChatClient`\n   (see `AgenticChatTests.cs`).\n\n## Protobuf wire-parity pattern\n\n`ProtobufParityRoute.cs` exposes three codec routes backed by `AGUIProtobuf`:\n\n| Route | In | Out | Backed by |\n|---|---|---|---|\n| `POST /protobuf/encode` | event JSON | raw proto bytes | `AGUIProtobuf.Encode` |\n| `POST /protobuf/decode` | raw proto bytes | event JSON | `AGUIProtobuf.Decode` |\n| `POST /protobuf/decode-framed` | 4-byte BE length-prefixed frames | event JSON array | `AGUIProtobuf.ReadFramedAsync` |\n\n`tests/protobuf-parity.test.ts` proves parity against `@ag-ui/proto`\n(`sdks/typescript/packages/proto/src/proto.ts`) and `@ag-ui/encoder` framing\n(`sdks/typescript/packages/encoder/src/encoder.ts`). For each fixture\n(`fixtures/protobuf-events.ts`):\n\n- `tsBytes = proto.encode(event)`; `reference = proto.decode(tsBytes)`.\n- **TS encode → .NET decode**: `expect(netDecode(tsBytes)).toEqual(reference)`.\n- **.NET encode → TS decode**: `expect(proto.decode(netEncode(event))).toEqual(reference)`.\n- **Byte parity** depends on the fixture's `byteParity` flag:\n  - `\"strict\"` — scalar-only events (only string/number fields, serialised in\n    field-number order): assert the TS and .NET bytes are byte-for-byte equal.\n  - `\"roundtrip\"` — payloads mapping to `google.protobuf.Struct`\n    (`map<string, Value>`): map-entry ordering is **not** canonical across\n    encoders, so do NOT assert byte equality. Assert both byte streams decode\n    (via the TS codec) to the same event instead.\n\nA framing test concatenates `encoder.encodeProtobuf(event)` frames (4-byte BE\nprefix) and posts them to `/protobuf/decode-framed` to exercise `ReadFramedAsync`.\nWhen adding a new protobuf event, add a fixture with the correct `byteParity`\nflag — scalar-only ⇒ `strict`, any object/array payload ⇒ `roundtrip`.\n\n## Transport parity (parameterize scenarios over SSE + protobuf)\n\nThe codec-parity pattern above isolates the **codecs** — it never goes through the\nTS `HttpAgent` or `Accept`-header negotiation. To prove the full **transport** path\n(TS client negotiates a protocol → .NET server encodes it → TS client decodes it),\nparameterize a scenario suite over both transports — the cross-language analogue of\nthe .NET integration tests' `TransportFormat {Json, Protobuf}` `[Theory]`.\n\n`helpers/transport.ts` is the shared mechanism: `TRANSPORTS = [\"sse\", \"protobuf\"]`,\n`TRANSPORT_MEDIA_TYPE`, and `createTransportAgent(config, transport)` which returns\nan `HttpAgent` that requests the transport (it opts into protobuf via the public\n`fetch` hook — the default agent hardcodes `Accept: text/event-stream` *after*\nspreading `headers`, so a `headers` option can't override it) and captures the\nresponse `Content-Type`. Drive the suite with `describe.each(TRANSPORTS)` and assert\n`lastResponseContentType() === TRANSPORT_MEDIA_TYPE[transport]` plus the usual\ndecoded-event assertions — see `tests/agentic-chat.test.ts`.\n\n```ts\ndescribe.each(TRANSPORTS)(\"… [%s]\", (transport) => {\n  it(\"…\", async () => {\n    const { agent, lastResponseContentType } = createTransportAgent(\n      { url: `${baseUrl()}/agentic_chat`, threadId: `t-${transport}` }, transport);\n    agent.messages = [{ id: \"u\", role: \"user\", content: \"Hi, I am duaa\" }];\n    const events: BaseEvent[] = [];\n    await agent.runAgent({}, { onEvent: ({ event }) => events.push(event) });\n    expect(lastResponseContentType()).toBe(TRANSPORT_MEDIA_TYPE[transport]);\n    // …assert decoded events (identical regardless of transport)…\n  });\n});\n```\n\nThe route under test must negotiate (`AGUIResults.Events`, with\n`ProtobufEventStreamFormatter` registered as an `IAGUIEventStreamFormatter` in\n`Program.cs`). `tests/agentic-chat.test.ts` and\n`tests/state-events.test.ts` are parameterized this way today.\n\n**Only parameterize protobuf-safe scenarios.** `ToolCallResult`, `Reasoning*`, and\n`Activity*` events have **no message/oneof entry in the shared `events.proto`** (the\none schema referenced by *both* `@ag-ui/proto` and .NET `AGUI.Protobuf`), so *neither*\nSDK can protobuf-encode them — the codec throwing `NotSupportedException` mirrors\nthe schema, it is not a .NET gap. A suite that emits any of those must stay SSE-only.\nAdding protobuf support for them is an **upstream schema change** (extend the canonical\nTS `events.proto`, regenerate both SDKs, add mappers) — see `agui-cross-sdk-parity`.\n\n`AGUI_MEDIA_TYPE` (`@ag-ui/proto`) and `ProtobufEventStreamFormatter.ProtobufMediaType` are the identical\nexact string, and `AGUIEventStreamResult` sets `Content-Type` to it with no charset\n— the client's exact `===` content-type match depends on that.\n\n## Running the suites\n\n```sh\n# TS → .NET + protobuf parity (builds + spawns the C# server automatically)\ncd sdks/dotnet/tests/CrossLanguage.Vitest\npnpm test\npnpm exec vitest run tests/protobuf-parity.test.ts   # just the parity suite\n\n# .NET → TS (shells out `pnpm run server`)\ncd sdks/dotnet/tests/AGUI.CrossLanguage.IntegrationTests\ndotnet test\n```\n\n`pnpm install` from the repo root once first. Requires .NET 10 SDK, Node at the\nversion in the repository's root `.node-version`, pnpm 10+.\n\n## ❌ Critical anti-patterns\n\n1. **Don't assert byte-equality for object/Struct payloads.** `google.protobuf.Struct`\n   map ordering is non-canonical; byte parity is only valid for scalar-only\n   (`\"strict\"`) fixtures. For object payloads, assert round-trip equivalence.\n2. **Don't make the .NET fixture the oracle.** The TS codec is the reference —\n   compare against `proto.decode(proto.encode(event))`, not the raw event object.\n3. **Don't add a route without registering it in BOTH `Program.cs` AND\n   `CrossLanguageJsonSerializerContext.cs`** (when it introduces new payload\n   types) — the server won't map the route or will fail AOT-safe serialization.\n4. **Don't depend on real LLM calls.** Phase 1 LLM responses come from aimock\n   fixtures keyed by `userMessage`/`toolCallId`; add a fixture for every new\n   prompt. Use fixed/deterministic tool outputs (see `ParallelToolCallsRoute`'s\n   frozen clock).\n5. **Don't use `dotnet run` to start the server in helpers, and don't assume\n   parallel test files.** The harness spawns the built `.exe` for a single\n   killable PID and runs files sequentially (`fileParallelism: false`) to avoid\n   build-lock contention and Windows port orphans.\n",".github/skills/agui-cross-sdk-parity/SKILL.md":"---\nname: agui-cross-sdk-parity\ndescription: >\n  Keep the AG-UI .NET SDK at feature and wire-format PARITY with the canonical\n  reference SDKs (TypeScript is the source of truth; Python is types/encoder only).\n  USE FOR: porting a feature/event/behavior that landed in the TS (or Python) SDK\n  into .NET, verifying the .NET wire format (JSON, SSE, protobuf) matches the\n  reference, locating where the reference implementation and compatibility fixtures\n  live, mapping a TS concept to the .NET event/client/encoder model, resolving an\n  upstream protocol fix (e.g. a Microsoft.Extensions.AI / Microsoft Agent Framework\n  issue) that needs a .NET counterpart, deciding which .NET package owns a change.\n  DO NOT USE FOR: the mechanics of writing a specific test (use agui-dotnet-unit-tests\n  for serialization round-trips, agui-dotnet-integration-tests for cross-language /\n  E2E harness mechanics, agui-dotnet-wire-types for JSON/proto type rules,\n  agui-dotnet-transport for SSE/HTTP transport details). This skill is about the\n  PARITY PROCESS and where the reference lives, not test authoring.\n---\n\n# AG-UI Cross-SDK Parity\n\nThe .NET SDK implements an upstream, multi-language protocol. This skill encodes the\n**parity process**: which SDK is authoritative, where its reference and fixtures live,\nhow to map reference concepts onto the .NET model, and how parity is guarded.\n\n## Parity Principle\n\n- **TypeScript is canonical** for wire format AND client run-loop behavior. When two\n  SDKs disagree, match TS.\n- **Python is types + encoder only.** It has `core` (types/events) and an `encoder`,\n  but **no client run-loop and no protobuf** (`sdks/python/ag_ui/` has `core/` and\n  `encoder/` but no `client/` or `proto/`). Use it only as a secondary check on\n  type/JSON shape — never for run-loop or proto questions.\n- Upstream protocol or SDK fixes (in the TS client run-loop, or in\n  Microsoft.Extensions.AI / Microsoft Agent Framework) sometimes need a .NET\n  counterpart; treat the TypeScript change as the contract to match.\n\n## Where the Reference Lives\n\n| Concern | TypeScript reference (source of truth) | .NET package it maps to |\n|---|---|---|\n| Event & type definitions | `sdks/typescript/packages/core/src/events.ts`, `types.ts`, `event-factories.ts` | `sdks/dotnet/src/AGUI.Abstractions/Events/`, `Messages/` |\n| Client run-loop / transport | `sdks/typescript/packages/client/src/run/`, `apply/`, `agent/`, `transform/` | `sdks/dotnet/src/AGUI.Client/` (`AGUIChatClient.cs`, `AGUIHttpTransport.cs`, `EventStreamConverter.cs`, `ToolCallBuilder.cs`) |\n| SSE / JSON wire framing | `sdks/typescript/packages/encoder/src/encoder.ts` | `sdks/dotnet/src/AGUI.Formatting/`, `AGUI.Abstractions/Serialization/` |\n| Protobuf wire format | `sdks/typescript/packages/proto/src/proto/events.proto`, `types.proto`, `patch.proto` | `sdks/dotnet/src/AGUI.Protobuf/` (`ProtoEventMapper.cs`, `ProtoMessageMapper.cs`) |\n\nThe `src/` packages are **AGUI.Abstractions, AGUI.Formatting, AGUI.Protobuf, AGUI.Client,\nAGUI.Server**; `sdks/dotnet/AGENTS.md` and `docs/architecture.md` are the canonical\ndescription of the layout and conventions.\n\n## Porting Workflow\n\n1. **Locate the feature in TS.** Find the change in `packages/core` (a new event/type),\n   `packages/client` (run-loop / event-application behavior), or\n   `packages/proto`+`encoder` (wire framing). Read the TS implementation and its tests\n   to capture the exact contract — field names, ordering, optionality, coalescing rules.\n2. **Identify the wire contract.** Determine the JSON shape, the proto schema impact\n   (if any), and whether client run-loop state changes. Cross-check the JSON property\n   names against `packages/core/src/events.ts`.\n3. **Map to the .NET model and the right package** (table above). Events/types →\n   `AGUI.Abstractions`; run-loop → `AGUI.Client`; SSE/JSON framing → `AGUI.Formatting`;\n   protobuf → `AGUI.Protobuf`. Follow the .NET conventions in `AGENTS.md` (one class\n   per file, `sealed`, source-generated JSON context, `PublicAPI.Unshipped.txt`).\n4. **Implement** the .NET change. For a new event, follow the \"Adding a new event type\"\n   checklist in `AGENTS.md` (class in `Events/`, `AGUIEventTypes` constant,\n   `[JsonSerializable]`, `BaseEventJsonConverter` case, PublicAPI entry).\n5. **Add parity assets** (see next section): a TS-produced JSON fixture under\n   `tests/AGUI.Abstractions.UnitTests/Compatibility/` and/or a cross-language test in\n   `tests/CrossLanguage.Vitest/tests/`.\n6. **Verify byte/semantic parity** — run the compatibility and cross-language tests.\n7. **Update docs.** Refresh `sdks/dotnet/AGENTS.md`, `docs/architecture.md`, and\n   `docs/cross-language-testing.md` if the change alters the model, package layout, or the\n   set of wire-supported events.\n\n## How Parity Is Guarded\n\nFour independent layers catch drift; add to whichever layer the change touches.\n\n- **Compatibility fixtures (catch JSON drift).**\n  `tests/AGUI.Abstractions.UnitTests/Compatibility/` holds TS-produced JSON fixtures\n  (`*-events.json`) loaded via `FixtureLoader` and deserialized into .NET types\n  (`{Category}CompatibilityTest.cs`, e.g. `RunEventsCompatibilityTest`,\n  `ToolCallEventsCompatibilityTest`). A new/changed event shape needs a fixture entry.\n- **Cross-language tests (catch end-to-end drift).** The harness in\n  `tests/CrossLanguage.TestServer/` (C# server) and `tests/CrossLanguage.Vitest/`\n  (TS client driving it) proves real interop — see `sdks/dotnet/docs/cross-language-testing.md`.\n  Scenario specs live in `tests/CrossLanguage.Vitest/tests/` (e.g.\n  `parallel-tool-calls.test.ts`, `state-events.test.ts`, `protobuf-parity.test.ts`).\n- **Protobuf byte-parity tests.** `protobuf-parity.test.ts` plus\n  `tests/AGUI.Protobuf.UnitTests/` verify the binary encoding matches the TS proto output.\n- **Shared cross-language fixtures (catch three-way drift).** `sdks/fixtures/` holds\n  language-neutral JSON that more than one SDK is held to, so an expectation is written down\n  once instead of three times. `null-omission.json` is the first: TypeScript, Python and .NET\n  each deserialize its `input` events, re-serialize through their own producer path, and\n  assert the result equals `expected`. A wire rule that all three must agree on belongs here\n  rather than in one SDK's test tree — see `sdks/fixtures/README.md`.\n\n## Known Parity Boundary: Proto Is a Subset\n\nThe protobuf schema covers a **subset** of events by design. `.NET`-only events\n(`Reasoning*`, `Activity*`, `ToolCallResult`) are not in the proto wire format and\n**throw `NotSupportedException`** when mapped — see `ProtoEventMapper.cs` (the `default`\ncase lists the 16 supported events: RUN_STARTED/FINISHED/ERROR, STEP_STARTED/FINISHED,\nTEXT_MESSAGE_START/CONTENT/END, TOOL_CALL_START/ARGS/END, STATE_SNAPSHOT/DELTA,\nMESSAGES_SNAPSHOT, RAW, CUSTOM) and `ProtoMessageMapper.cs`. This is a **deliberate,\ndocumented boundary** — do not \"fix\" it by inventing proto messages that don't exist in\n`events.proto`. JSON/SSE remains the full-fidelity wire; protobuf is the constrained one.\n\n## Critical Anti-patterns\n\n1. **Never treat .NET as the source of truth.** If the .NET behavior differs from TS,\n   the .NET side is the candidate for change — confirm against `packages/core` /\n   `packages/client` first.\n2. **Never consult Python for run-loop or proto parity.** Python has neither. Use it\n   only as a type/JSON cross-check.\n3. **Never add a proto mapping for a `.NET`-only event** (`Reasoning*`, `Activity*`,\n   `ToolCallResult`). The `NotSupportedException` is intentional.\n4. **Never land a wire change without a parity asset.** A JSON-shape change needs a\n   Compatibility fixture; an interop/behavioral change needs a cross-language test.\n\n## Routing to Sibling Skills\n\nThis skill governs *what* to port and *where the reference is* — delegate test\nmechanics:\n\n- **agui-dotnet-unit-tests** — serialization round-trips and Compatibility fixture tests.\n- **agui-dotnet-integration-tests** — cross-language / E2E harness (TestServer + Vitest).\n- **agui-dotnet-wire-types** — JSON/proto type and serialization-context rules.\n- **agui-dotnet-transport** — SSE / HTTP transport details.\n",".github/skills/agui-dojo/SKILL.md":"---\nname: agui-dojo\ndescription: >\n  Run the AG-UI Dojo demo viewer locally and wire the AG-UI .NET SDK in as a dojo\n  integration. USE FOR: starting the dojo app (apps/dojo), running the .NET dojo\n  backend (AGUIDojoServer), registering or modifying the ag-ui-dotnet integration\n  (agents.ts/menu.ts/env.ts/files.json), running the dojo Playwright e2e suite for\n  the .NET integration (agUiDotnetTests), or understanding how dojo-e2e.yml runs it\n  in CI. DO NOT USE FOR: generic Playwright validation of arbitrary pages (use\n  agui-playwright-validate), or the docs site (use agui-dotnet-sdk-docs).\n---\n\n# AG-UI Dojo (.NET integration)\n\nThe **Dojo** is a Next.js \"demo viewer\" (`apps/dojo`) that showcases AG-UI protocol\nfeatures (agentic chat, generative UI, human-in-the-loop, shared state, etc.) against\nmany framework integrations. The AG-UI .NET SDK is one integration, id **`ag-ui-dotnet`**.\n\n## Where the pieces live\n\n| Piece | Path | Role |\n|-------|------|------|\n| Dojo app (frontend) | `apps/dojo` | Next.js viewer, runs on port **9999** |\n| .NET backend | `sdks/dotnet/samples/AGUIClientServer/AGUIDojoServer/` | ASP.NET host exposing AG-UI endpoints, port **8023** |\n| Agent registry | `apps/dojo/src/agents.ts` | `ag-ui-dotnet` → `HttpAgent` per feature |\n| Menu / feature list | `apps/dojo/src/menu.ts` | integration id, name, enabled features |\n| Env config | `apps/dojo/src/env.ts` | `aguiDotnetUrl` ← `AGUI_DOTNET_URL` (default `http://localhost:8023`) |\n| Generated source viewer data | `apps/dojo/src/files.json` | generated, **committed** |\n| Content generator | `apps/dojo/scripts/generate-content-json.ts` | builds `files.json` from `menu.ts` |\n| Prep / run orchestrators | `apps/dojo/scripts/{prep,run}-dojo-everything.js` | install/build + start services |\n| .NET e2e suite | `apps/dojo/e2e/tests/agUiDotnetTests/*.spec.ts` | Playwright tests |\n| CI | `.github/workflows/dojo-e2e.yml` | suite `ag-ui-dotnet` (triggers on `sdks/dotnet/**`) |\n\n## Run the dojo + .NET backend locally\n\nFrom the repo root (the scripts shell out to `git rev-parse`):\n\n```bash\npnpm install --no-frozen-lockfile\n\n# 1) Prep: builds the .NET backend AND the dojo (use the stable ids)\nnode apps/dojo/scripts/prep-dojo-everything.js --only dojo,ag-ui-dotnet\n\n# 2) Run: starts the dojo (9999) + AGUIDojoServer (8023) together, with LLMock env injected\nnode apps/dojo/scripts/run-dojo-everything.js --only dojo,ag-ui-dotnet\n```\n\n- Browse `http://localhost:9999/ag-ui-dotnet/feature/agentic_chat`.\n- `prep` for `ag-ui-dotnet` runs `dotnet restore && dotnet build` on\n  `AGUIDojoServer/AGUIDojoServer.csproj` in `sdks/dotnet/samples/AGUIClientServer`.\n- `run` for `ag-ui-dotnet` runs `dotnet run --project AGUIDojoServer/AGUIDojoServer.csproj\n  --urls \"http://localhost:8023\" --no-build` — **prep first or there's no build to run**.\n\nStart just the .NET backend by hand (e.g. to debug):\n\n```bash\ncd sdks/dotnet/samples/AGUIClientServer\ndotnet run --project AGUIDojoServer/AGUIDojoServer.csproj --urls \"http://localhost:8023\"\n```\n\nThe backend resolves its `ChatClient` from configuration (`ChatClientAgentFactory.Initialize`):\n`OPENAI_BASE_URL` (any OpenAI-compatible endpoint / LLMock), else `AZURE_OPENAI_ENDPOINT`\n(Entra ID), else public OpenAI with `OPENAI_API_KEY`. `run-dojo-everything.js` injects\n`OPENAI_BASE_URL=http://localhost:5555/v1` and `OPENAI_API_KEY=sk-mock` so it hits the LLMock.\n\n## How the .NET SDK is registered as an integration\n\nEach scenario is an AG-UI endpoint on the .NET host wired to a frontend feature. To add or\nchange a `.NET` dojo scenario, touch these in lockstep:\n\n1. **Backend endpoint** — `AGUIDojoServer/Program.cs`: add `app.MapDojoEndpoint(\"/<feature>\", ChatClientAgentFactory.Create…())`.\n   Agent logic lives in `ChatClientAgentFactory.cs`.\n2. **Agent mapping** — `apps/dojo/src/agents.ts` (`\"ag-ui-dotnet\"` block): add `<feature>: \"<feature>\"`\n   inside `mapAgents`; each maps to `new HttpAgent({ url: \\`${envVars.aguiDotnetUrl}/<feature>\\` })`.\n3. **Menu** — `apps/dojo/src/menu.ts` (`id: \"ag-ui-dotnet\"`): add the feature to `features`.\n4. **Source viewer** — `apps/dojo/scripts/generate-content-json.ts` already maps `ag-ui-dotnet` to\n   `Program.cs` + `ChatClientAgentFactory.cs`; then regenerate `files.json` (below).\n5. **env.ts** — only edit if changing the URL/port; `aguiDotnetUrl`/`AGUI_DOTNET_URL` already exist.\n\nRegenerate the committed source-viewer data after any `menu.ts` change:\n\n```bash\ncd apps/dojo && pnpm generate-content-json   # writes src/files.json\n```\n\n> ⚠️ CI job `check-generated-files` fails if `src/files.json` is stale. Always regenerate and\n> commit it after editing `menu.ts` (or feature/README files).\n\n## Run the .NET e2e suite locally\n\n```bash\ncd apps/dojo/e2e\npnpm install --ignore-scripts\npnpm exec playwright install --with-deps chromium   # first time only\n# dojo (9999) + AGUIDojoServer (8023) must already be running (see above)\nBASE_URL=http://localhost:9999 PLAYWRIGHT_SUITE=ag-ui-dotnet pnpm test -- tests/agUiDotnetTests\n```\n\nTests navigate to `/ag-ui-dotnet/feature/<feature>` and drive the chat UI via page objects in\n`apps/dojo/e2e/featurePages/`.\n\n## How CI runs it (`dojo-e2e.yml`)\n\n- Matrix suite `ag-ui-dotnet`: `test_path: tests/agUiDotnetTests`, `services: [\"dojo\", \"ag-ui-dotnet\"]`,\n  `wait_on: http://localhost:9999,tcp:localhost:8023`.\n- Triggers on `pull_request`/`push` paths including **`sdks/dotnet/**`**.\n- Installs .NET `9.0.x` + `10.0.x`, runs `prep-dojo-everything.js --only` then\n  `run-dojo-everything.js --only`, waits on the ports, then `pnpm test -- tests/agUiDotnetTests`.\n\n## Gotchas\n\n- **Ports are fixed**: dojo `9999`, AGUIDojoServer `8023`. The dojo's `AGUI_DOTNET_URL` must point\n  to `http://localhost:8023` (default in `run-dojo-everything.js` and `env.ts`).\n- **`--no-build` in run** means you must run the prep step first; otherwise the `dotnet run` fails.\n- **LLMock, not a real LLM**: `OPENAI_BASE_URL=http://localhost:5555/v1` + `OPENAI_API_KEY=sk-mock`\n  are injected. Backend tool-rendering scenarios also honor `AG_UI_MOCK_WEATHER=1` for determinism.\n- **`BASE_URL` is required** — `playwright.config.ts` calls `process.exit(1)` if it's unset.\n- **Stale `files.json`** is the most common CI failure after touching `menu.ts` — run\n  `pnpm generate-content-json` and commit the result.\n","skills/ag-ui-a2ui-integration/SKILL.md":"---\nname: ag-ui-a2ui-integration\ndescription: \"Use when adding A2UI rendering to any AG-UI-supported framework or custom AG-UI application, scaffolding an AG-UI app that should render A2UI, adapting an AG-UI integration to emit A2UI surfaces, or wiring the AG-UI A2UI middleware/toolkit with a compatible renderer.\"\nversion: 1.1.0\n---\n\n# AG-UI + A2UI Integration Skill\n\n## Overview\n\nUse this skill to add A2UI rendering to an AG-UI application. Treat AG-UI as\nthe transport and agent integration layer, `@ag-ui/a2ui-middleware` as the\nserver-side bridge that detects and paints A2UI operations, and A2UI as the UI\npayload format that the client renderer displays.\n\nThis is a developer-facing skill artifact. It is meant to be loaded by coding\nagents and used against a real app or repo, not published as a docs page.\n\n## When to Use\n\n- Adding A2UI rendering to an existing AG-UI app.\n- Creating an AG-UI quickstart that should display A2UI surfaces.\n- Connecting any AG-UI-supported framework or custom AG-UI agent to an\n  A2UI-capable frontend.\n- Adding or extending an A2UI component catalog.\n- Debugging why an A2UI surface does not render or why a user action does not\n  flow back to the agent.\n\n## When NOT to Use\n\n- For AG-UI protocol event semantics only, use the AG-UI protocol skill or\n  protocol docs.\n- For A2UI renderer internals outside an AG-UI app, use the A2UI renderer\n  docs or renderer-specific skills.\n- For generic CopilotKit frontend work without A2UI, use CopilotKit-specific\n  setup and React skills.\n\n## Workflow\n\n1. Inspect the app shape: framework adapter, AG-UI agent endpoint, runtime\n   host, frontend shell, and any existing A2UI renderer/catalog.\n2. Decide the A2UI mode before editing code:\n   - Fixed schema: backend tools return an `a2ui_operations` envelope with\n     `createSurface`, `updateComponents`, and `updateDataModel`.\n   - Dynamic schema: a framework A2UI tool (`generate_a2ui`) delegates to a\n     sub-agent that streams `render_a2ui` args through `A2UIMiddleware`.\n3. Select framework-specific wiring from\n   `references/framework-adapters.md`, or use that reference to find the\n   closest AG-UI integration pattern. Preserve the app's existing agent\n   architecture.\n4. Wire server middleware/runtime and client renderer using\n   `references/a2ui-runtime-and-renderer.md`. Avoid double-applying\n   `A2UIMiddleware`; use either runtime-level A2UI config or per-agent\n   `agent.use(new A2UIMiddleware(...))` for a given agent.\n5. Register a catalog on the client. With CopilotKit >= 1.61.2, forwarding it to\n   the provider (`a2ui={{ catalog }}`) auto-enables A2UI and auto-derives\n   `defaultCatalogId` from the catalog's id. Only when you are not forwarding a\n   catalog, ensure the middleware or adapter sets a `defaultCatalogId` matching\n   the renderer-registered catalog.\n6. Verify the streaming path with `references/verification.md`: AG-UI stream,\n   `a2ui-surface` activity snapshots or `a2ui_operations`, rendered A2UI\n   surface, and a user interaction flowing back through AG-UI.\n\n## AG-UI Framework Support\n\nThis skill is not limited to the framework examples below. For any target\nframework, first check the AG-UI repository's `integrations/` directory, the\nAG-UI docs, the framework adapter's A2UI files, and the current CLI source. If\nAG-UI supports the framework, use that integration's documented package,\nendpoint helper, A2UI tool factory, or scaffold path. If there is no framework\nA2UI adapter, implement the custom AG-UI agent path, return `a2ui_operations`\nfrom backend tools for fixed layouts, and keep the middleware/client wiring the\nsame.\n\n## Common AG-UI CLI Flags\n\nUse the CLI flags that exist in `sdks/typescript/packages/cli/src/index.ts`.\nThe table is a quick reference for known scaffold paths, not the full AG-UI\nsupport matrix. Do not invent flags.\n\n| Framework            | CLI flag         |\n| -------------------- | ---------------- |\n| ADK                  | `--adk`          |\n| LangGraph Python     | `--langgraph-py` |\n| LangGraph JavaScript | `--langgraph-js` |\n| CrewAI Flows         | `--crewai-flows` |\n| Mastra               | `--mastra`       |\n| Pydantic AI          | `--pydantic-ai`  |\n| LlamaIndex           | `--llamaindex`   |\n| Agno                 | `--agno`         |\n| AG2                  | `--ag2`          |\n\nStrands has AG-UI integration packages and examples, but no Strands CLI flag\nis present in the current AG-UI CLI source. Use the Strands integration docs\ninstead of guessing a scaffold command.\n\n## Key Rules\n\n- Keep the integration AG-UI-first for every supported framework. CopilotKit is\n  a common runtime/renderer path for web apps, but AG-UI owns the middleware,\n  framework adapters, and wire events.\n- Enable A2UI on both sides: `A2UIMiddleware` or runtime A2UI config on the\n  server, and an A2UI-capable renderer/catalog on the client.\n- For dynamic schema, prefer the framework adapter's A2UI tool factory or\n  auto-injection path. The model should call `generate_a2ui`; the sub-agent\n  should stream `render_a2ui` args so the middleware can progressively paint.\n- For fixed schema, return an `a2ui_operations` envelope from backend tools\n  rather than asking the model to invent component trees.\n- Emit `createSurface` once per `surfaceId`; use update operations for later\n  changes.\n- Do not let the model invent catalog ids. When the client forwards a catalog to\n  the provider (CopilotKit >= 1.61.2), its `catalogId` is derived automatically;\n  otherwise the host/middleware/adapter should stamp a `defaultCatalogId` that\n  matches the client-registered catalog.\n- Preserve AG-UI run boundaries and error events. Do not swallow server or\n  stream errors.\n- Verify with a real browser or client run when possible. A static typecheck is\n  not enough for streaming UI work.\n\n## References\n\n- `references/framework-adapters.md` - framework-specific AG-UI adapter\n  patterns.\n- `references/a2ui-runtime-and-renderer.md` - server/client A2UI wiring and\n  catalog patterns.\n- `references/verification.md` - checks to confirm the integration works.\n- `sources.md` - source files and docs used by this skill.\n",".github/skills/agui-dotnet-code-review/SKILL.md":"---\nname: agui-dotnet-code-review\ndescription: >\n  Review C#/.NET code changes to the AG-UI .NET SDK (sdks/dotnet/) against its\n  specific conventions and architectural rules — AOT serialization, the\n  \"no ASP.NET in src/\" boundary, the PublicAPI analyzer workflow, wire\n  compatibility with the TypeScript reference, and the house style\n  (sealed/no-records/ConfigureAwait). Runs a phased, rule-by-rule review.\n  USE FOR: reviewing a PR, diff, or branch that touches sdks/dotnet/; checking a\n  new event/message type; verifying serialization, package placement, or\n  public-API changes in the .NET SDK. DO NOT USE FOR: generic C# style nits\n  already enforced by analyzers/EditorConfig; reviewing the TypeScript SDK\n  (sdks/typescript/) or Python SDK (sdks/python/); writing new features (only\n  flag violations, never rewrite code).\n---\n\n# AG-UI .NET SDK Code Review\n\nEncodes the AG-UI .NET SDK's house rules so a reviewer flags real violations a\ngeneric C# reviewer misses. Authoritative sources: `sdks/dotnet/AGENTS.md`\n(house rules) and `sdks/dotnet/docs/architecture.md` (design boundaries). Each\nrule cites a real enforcement example in the repo; full BAD→GOOD examples and\nper-rule exceptions live in [`references/rules.md`](references/rules.md). The\nchange-footprint and test rules below distil the `minimize-change-footprint`,\n`ensure-test-coverage`, and `ensure-test-quality` review conventions for this SDK.\n\n## Reviewer discipline\n\n- **High signal-to-noise.** Only flag a genuine violation of a rule below, tied\n  to its cited convention. Don't invent nits or restate analyzer output.\n- **Verify before flagging.** Read the actual changed code and confirm the rule\n  applies. Automated reviewers have high false-positive rates.\n- **Scope.** Review only files under `sdks/dotnet/`. Skip generic style already\n  enforced by `TreatWarningsAsErrors`, nullable, and EditorConfig.\n- **Blast radius.** Fix nothing — this skill only reports. Local convention\n  violations get a finding; codebase-wide concerns are noted as out-of-scope\n  follow-ups, not per-line nits.\n- **Severity:** ❌ must fix (breaks AOT/wire/build/boundary); ⚠️ should fix\n  (convention drift); 💡 optional polish.\n\n## The review process\n\n**Step 0 — Ground truth & file classification.** Derive the package map from\n`AGUI.slnx`; skim `AGENTS.md` + `docs/architecture.md`. Classify each changed\nfile: `production | test | sample | proto | csproj | public-api | docs`. Rules\nare gated by class.\n\n**Step 1 — Determine and summarize the change set.** Resolve what is under\nreview, in order: an explicit target (PR number / branch / commit range); else\nthe current branch vs. its tracking/base branch (`git merge-base <base> HEAD`);\nplus **staged, unstaged, and untracked** working-tree changes. Then write a short\nsummary of what the diff does — new types, wire/protocol changes, public-surface\nchanges, new dependencies, src-vs-sample placement. This frames every phase and\ncatches scope creep early.\n\n**Step 2 — Walk the rules, phase by phase (A→G).** For each phase, check every\napplicable changed file against every rule in that phase. Write each finding\nimmediately: `file:line`, rule ID, severity, one-line fix. Verify the code first.\n\n**Step 3 — Self-validation.** Dedupe; confirm each finding cites a real rule and\na real line; confirm no rule was applied to the wrong file class; drop anything\nnot verifiable in the actual diff.\n\n**Step 4 — Emit the review summary** (see below) — a single human-readable comment,\nfindings grouped by severity with a verdict and coverage line.\n\n## Phase A — Scope / scenarios\n\n- `NET-SCOPE-01` Every change traces to a spec requirement or issue `[⚠️]`\n- `NET-SCOPE-02` No unrequested capability, configurability, or dependency `[⚠️]`\n- `NET-SCOPE-03` A wire/protocol change carries compatibility coverage `[❌]`\n- `NET-SCOPE-04` Sample-only behavior stays out of `src/` `[⚠️]`\n- `NET-SCOPE-05` Minimal footprint — every diff line serves the task; no unrelated\n  refactor, speculative abstraction, or cosmetic churn `[⚠️]`\n\n## Phase B — Design / architecture\n\nFrom `docs/architecture.md` \"Architectural constraints\".\n\n- `NET-ARCH-01` No `src/` project references `Microsoft.AspNetCore.App` `[❌]` —\n  `git grep \"Microsoft.AspNetCore\" -- sdks/dotnet/src` must be empty.\n- `NET-ARCH-02` Correct package placement (wire→Abstractions, SSE→Formatting,\n  proto→Protobuf, client/transport→Client, hosting→Server) `[❌]`\n- `NET-ARCH-03` Dependency direction — `Client` and `Server` never reference each\n  other `[❌]`. Cite: `src/AGUI.Server/AGUI.Server.csproj`.\n- `NET-ARCH-04` `IChatClient` is the only integration point — no bespoke agent\n  abstraction `[💡]`\n- `NET-ARCH-05` Every type has a single reason to change `[⚠️]`\n- `NET-ARCH-06` No interface without multiple implementations or a test-double need `[⚠️]`\n- `NET-ARCH-07` Make invalid states unrepresentable (enums/types over bool/string) `[⚠️]`\n- `NET-ARCH-08` One class per file; file name matches the type `[⚠️]`\n\n## Phase C — Implementation / correctness\n\nFrom `AGENTS.md` \"JSON serialization\" / \"Code style\".\n\n- `NET-IMPL-01` Every serializable type registered in `AGUIJsonSerializerContext`\n  via `[JsonSerializable(typeof(T))]` `[❌]`. Cite:\n  `src/AGUI.Abstractions/Serialization/AGUIJsonSerializerContext.cs`.\n- `NET-IMPL-02` No `JsonSerializer.Serialize<object>` and no reflection-based\n  serialization — go through the source-gen context `[❌]`\n- `NET-IMPL-03` Polymorphic JSON uses a hand-written discriminator `JsonConverter<T>` `[❌]`.\n  Cite: `src/AGUI.Abstractions/Events/BaseEventJsonConverter.cs`.\n- `NET-IMPL-04` Property attribute kit present: explicit `[JsonPropertyName]`, **no**\n  `[JsonIgnore(WhenWritingNull)]` on optionals (the context-wide default does that),\n  required strings = `string.Empty`, collections = `[]` `[⚠️]`.\n  Cite: `src/AGUI.Abstractions/Events/RunStartedEvent.cs`.\n- `NET-IMPL-05` `ConfigureAwait(false)` on every `await` in `src/` `[⚠️]`. Cite:\n  `src/AGUI.Client/AGUIChatClient.cs`.\n- `NET-IMPL-06` `[EnumeratorCancellation]` on the token of any `IAsyncEnumerable<T>`\n  method `[⚠️]`. Cite: `src/AGUI.Formatting/SseEventStreamFormatter.cs`.\n- `NET-IMPL-07` `ArgumentNullException.ThrowIfNull(...)` for public-API argument\n  validation `[⚠️]`\n- `NET-IMPL-08` Validate external input at the boundary, not deep in the stack `[⚠️]`\n- `NET-IMPL-09` Guard every code path — no silent `default`/fallthrough `[⚠️]`\n- `NET-IMPL-10` No swallowed exceptions (empty or log-only `catch`) `[⚠️]`\n- `NET-IMPL-11` Never log or expose sensitive data in errors `[❌]`\n- `NET-IMPL-12` No dead, commented-out, or impossible-condition defensive code `[⚠️]`\n- `NET-IMPL-13` No logic duplicated across the changeset — extract a shared helper\n  at 3+ uses (Rule of Three; don't extract for 1–2) `[⚠️]`\n- `NET-IMPL-14` Prefer BCL/platform APIs over hand-rolled equivalents `[⚠️]` —\n  exception: deliberate AOT-safe hand-written paths (the `JsonElement`↔`Value`\n  bridge, the discriminator converters) are intentional, not violations.\n\n## Phase D — Wire compatibility\n\n- `NET-WIRE-01` Protocol types match the TS reference — honor the\n  `// Keep in sync with sdks/typescript/...` markers `[❌]`. Cite:\n  `src/AGUI.Abstractions/Events/RunStartedEvent.cs`.\n- `NET-WIRE-02` Events are additive — unknown types round-trip via `RawEvent`;\n  don't remove or repurpose existing fields `[⚠️]`\n- `NET-WIRE-03` Protobuf parity preserved for the supported event set `[❌]`\n\n## Phase E — PublicAPI analyzer\n\n- `NET-API-01` Any public-surface change updates that project's\n  `PublicAPI.Unshipped.txt` (build fails RS0016 otherwise) `[❌]`. Cite:\n  `sdks/dotnet/Directory.Build.targets`, `src/AGUI.Abstractions/PublicAPI.Unshipped.txt`.\n- `NET-API-02` A new event type completes the full checklist (class in `Events/`\n  deriving `BaseEvent`; `Type` → `AGUIEventTypes` constant; `[JsonSerializable]`;\n  read case in `BaseEventJsonConverter`; `PublicAPI.Unshipped.txt`; round-trip\n  test) `[⚠️]`\n\n## Phase F — Style / naming\n\nFrom `AGENTS.md` \"Code style\" / \"Naming\" (not all analyzer-enforced).\n\n- `NET-STYLE-01` `sealed` on every non-abstract class `[⚠️]`\n- `NET-STYLE-02` No `record` types — use `sealed class` with properties `[❌]`\n- `NET-STYLE-03` No tuples in public APIs — define a named type `[⚠️]`\n- `NET-STYLE-04` Braces always on `if`/`for`/`foreach`/`while` `[⚠️]`\n- `NET-STYLE-05` Naming: events `{Name}Event`; discriminators `SCREAMING_SNAKE_CASE`\n  constants in `AGUIEventTypes`; outcome/role constants lowercase (never enums);\n  options `AGUI{Purpose}Options`; extensions `{Target}Extensions`; tests\n  `{TypeUnderTest}Test` `[⚠️]`\n- `NET-STYLE-06` DI-extension types use the `Microsoft.Extensions.DependencyInjection`\n  namespace; all other types use the project `RootNamespace` with no sub-namespaces `[⚠️]`\n- `NET-STYLE-07` No XML docs (`///`) on `internal`/`private` members `[⚠️]`\n- `NET-STYLE-08` Don't reformat code you didn't otherwise change `[⚠️]`\n\n## Phase G — Tests\n\nFrom `AGENTS.md` \"Running tests\"; coverage/quality rules distilled from\n`ensure-test-coverage` and `ensure-test-quality`.\n\nSDK-specific:\n- `NET-TEST-01` Serialization tests assert concrete JSON property names via\n  `JsonDocument` — not via the deserialized object `[⚠️]`\n- `NET-TEST-02` No full-JSON-string comparisons — assert individual properties `[❌]`\n- `NET-TEST-03` No reflection to enumerate types or verify membership `[❌]`\n- `NET-TEST-04` Wire-affecting change ⇒ compatibility fixture + round-trip in\n  `tests/AGUI.Abstractions.UnitTests/Compatibility/` `[⚠️]`\n- `NET-TEST-05` New public behavior ⇒ unit test; server-pipeline change ⇒\n  integration test (`tests/AGUI.Hosting.AspNetCore.IntegrationTests/`) `[⚠️/💡]`\n\nCoverage:\n- `NET-TEST-06` A new/changed class with branching logic has a test covering happy\n  path, primary error path, and boundary values (null/empty/zero/single) `[⚠️]`\n- `NET-TEST-07` Don't test trivial code — DTOs/records with no logic, one-line\n  delegations, constant returns `[💡]`\n- `NET-TEST-08` Test through DI + `InternalsVisibleTo`, not members made `public`\n  for tests `[⚠️]`\n\nQuality:\n- `NET-TEST-09` Every test asserts a specific observable value — no assertion-free\n  tests, no bare `Assert.NotNull`/`True`/`NotEmpty` standing in for the real value `[❌]`\n- `NET-TEST-10` Deterministic and isolated — no `Thread.Sleep`/`Task.Delay` for\n  synchronization, no execution-order dependence, side effects cleaned up\n  (files/ports/env) `[❌]`\n- `NET-TEST-11` Test behavior, not implementation — prefer hand-written fakes over\n  `mock.Verify(Times.*)` (unless the call count is the spec'd behavior); `[Theory]`\n  for data variation, `[Fact]` for behavior; AAA visible inline with factory\n  helpers (not shared mutable fixtures) below the tests; no `// TODO` or empty\n  test bodies `[⚠️]`\n\n## Self-validation\n\n- [ ] The change set was resolved (target / tracking branch / working tree) and summarized\n- [ ] Every applicable changed file was walked against every phase's rules\n- [ ] Each finding cites a real rule ID, file, and line, and was verified in the diff\n- [ ] No rule applied to the wrong file class; no duplicates\n- [ ] Clean diffs are reported as clean — no padding\n\n## Common pitfalls\n\n| Pitfall | Solution |\n|---------|----------|\n| Restating analyzer/EditorConfig output | Only flag rules above that tooling does not enforce |\n| Flagging a \"missing\" registration without checking the context | Open `AGUIJsonSerializerContext.cs` and confirm |\n| Treating a sample's ASP.NET usage as a `src/` violation | `NET-ARCH-01` applies to `src/` only |\n| Calling an additive new event a wire break | `NET-WIRE-02` — additive is allowed |\n| Nitpicking style in files with substantive changes | Focus on the substantive change |\n\n## Review summary\n\nProduce a single human-readable Markdown comment — a reviewer's summary the author\ncan read top to bottom. Lead with the verdict, then the findings grouped by\nseverity (most severe first), each one self-contained.\n\n```markdown\n## AG-UI .NET SDK code review\n\n**Verdict:** <Request changes | Comment | Looks good> — <one-sentence reason>\n**Change set:** <branch vs base, e.g. `feat/x` vs `main`> · <N files reviewed>\n(+<U untracked>) · **Findings:** ❌ <a> · ⚠️ <b> · 💡 <c>\n\n<One short paragraph: what the change does and the overall read.>\n\n### ❌ Must fix\n- **`src/AGUI.Abstractions/Events/FooEvent.cs:42`** · `NET-IMPL-01` — new event type\n  isn't registered in `AGUIJsonSerializerContext`; it fails under AOT.\n  **Fix:** add `[JsonSerializable(typeof(FooEvent))]`.\n\n### ⚠️ Should fix\n- **`src/AGUI.Client/AGUIChatClient.cs:88`** · `NET-IMPL-05` — bare `await` in\n  library code. **Fix:** append `.ConfigureAwait(false)`.\n\n### 💡 Optional\n- **`src/AGUI.Server/StreamAdapter.cs:17`** · `NET-ARCH-04` — bespoke agent\n  abstraction; the SDK integrates via `IChatClient`. **Fix:** drop the wrapper.\n\n### Coverage\nPhases checked: A–G. No findings in: **B Design**, **D Wire**, **E PublicAPI**.\n```\n\nRules for the summary:\n- **Order** findings by severity (❌ → ⚠️ → 💡), then by file. One bullet per finding:\n  bold `file:line`, the `RULE-ID`, a plain-language description, and an italic\n  **Fix:** with a one-line remedy. The reader can look the ID up in\n  [`references/rules.md`](references/rules.md).\n- **Omit empty severity sections.** Always include the **Coverage** line so the\n  author sees which phases were clean versus untouched.\n- **Clean diff:** skip the severity sections and write a single line —\n  `✅ No violations of the AG-UI .NET house rules — checked phases A–G across N files.`\n- **Verdict mapping:** any ❌ → *Request changes*; only ⚠️/💡 → *Comment*; none →\n  *Looks good*. The skill never approves or blocks automatically — the verdict is\n  advisory and the author decides.\n\n",".github/skills/agui-dotnet-agents-sync/SKILL.md":"---\nname: agui-dotnet-agents-sync\ndescription: >\n  Keep the AG-UI .NET SDK docs (sdks/dotnet/AGENTS.md and docs/architecture.md) in\n  sync with the real code tree after structural changes. USE FOR: \"update\n  AGENTS.md / docs/architecture.md\", \"check the dotnet docs are current\", verifying\n  docs after a .NET SDK refactor (package rename, added/removed project,\n  changed endpoint pattern, new/renamed test project, sample step added, new\n  convention). DO NOT USE FOR: writing product code or tests (follow AGENTS.md\n  itself), Python/TypeScript SDK docs, or generic markdown editing unrelated to\n  the dotnet SDK structure.\n---\n\n# AG-UI .NET SDK — Docs Sync\n\n`sdks/dotnet/AGENTS.md` (coding instructions) and `sdks/dotnet/docs/architecture.md`\n(design overview) describe the SDK's structure, naming, and conventions. They\ndrift silently after refactors because nothing fails the build when prose goes\nstale. This skill reconciles them against the live tree.\n\n> Typical drift this catches: a package rename, a moved/removed project, a changed\n> endpoint pattern, or a new sample step that the prose never caught up with. An agent\n> that edits these files from memory re-introduces the same kind of drift, so always\n> derive the truth from the tree first.\n\n## Process\n\n1. **Establish ground truth from the tree, not from the doc.** The authoritative\n   source is `sdks/dotnet/AGUI.slnx` plus the folder listing — never the prose\n   you are about to edit.\n   - Projects: read `<Project Path=...>` entries from `AGUI.slnx`.\n   - Folders: `Get-ChildItem src,tests,samples -Directory`.\n   - Samples/steps: list `samples/GettingStarted/Step*` to get the real range.\n2. **Drift scan — diff each doc claim against the tree.** For every concrete\n   claim in AGENTS.md / docs/architecture.md, confirm it against ground truth:\n   - Project & package names exist in `AGUI.slnx` (and in `src/`, `tests/`).\n   - Symbols the docs name still exist: `Select-String -Path src\\*\\*.cs,samples\\*\\*.cs -Pattern \"<Symbol>\"`.\n   - Renamed/removed symbols are GONE everywhere: grep the repo for the old\n     name (e.g. `AGUI.Hosting.AspNetCore`, `TypedResults.ServerSentEvents`); a\n     hit in prose-only is the drift to fix.\n3. **Fix surgically.** Edit only the stale lines. Match existing tone, tables,\n   and code-fence style. Do not restructure or invent conventions.\n4. **Verify.** Re-grep every symbol/name you wrote to confirm it exists in the\n   tree. Optionally `dotnet build` from `sdks/dotnet/` if you touched code-style\n   or build claims.\n\n## Drift checklist (the claims that rot)\n\n| Doc claim | Reconcile against |\n|---|---|\n| **src package list / names** | `AGUI.slnx` `/src/` folder + `src/` dirs |\n| **Package dependency table & framework refs** | `grep Microsoft.AspNetCore src\\*\\*.csproj` (must be empty — no src project references ASP.NET) |\n| **Where ASP.NET glue lives** | `samples/AGUI.Samples.Shared` (the only `FrameworkReference Microsoft.AspNetCore.App`) |\n| **Test-project table & count** | `AGUI.slnx` `/tests/` + `tests/` dirs |\n| **Sample step range / count** | `samples/GettingStarted/Step*` listing |\n| **Endpoint pattern code** | actual sample `Program.cs` + `samples/AGUI.Samples.Shared` |\n| **Project layout bullet list** | `src/`, `tests/`, `samples/` dirs |\n| **Code-style / naming / serialization rules** | `Directory.Build.props/.targets`, `Directory.Packages.props`, source |\n| **PublicAPI workflow** | presence of `PublicAPI.*.txt` in each `src/` project |\n\n## Deriving ground truth (commands, not a snapshot)\n\nDon't trust any embedded list (including this skill). Re-derive the current state\nfrom the tree every time:\n\n```powershell\n# from sdks/dotnet/\nSelect-String -Path AGUI.slnx -Pattern '<Project Path'   # all projects\nGet-ChildItem src,tests,samples -Directory               # folders\nGet-ChildItem samples/GettingStarted -Directory -Filter Step*  # sample step range\nSelect-String -Path src\\*\\*.csproj -Pattern Microsoft.AspNetCore  # must be empty (no ASP.NET in src/)\n```\n\nA couple of durable facts that are easy to get wrong: the server package is\n`AGUI.Server` (ASP.NET hosting glue lives only in `samples/AGUI.Samples.Shared`),\nand the integration-test **project name** stays `AGUI.Hosting.AspNetCore.IntegrationTests`\neven though its types are in namespace `AGUI.Server.IntegrationTests`. Everything else,\nderive from the commands above.\n\n## ❌ Critical anti-patterns\n\n1. **Never edit the docs from memory or from the doc's own current text.** The\n   stale prose is exactly what misleads you. Derive every name from `AGUI.slnx`\n   and the folder listing first.\n2. **Never rename a symbol in prose without grepping the whole tree** for the\n   old name — a lingering reference (or an unchanged code fence) is silent drift.\n3. **Don't invent conventions or restructure the docs.** Reconcile only what the\n   tree proves changed; keep tables, tone, and code-fence style intact.\n4. **Don't confuse a kept project name with a moved concept.** The integration\n   test project is still `AGUI.Hosting.AspNetCore.IntegrationTests` even though\n   the src package was renamed to `AGUI.Server`.\n\n## Files to mine\n\n`sdks/dotnet/AGENTS.md`, `sdks/dotnet/docs/architecture.md`, `sdks/dotnet/AGUI.slnx`,\n`sdks/dotnet/Directory.Build.props`, `Directory.Build.targets`,\n`Directory.Packages.props`, and the `src/`, `tests/`, `samples/` folder trees.\n",".github/skills/agui-dotnet-transport/SKILL.md":"---\nname: agui-dotnet-transport\ndescription: >\n  Add or modify a wire transport / event-stream encoding in the AG-UI .NET SDK — the protobuf\n  codec, the SSE format, content negotiation, the JsonElement-to-protobuf Value bridge, or a brand\n  new encoding — while preserving Native AOT compatibility and byte-level wire compatibility with\n  @ag-ui/proto. USE FOR: working on AGUI.Formatting / AGUI.Protobuf, IAGUIEventStreamFormatter,\n  transport content negotiation, the JsonElement-to-google.protobuf.Value bridge, SSE or protobuf\n  framing, server formatter registration / AGUIResults.Events negotiation. DO NOT USE FOR: adding a new wire event\n  TYPE (use agui-dotnet-wire-types), writing tests (use agui-dotnet-integration-tests).\n---\n\n# AG-UI .NET Transport & Encoding\n\nEncodes the non-obvious design constraints of the AG-UI .NET transport layer, discovered while\nbuilding protobuf support. Apply when adding/changing an encoding or the negotiation that selects\none. Read `references/wire-format.md` before touching the protobuf codec or framing.\n\n## Transport architecture\n\nOne bidirectional abstraction, `IAGUIEventStreamFormatter` (in `AGUI.Formatting`), serves every\ntransport and both directions:\n\n| Member | Role |\n|--------|------|\n| `MediaType` | Advertised in client `Accept` and written as server `Content-Type`. Registration order = preference. |\n| `CanRead(contentType)` | Client picks the decoder for the response `Content-Type`. |\n| `ReadAsync(body, ct)` | Decode body → `IAsyncEnumerable<BaseEvent>`. |\n| `WriteAsync(events, output, ct)` | Encode events → body. |\n\n`SseEventStreamFormatter` (`text/event-stream`) is the always-available default;\n`ProtobufEventStreamFormatter` (`ProtobufEventStreamFormatter.ProtobufMediaType`) is opt-in.\n\n**Client negotiation** = `DelegatingHandler` + decode helper:\n- `AGUIEventStreamHandler` (public, in `AGUI.Client`) advertises every registered formatter's\n  `MediaType` in `Accept`, then inspects the response `Content-Type`, finds the first `CanRead`\n  formatter, and records it on the request. The body is left untouched for lazy streaming.\n- `AGUIResponseExtensions.ReadAGUIEventStreamAsync` reads that recorded formatter (falling back to\n  SSE) and decodes. The SDK ships no `IHttpClientFactory` integration: a caller that wants protobuf\n  wires the handler into its own `HttpClient`, and constructs `AGUIChatClient` from\n  `AGUIChatClientOptions`.\n\n**Server negotiation** = `AGUIResults.Events` (samples `AGUI.Samples.Shared`): collects registered\n`IAGUIEventStreamFormatter` services (+ built-in SSE), then picks protobuf **only when its media\ntype is explicitly present** in `Accept` with non-zero quality, else SSE for `text/event-stream`/\nwildcard/absent, else `406`. Mirrors `preferredMediaTypes(accept, [proto])` in `@ag-ui/encoder`.\nA server opts in by registering the formatter (for example,\n`services.AddSingleton<IAGUIEventStreamFormatter, ProtobufEventStreamFormatter>()`).\n\n## Wire format facts\n\n- Protobuf media type: `application/vnd.ag-ui.event+proto` (`ProtobufEventStreamFormatter.ProtobufMediaType`).\n- Framing: **4-byte big-endian `uint32` length prefix + protobuf message bytes**, per event —\n  matches `@ag-ui/encoder` `encodeProtobuf` (`dataView.setUint32(0, length, false)`). See\n  `AGUIProtobuf.WriteFramed` / `ReadFramedAsync`.\n- `Encode`/`Decode` = single message, no length prefix (mirror TS `proto.encode`/`proto.decode`).\n- Dynamic payloads (state, args, results) use `google.protobuf.Value` (Struct/ListValue/scalars) —\n  **never `Any` and never a JSON-string field**.\n\n## The CRITICAL Native AOT rule\n\nImplement the `JsonElement` <-> `google.protobuf.Value` bridge **by hand over the generated\nWellKnownTypes** (`ProtoValueConverter`). **NEVER** use Google.Protobuf's reflection-based\n`JsonFormatter`/`JsonParser` or any descriptor reflection API — they are not trim/AOT safe and the\npackage multi-targets `net10/9/8/netstandard2.0/net472`.\n\n- **Number caveat**: `Value` is double-only. `long`/`decimal` beyond 2^53 lose precision on round\n  trip. This is intentional — it matches the JS `@ag-ui/proto` limitation.\n\n## Schema-first extension\n\nThe `.proto` schema is **canonical** and lives in the TS package. `AGUI.Protobuf.csproj`\n`<Protobuf>` references `sdks/typescript/packages/proto/src/proto/*.proto` directly\n(`csharp_namespace = AGUI.ProtocolBuffers`, generated types `Access=\"Internal\"`) — **do not fork or\ncopy it**. To add a wire-representable event:\n\n1. Extend the shared `.proto` (coordinated across all SDKs — it is the cross-language contract).\n2. Add a mapper case in `ProtoEventMapper` (event oneof) / `ProtoMessageMapper` (messages),\n   mirroring `sdks/typescript/packages/proto/src/proto.ts` reshaping verbatim.\n\nSubset coverage is intentional: .NET-only events that have no wire representation throw\n`NotSupportedException` from the mapper's `default` case. Don't invent a wire shape unilaterally.\n\n## How to verify\n\n- **Byte-parity** against `@ag-ui/proto` via the cross-language tests (see\n  `agui-dotnet-integration-tests` and `sdks/dotnet/docs/cross-language-testing.md`). The JSON\n  compatibility fixtures in `tests/AGUI.Abstractions.UnitTests/Compatibility/` guard SSE drift.\n- **Multi-TFM AOT build**: `dotnet build` from `sdks/dotnet/` (targets net10/9/8/netstandard2.0/\n  net472; warnings are errors). Update `PublicAPI.Unshipped.txt` for any public surface change.\n\n## ❌ Anti-patterns\n\n1. **Don't embed JSON-as-string inside a `Value`.** Map structured payloads recursively to\n   Struct/ListValue/scalars via `ProtoValueConverter`. A string field breaks @ag-ui/proto parity.\n2. **Don't use `JsonFormatter`/`JsonParser`/descriptor reflection.** Not AOT-safe — hand-write the\n   bridge over generated WellKnownTypes.\n3. **Don't copy or fork the `.proto`.** Reference the canonical TS schema from the `.csproj` so the\n   codec can't drift from the wire contract.\n4. **Don't make `AGUI.Protobuf` depend on `AGUI.Client` or the hosting/server package.** The codec\n   stays transport-neutral; it references only `AGUI.Abstractions` + `AGUI.Formatting`.\n5. **Don't change framing or use little-endian.** Length is big-endian `uint32`; both SDKs depend\n   on exact byte layout.\n\n## References\n\n- **Wire format & codec internals** (framing, oneof mapping, Value bridge, negotiation parity):\n  [references/wire-format.md](references/wire-format.md)\n",".github/skills/agui-dotnet-feature-workflow/SKILL.md":"---\nname: agui-dotnet-feature-workflow\ndescription: >\n  Orchestrator/hub for implementing a feature or change in the AG-UI .NET SDK\n  (sdks/dotnet). USE FOR: \"what's the workflow\", \"what order do I do things in\",\n  \"how do I implement a feature in the .NET SDK\", starting any non-trivial\n  AG-UI .NET SDK change, planning the end-to-end steps and definition-of-done\n  (code + AOT serialization + client/server mapping + unit/integration/cross-language\n  tests + docs + PublicAPI + AGENTS.md sync). DO NOT USE FOR: the deep how-to of a\n  single step — this skill ROUTES to focused siblings: adding wire types\n  (agui-dotnet-wire-types), transport/encoding (agui-dotnet-transport), unit tests\n  (agui-dotnet-unit-tests), integration tests (agui-dotnet-integration-tests),\n  cross-language tests (agui-dotnet-cross-language-tests), porting from TS/Python\n  (agui-cross-sdk-parity), adding a GettingStarted sample Step\n  (agui-dotnet-sample-step), SDK docs (agui-dotnet-sdk-docs), AGENTS/Architecture\n  sync (agui-dotnet-agents-sync), the dojo (agui-dojo), review\n  (agui-dotnet-code-review).\n---\n\n# AG-UI .NET SDK — Feature Workflow (Orchestrator)\n\nThis is the **hub** skill. Given a request to build or change a feature in the AG-UI\n.NET SDK (`sdks/dotnet/`), it lays out the correct end-to-end order and **routes the\ndepth of each step to a focused sibling skill**. It does not duplicate their content.\n\nThe SDK has a multi-artifact **definition of done**. An agent working ad hoc forgets\nartifacts — most often cross-language parity, docs, `AGENTS.md`/`docs/architecture.md` sync,\nand `PublicAPI.Unshipped.txt`. Use this skill to avoid that.\n\n## Package map\n\n`sdks/dotnet/src/`:\n\n| Package | Responsibility |\n|---|---|\n| `AGUI.Abstractions` | Wire types: events, messages, tools, capabilities, `AGUIJsonSerializerContext` |\n| `AGUI.Formatting` | JSON formatter + SSE encode/decode |\n| `AGUI.Protobuf` | Protobuf encoding of the protocol |\n| `AGUI.Client` | `AGUIChatClient` (`IChatClient`) + transport negotiation |\n| `AGUI.Server` | Hosting-agnostic agent-side conversion (`ChatResponseUpdate` → events) |\n\nASP.NET hosting glue lives in `samples/AGUI.Samples.Shared` (not a `src/` package).\n`sdks/dotnet/AGENTS.md` and `docs/architecture.md` are the canonical description of\nthe layout and conventions (kept current via `agui-dotnet-agents-sync`); `AGUI.slnx`\nis the ground truth if you need to re-derive the package list.\n\n## Build & test commands\n\n```bash\n# from sdks/dotnet/\ndotnet build sdks/dotnet/AGUI.slnx        # whole solution\ndotnet test  tests/AGUI.Abstractions.UnitTests/   # per-project, fast feedback\n```\n\n`Directory.Build.props` **treats warnings as errors**, and `PublicApiAnalyzers` is on\nfor every `src/` project with a `PublicAPI.Shipped.txt`. **The build fails if you skip\nthe AOT serialization wiring or forget `PublicAPI.Unshipped.txt`** — these are not\noptional polish steps, they are enforced.\n\n## Definition of done (feature checklist)\n\n- [ ] Wire contract understood (matched against TS/Python reference if wire-affecting)\n- [ ] Type/behavior implemented in the **right package** (see map)\n- [ ] AOT serialization wired (`[JsonSerializable]` in `AGUIJsonSerializerContext`, converter case, `[JsonPropertyName]`)\n- [ ] Client/server mapping updated (`AGUI.Client` event→update and/or `AGUI.Server` update→event)\n- [ ] Unit tests (serialization round-trip + behavior)\n- [ ] Integration tests (full pipeline) if it crosses the HTTP/SSE boundary\n- [ ] Cross-language parity tests if wire-affecting\n- [ ] `PublicAPI.Unshipped.txt` updated for every changed public member\n- [ ] Docs updated (docs.ag-ui.com / SDK docs) if user-facing\n- [ ] `AGENTS.md` / `docs/architecture.md` synced if structure/recipe changed\n- [ ] `dotnet build sdks/dotnet/AGUI.slnx` and relevant `dotnet test` projects green\n\n## Ordered workflow → route each step\n\nDo the steps **in this order**. Skip a step only if it genuinely doesn't apply\n(e.g. a non-wire-affecting internal refactor skips cross-language parity).\n\n1. **Understand the wire contract.** Read the TypeScript (and Python) reference for\n   the type/behavior so the .NET shape matches the spec. Porting an existing feature\n   from another SDK? → **`agui-cross-sdk-parity`**.\n\n2. **Implement the type/behavior in the right package.**\n   - New/changed wire type (event, message, tool, capability) → **`agui-dotnet-wire-types`**\n     (covers the `AGUI.Abstractions` recipe: class in `Events/`, `AGUIEventTypes`\n     constant, converter case, AOT registration, `PublicAPI.Unshipped.txt`).\n   - New/changed transport or encoding (SSE, protobuf, formatter) →\n     **`agui-dotnet-transport`** (`AGUI.Formatting`, `AGUI.Protobuf`).\n\n3. **Wire AOT serialization.** Every protocol type goes through\n   `AGUIJsonSerializerContext` — no reflection. `agui-dotnet-wire-types` has the\n   per-type recipe; the build enforces it.\n\n4. **Update client/server mapping.** Server-side `ChatResponseUpdate` → event lives in\n   `AGUI.Server`; client-side event → `ChatResponseUpdate` lives in `AGUI.Client`\n   (`EventStreamConverter`, builders). Update both directions if the wire shape changed.\n\n5. **Unit tests** (round-trip + behavior) → **`agui-dotnet-unit-tests`**.\n\n6. **Integration tests** (HTTP + SSE pipeline, `WebApplicationFactory`,\n   `AGUIChatClient`) → **`agui-dotnet-integration-tests`**. Required when the change\n   crosses the transport boundary.\n\n7. **Cross-language parity tests** (if wire-affecting) →\n   **`agui-dotnet-cross-language-tests`** (`tests/AGUI.CrossLanguage.IntegrationTests`,\n   `CrossLanguage.TestServer`, `CrossLanguage.Vitest`). This is the step agents most\n   often forget — .NET must agree with TS/Python on the bytes.\n\n8. **Update `PublicAPI.Unshipped.txt`** for every changed public member, in each\n   affected `src/` project. The PublicAPI analyzer fails the build otherwise.\n\n9. **Docs** (user-facing change) → **`agui-dotnet-sdk-docs`** (docs.ag-ui.com).\n\n10. **Sync `AGENTS.md` / `docs/architecture.md`** if you changed structure, recipes, or\n    commands → **`agui-dotnet-agents-sync`**. Fix stale package references while here.\n\n11. **Build + test green.** `dotnet build sdks/dotnet/AGUI.slnx`, then the relevant\n    `dotnet test <project>` (unit + integration + cross-language as applicable).\n\n12. **Validate & review.** Run/inspect in the dojo → **`agui-dojo`**; manual UI/docs\n    checks → **`agui-playwright-validate`**; review the change → **`agui-dotnet-code-review`**.\n\n## Routing table (quick reference)\n\n| Step / need | Sibling skill |\n|---|---|\n| Add/modify a wire type | `agui-dotnet-wire-types` |\n| Add/modify transport or encoding | `agui-dotnet-transport` |\n| Port a feature from TS/Python | `agui-cross-sdk-parity` |\n| Write unit tests | `agui-dotnet-unit-tests` |\n| Write integration tests | `agui-dotnet-integration-tests` |\n| Write cross-language tests | `agui-dotnet-cross-language-tests` |\n| Add a GettingStarted sample Step (Server/Client pair) | `agui-dotnet-sample-step` |\n| Update SDK docs site | `agui-dotnet-sdk-docs` |\n| Keep AGENTS.md / docs/architecture.md current | `agui-dotnet-agents-sync` |\n| Run/validate in the dojo | `agui-dojo` |\n| Manual UI/docs validation | `agui-playwright-validate` |\n| Review the change | `agui-dotnet-code-review` |\n\n> The depth of each step lives in the sibling skill it routes to; fall back to the\n> recipes in `AGENTS.md` and the deep content in `docs/architecture.md` for anything a\n> sibling doesn't cover.\n\n## ❌ Anti-patterns\n\n1. **Don't stop at \"it compiles and unit tests pass.\"** Wire-affecting changes are not\n   done until cross-language parity tests and docs are updated.\n2. **Don't put protocol or server code in a sample.** It belongs in `src/`; the server is\n   `AGUI.Server`, hosting glue is in `samples/AGUI.Samples.Shared`, and no `src/` project\n   references ASP.NET.\n3. **Don't skip `PublicAPI.Unshipped.txt` or AOT registration** \"to fix later\" — the\n   warnings-as-errors build will block you immediately.\n4. **Don't do the deep work here.** This skill routes; the depth lives in the sibling\n   skills. Open the relevant one before implementing a step.\n",".github/skills/agui-dotnet-wire-types/SKILL.md":"# agui-dotnet-wire-types\n\nPath: `.github/skills/agui-dotnet-wire-types/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-wire-types/SKILL.md)",".github/skills/agui-playwright-validate/SKILL.md":"# agui-playwright-validate\n\nPath: `.github/skills/agui-playwright-validate/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-playwright-validate/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-client-tools/SKILL.md":"# agui-dotnet-client-tools\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-client-tools/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-client-tools/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-human-in-the-loop/SKILL.md":"# agui-dotnet-human-in-the-loop\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-human-in-the-loop/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-human-in-the-loop/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-multimodal/SKILL.md":"# agui-dotnet-multimodal\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-multimodal/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-multimodal/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-protobuf/SKILL.md":"# agui-dotnet-protobuf\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-protobuf/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-protobuf/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-reasoning/SKILL.md":"# agui-dotnet-reasoning\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-reasoning/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-reasoning/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-server-tools/SKILL.md":"# agui-dotnet-server-tools\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-server-tools/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-server-tools/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-shared-state/SKILL.md":"# agui-dotnet-shared-state\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-shared-state/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-shared-state/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-streaming-chat/SKILL.md":"# agui-dotnet-streaming-chat\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-streaming-chat/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-streaming-chat/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-troubleshoot/SKILL.md":"# agui-dotnet-troubleshoot\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-troubleshoot/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-troubleshoot/SKILL.md)","AGENTS.md":"# AI Agent Protocol & Instructions\n\nPath: `AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/AGENTS.md)","CLAUDE.md":"# Claude Agent Guidelines & System Prompt\n\nPath: `CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/CLAUDE.md)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.claude-plugin/marketplace.json)","skills/ag-ui-a2ui-integration/sources.md":"# Ag-ui-a2ui-integration Skill\n\nPath: `skills/ag-ui-a2ui-integration/sources.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/sources.md)","skills/ag-ui-a2ui-integration/references/a2ui-runtime-and-renderer.md":"# References Skill\n\nPath: `skills/ag-ui-a2ui-integration/references/a2ui-runtime-and-renderer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/references/a2ui-runtime-and-renderer.md)","skills/ag-ui-a2ui-integration/references/framework-adapters.md":"# References Skill\n\nPath: `skills/ag-ui-a2ui-integration/references/framework-adapters.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/references/framework-adapters.md)","skills/ag-ui-a2ui-integration/references/verification.md":"# References Skill\n\nPath: `skills/ag-ui-a2ui-integration/references/verification.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/references/verification.md)",".github/skills/agui-dotnet-code-review/references/rules.md":"# References Skill\n\nPath: `.github/skills/agui-dotnet-code-review/references/rules.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-code-review/references/rules.md)",".github/skills/agui-dotnet-transport/references/wire-format.md":"# References Skill\n\nPath: `.github/skills/agui-dotnet-transport/references/wire-format.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-transport/references/wire-format.md)","sdks/dotnet/plugins/ag-ui-dotnet/README.md":"# ag-ui-dotnet Documentation\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/README.md)","sdks/dotnet/plugins/ag-ui-dotnet/plugin.json":"# ag-ui-dotnet Plugin Manifest\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/plugin.json)","sdks/typescript/.cursor/rules/project-rules.mdc":"# Cursor Rule: project-rules\n\nPath: `sdks/typescript/.cursor/rules/project-rules.mdc`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/.cursor/rules/project-rules.mdc)","sdks/typescript/packages/a2ui-toolkit/CHANGELOG.md":"# A2ui-toolkit Skill\n\nPath: `sdks/typescript/packages/a2ui-toolkit/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/CHANGELOG.md)","sdks/typescript/packages/a2ui-toolkit/README.md":"# a2ui-toolkit Documentation\n\nPath: `sdks/typescript/packages/a2ui-toolkit/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/README.md)","sdks/typescript/packages/a2ui-toolkit/package.json":"# A2ui-toolkit Skill\n\nPath: `sdks/typescript/packages/a2ui-toolkit/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/package.json)","sdks/typescript/packages/a2ui-toolkit/tsconfig.json":"# A2ui-toolkit Skill\n\nPath: `sdks/typescript/packages/a2ui-toolkit/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/tsconfig.json)","sdks/typescript/packages/cli/CHANGELOG.md":"# Cli Skill\n\nPath: `sdks/typescript/packages/cli/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/CHANGELOG.md)","sdks/typescript/packages/cli/README.md":"# cli Documentation\n\nPath: `sdks/typescript/packages/cli/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/README.md)","sdks/typescript/packages/cli/package.json":"# Cli Skill\n\nPath: `sdks/typescript/packages/cli/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/package.json)","sdks/typescript/packages/cli/tsconfig.json":"# Cli Skill\n\nPath: `sdks/typescript/packages/cli/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/tsconfig.json)","sdks/typescript/packages/client/CHANGELOG.md":"# Client Skill\n\nPath: `sdks/typescript/packages/client/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/CHANGELOG.md)","sdks/typescript/packages/client/DEPRECATIONS.md":"# Client Skill\n\nPath: `sdks/typescript/packages/client/DEPRECATIONS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/DEPRECATIONS.md)","sdks/typescript/packages/client/README.md":"# client Documentation\n\nPath: `sdks/typescript/packages/client/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/README.md)","sdks/typescript/packages/client/package.json":"# Client Skill\n\nPath: `sdks/typescript/packages/client/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/package.json)","sdks/typescript/packages/client/tsconfig.json":"# Client Skill\n\nPath: `sdks/typescript/packages/client/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/tsconfig.json)","sdks/typescript/packages/core/CHANGELOG.md":"# Core Skill\n\nPath: `sdks/typescript/packages/core/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/CHANGELOG.md)","sdks/typescript/packages/core/README.md":"# core Documentation\n\nPath: `sdks/typescript/packages/core/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/README.md)","sdks/typescript/packages/core/package.json":"# Core Skill\n\nPath: `sdks/typescript/packages/core/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/package.json)","sdks/typescript/packages/core/tsconfig.json":"# Core Skill\n\nPath: `sdks/typescript/packages/core/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/tsconfig.json)","sdks/typescript/packages/encoder/CHANGELOG.md":"# Encoder Skill\n\nPath: `sdks/typescript/packages/encoder/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/CHANGELOG.md)","sdks/typescript/packages/encoder/README.md":"# encoder Documentation\n\nPath: `sdks/typescript/packages/encoder/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/README.md)","sdks/typescript/packages/encoder/package.json":"# Encoder Skill\n\nPath: `sdks/typescript/packages/encoder/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/package.json)","sdks/typescript/packages/encoder/tsconfig.json":"# Encoder Skill\n\nPath: `sdks/typescript/packages/encoder/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/tsconfig.json)","sdks/typescript/packages/proto/CHANGELOG.md":"# Proto Skill\n\nPath: `sdks/typescript/packages/proto/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/CHANGELOG.md)","sdks/typescript/packages/proto/README.md":"# proto Documentation\n\nPath: `sdks/typescript/packages/proto/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/README.md)","sdks/typescript/packages/proto/package.json":"# Proto Skill\n\nPath: `sdks/typescript/packages/proto/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/package.json)","sdks/typescript/packages/proto/tsconfig.json":"# Proto Skill\n\nPath: `sdks/typescript/packages/proto/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/tsconfig.json)","sdks/typescript/packages/proto/tsconfig.typecheck.json":"# Proto Skill\n\nPath: `sdks/typescript/packages/proto/tsconfig.typecheck.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/tsconfig.typecheck.json)","sdks/dotnet/plugins/ag-ui-dotnet/.claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/.claude-plugin/plugin.json)","integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/flight_schema.json":"# A2ui_fixed_schema_schemas Skill\n\nPath: `integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/flight_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/flight_schema.json)","integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/hotel_schema.json":"# A2ui_fixed_schema_schemas Skill\n\nPath: `integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/hotel_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/hotel_schema.json)","integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/flight_schema.json":"# Schemas Skill\n\nPath: `integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/flight_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/flight_schema.json)","integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/hotel_schema.json":"# Schemas Skill\n\nPath: `integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/hotel_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/hotel_schema.json)","sdks/typescript/packages/client/src/apply/__tests__/fixtures/strands-native-resume.json":"# Fixtures Skill\n\nPath: `sdks/typescript/packages/client/src/apply/__tests__/fixtures/strands-native-resume.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/src/apply/__tests__/fixtures/strands-native-resume.json)"},"files":{".github/skills/agui-dotnet-cross-language-tests/SKILL.md":"---\nname: agui-dotnet-cross-language-tests\ndescription: >\n  Author cross-language interop tests that verify the AG-UI .NET SDK is\n  wire-compatible with the TypeScript SDK — a Vitest TS client driving a C#\n  CrossLanguage.TestServer over HTTP, both directions, including protobuf\n  byte-parity against @ag-ui/proto. USE FOR: adding or modifying cross-language\n  interop coverage, CrossLanguage.TestServer routes, the CrossLanguage.Vitest\n  suite, protobuf wire parity tests, TS-client-to-C#-server or\n  C#-client-to-TS-server scenarios. DO NOT USE FOR: .NET-only unit tests (use\n  agui-dotnet-unit-tests), ASP.NET Core hosting integration tests (use\n  agui-dotnet-integration-tests).\n---\n\n# AG-UI .NET Cross-Language Interop Tests\n\nHow to add tests proving the .NET AG-UI SDK interoperates with the TypeScript\nSDK on the wire. The harness lives under `sdks/dotnet/tests/`. Read\n`sdks/dotnet/docs/cross-language-testing.md` (design plus the \"Harness reference\"\nsection) for full background.\n\n## Interop philosophy\n\n- **The TypeScript SDK is the reference (oracle).** A round-trip through the TS\n  codec — `proto.decode(proto.encode(event))` — is the canonical normalised form\n  both SDKs must agree on. Assert .NET output against *that*, not against the raw\n  fixture object.\n- **Round-trip semantic equivalence is the real guarantee**, in both directions\n  (TS→.NET and .NET→TS). Byte-for-byte parity is a stronger claim asserted only\n  where deterministic.\n- Tests exercise *our* code via project references (`AGUI.Abstractions`,\n  `AGUI.Server`, `AGUI.Protobuf`), never the published NuGet packages.\n\n## Harness architecture\n\nTwo directions, two server processes (see the \"Harness reference\" section of\n`sdks/dotnet/docs/cross-language-testing.md`):\n\n| Direction | Driver | Target server | Runner |\n|---|---|---|---|\n| TS → .NET (Phase 1) | TS `HttpAgent` (`@ag-ui/client`) | C# `CrossLanguage.TestServer` on :8091 | Vitest |\n| .NET → TS (Phase 2) | C# `AGUIChatClient` | TS fake-agent server (`server/main.ts`) on :8092 | xUnit |\n\nPhase 1 mechanism: Vitest `globalSetup`\n(`CrossLanguage.Vitest/helpers/global-setup.ts`) starts LLMock\n(`@copilotkit/aimock`, deterministic LLM responses), then\n`helpers/dotnet-server.ts` runs `dotnet build` and spawns the produced\n`CrossLanguage.TestServer.exe` (not `dotnet run` — single PID for clean Windows\nteardown) with `OPENAI_BASE_URL` pointed at LLMock. It waits for the HTTP\nlistener, then test files `fetch` the routes. Both server and LLMock stay alive\nacross the whole run; `vitest.config.ts` sets `fileParallelism: false` so\nconcurrent SDK builds don't contend for artifact locks.\n\nPhase 2 mechanism: `TsServerFixture` (`IAsyncLifetime`, shared via\n`[Collection(nameof(TsServerCollection))]`) shells out `pnpm run server`\n(`tsx server/main.ts`) which emits canned AG-UI events via `@ag-ui/encoder`;\n`AGUIChatClient` consumes them.\n\n## Adding a TS → .NET scenario (Phase 1)\n\n1. **Add a server-side route** under `CrossLanguage.TestServer/` following the\n   endpoint pattern (`MapPost` → `input.ToChatRequestContext(...)` →\n   `GetStreamingResponseAsync` → `.AsAGUIEventStreamAsync(ctx)` →\n   `TypedResults.ServerSentEvents(AgenticChatRoute.WrapAsSseItems(...))`). See\n   `ParallelToolCallsRoute.cs`. For a route that must **negotiate the transport**\n   (SSE *or* protobuf from the `Accept` header), end with\n   `AGUIResults.Events(events, httpContext, cancellationToken)` instead and make\n   sure `Program.cs` registers `ProtobufEventStreamFormatter` as an `IAGUIEventStreamFormatter` — see `AgenticChatRoute.cs`.\n2. **Register it in `Program.cs`** (e.g. `app.MapParallelToolCalls(\"/parallel_tool_calls\")`).\n3. **Register any new payload types in `CrossLanguageJsonSerializerContext.cs`**\n   (`[JsonSerializable(typeof(YourReport))]`). This context is snake_case to\n   match the TS wire shape.\n4. **Add an aimock fixture** in `fixtures/*.json` keyed by `userMessage` /\n   `toolCallId` so LLM responses are deterministic (see\n   `fixtures/parallel-tool-calls.json`).\n5. **Add a `tests/<scenario>.test.ts`** that drives the route with `HttpAgent`\n   and asserts on the collected event stream (see `parallel-tool-calls.test.ts`).\n\n## Adding a .NET → TS scenario (Phase 2)\n\n1. Add a fake agent (`(RunAgentInput) => BaseEvent[]`) in `server/fakeAgents.ts`.\n2. Mount its route in `server/main.ts`.\n3. Add a `*.cs` test in `AGUI.CrossLanguage.IntegrationTests/`, decorated\n   `[Collection(nameof(TsServerCollection))]`, driving it with `AGUIChatClient`\n   (see `AgenticChatTests.cs`).\n\n## Protobuf wire-parity pattern\n\n`ProtobufParityRoute.cs` exposes three codec routes backed by `AGUIProtobuf`:\n\n| Route | In | Out | Backed by |\n|---|---|---|---|\n| `POST /protobuf/encode` | event JSON | raw proto bytes | `AGUIProtobuf.Encode` |\n| `POST /protobuf/decode` | raw proto bytes | event JSON | `AGUIProtobuf.Decode` |\n| `POST /protobuf/decode-framed` | 4-byte BE length-prefixed frames | event JSON array | `AGUIProtobuf.ReadFramedAsync` |\n\n`tests/protobuf-parity.test.ts` proves parity against `@ag-ui/proto`\n(`sdks/typescript/packages/proto/src/proto.ts`) and `@ag-ui/encoder` framing\n(`sdks/typescript/packages/encoder/src/encoder.ts`). For each fixture\n(`fixtures/protobuf-events.ts`):\n\n- `tsBytes = proto.encode(event)`; `reference = proto.decode(tsBytes)`.\n- **TS encode → .NET decode**: `expect(netDecode(tsBytes)).toEqual(reference)`.\n- **.NET encode → TS decode**: `expect(proto.decode(netEncode(event))).toEqual(reference)`.\n- **Byte parity** depends on the fixture's `byteParity` flag:\n  - `\"strict\"` — scalar-only events (only string/number fields, serialised in\n    field-number order): assert the TS and .NET bytes are byte-for-byte equal.\n  - `\"roundtrip\"` — payloads mapping to `google.protobuf.Struct`\n    (`map<string, Value>`): map-entry ordering is **not** canonical across\n    encoders, so do NOT assert byte equality. Assert both byte streams decode\n    (via the TS codec) to the same event instead.\n\nA framing test concatenates `encoder.encodeProtobuf(event)` frames (4-byte BE\nprefix) and posts them to `/protobuf/decode-framed` to exercise `ReadFramedAsync`.\nWhen adding a new protobuf event, add a fixture with the correct `byteParity`\nflag — scalar-only ⇒ `strict`, any object/array payload ⇒ `roundtrip`.\n\n## Transport parity (parameterize scenarios over SSE + protobuf)\n\nThe codec-parity pattern above isolates the **codecs** — it never goes through the\nTS `HttpAgent` or `Accept`-header negotiation. To prove the full **transport** path\n(TS client negotiates a protocol → .NET server encodes it → TS client decodes it),\nparameterize a scenario suite over both transports — the cross-language analogue of\nthe .NET integration tests' `TransportFormat {Json, Protobuf}` `[Theory]`.\n\n`helpers/transport.ts` is the shared mechanism: `TRANSPORTS = [\"sse\", \"protobuf\"]`,\n`TRANSPORT_MEDIA_TYPE`, and `createTransportAgent(config, transport)` which returns\nan `HttpAgent` that requests the transport (it opts into protobuf via the public\n`fetch` hook — the default agent hardcodes `Accept: text/event-stream` *after*\nspreading `headers`, so a `headers` option can't override it) and captures the\nresponse `Content-Type`. Drive the suite with `describe.each(TRANSPORTS)` and assert\n`lastResponseContentType() === TRANSPORT_MEDIA_TYPE[transport]` plus the usual\ndecoded-event assertions — see `tests/agentic-chat.test.ts`.\n\n```ts\ndescribe.each(TRANSPORTS)(\"… [%s]\", (transport) => {\n  it(\"…\", async () => {\n    const { agent, lastResponseContentType } = createTransportAgent(\n      { url: `${baseUrl()}/agentic_chat`, threadId: `t-${transport}` }, transport);\n    agent.messages = [{ id: \"u\", role: \"user\", content: \"Hi, I am duaa\" }];\n    const events: BaseEvent[] = [];\n    await agent.runAgent({}, { onEvent: ({ event }) => events.push(event) });\n    expect(lastResponseContentType()).toBe(TRANSPORT_MEDIA_TYPE[transport]);\n    // …assert decoded events (identical regardless of transport)…\n  });\n});\n```\n\nThe route under test must negotiate (`AGUIResults.Events`, with\n`ProtobufEventStreamFormatter` registered as an `IAGUIEventStreamFormatter` in\n`Program.cs`). `tests/agentic-chat.test.ts` and\n`tests/state-events.test.ts` are parameterized this way today.\n\n**Only parameterize protobuf-safe scenarios.** `ToolCallResult`, `Reasoning*`, and\n`Activity*` events have **no message/oneof entry in the shared `events.proto`** (the\none schema referenced by *both* `@ag-ui/proto` and .NET `AGUI.Protobuf`), so *neither*\nSDK can protobuf-encode them — the codec throwing `NotSupportedException` mirrors\nthe schema, it is not a .NET gap. A suite that emits any of those must stay SSE-only.\nAdding protobuf support for them is an **upstream schema change** (extend the canonical\nTS `events.proto`, regenerate both SDKs, add mappers) — see `agui-cross-sdk-parity`.\n\n`AGUI_MEDIA_TYPE` (`@ag-ui/proto`) and `ProtobufEventStreamFormatter.ProtobufMediaType` are the identical\nexact string, and `AGUIEventStreamResult` sets `Content-Type` to it with no charset\n— the client's exact `===` content-type match depends on that.\n\n## Running the suites\n\n```sh\n# TS → .NET + protobuf parity (builds + spawns the C# server automatically)\ncd sdks/dotnet/tests/CrossLanguage.Vitest\npnpm test\npnpm exec vitest run tests/protobuf-parity.test.ts   # just the parity suite\n\n# .NET → TS (shells out `pnpm run server`)\ncd sdks/dotnet/tests/AGUI.CrossLanguage.IntegrationTests\ndotnet test\n```\n\n`pnpm install` from the repo root once first. Requires .NET 10 SDK, Node at the\nversion in the repository's root `.node-version`, pnpm 10+.\n\n## ❌ Critical anti-patterns\n\n1. **Don't assert byte-equality for object/Struct payloads.** `google.protobuf.Struct`\n   map ordering is non-canonical; byte parity is only valid for scalar-only\n   (`\"strict\"`) fixtures. For object payloads, assert round-trip equivalence.\n2. **Don't make the .NET fixture the oracle.** The TS codec is the reference —\n   compare against `proto.decode(proto.encode(event))`, not the raw event object.\n3. **Don't add a route without registering it in BOTH `Program.cs` AND\n   `CrossLanguageJsonSerializerContext.cs`** (when it introduces new payload\n   types) — the server won't map the route or will fail AOT-safe serialization.\n4. **Don't depend on real LLM calls.** Phase 1 LLM responses come from aimock\n   fixtures keyed by `userMessage`/`toolCallId`; add a fixture for every new\n   prompt. Use fixed/deterministic tool outputs (see `ParallelToolCallsRoute`'s\n   frozen clock).\n5. **Don't use `dotnet run` to start the server in helpers, and don't assume\n   parallel test files.** The harness spawns the built `.exe` for a single\n   killable PID and runs files sequentially (`fileParallelism: false`) to avoid\n   build-lock contention and Windows port orphans.\n",".github/skills/agui-cross-sdk-parity/SKILL.md":"---\nname: agui-cross-sdk-parity\ndescription: >\n  Keep the AG-UI .NET SDK at feature and wire-format PARITY with the canonical\n  reference SDKs (TypeScript is the source of truth; Python is types/encoder only).\n  USE FOR: porting a feature/event/behavior that landed in the TS (or Python) SDK\n  into .NET, verifying the .NET wire format (JSON, SSE, protobuf) matches the\n  reference, locating where the reference implementation and compatibility fixtures\n  live, mapping a TS concept to the .NET event/client/encoder model, resolving an\n  upstream protocol fix (e.g. a Microsoft.Extensions.AI / Microsoft Agent Framework\n  issue) that needs a .NET counterpart, deciding which .NET package owns a change.\n  DO NOT USE FOR: the mechanics of writing a specific test (use agui-dotnet-unit-tests\n  for serialization round-trips, agui-dotnet-integration-tests for cross-language /\n  E2E harness mechanics, agui-dotnet-wire-types for JSON/proto type rules,\n  agui-dotnet-transport for SSE/HTTP transport details). This skill is about the\n  PARITY PROCESS and where the reference lives, not test authoring.\n---\n\n# AG-UI Cross-SDK Parity\n\nThe .NET SDK implements an upstream, multi-language protocol. This skill encodes the\n**parity process**: which SDK is authoritative, where its reference and fixtures live,\nhow to map reference concepts onto the .NET model, and how parity is guarded.\n\n## Parity Principle\n\n- **TypeScript is canonical** for wire format AND client run-loop behavior. When two\n  SDKs disagree, match TS.\n- **Python is types + encoder only.** It has `core` (types/events) and an `encoder`,\n  but **no client run-loop and no protobuf** (`sdks/python/ag_ui/` has `core/` and\n  `encoder/` but no `client/` or `proto/`). Use it only as a secondary check on\n  type/JSON shape — never for run-loop or proto questions.\n- Upstream protocol or SDK fixes (in the TS client run-loop, or in\n  Microsoft.Extensions.AI / Microsoft Agent Framework) sometimes need a .NET\n  counterpart; treat the TypeScript change as the contract to match.\n\n## Where the Reference Lives\n\n| Concern | TypeScript reference (source of truth) | .NET package it maps to |\n|---|---|---|\n| Event & type definitions | `sdks/typescript/packages/core/src/events.ts`, `types.ts`, `event-factories.ts` | `sdks/dotnet/src/AGUI.Abstractions/Events/`, `Messages/` |\n| Client run-loop / transport | `sdks/typescript/packages/client/src/run/`, `apply/`, `agent/`, `transform/` | `sdks/dotnet/src/AGUI.Client/` (`AGUIChatClient.cs`, `AGUIHttpTransport.cs`, `EventStreamConverter.cs`, `ToolCallBuilder.cs`) |\n| SSE / JSON wire framing | `sdks/typescript/packages/encoder/src/encoder.ts` | `sdks/dotnet/src/AGUI.Formatting/`, `AGUI.Abstractions/Serialization/` |\n| Protobuf wire format | `sdks/typescript/packages/proto/src/proto/events.proto`, `types.proto`, `patch.proto` | `sdks/dotnet/src/AGUI.Protobuf/` (`ProtoEventMapper.cs`, `ProtoMessageMapper.cs`) |\n\nThe `src/` packages are **AGUI.Abstractions, AGUI.Formatting, AGUI.Protobuf, AGUI.Client,\nAGUI.Server**; `sdks/dotnet/AGENTS.md` and `docs/architecture.md` are the canonical\ndescription of the layout and conventions.\n\n## Porting Workflow\n\n1. **Locate the feature in TS.** Find the change in `packages/core` (a new event/type),\n   `packages/client` (run-loop / event-application behavior), or\n   `packages/proto`+`encoder` (wire framing). Read the TS implementation and its tests\n   to capture the exact contract — field names, ordering, optionality, coalescing rules.\n2. **Identify the wire contract.** Determine the JSON shape, the proto schema impact\n   (if any), and whether client run-loop state changes. Cross-check the JSON property\n   names against `packages/core/src/events.ts`.\n3. **Map to the .NET model and the right package** (table above). Events/types →\n   `AGUI.Abstractions`; run-loop → `AGUI.Client`; SSE/JSON framing → `AGUI.Formatting`;\n   protobuf → `AGUI.Protobuf`. Follow the .NET conventions in `AGENTS.md` (one class\n   per file, `sealed`, source-generated JSON context, `PublicAPI.Unshipped.txt`).\n4. **Implement** the .NET change. For a new event, follow the \"Adding a new event type\"\n   checklist in `AGENTS.md` (class in `Events/`, `AGUIEventTypes` constant,\n   `[JsonSerializable]`, `BaseEventJsonConverter` case, PublicAPI entry).\n5. **Add parity assets** (see next section): a TS-produced JSON fixture under\n   `tests/AGUI.Abstractions.UnitTests/Compatibility/` and/or a cross-language test in\n   `tests/CrossLanguage.Vitest/tests/`.\n6. **Verify byte/semantic parity** — run the compatibility and cross-language tests.\n7. **Update docs.** Refresh `sdks/dotnet/AGENTS.md`, `docs/architecture.md`, and\n   `docs/cross-language-testing.md` if the change alters the model, package layout, or the\n   set of wire-supported events.\n\n## How Parity Is Guarded\n\nFour independent layers catch drift; add to whichever layer the change touches.\n\n- **Compatibility fixtures (catch JSON drift).**\n  `tests/AGUI.Abstractions.UnitTests/Compatibility/` holds TS-produced JSON fixtures\n  (`*-events.json`) loaded via `FixtureLoader` and deserialized into .NET types\n  (`{Category}CompatibilityTest.cs`, e.g. `RunEventsCompatibilityTest`,\n  `ToolCallEventsCompatibilityTest`). A new/changed event shape needs a fixture entry.\n- **Cross-language tests (catch end-to-end drift).** The harness in\n  `tests/CrossLanguage.TestServer/` (C# server) and `tests/CrossLanguage.Vitest/`\n  (TS client driving it) proves real interop — see `sdks/dotnet/docs/cross-language-testing.md`.\n  Scenario specs live in `tests/CrossLanguage.Vitest/tests/` (e.g.\n  `parallel-tool-calls.test.ts`, `state-events.test.ts`, `protobuf-parity.test.ts`).\n- **Protobuf byte-parity tests.** `protobuf-parity.test.ts` plus\n  `tests/AGUI.Protobuf.UnitTests/` verify the binary encoding matches the TS proto output.\n- **Shared cross-language fixtures (catch three-way drift).** `sdks/fixtures/` holds\n  language-neutral JSON that more than one SDK is held to, so an expectation is written down\n  once instead of three times. `null-omission.json` is the first: TypeScript, Python and .NET\n  each deserialize its `input` events, re-serialize through their own producer path, and\n  assert the result equals `expected`. A wire rule that all three must agree on belongs here\n  rather than in one SDK's test tree — see `sdks/fixtures/README.md`.\n\n## Known Parity Boundary: Proto Is a Subset\n\nThe protobuf schema covers a **subset** of events by design. `.NET`-only events\n(`Reasoning*`, `Activity*`, `ToolCallResult`) are not in the proto wire format and\n**throw `NotSupportedException`** when mapped — see `ProtoEventMapper.cs` (the `default`\ncase lists the 16 supported events: RUN_STARTED/FINISHED/ERROR, STEP_STARTED/FINISHED,\nTEXT_MESSAGE_START/CONTENT/END, TOOL_CALL_START/ARGS/END, STATE_SNAPSHOT/DELTA,\nMESSAGES_SNAPSHOT, RAW, CUSTOM) and `ProtoMessageMapper.cs`. This is a **deliberate,\ndocumented boundary** — do not \"fix\" it by inventing proto messages that don't exist in\n`events.proto`. JSON/SSE remains the full-fidelity wire; protobuf is the constrained one.\n\n## Critical Anti-patterns\n\n1. **Never treat .NET as the source of truth.** If the .NET behavior differs from TS,\n   the .NET side is the candidate for change — confirm against `packages/core` /\n   `packages/client` first.\n2. **Never consult Python for run-loop or proto parity.** Python has neither. Use it\n   only as a type/JSON cross-check.\n3. **Never add a proto mapping for a `.NET`-only event** (`Reasoning*`, `Activity*`,\n   `ToolCallResult`). The `NotSupportedException` is intentional.\n4. **Never land a wire change without a parity asset.** A JSON-shape change needs a\n   Compatibility fixture; an interop/behavioral change needs a cross-language test.\n\n## Routing to Sibling Skills\n\nThis skill governs *what* to port and *where the reference is* — delegate test\nmechanics:\n\n- **agui-dotnet-unit-tests** — serialization round-trips and Compatibility fixture tests.\n- **agui-dotnet-integration-tests** — cross-language / E2E harness (TestServer + Vitest).\n- **agui-dotnet-wire-types** — JSON/proto type and serialization-context rules.\n- **agui-dotnet-transport** — SSE / HTTP transport details.\n",".github/skills/agui-dojo/SKILL.md":"---\nname: agui-dojo\ndescription: >\n  Run the AG-UI Dojo demo viewer locally and wire the AG-UI .NET SDK in as a dojo\n  integration. USE FOR: starting the dojo app (apps/dojo), running the .NET dojo\n  backend (AGUIDojoServer), registering or modifying the ag-ui-dotnet integration\n  (agents.ts/menu.ts/env.ts/files.json), running the dojo Playwright e2e suite for\n  the .NET integration (agUiDotnetTests), or understanding how dojo-e2e.yml runs it\n  in CI. DO NOT USE FOR: generic Playwright validation of arbitrary pages (use\n  agui-playwright-validate), or the docs site (use agui-dotnet-sdk-docs).\n---\n\n# AG-UI Dojo (.NET integration)\n\nThe **Dojo** is a Next.js \"demo viewer\" (`apps/dojo`) that showcases AG-UI protocol\nfeatures (agentic chat, generative UI, human-in-the-loop, shared state, etc.) against\nmany framework integrations. The AG-UI .NET SDK is one integration, id **`ag-ui-dotnet`**.\n\n## Where the pieces live\n\n| Piece | Path | Role |\n|-------|------|------|\n| Dojo app (frontend) | `apps/dojo` | Next.js viewer, runs on port **9999** |\n| .NET backend | `sdks/dotnet/samples/AGUIClientServer/AGUIDojoServer/` | ASP.NET host exposing AG-UI endpoints, port **8023** |\n| Agent registry | `apps/dojo/src/agents.ts` | `ag-ui-dotnet` → `HttpAgent` per feature |\n| Menu / feature list | `apps/dojo/src/menu.ts` | integration id, name, enabled features |\n| Env config | `apps/dojo/src/env.ts` | `aguiDotnetUrl` ← `AGUI_DOTNET_URL` (default `http://localhost:8023`) |\n| Generated source viewer data | `apps/dojo/src/files.json` | generated, **committed** |\n| Content generator | `apps/dojo/scripts/generate-content-json.ts` | builds `files.json` from `menu.ts` |\n| Prep / run orchestrators | `apps/dojo/scripts/{prep,run}-dojo-everything.js` | install/build + start services |\n| .NET e2e suite | `apps/dojo/e2e/tests/agUiDotnetTests/*.spec.ts` | Playwright tests |\n| CI | `.github/workflows/dojo-e2e.yml` | suite `ag-ui-dotnet` (triggers on `sdks/dotnet/**`) |\n\n## Run the dojo + .NET backend locally\n\nFrom the repo root (the scripts shell out to `git rev-parse`):\n\n```bash\npnpm install --no-frozen-lockfile\n\n# 1) Prep: builds the .NET backend AND the dojo (use the stable ids)\nnode apps/dojo/scripts/prep-dojo-everything.js --only dojo,ag-ui-dotnet\n\n# 2) Run: starts the dojo (9999) + AGUIDojoServer (8023) together, with LLMock env injected\nnode apps/dojo/scripts/run-dojo-everything.js --only dojo,ag-ui-dotnet\n```\n\n- Browse `http://localhost:9999/ag-ui-dotnet/feature/agentic_chat`.\n- `prep` for `ag-ui-dotnet` runs `dotnet restore && dotnet build` on\n  `AGUIDojoServer/AGUIDojoServer.csproj` in `sdks/dotnet/samples/AGUIClientServer`.\n- `run` for `ag-ui-dotnet` runs `dotnet run --project AGUIDojoServer/AGUIDojoServer.csproj\n  --urls \"http://localhost:8023\" --no-build` — **prep first or there's no build to run**.\n\nStart just the .NET backend by hand (e.g. to debug):\n\n```bash\ncd sdks/dotnet/samples/AGUIClientServer\ndotnet run --project AGUIDojoServer/AGUIDojoServer.csproj --urls \"http://localhost:8023\"\n```\n\nThe backend resolves its `ChatClient` from configuration (`ChatClientAgentFactory.Initialize`):\n`OPENAI_BASE_URL` (any OpenAI-compatible endpoint / LLMock), else `AZURE_OPENAI_ENDPOINT`\n(Entra ID), else public OpenAI with `OPENAI_API_KEY`. `run-dojo-everything.js` injects\n`OPENAI_BASE_URL=http://localhost:5555/v1` and `OPENAI_API_KEY=sk-mock` so it hits the LLMock.\n\n## How the .NET SDK is registered as an integration\n\nEach scenario is an AG-UI endpoint on the .NET host wired to a frontend feature. To add or\nchange a `.NET` dojo scenario, touch these in lockstep:\n\n1. **Backend endpoint** — `AGUIDojoServer/Program.cs`: add `app.MapDojoEndpoint(\"/<feature>\", ChatClientAgentFactory.Create…())`.\n   Agent logic lives in `ChatClientAgentFactory.cs`.\n2. **Agent mapping** — `apps/dojo/src/agents.ts` (`\"ag-ui-dotnet\"` block): add `<feature>: \"<feature>\"`\n   inside `mapAgents`; each maps to `new HttpAgent({ url: \\`${envVars.aguiDotnetUrl}/<feature>\\` })`.\n3. **Menu** — `apps/dojo/src/menu.ts` (`id: \"ag-ui-dotnet\"`): add the feature to `features`.\n4. **Source viewer** — `apps/dojo/scripts/generate-content-json.ts` already maps `ag-ui-dotnet` to\n   `Program.cs` + `ChatClientAgentFactory.cs`; then regenerate `files.json` (below).\n5. **env.ts** — only edit if changing the URL/port; `aguiDotnetUrl`/`AGUI_DOTNET_URL` already exist.\n\nRegenerate the committed source-viewer data after any `menu.ts` change:\n\n```bash\ncd apps/dojo && pnpm generate-content-json   # writes src/files.json\n```\n\n> ⚠️ CI job `check-generated-files` fails if `src/files.json` is stale. Always regenerate and\n> commit it after editing `menu.ts` (or feature/README files).\n\n## Run the .NET e2e suite locally\n\n```bash\ncd apps/dojo/e2e\npnpm install --ignore-scripts\npnpm exec playwright install --with-deps chromium   # first time only\n# dojo (9999) + AGUIDojoServer (8023) must already be running (see above)\nBASE_URL=http://localhost:9999 PLAYWRIGHT_SUITE=ag-ui-dotnet pnpm test -- tests/agUiDotnetTests\n```\n\nTests navigate to `/ag-ui-dotnet/feature/<feature>` and drive the chat UI via page objects in\n`apps/dojo/e2e/featurePages/`.\n\n## How CI runs it (`dojo-e2e.yml`)\n\n- Matrix suite `ag-ui-dotnet`: `test_path: tests/agUiDotnetTests`, `services: [\"dojo\", \"ag-ui-dotnet\"]`,\n  `wait_on: http://localhost:9999,tcp:localhost:8023`.\n- Triggers on `pull_request`/`push` paths including **`sdks/dotnet/**`**.\n- Installs .NET `9.0.x` + `10.0.x`, runs `prep-dojo-everything.js --only` then\n  `run-dojo-everything.js --only`, waits on the ports, then `pnpm test -- tests/agUiDotnetTests`.\n\n## Gotchas\n\n- **Ports are fixed**: dojo `9999`, AGUIDojoServer `8023`. The dojo's `AGUI_DOTNET_URL` must point\n  to `http://localhost:8023` (default in `run-dojo-everything.js` and `env.ts`).\n- **`--no-build` in run** means you must run the prep step first; otherwise the `dotnet run` fails.\n- **LLMock, not a real LLM**: `OPENAI_BASE_URL=http://localhost:5555/v1` + `OPENAI_API_KEY=sk-mock`\n  are injected. Backend tool-rendering scenarios also honor `AG_UI_MOCK_WEATHER=1` for determinism.\n- **`BASE_URL` is required** — `playwright.config.ts` calls `process.exit(1)` if it's unset.\n- **Stale `files.json`** is the most common CI failure after touching `menu.ts` — run\n  `pnpm generate-content-json` and commit the result.\n","skills/ag-ui-a2ui-integration/SKILL.md":"---\nname: ag-ui-a2ui-integration\ndescription: \"Use when adding A2UI rendering to any AG-UI-supported framework or custom AG-UI application, scaffolding an AG-UI app that should render A2UI, adapting an AG-UI integration to emit A2UI surfaces, or wiring the AG-UI A2UI middleware/toolkit with a compatible renderer.\"\nversion: 1.1.0\n---\n\n# AG-UI + A2UI Integration Skill\n\n## Overview\n\nUse this skill to add A2UI rendering to an AG-UI application. Treat AG-UI as\nthe transport and agent integration layer, `@ag-ui/a2ui-middleware` as the\nserver-side bridge that detects and paints A2UI operations, and A2UI as the UI\npayload format that the client renderer displays.\n\nThis is a developer-facing skill artifact. It is meant to be loaded by coding\nagents and used against a real app or repo, not published as a docs page.\n\n## When to Use\n\n- Adding A2UI rendering to an existing AG-UI app.\n- Creating an AG-UI quickstart that should display A2UI surfaces.\n- Connecting any AG-UI-supported framework or custom AG-UI agent to an\n  A2UI-capable frontend.\n- Adding or extending an A2UI component catalog.\n- Debugging why an A2UI surface does not render or why a user action does not\n  flow back to the agent.\n\n## When NOT to Use\n\n- For AG-UI protocol event semantics only, use the AG-UI protocol skill or\n  protocol docs.\n- For A2UI renderer internals outside an AG-UI app, use the A2UI renderer\n  docs or renderer-specific skills.\n- For generic CopilotKit frontend work without A2UI, use CopilotKit-specific\n  setup and React skills.\n\n## Workflow\n\n1. Inspect the app shape: framework adapter, AG-UI agent endpoint, runtime\n   host, frontend shell, and any existing A2UI renderer/catalog.\n2. Decide the A2UI mode before editing code:\n   - Fixed schema: backend tools return an `a2ui_operations` envelope with\n     `createSurface`, `updateComponents`, and `updateDataModel`.\n   - Dynamic schema: a framework A2UI tool (`generate_a2ui`) delegates to a\n     sub-agent that streams `render_a2ui` args through `A2UIMiddleware`.\n3. Select framework-specific wiring from\n   `references/framework-adapters.md`, or use that reference to find the\n   closest AG-UI integration pattern. Preserve the app's existing agent\n   architecture.\n4. Wire server middleware/runtime and client renderer using\n   `references/a2ui-runtime-and-renderer.md`. Avoid double-applying\n   `A2UIMiddleware`; use either runtime-level A2UI config or per-agent\n   `agent.use(new A2UIMiddleware(...))` for a given agent.\n5. Register a catalog on the client. With CopilotKit >= 1.61.2, forwarding it to\n   the provider (`a2ui={{ catalog }}`) auto-enables A2UI and auto-derives\n   `defaultCatalogId` from the catalog's id. Only when you are not forwarding a\n   catalog, ensure the middleware or adapter sets a `defaultCatalogId` matching\n   the renderer-registered catalog.\n6. Verify the streaming path with `references/verification.md`: AG-UI stream,\n   `a2ui-surface` activity snapshots or `a2ui_operations`, rendered A2UI\n   surface, and a user interaction flowing back through AG-UI.\n\n## AG-UI Framework Support\n\nThis skill is not limited to the framework examples below. For any target\nframework, first check the AG-UI repository's `integrations/` directory, the\nAG-UI docs, the framework adapter's A2UI files, and the current CLI source. If\nAG-UI supports the framework, use that integration's documented package,\nendpoint helper, A2UI tool factory, or scaffold path. If there is no framework\nA2UI adapter, implement the custom AG-UI agent path, return `a2ui_operations`\nfrom backend tools for fixed layouts, and keep the middleware/client wiring the\nsame.\n\n## Common AG-UI CLI Flags\n\nUse the CLI flags that exist in `sdks/typescript/packages/cli/src/index.ts`.\nThe table is a quick reference for known scaffold paths, not the full AG-UI\nsupport matrix. Do not invent flags.\n\n| Framework            | CLI flag         |\n| -------------------- | ---------------- |\n| ADK                  | `--adk`          |\n| LangGraph Python     | `--langgraph-py` |\n| LangGraph JavaScript | `--langgraph-js` |\n| CrewAI Flows         | `--crewai-flows` |\n| Mastra               | `--mastra`       |\n| Pydantic AI          | `--pydantic-ai`  |\n| LlamaIndex           | `--llamaindex`   |\n| Agno                 | `--agno`         |\n| AG2                  | `--ag2`          |\n\nStrands has AG-UI integration packages and examples, but no Strands CLI flag\nis present in the current AG-UI CLI source. Use the Strands integration docs\ninstead of guessing a scaffold command.\n\n## Key Rules\n\n- Keep the integration AG-UI-first for every supported framework. CopilotKit is\n  a common runtime/renderer path for web apps, but AG-UI owns the middleware,\n  framework adapters, and wire events.\n- Enable A2UI on both sides: `A2UIMiddleware` or runtime A2UI config on the\n  server, and an A2UI-capable renderer/catalog on the client.\n- For dynamic schema, prefer the framework adapter's A2UI tool factory or\n  auto-injection path. The model should call `generate_a2ui`; the sub-agent\n  should stream `render_a2ui` args so the middleware can progressively paint.\n- For fixed schema, return an `a2ui_operations` envelope from backend tools\n  rather than asking the model to invent component trees.\n- Emit `createSurface` once per `surfaceId`; use update operations for later\n  changes.\n- Do not let the model invent catalog ids. When the client forwards a catalog to\n  the provider (CopilotKit >= 1.61.2), its `catalogId` is derived automatically;\n  otherwise the host/middleware/adapter should stamp a `defaultCatalogId` that\n  matches the client-registered catalog.\n- Preserve AG-UI run boundaries and error events. Do not swallow server or\n  stream errors.\n- Verify with a real browser or client run when possible. A static typecheck is\n  not enough for streaming UI work.\n\n## References\n\n- `references/framework-adapters.md` - framework-specific AG-UI adapter\n  patterns.\n- `references/a2ui-runtime-and-renderer.md` - server/client A2UI wiring and\n  catalog patterns.\n- `references/verification.md` - checks to confirm the integration works.\n- `sources.md` - source files and docs used by this skill.\n",".github/skills/agui-dotnet-code-review/SKILL.md":"---\nname: agui-dotnet-code-review\ndescription: >\n  Review C#/.NET code changes to the AG-UI .NET SDK (sdks/dotnet/) against its\n  specific conventions and architectural rules — AOT serialization, the\n  \"no ASP.NET in src/\" boundary, the PublicAPI analyzer workflow, wire\n  compatibility with the TypeScript reference, and the house style\n  (sealed/no-records/ConfigureAwait). Runs a phased, rule-by-rule review.\n  USE FOR: reviewing a PR, diff, or branch that touches sdks/dotnet/; checking a\n  new event/message type; verifying serialization, package placement, or\n  public-API changes in the .NET SDK. DO NOT USE FOR: generic C# style nits\n  already enforced by analyzers/EditorConfig; reviewing the TypeScript SDK\n  (sdks/typescript/) or Python SDK (sdks/python/); writing new features (only\n  flag violations, never rewrite code).\n---\n\n# AG-UI .NET SDK Code Review\n\nEncodes the AG-UI .NET SDK's house rules so a reviewer flags real violations a\ngeneric C# reviewer misses. Authoritative sources: `sdks/dotnet/AGENTS.md`\n(house rules) and `sdks/dotnet/docs/architecture.md` (design boundaries). Each\nrule cites a real enforcement example in the repo; full BAD→GOOD examples and\nper-rule exceptions live in [`references/rules.md`](references/rules.md). The\nchange-footprint and test rules below distil the `minimize-change-footprint`,\n`ensure-test-coverage`, and `ensure-test-quality` review conventions for this SDK.\n\n## Reviewer discipline\n\n- **High signal-to-noise.** Only flag a genuine violation of a rule below, tied\n  to its cited convention. Don't invent nits or restate analyzer output.\n- **Verify before flagging.** Read the actual changed code and confirm the rule\n  applies. Automated reviewers have high false-positive rates.\n- **Scope.** Review only files under `sdks/dotnet/`. Skip generic style already\n  enforced by `TreatWarningsAsErrors`, nullable, and EditorConfig.\n- **Blast radius.** Fix nothing — this skill only reports. Local convention\n  violations get a finding; codebase-wide concerns are noted as out-of-scope\n  follow-ups, not per-line nits.\n- **Severity:** ❌ must fix (breaks AOT/wire/build/boundary); ⚠️ should fix\n  (convention drift); 💡 optional polish.\n\n## The review process\n\n**Step 0 — Ground truth & file classification.** Derive the package map from\n`AGUI.slnx`; skim `AGENTS.md` + `docs/architecture.md`. Classify each changed\nfile: `production | test | sample | proto | csproj | public-api | docs`. Rules\nare gated by class.\n\n**Step 1 — Determine and summarize the change set.** Resolve what is under\nreview, in order: an explicit target (PR number / branch / commit range); else\nthe current branch vs. its tracking/base branch (`git merge-base <base> HEAD`);\nplus **staged, unstaged, and untracked** working-tree changes. Then write a short\nsummary of what the diff does — new types, wire/protocol changes, public-surface\nchanges, new dependencies, src-vs-sample placement. This frames every phase and\ncatches scope creep early.\n\n**Step 2 — Walk the rules, phase by phase (A→G).** For each phase, check every\napplicable changed file against every rule in that phase. Write each finding\nimmediately: `file:line`, rule ID, severity, one-line fix. Verify the code first.\n\n**Step 3 — Self-validation.** Dedupe; confirm each finding cites a real rule and\na real line; confirm no rule was applied to the wrong file class; drop anything\nnot verifiable in the actual diff.\n\n**Step 4 — Emit the review summary** (see below) — a single human-readable comment,\nfindings grouped by severity with a verdict and coverage line.\n\n## Phase A — Scope / scenarios\n\n- `NET-SCOPE-01` Every change traces to a spec requirement or issue `[⚠️]`\n- `NET-SCOPE-02` No unrequested capability, configurability, or dependency `[⚠️]`\n- `NET-SCOPE-03` A wire/protocol change carries compatibility coverage `[❌]`\n- `NET-SCOPE-04` Sample-only behavior stays out of `src/` `[⚠️]`\n- `NET-SCOPE-05` Minimal footprint — every diff line serves the task; no unrelated\n  refactor, speculative abstraction, or cosmetic churn `[⚠️]`\n\n## Phase B — Design / architecture\n\nFrom `docs/architecture.md` \"Architectural constraints\".\n\n- `NET-ARCH-01` No `src/` project references `Microsoft.AspNetCore.App` `[❌]` —\n  `git grep \"Microsoft.AspNetCore\" -- sdks/dotnet/src` must be empty.\n- `NET-ARCH-02` Correct package placement (wire→Abstractions, SSE→Formatting,\n  proto→Protobuf, client/transport→Client, hosting→Server) `[❌]`\n- `NET-ARCH-03` Dependency direction — `Client` and `Server` never reference each\n  other `[❌]`. Cite: `src/AGUI.Server/AGUI.Server.csproj`.\n- `NET-ARCH-04` `IChatClient` is the only integration point — no bespoke agent\n  abstraction `[💡]`\n- `NET-ARCH-05` Every type has a single reason to change `[⚠️]`\n- `NET-ARCH-06` No interface without multiple implementations or a test-double need `[⚠️]`\n- `NET-ARCH-07` Make invalid states unrepresentable (enums/types over bool/string) `[⚠️]`\n- `NET-ARCH-08` One class per file; file name matches the type `[⚠️]`\n\n## Phase C — Implementation / correctness\n\nFrom `AGENTS.md` \"JSON serialization\" / \"Code style\".\n\n- `NET-IMPL-01` Every serializable type registered in `AGUIJsonSerializerContext`\n  via `[JsonSerializable(typeof(T))]` `[❌]`. Cite:\n  `src/AGUI.Abstractions/Serialization/AGUIJsonSerializerContext.cs`.\n- `NET-IMPL-02` No `JsonSerializer.Serialize<object>` and no reflection-based\n  serialization — go through the source-gen context `[❌]`\n- `NET-IMPL-03` Polymorphic JSON uses a hand-written discriminator `JsonConverter<T>` `[❌]`.\n  Cite: `src/AGUI.Abstractions/Events/BaseEventJsonConverter.cs`.\n- `NET-IMPL-04` Property attribute kit present: explicit `[JsonPropertyName]`, **no**\n  `[JsonIgnore(WhenWritingNull)]` on optionals (the context-wide default does that),\n  required strings = `string.Empty`, collections = `[]` `[⚠️]`.\n  Cite: `src/AGUI.Abstractions/Events/RunStartedEvent.cs`.\n- `NET-IMPL-05` `ConfigureAwait(false)` on every `await` in `src/` `[⚠️]`. Cite:\n  `src/AGUI.Client/AGUIChatClient.cs`.\n- `NET-IMPL-06` `[EnumeratorCancellation]` on the token of any `IAsyncEnumerable<T>`\n  method `[⚠️]`. Cite: `src/AGUI.Formatting/SseEventStreamFormatter.cs`.\n- `NET-IMPL-07` `ArgumentNullException.ThrowIfNull(...)` for public-API argument\n  validation `[⚠️]`\n- `NET-IMPL-08` Validate external input at the boundary, not deep in the stack `[⚠️]`\n- `NET-IMPL-09` Guard every code path — no silent `default`/fallthrough `[⚠️]`\n- `NET-IMPL-10` No swallowed exceptions (empty or log-only `catch`) `[⚠️]`\n- `NET-IMPL-11` Never log or expose sensitive data in errors `[❌]`\n- `NET-IMPL-12` No dead, commented-out, or impossible-condition defensive code `[⚠️]`\n- `NET-IMPL-13` No logic duplicated across the changeset — extract a shared helper\n  at 3+ uses (Rule of Three; don't extract for 1–2) `[⚠️]`\n- `NET-IMPL-14` Prefer BCL/platform APIs over hand-rolled equivalents `[⚠️]` —\n  exception: deliberate AOT-safe hand-written paths (the `JsonElement`↔`Value`\n  bridge, the discriminator converters) are intentional, not violations.\n\n## Phase D — Wire compatibility\n\n- `NET-WIRE-01` Protocol types match the TS reference — honor the\n  `// Keep in sync with sdks/typescript/...` markers `[❌]`. Cite:\n  `src/AGUI.Abstractions/Events/RunStartedEvent.cs`.\n- `NET-WIRE-02` Events are additive — unknown types round-trip via `RawEvent`;\n  don't remove or repurpose existing fields `[⚠️]`\n- `NET-WIRE-03` Protobuf parity preserved for the supported event set `[❌]`\n\n## Phase E — PublicAPI analyzer\n\n- `NET-API-01` Any public-surface change updates that project's\n  `PublicAPI.Unshipped.txt` (build fails RS0016 otherwise) `[❌]`. Cite:\n  `sdks/dotnet/Directory.Build.targets`, `src/AGUI.Abstractions/PublicAPI.Unshipped.txt`.\n- `NET-API-02` A new event type completes the full checklist (class in `Events/`\n  deriving `BaseEvent`; `Type` → `AGUIEventTypes` constant; `[JsonSerializable]`;\n  read case in `BaseEventJsonConverter`; `PublicAPI.Unshipped.txt`; round-trip\n  test) `[⚠️]`\n\n## Phase F — Style / naming\n\nFrom `AGENTS.md` \"Code style\" / \"Naming\" (not all analyzer-enforced).\n\n- `NET-STYLE-01` `sealed` on every non-abstract class `[⚠️]`\n- `NET-STYLE-02` No `record` types — use `sealed class` with properties `[❌]`\n- `NET-STYLE-03` No tuples in public APIs — define a named type `[⚠️]`\n- `NET-STYLE-04` Braces always on `if`/`for`/`foreach`/`while` `[⚠️]`\n- `NET-STYLE-05` Naming: events `{Name}Event`; discriminators `SCREAMING_SNAKE_CASE`\n  constants in `AGUIEventTypes`; outcome/role constants lowercase (never enums);\n  options `AGUI{Purpose}Options`; extensions `{Target}Extensions`; tests\n  `{TypeUnderTest}Test` `[⚠️]`\n- `NET-STYLE-06` DI-extension types use the `Microsoft.Extensions.DependencyInjection`\n  namespace; all other types use the project `RootNamespace` with no sub-namespaces `[⚠️]`\n- `NET-STYLE-07` No XML docs (`///`) on `internal`/`private` members `[⚠️]`\n- `NET-STYLE-08` Don't reformat code you didn't otherwise change `[⚠️]`\n\n## Phase G — Tests\n\nFrom `AGENTS.md` \"Running tests\"; coverage/quality rules distilled from\n`ensure-test-coverage` and `ensure-test-quality`.\n\nSDK-specific:\n- `NET-TEST-01` Serialization tests assert concrete JSON property names via\n  `JsonDocument` — not via the deserialized object `[⚠️]`\n- `NET-TEST-02` No full-JSON-string comparisons — assert individual properties `[❌]`\n- `NET-TEST-03` No reflection to enumerate types or verify membership `[❌]`\n- `NET-TEST-04` Wire-affecting change ⇒ compatibility fixture + round-trip in\n  `tests/AGUI.Abstractions.UnitTests/Compatibility/` `[⚠️]`\n- `NET-TEST-05` New public behavior ⇒ unit test; server-pipeline change ⇒\n  integration test (`tests/AGUI.Hosting.AspNetCore.IntegrationTests/`) `[⚠️/💡]`\n\nCoverage:\n- `NET-TEST-06` A new/changed class with branching logic has a test covering happy\n  path, primary error path, and boundary values (null/empty/zero/single) `[⚠️]`\n- `NET-TEST-07` Don't test trivial code — DTOs/records with no logic, one-line\n  delegations, constant returns `[💡]`\n- `NET-TEST-08` Test through DI + `InternalsVisibleTo`, not members made `public`\n  for tests `[⚠️]`\n\nQuality:\n- `NET-TEST-09` Every test asserts a specific observable value — no assertion-free\n  tests, no bare `Assert.NotNull`/`True`/`NotEmpty` standing in for the real value `[❌]`\n- `NET-TEST-10` Deterministic and isolated — no `Thread.Sleep`/`Task.Delay` for\n  synchronization, no execution-order dependence, side effects cleaned up\n  (files/ports/env) `[❌]`\n- `NET-TEST-11` Test behavior, not implementation — prefer hand-written fakes over\n  `mock.Verify(Times.*)` (unless the call count is the spec'd behavior); `[Theory]`\n  for data variation, `[Fact]` for behavior; AAA visible inline with factory\n  helpers (not shared mutable fixtures) below the tests; no `// TODO` or empty\n  test bodies `[⚠️]`\n\n## Self-validation\n\n- [ ] The change set was resolved (target / tracking branch / working tree) and summarized\n- [ ] Every applicable changed file was walked against every phase's rules\n- [ ] Each finding cites a real rule ID, file, and line, and was verified in the diff\n- [ ] No rule applied to the wrong file class; no duplicates\n- [ ] Clean diffs are reported as clean — no padding\n\n## Common pitfalls\n\n| Pitfall | Solution |\n|---------|----------|\n| Restating analyzer/EditorConfig output | Only flag rules above that tooling does not enforce |\n| Flagging a \"missing\" registration without checking the context | Open `AGUIJsonSerializerContext.cs` and confirm |\n| Treating a sample's ASP.NET usage as a `src/` violation | `NET-ARCH-01` applies to `src/` only |\n| Calling an additive new event a wire break | `NET-WIRE-02` — additive is allowed |\n| Nitpicking style in files with substantive changes | Focus on the substantive change |\n\n## Review summary\n\nProduce a single human-readable Markdown comment — a reviewer's summary the author\ncan read top to bottom. Lead with the verdict, then the findings grouped by\nseverity (most severe first), each one self-contained.\n\n```markdown\n## AG-UI .NET SDK code review\n\n**Verdict:** <Request changes | Comment | Looks good> — <one-sentence reason>\n**Change set:** <branch vs base, e.g. `feat/x` vs `main`> · <N files reviewed>\n(+<U untracked>) · **Findings:** ❌ <a> · ⚠️ <b> · 💡 <c>\n\n<One short paragraph: what the change does and the overall read.>\n\n### ❌ Must fix\n- **`src/AGUI.Abstractions/Events/FooEvent.cs:42`** · `NET-IMPL-01` — new event type\n  isn't registered in `AGUIJsonSerializerContext`; it fails under AOT.\n  **Fix:** add `[JsonSerializable(typeof(FooEvent))]`.\n\n### ⚠️ Should fix\n- **`src/AGUI.Client/AGUIChatClient.cs:88`** · `NET-IMPL-05` — bare `await` in\n  library code. **Fix:** append `.ConfigureAwait(false)`.\n\n### 💡 Optional\n- **`src/AGUI.Server/StreamAdapter.cs:17`** · `NET-ARCH-04` — bespoke agent\n  abstraction; the SDK integrates via `IChatClient`. **Fix:** drop the wrapper.\n\n### Coverage\nPhases checked: A–G. No findings in: **B Design**, **D Wire**, **E PublicAPI**.\n```\n\nRules for the summary:\n- **Order** findings by severity (❌ → ⚠️ → 💡), then by file. One bullet per finding:\n  bold `file:line`, the `RULE-ID`, a plain-language description, and an italic\n  **Fix:** with a one-line remedy. The reader can look the ID up in\n  [`references/rules.md`](references/rules.md).\n- **Omit empty severity sections.** Always include the **Coverage** line so the\n  author sees which phases were clean versus untouched.\n- **Clean diff:** skip the severity sections and write a single line —\n  `✅ No violations of the AG-UI .NET house rules — checked phases A–G across N files.`\n- **Verdict mapping:** any ❌ → *Request changes*; only ⚠️/💡 → *Comment*; none →\n  *Looks good*. The skill never approves or blocks automatically — the verdict is\n  advisory and the author decides.\n\n",".github/skills/agui-dotnet-agents-sync/SKILL.md":"---\nname: agui-dotnet-agents-sync\ndescription: >\n  Keep the AG-UI .NET SDK docs (sdks/dotnet/AGENTS.md and docs/architecture.md) in\n  sync with the real code tree after structural changes. USE FOR: \"update\n  AGENTS.md / docs/architecture.md\", \"check the dotnet docs are current\", verifying\n  docs after a .NET SDK refactor (package rename, added/removed project,\n  changed endpoint pattern, new/renamed test project, sample step added, new\n  convention). DO NOT USE FOR: writing product code or tests (follow AGENTS.md\n  itself), Python/TypeScript SDK docs, or generic markdown editing unrelated to\n  the dotnet SDK structure.\n---\n\n# AG-UI .NET SDK — Docs Sync\n\n`sdks/dotnet/AGENTS.md` (coding instructions) and `sdks/dotnet/docs/architecture.md`\n(design overview) describe the SDK's structure, naming, and conventions. They\ndrift silently after refactors because nothing fails the build when prose goes\nstale. This skill reconciles them against the live tree.\n\n> Typical drift this catches: a package rename, a moved/removed project, a changed\n> endpoint pattern, or a new sample step that the prose never caught up with. An agent\n> that edits these files from memory re-introduces the same kind of drift, so always\n> derive the truth from the tree first.\n\n## Process\n\n1. **Establish ground truth from the tree, not from the doc.** The authoritative\n   source is `sdks/dotnet/AGUI.slnx` plus the folder listing — never the prose\n   you are about to edit.\n   - Projects: read `<Project Path=...>` entries from `AGUI.slnx`.\n   - Folders: `Get-ChildItem src,tests,samples -Directory`.\n   - Samples/steps: list `samples/GettingStarted/Step*` to get the real range.\n2. **Drift scan — diff each doc claim against the tree.** For every concrete\n   claim in AGENTS.md / docs/architecture.md, confirm it against ground truth:\n   - Project & package names exist in `AGUI.slnx` (and in `src/`, `tests/`).\n   - Symbols the docs name still exist: `Select-String -Path src\\*\\*.cs,samples\\*\\*.cs -Pattern \"<Symbol>\"`.\n   - Renamed/removed symbols are GONE everywhere: grep the repo for the old\n     name (e.g. `AGUI.Hosting.AspNetCore`, `TypedResults.ServerSentEvents`); a\n     hit in prose-only is the drift to fix.\n3. **Fix surgically.** Edit only the stale lines. Match existing tone, tables,\n   and code-fence style. Do not restructure or invent conventions.\n4. **Verify.** Re-grep every symbol/name you wrote to confirm it exists in the\n   tree. Optionally `dotnet build` from `sdks/dotnet/` if you touched code-style\n   or build claims.\n\n## Drift checklist (the claims that rot)\n\n| Doc claim | Reconcile against |\n|---|---|\n| **src package list / names** | `AGUI.slnx` `/src/` folder + `src/` dirs |\n| **Package dependency table & framework refs** | `grep Microsoft.AspNetCore src\\*\\*.csproj` (must be empty — no src project references ASP.NET) |\n| **Where ASP.NET glue lives** | `samples/AGUI.Samples.Shared` (the only `FrameworkReference Microsoft.AspNetCore.App`) |\n| **Test-project table & count** | `AGUI.slnx` `/tests/` + `tests/` dirs |\n| **Sample step range / count** | `samples/GettingStarted/Step*` listing |\n| **Endpoint pattern code** | actual sample `Program.cs` + `samples/AGUI.Samples.Shared` |\n| **Project layout bullet list** | `src/`, `tests/`, `samples/` dirs |\n| **Code-style / naming / serialization rules** | `Directory.Build.props/.targets`, `Directory.Packages.props`, source |\n| **PublicAPI workflow** | presence of `PublicAPI.*.txt` in each `src/` project |\n\n## Deriving ground truth (commands, not a snapshot)\n\nDon't trust any embedded list (including this skill). Re-derive the current state\nfrom the tree every time:\n\n```powershell\n# from sdks/dotnet/\nSelect-String -Path AGUI.slnx -Pattern '<Project Path'   # all projects\nGet-ChildItem src,tests,samples -Directory               # folders\nGet-ChildItem samples/GettingStarted -Directory -Filter Step*  # sample step range\nSelect-String -Path src\\*\\*.csproj -Pattern Microsoft.AspNetCore  # must be empty (no ASP.NET in src/)\n```\n\nA couple of durable facts that are easy to get wrong: the server package is\n`AGUI.Server` (ASP.NET hosting glue lives only in `samples/AGUI.Samples.Shared`),\nand the integration-test **project name** stays `AGUI.Hosting.AspNetCore.IntegrationTests`\neven though its types are in namespace `AGUI.Server.IntegrationTests`. Everything else,\nderive from the commands above.\n\n## ❌ Critical anti-patterns\n\n1. **Never edit the docs from memory or from the doc's own current text.** The\n   stale prose is exactly what misleads you. Derive every name from `AGUI.slnx`\n   and the folder listing first.\n2. **Never rename a symbol in prose without grepping the whole tree** for the\n   old name — a lingering reference (or an unchanged code fence) is silent drift.\n3. **Don't invent conventions or restructure the docs.** Reconcile only what the\n   tree proves changed; keep tables, tone, and code-fence style intact.\n4. **Don't confuse a kept project name with a moved concept.** The integration\n   test project is still `AGUI.Hosting.AspNetCore.IntegrationTests` even though\n   the src package was renamed to `AGUI.Server`.\n\n## Files to mine\n\n`sdks/dotnet/AGENTS.md`, `sdks/dotnet/docs/architecture.md`, `sdks/dotnet/AGUI.slnx`,\n`sdks/dotnet/Directory.Build.props`, `Directory.Build.targets`,\n`Directory.Packages.props`, and the `src/`, `tests/`, `samples/` folder trees.\n",".github/skills/agui-dotnet-transport/SKILL.md":"---\nname: agui-dotnet-transport\ndescription: >\n  Add or modify a wire transport / event-stream encoding in the AG-UI .NET SDK — the protobuf\n  codec, the SSE format, content negotiation, the JsonElement-to-protobuf Value bridge, or a brand\n  new encoding — while preserving Native AOT compatibility and byte-level wire compatibility with\n  @ag-ui/proto. USE FOR: working on AGUI.Formatting / AGUI.Protobuf, IAGUIEventStreamFormatter,\n  transport content negotiation, the JsonElement-to-google.protobuf.Value bridge, SSE or protobuf\n  framing, server formatter registration / AGUIResults.Events negotiation. DO NOT USE FOR: adding a new wire event\n  TYPE (use agui-dotnet-wire-types), writing tests (use agui-dotnet-integration-tests).\n---\n\n# AG-UI .NET Transport & Encoding\n\nEncodes the non-obvious design constraints of the AG-UI .NET transport layer, discovered while\nbuilding protobuf support. Apply when adding/changing an encoding or the negotiation that selects\none. Read `references/wire-format.md` before touching the protobuf codec or framing.\n\n## Transport architecture\n\nOne bidirectional abstraction, `IAGUIEventStreamFormatter` (in `AGUI.Formatting`), serves every\ntransport and both directions:\n\n| Member | Role |\n|--------|------|\n| `MediaType` | Advertised in client `Accept` and written as server `Content-Type`. Registration order = preference. |\n| `CanRead(contentType)` | Client picks the decoder for the response `Content-Type`. |\n| `ReadAsync(body, ct)` | Decode body → `IAsyncEnumerable<BaseEvent>`. |\n| `WriteAsync(events, output, ct)` | Encode events → body. |\n\n`SseEventStreamFormatter` (`text/event-stream`) is the always-available default;\n`ProtobufEventStreamFormatter` (`ProtobufEventStreamFormatter.ProtobufMediaType`) is opt-in.\n\n**Client negotiation** = `DelegatingHandler` + decode helper:\n- `AGUIEventStreamHandler` (public, in `AGUI.Client`) advertises every registered formatter's\n  `MediaType` in `Accept`, then inspects the response `Content-Type`, finds the first `CanRead`\n  formatter, and records it on the request. The body is left untouched for lazy streaming.\n- `AGUIResponseExtensions.ReadAGUIEventStreamAsync` reads that recorded formatter (falling back to\n  SSE) and decodes. The SDK ships no `IHttpClientFactory` integration: a caller that wants protobuf\n  wires the handler into its own `HttpClient`, and constructs `AGUIChatClient` from\n  `AGUIChatClientOptions`.\n\n**Server negotiation** = `AGUIResults.Events` (samples `AGUI.Samples.Shared`): collects registered\n`IAGUIEventStreamFormatter` services (+ built-in SSE), then picks protobuf **only when its media\ntype is explicitly present** in `Accept` with non-zero quality, else SSE for `text/event-stream`/\nwildcard/absent, else `406`. Mirrors `preferredMediaTypes(accept, [proto])` in `@ag-ui/encoder`.\nA server opts in by registering the formatter (for example,\n`services.AddSingleton<IAGUIEventStreamFormatter, ProtobufEventStreamFormatter>()`).\n\n## Wire format facts\n\n- Protobuf media type: `application/vnd.ag-ui.event+proto` (`ProtobufEventStreamFormatter.ProtobufMediaType`).\n- Framing: **4-byte big-endian `uint32` length prefix + protobuf message bytes**, per event —\n  matches `@ag-ui/encoder` `encodeProtobuf` (`dataView.setUint32(0, length, false)`). See\n  `AGUIProtobuf.WriteFramed` / `ReadFramedAsync`.\n- `Encode`/`Decode` = single message, no length prefix (mirror TS `proto.encode`/`proto.decode`).\n- Dynamic payloads (state, args, results) use `google.protobuf.Value` (Struct/ListValue/scalars) —\n  **never `Any` and never a JSON-string field**.\n\n## The CRITICAL Native AOT rule\n\nImplement the `JsonElement` <-> `google.protobuf.Value` bridge **by hand over the generated\nWellKnownTypes** (`ProtoValueConverter`). **NEVER** use Google.Protobuf's reflection-based\n`JsonFormatter`/`JsonParser` or any descriptor reflection API — they are not trim/AOT safe and the\npackage multi-targets `net10/9/8/netstandard2.0/net472`.\n\n- **Number caveat**: `Value` is double-only. `long`/`decimal` beyond 2^53 lose precision on round\n  trip. This is intentional — it matches the JS `@ag-ui/proto` limitation.\n\n## Schema-first extension\n\nThe `.proto` schema is **canonical** and lives in the TS package. `AGUI.Protobuf.csproj`\n`<Protobuf>` references `sdks/typescript/packages/proto/src/proto/*.proto` directly\n(`csharp_namespace = AGUI.ProtocolBuffers`, generated types `Access=\"Internal\"`) — **do not fork or\ncopy it**. To add a wire-representable event:\n\n1. Extend the shared `.proto` (coordinated across all SDKs — it is the cross-language contract).\n2. Add a mapper case in `ProtoEventMapper` (event oneof) / `ProtoMessageMapper` (messages),\n   mirroring `sdks/typescript/packages/proto/src/proto.ts` reshaping verbatim.\n\nSubset coverage is intentional: .NET-only events that have no wire representation throw\n`NotSupportedException` from the mapper's `default` case. Don't invent a wire shape unilaterally.\n\n## How to verify\n\n- **Byte-parity** against `@ag-ui/proto` via the cross-language tests (see\n  `agui-dotnet-integration-tests` and `sdks/dotnet/docs/cross-language-testing.md`). The JSON\n  compatibility fixtures in `tests/AGUI.Abstractions.UnitTests/Compatibility/` guard SSE drift.\n- **Multi-TFM AOT build**: `dotnet build` from `sdks/dotnet/` (targets net10/9/8/netstandard2.0/\n  net472; warnings are errors). Update `PublicAPI.Unshipped.txt` for any public surface change.\n\n## ❌ Anti-patterns\n\n1. **Don't embed JSON-as-string inside a `Value`.** Map structured payloads recursively to\n   Struct/ListValue/scalars via `ProtoValueConverter`. A string field breaks @ag-ui/proto parity.\n2. **Don't use `JsonFormatter`/`JsonParser`/descriptor reflection.** Not AOT-safe — hand-write the\n   bridge over generated WellKnownTypes.\n3. **Don't copy or fork the `.proto`.** Reference the canonical TS schema from the `.csproj` so the\n   codec can't drift from the wire contract.\n4. **Don't make `AGUI.Protobuf` depend on `AGUI.Client` or the hosting/server package.** The codec\n   stays transport-neutral; it references only `AGUI.Abstractions` + `AGUI.Formatting`.\n5. **Don't change framing or use little-endian.** Length is big-endian `uint32`; both SDKs depend\n   on exact byte layout.\n\n## References\n\n- **Wire format & codec internals** (framing, oneof mapping, Value bridge, negotiation parity):\n  [references/wire-format.md](references/wire-format.md)\n",".github/skills/agui-dotnet-feature-workflow/SKILL.md":"---\nname: agui-dotnet-feature-workflow\ndescription: >\n  Orchestrator/hub for implementing a feature or change in the AG-UI .NET SDK\n  (sdks/dotnet). USE FOR: \"what's the workflow\", \"what order do I do things in\",\n  \"how do I implement a feature in the .NET SDK\", starting any non-trivial\n  AG-UI .NET SDK change, planning the end-to-end steps and definition-of-done\n  (code + AOT serialization + client/server mapping + unit/integration/cross-language\n  tests + docs + PublicAPI + AGENTS.md sync). DO NOT USE FOR: the deep how-to of a\n  single step — this skill ROUTES to focused siblings: adding wire types\n  (agui-dotnet-wire-types), transport/encoding (agui-dotnet-transport), unit tests\n  (agui-dotnet-unit-tests), integration tests (agui-dotnet-integration-tests),\n  cross-language tests (agui-dotnet-cross-language-tests), porting from TS/Python\n  (agui-cross-sdk-parity), adding a GettingStarted sample Step\n  (agui-dotnet-sample-step), SDK docs (agui-dotnet-sdk-docs), AGENTS/Architecture\n  sync (agui-dotnet-agents-sync), the dojo (agui-dojo), review\n  (agui-dotnet-code-review).\n---\n\n# AG-UI .NET SDK — Feature Workflow (Orchestrator)\n\nThis is the **hub** skill. Given a request to build or change a feature in the AG-UI\n.NET SDK (`sdks/dotnet/`), it lays out the correct end-to-end order and **routes the\ndepth of each step to a focused sibling skill**. It does not duplicate their content.\n\nThe SDK has a multi-artifact **definition of done**. An agent working ad hoc forgets\nartifacts — most often cross-language parity, docs, `AGENTS.md`/`docs/architecture.md` sync,\nand `PublicAPI.Unshipped.txt`. Use this skill to avoid that.\n\n## Package map\n\n`sdks/dotnet/src/`:\n\n| Package | Responsibility |\n|---|---|\n| `AGUI.Abstractions` | Wire types: events, messages, tools, capabilities, `AGUIJsonSerializerContext` |\n| `AGUI.Formatting` | JSON formatter + SSE encode/decode |\n| `AGUI.Protobuf` | Protobuf encoding of the protocol |\n| `AGUI.Client` | `AGUIChatClient` (`IChatClient`) + transport negotiation |\n| `AGUI.Server` | Hosting-agnostic agent-side conversion (`ChatResponseUpdate` → events) |\n\nASP.NET hosting glue lives in `samples/AGUI.Samples.Shared` (not a `src/` package).\n`sdks/dotnet/AGENTS.md` and `docs/architecture.md` are the canonical description of\nthe layout and conventions (kept current via `agui-dotnet-agents-sync`); `AGUI.slnx`\nis the ground truth if you need to re-derive the package list.\n\n## Build & test commands\n\n```bash\n# from sdks/dotnet/\ndotnet build sdks/dotnet/AGUI.slnx        # whole solution\ndotnet test  tests/AGUI.Abstractions.UnitTests/   # per-project, fast feedback\n```\n\n`Directory.Build.props` **treats warnings as errors**, and `PublicApiAnalyzers` is on\nfor every `src/` project with a `PublicAPI.Shipped.txt`. **The build fails if you skip\nthe AOT serialization wiring or forget `PublicAPI.Unshipped.txt`** — these are not\noptional polish steps, they are enforced.\n\n## Definition of done (feature checklist)\n\n- [ ] Wire contract understood (matched against TS/Python reference if wire-affecting)\n- [ ] Type/behavior implemented in the **right package** (see map)\n- [ ] AOT serialization wired (`[JsonSerializable]` in `AGUIJsonSerializerContext`, converter case, `[JsonPropertyName]`)\n- [ ] Client/server mapping updated (`AGUI.Client` event→update and/or `AGUI.Server` update→event)\n- [ ] Unit tests (serialization round-trip + behavior)\n- [ ] Integration tests (full pipeline) if it crosses the HTTP/SSE boundary\n- [ ] Cross-language parity tests if wire-affecting\n- [ ] `PublicAPI.Unshipped.txt` updated for every changed public member\n- [ ] Docs updated (docs.ag-ui.com / SDK docs) if user-facing\n- [ ] `AGENTS.md` / `docs/architecture.md` synced if structure/recipe changed\n- [ ] `dotnet build sdks/dotnet/AGUI.slnx` and relevant `dotnet test` projects green\n\n## Ordered workflow → route each step\n\nDo the steps **in this order**. Skip a step only if it genuinely doesn't apply\n(e.g. a non-wire-affecting internal refactor skips cross-language parity).\n\n1. **Understand the wire contract.** Read the TypeScript (and Python) reference for\n   the type/behavior so the .NET shape matches the spec. Porting an existing feature\n   from another SDK? → **`agui-cross-sdk-parity`**.\n\n2. **Implement the type/behavior in the right package.**\n   - New/changed wire type (event, message, tool, capability) → **`agui-dotnet-wire-types`**\n     (covers the `AGUI.Abstractions` recipe: class in `Events/`, `AGUIEventTypes`\n     constant, converter case, AOT registration, `PublicAPI.Unshipped.txt`).\n   - New/changed transport or encoding (SSE, protobuf, formatter) →\n     **`agui-dotnet-transport`** (`AGUI.Formatting`, `AGUI.Protobuf`).\n\n3. **Wire AOT serialization.** Every protocol type goes through\n   `AGUIJsonSerializerContext` — no reflection. `agui-dotnet-wire-types` has the\n   per-type recipe; the build enforces it.\n\n4. **Update client/server mapping.** Server-side `ChatResponseUpdate` → event lives in\n   `AGUI.Server`; client-side event → `ChatResponseUpdate` lives in `AGUI.Client`\n   (`EventStreamConverter`, builders). Update both directions if the wire shape changed.\n\n5. **Unit tests** (round-trip + behavior) → **`agui-dotnet-unit-tests`**.\n\n6. **Integration tests** (HTTP + SSE pipeline, `WebApplicationFactory`,\n   `AGUIChatClient`) → **`agui-dotnet-integration-tests`**. Required when the change\n   crosses the transport boundary.\n\n7. **Cross-language parity tests** (if wire-affecting) →\n   **`agui-dotnet-cross-language-tests`** (`tests/AGUI.CrossLanguage.IntegrationTests`,\n   `CrossLanguage.TestServer`, `CrossLanguage.Vitest`). This is the step agents most\n   often forget — .NET must agree with TS/Python on the bytes.\n\n8. **Update `PublicAPI.Unshipped.txt`** for every changed public member, in each\n   affected `src/` project. The PublicAPI analyzer fails the build otherwise.\n\n9. **Docs** (user-facing change) → **`agui-dotnet-sdk-docs`** (docs.ag-ui.com).\n\n10. **Sync `AGENTS.md` / `docs/architecture.md`** if you changed structure, recipes, or\n    commands → **`agui-dotnet-agents-sync`**. Fix stale package references while here.\n\n11. **Build + test green.** `dotnet build sdks/dotnet/AGUI.slnx`, then the relevant\n    `dotnet test <project>` (unit + integration + cross-language as applicable).\n\n12. **Validate & review.** Run/inspect in the dojo → **`agui-dojo`**; manual UI/docs\n    checks → **`agui-playwright-validate`**; review the change → **`agui-dotnet-code-review`**.\n\n## Routing table (quick reference)\n\n| Step / need | Sibling skill |\n|---|---|\n| Add/modify a wire type | `agui-dotnet-wire-types` |\n| Add/modify transport or encoding | `agui-dotnet-transport` |\n| Port a feature from TS/Python | `agui-cross-sdk-parity` |\n| Write unit tests | `agui-dotnet-unit-tests` |\n| Write integration tests | `agui-dotnet-integration-tests` |\n| Write cross-language tests | `agui-dotnet-cross-language-tests` |\n| Add a GettingStarted sample Step (Server/Client pair) | `agui-dotnet-sample-step` |\n| Update SDK docs site | `agui-dotnet-sdk-docs` |\n| Keep AGENTS.md / docs/architecture.md current | `agui-dotnet-agents-sync` |\n| Run/validate in the dojo | `agui-dojo` |\n| Manual UI/docs validation | `agui-playwright-validate` |\n| Review the change | `agui-dotnet-code-review` |\n\n> The depth of each step lives in the sibling skill it routes to; fall back to the\n> recipes in `AGENTS.md` and the deep content in `docs/architecture.md` for anything a\n> sibling doesn't cover.\n\n## ❌ Anti-patterns\n\n1. **Don't stop at \"it compiles and unit tests pass.\"** Wire-affecting changes are not\n   done until cross-language parity tests and docs are updated.\n2. **Don't put protocol or server code in a sample.** It belongs in `src/`; the server is\n   `AGUI.Server`, hosting glue is in `samples/AGUI.Samples.Shared`, and no `src/` project\n   references ASP.NET.\n3. **Don't skip `PublicAPI.Unshipped.txt` or AOT registration** \"to fix later\" — the\n   warnings-as-errors build will block you immediately.\n4. **Don't do the deep work here.** This skill routes; the depth lives in the sibling\n   skills. Open the relevant one before implementing a step.\n",".github/skills/agui-dotnet-wire-types/SKILL.md":"# agui-dotnet-wire-types\n\nPath: `.github/skills/agui-dotnet-wire-types/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-wire-types/SKILL.md)",".github/skills/agui-playwright-validate/SKILL.md":"# agui-playwright-validate\n\nPath: `.github/skills/agui-playwright-validate/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-playwright-validate/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-client-tools/SKILL.md":"# agui-dotnet-client-tools\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-client-tools/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-client-tools/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-human-in-the-loop/SKILL.md":"# agui-dotnet-human-in-the-loop\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-human-in-the-loop/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-human-in-the-loop/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-multimodal/SKILL.md":"# agui-dotnet-multimodal\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-multimodal/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-multimodal/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-protobuf/SKILL.md":"# agui-dotnet-protobuf\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-protobuf/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-protobuf/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-reasoning/SKILL.md":"# agui-dotnet-reasoning\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-reasoning/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-reasoning/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-server-tools/SKILL.md":"# agui-dotnet-server-tools\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-server-tools/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-server-tools/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-shared-state/SKILL.md":"# agui-dotnet-shared-state\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-shared-state/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-shared-state/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-streaming-chat/SKILL.md":"# agui-dotnet-streaming-chat\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-streaming-chat/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-streaming-chat/SKILL.md)","sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-troubleshoot/SKILL.md":"# agui-dotnet-troubleshoot\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-troubleshoot/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-troubleshoot/SKILL.md)","AGENTS.md":"# AI Agent Protocol & Instructions\n\nPath: `AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/AGENTS.md)","CLAUDE.md":"# Claude Agent Guidelines & System Prompt\n\nPath: `CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/CLAUDE.md)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.claude-plugin/marketplace.json)","skills/ag-ui-a2ui-integration/sources.md":"# Ag-ui-a2ui-integration Skill\n\nPath: `skills/ag-ui-a2ui-integration/sources.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/sources.md)","skills/ag-ui-a2ui-integration/references/a2ui-runtime-and-renderer.md":"# References Skill\n\nPath: `skills/ag-ui-a2ui-integration/references/a2ui-runtime-and-renderer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/references/a2ui-runtime-and-renderer.md)","skills/ag-ui-a2ui-integration/references/framework-adapters.md":"# References Skill\n\nPath: `skills/ag-ui-a2ui-integration/references/framework-adapters.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/references/framework-adapters.md)","skills/ag-ui-a2ui-integration/references/verification.md":"# References Skill\n\nPath: `skills/ag-ui-a2ui-integration/references/verification.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/references/verification.md)",".github/skills/agui-dotnet-code-review/references/rules.md":"# References Skill\n\nPath: `.github/skills/agui-dotnet-code-review/references/rules.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-code-review/references/rules.md)",".github/skills/agui-dotnet-transport/references/wire-format.md":"# References Skill\n\nPath: `.github/skills/agui-dotnet-transport/references/wire-format.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-transport/references/wire-format.md)","sdks/dotnet/plugins/ag-ui-dotnet/README.md":"# ag-ui-dotnet Documentation\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/README.md)","sdks/dotnet/plugins/ag-ui-dotnet/plugin.json":"# ag-ui-dotnet Plugin Manifest\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/plugin.json)","sdks/typescript/.cursor/rules/project-rules.mdc":"# Cursor Rule: project-rules\n\nPath: `sdks/typescript/.cursor/rules/project-rules.mdc`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/.cursor/rules/project-rules.mdc)","sdks/typescript/packages/a2ui-toolkit/CHANGELOG.md":"# A2ui-toolkit Skill\n\nPath: `sdks/typescript/packages/a2ui-toolkit/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/CHANGELOG.md)","sdks/typescript/packages/a2ui-toolkit/README.md":"# a2ui-toolkit Documentation\n\nPath: `sdks/typescript/packages/a2ui-toolkit/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/README.md)","sdks/typescript/packages/a2ui-toolkit/package.json":"# A2ui-toolkit Skill\n\nPath: `sdks/typescript/packages/a2ui-toolkit/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/package.json)","sdks/typescript/packages/a2ui-toolkit/tsconfig.json":"# A2ui-toolkit Skill\n\nPath: `sdks/typescript/packages/a2ui-toolkit/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/tsconfig.json)","sdks/typescript/packages/cli/CHANGELOG.md":"# Cli Skill\n\nPath: `sdks/typescript/packages/cli/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/CHANGELOG.md)","sdks/typescript/packages/cli/README.md":"# cli Documentation\n\nPath: `sdks/typescript/packages/cli/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/README.md)","sdks/typescript/packages/cli/package.json":"# Cli Skill\n\nPath: `sdks/typescript/packages/cli/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/package.json)","sdks/typescript/packages/cli/tsconfig.json":"# Cli Skill\n\nPath: `sdks/typescript/packages/cli/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/tsconfig.json)","sdks/typescript/packages/client/CHANGELOG.md":"# Client Skill\n\nPath: `sdks/typescript/packages/client/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/CHANGELOG.md)","sdks/typescript/packages/client/DEPRECATIONS.md":"# Client Skill\n\nPath: `sdks/typescript/packages/client/DEPRECATIONS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/DEPRECATIONS.md)","sdks/typescript/packages/client/README.md":"# client Documentation\n\nPath: `sdks/typescript/packages/client/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/README.md)","sdks/typescript/packages/client/package.json":"# Client Skill\n\nPath: `sdks/typescript/packages/client/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/package.json)","sdks/typescript/packages/client/tsconfig.json":"# Client Skill\n\nPath: `sdks/typescript/packages/client/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/tsconfig.json)","sdks/typescript/packages/core/CHANGELOG.md":"# Core Skill\n\nPath: `sdks/typescript/packages/core/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/CHANGELOG.md)","sdks/typescript/packages/core/README.md":"# core Documentation\n\nPath: `sdks/typescript/packages/core/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/README.md)","sdks/typescript/packages/core/package.json":"# Core Skill\n\nPath: `sdks/typescript/packages/core/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/package.json)","sdks/typescript/packages/core/tsconfig.json":"# Core Skill\n\nPath: `sdks/typescript/packages/core/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/tsconfig.json)","sdks/typescript/packages/encoder/CHANGELOG.md":"# Encoder Skill\n\nPath: `sdks/typescript/packages/encoder/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/CHANGELOG.md)","sdks/typescript/packages/encoder/README.md":"# encoder Documentation\n\nPath: `sdks/typescript/packages/encoder/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/README.md)","sdks/typescript/packages/encoder/package.json":"# Encoder Skill\n\nPath: `sdks/typescript/packages/encoder/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/package.json)","sdks/typescript/packages/encoder/tsconfig.json":"# Encoder Skill\n\nPath: `sdks/typescript/packages/encoder/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/tsconfig.json)","sdks/typescript/packages/proto/CHANGELOG.md":"# Proto Skill\n\nPath: `sdks/typescript/packages/proto/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/CHANGELOG.md)","sdks/typescript/packages/proto/README.md":"# proto Documentation\n\nPath: `sdks/typescript/packages/proto/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/README.md)","sdks/typescript/packages/proto/package.json":"# Proto Skill\n\nPath: `sdks/typescript/packages/proto/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/package.json)","sdks/typescript/packages/proto/tsconfig.json":"# Proto Skill\n\nPath: `sdks/typescript/packages/proto/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/tsconfig.json)","sdks/typescript/packages/proto/tsconfig.typecheck.json":"# Proto Skill\n\nPath: `sdks/typescript/packages/proto/tsconfig.typecheck.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/tsconfig.typecheck.json)","sdks/dotnet/plugins/ag-ui-dotnet/.claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/.claude-plugin/plugin.json)","integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/flight_schema.json":"# A2ui_fixed_schema_schemas Skill\n\nPath: `integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/flight_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/flight_schema.json)","integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/hotel_schema.json":"# A2ui_fixed_schema_schemas Skill\n\nPath: `integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/hotel_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/hotel_schema.json)","integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/flight_schema.json":"# Schemas Skill\n\nPath: `integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/flight_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/flight_schema.json)","integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/hotel_schema.json":"# Schemas Skill\n\nPath: `integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/hotel_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/hotel_schema.json)","sdks/typescript/packages/client/src/apply/__tests__/fixtures/strands-native-resume.json":"# Fixtures Skill\n\nPath: `sdks/typescript/packages/client/src/apply/__tests__/fixtures/strands-native-resume.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/src/apply/__tests__/fixtures/strands-native-resume.json)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AI Agent Protocol & Instructions\n\nPath: `AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/AGENTS.md)","tokens":300,"sizeBytes":154},{"name":"SKILL.md","path":".github/skills/agui-cross-sdk-parity/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-cross-sdk-parity/SKILL.md","title":"agui-cross-sdk-parity","category":"anthropic-skill","format":"markdown","content":"---\nname: agui-cross-sdk-parity\ndescription: >\n  Keep the AG-UI .NET SDK at feature and wire-format PARITY with the canonical\n  reference SDKs (TypeScript is the source of truth; Python is types/encoder only).\n  USE FOR: porting a feature/event/behavior that landed in the TS (or Python) SDK\n  into .NET, verifying the .NET wire format (JSON, SSE, protobuf) matches the\n  reference, locating where the reference implementation and compatibility fixtures\n  live, mapping a TS concept to the .NET event/client/encoder model, resolving an\n  upstream protocol fix (e.g. a Microsoft.Extensions.AI / Microsoft Agent Framework\n  issue) that needs a .NET counterpart, deciding which .NET package owns a change.\n  DO NOT USE FOR: the mechanics of writing a specific test (use agui-dotnet-unit-tests\n  for serialization round-trips, agui-dotnet-integration-tests for cross-language /\n  E2E harness mechanics, agui-dotnet-wire-types for JSON/proto type rules,\n  agui-dotnet-transport for SSE/HTTP transport details). This skill is about the\n  PARITY PROCESS and where the reference lives, not test authoring.\n---\n\n# AG-UI Cross-SDK Parity\n\nThe .NET SDK implements an upstream, multi-language protocol. This skill encodes the\n**parity process**: which SDK is authoritative, where its reference and fixtures live,\nhow to map reference concepts onto the .NET model, and how parity is guarded.\n\n## Parity Principle\n\n- **TypeScript is canonical** for wire format AND client run-loop behavior. When two\n  SDKs disagree, match TS.\n- **Python is types + encoder only.** It has `core` (types/events) and an `encoder`,\n  but **no client run-loop and no protobuf** (`sdks/python/ag_ui/` has `core/` and\n  `encoder/` but no `client/` or `proto/`). Use it only as a secondary check on\n  type/JSON shape — never for run-loop or proto questions.\n- Upstream protocol or SDK fixes (in the TS client run-loop, or in\n  Microsoft.Extensions.AI / Microsoft Agent Framework) sometimes need a .NET\n  counterpart; treat the TypeScript change as the contract to match.\n\n## Where the Reference Lives\n\n| Concern | TypeScript reference (source of truth) | .NET package it maps to |\n|---|---|---|\n| Event & type definitions | `sdks/typescript/packages/core/src/events.ts`, `types.ts`, `event-factories.ts` | `sdks/dotnet/src/AGUI.Abstractions/Events/`, `Messages/` |\n| Client run-loop / transport | `sdks/typescript/packages/client/src/run/`, `apply/`, `agent/`, `transform/` | `sdks/dotnet/src/AGUI.Client/` (`AGUIChatClient.cs`, `AGUIHttpTransport.cs`, `EventStreamConverter.cs`, `ToolCallBuilder.cs`) |\n| SSE / JSON wire framing | `sdks/typescript/packages/encoder/src/encoder.ts` | `sdks/dotnet/src/AGUI.Formatting/`, `AGUI.Abstractions/Serialization/` |\n| Protobuf wire format | `sdks/typescript/packages/proto/src/proto/events.proto`, `types.proto`, `patch.proto` | `sdks/dotnet/src/AGUI.Protobuf/` (`ProtoEventMapper.cs`, `ProtoMessageMapper.cs`) |\n\nThe `src/` packages are **AGUI.Abstractions, AGUI.Formatting, AGUI.Protobuf, AGUI.Client,\nAGUI.Server**; `sdks/dotnet/AGENTS.md` and `docs/architecture.md` are the canonical\ndescription of the layout and conventions.\n\n## Porting Workflow\n\n1. **Locate the feature in TS.** Find the change in `packages/core` (a new event/type),\n   `packages/client` (run-loop / event-application behavior), or\n   `packages/proto`+`encoder` (wire framing). Read the TS implementation and its tests\n   to capture the exact contract — field names, ordering, optionality, coalescing rules.\n2. **Identify the wire contract.** Determine the JSON shape, the proto schema impact\n   (if any), and whether client run-loop state changes. Cross-check the JSON property\n   names against `packages/core/src/events.ts`.\n3. **Map to the .NET model and the right package** (table above). Events/types →\n   `AGUI.Abstractions`; run-loop → `AGUI.Client`; SSE/JSON framing → `AGUI.Formatting`;\n   protobuf → `AGUI.Protobuf`. Follow the .NET conventions in `AGENTS.md` (one class\n   per file, `sealed`, source-generated JSON context, `PublicAPI.Unshipped.txt`).\n4. **Implement** the .NET change. For a new event, follow the \"Adding a new event type\"\n   checklist in `AGENTS.md` (class in `Events/`, `AGUIEventTypes` constant,\n   `[JsonSerializable]`, `BaseEventJsonConverter` case, PublicAPI entry).\n5. **Add parity assets** (see next section): a TS-produced JSON fixture under\n   `tests/AGUI.Abstractions.UnitTests/Compatibility/` and/or a cross-language test in\n   `tests/CrossLanguage.Vitest/tests/`.\n6. **Verify byte/semantic parity** — run the compatibility and cross-language tests.\n7. **Update docs.** Refresh `sdks/dotnet/AGENTS.md`, `docs/architecture.md`, and\n   `docs/cross-language-testing.md` if the change alters the model, package layout, or the\n   set of wire-supported events.\n\n## How Parity Is Guarded\n\nFour independent layers catch drift; add to whichever layer the change touches.\n\n- **Compatibility fixtures (catch JSON drift).**\n  `tests/AGUI.Abstractions.UnitTests/Compatibility/` holds TS-produced JSON fixtures\n  (`*-events.json`) loaded via `FixtureLoader` and deserialized into .NET types\n  (`{Category}CompatibilityTest.cs`, e.g. `RunEventsCompatibilityTest`,\n  `ToolCallEventsCompatibilityTest`). A new/changed event shape needs a fixture entry.\n- **Cross-language tests (catch end-to-end drift).** The harness in\n  `tests/CrossLanguage.TestServer/` (C# server) and `tests/CrossLanguage.Vitest/`\n  (TS client driving it) proves real interop — see `sdks/dotnet/docs/cross-language-testing.md`.\n  Scenario specs live in `tests/CrossLanguage.Vitest/tests/` (e.g.\n  `parallel-tool-calls.test.ts`, `state-events.test.ts`, `protobuf-parity.test.ts`).\n- **Protobuf byte-parity tests.** `protobuf-parity.test.ts` plus\n  `tests/AGUI.Protobuf.UnitTests/` verify the binary encoding matches the TS proto output.\n- **Shared cross-language fixtures (catch three-way drift).** `sdks/fixtures/` holds\n  language-neutral JSON that more than one SDK is held to, so an expectation is written down\n  once instead of three times. `null-omission.json` is the first: TypeScript, Python and .NET\n  each deserialize its `input` events, re-serialize through their own producer path, and\n  assert the result equals `expected`. A wire rule that all three must agree on belongs here\n  rather than in one SDK's test tree — see `sdks/fixtures/README.md`.\n\n## Known Parity Boundary: Proto Is a Subset\n\nThe protobuf schema covers a **subset** of events by design. `.NET`-only events\n(`Reasoning*`, `Activity*`, `ToolCallResult`) are not in the proto wire format and\n**throw `NotSupportedException`** when mapped — see `ProtoEventMapper.cs` (the `default`\ncase lists the 16 supported events: RUN_STARTED/FINISHED/ERROR, STEP_STARTED/FINISHED,\nTEXT_MESSAGE_START/CONTENT/END, TOOL_CALL_START/ARGS/END, STATE_SNAPSHOT/DELTA,\nMESSAGES_SNAPSHOT, RAW, CUSTOM) and `ProtoMessageMapper.cs`. This is a **deliberate,\ndocumented boundary** — do not \"fix\" it by inventing proto messages that don't exist in\n`events.proto`. JSON/SSE remains the full-fidelity wire; protobuf is the constrained one.\n\n## Critical Anti-patterns\n\n1. **Never treat .NET as the source of truth.** If the .NET behavior differs from TS,\n   the .NET side is the candidate for change — confirm against `packages/core` /\n   `packages/client` first.\n2. **Never consult Python for run-loop or proto parity.** Python has neither. Use it\n   only as a type/JSON cross-check.\n3. **Never add a proto mapping for a `.NET`-only event** (`Reasoning*`, `Activity*`,\n   `ToolCallResult`). The `NotSupportedException` is intentional.\n4. **Never land a wire change without a parity asset.** A JSON-shape change needs a\n   Compatibility fixture; an interop/behavioral change needs a cross-language test.\n\n## Routing to Sibling Skills\n\nThis skill governs *what* to port and *where the reference is* — delegate test\nmechanics:\n\n- **agui-dotnet-unit-tests** — serialization round-trips and Compatibility fixture tests.\n- **agui-dotnet-integration-tests** — cross-language / E2E harness (TestServer + Vitest).\n- **agui-dotnet-wire-types** — JSON/proto type and serialization-context rules.\n- **agui-dotnet-transport** — SSE / HTTP transport details.\n","frontmatter":{"name":"agui-cross-sdk-parity","description":"Keep the AG-UI .NET SDK at feature and wire-format PARITY with the canonical reference SDKs (TypeScript is the source of truth; Python is types/encoder only). USE FOR: porting a feature/event/behavior that landed in the TS (or Python) SDK into .NET, verifying the .NET wire format (JSON, SSE, protobuf) matches the reference, locating where the reference implementation and compatibility fixtures live, mapping a TS concept to the .NET event/client/encoder model, resolving an upstream protocol fix (e.g. a Microsoft.Extensions.AI / Microsoft Agent Framework issue) that needs a .NET counterpart, deciding which .NET package owns a change. DO NOT USE FOR: the mechanics of writing a specific test (use agui-dotnet-unit-tests for serialization round-trips, agui-dotnet-integration-tests for cross-language / E2E harness mechanics, agui-dotnet-wire-types for JSON/proto type rules, agui-dotnet-transport for SSE/HTTP transport details). This skill is about the PARITY PROCESS and where the reference lives, not test authoring.\n"},"isInternal":false,"tokens":2053,"sizeBytes":8199},{"name":"SKILL.md","path":".github/skills/agui-dojo/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dojo/SKILL.md","title":"agui-dojo","category":"anthropic-skill","format":"markdown","content":"---\nname: agui-dojo\ndescription: >\n  Run the AG-UI Dojo demo viewer locally and wire the AG-UI .NET SDK in as a dojo\n  integration. USE FOR: starting the dojo app (apps/dojo), running the .NET dojo\n  backend (AGUIDojoServer), registering or modifying the ag-ui-dotnet integration\n  (agents.ts/menu.ts/env.ts/files.json), running the dojo Playwright e2e suite for\n  the .NET integration (agUiDotnetTests), or understanding how dojo-e2e.yml runs it\n  in CI. DO NOT USE FOR: generic Playwright validation of arbitrary pages (use\n  agui-playwright-validate), or the docs site (use agui-dotnet-sdk-docs).\n---\n\n# AG-UI Dojo (.NET integration)\n\nThe **Dojo** is a Next.js \"demo viewer\" (`apps/dojo`) that showcases AG-UI protocol\nfeatures (agentic chat, generative UI, human-in-the-loop, shared state, etc.) against\nmany framework integrations. The AG-UI .NET SDK is one integration, id **`ag-ui-dotnet`**.\n\n## Where the pieces live\n\n| Piece | Path | Role |\n|-------|------|------|\n| Dojo app (frontend) | `apps/dojo` | Next.js viewer, runs on port **9999** |\n| .NET backend | `sdks/dotnet/samples/AGUIClientServer/AGUIDojoServer/` | ASP.NET host exposing AG-UI endpoints, port **8023** |\n| Agent registry | `apps/dojo/src/agents.ts` | `ag-ui-dotnet` → `HttpAgent` per feature |\n| Menu / feature list | `apps/dojo/src/menu.ts` | integration id, name, enabled features |\n| Env config | `apps/dojo/src/env.ts` | `aguiDotnetUrl` ← `AGUI_DOTNET_URL` (default `http://localhost:8023`) |\n| Generated source viewer data | `apps/dojo/src/files.json` | generated, **committed** |\n| Content generator | `apps/dojo/scripts/generate-content-json.ts` | builds `files.json` from `menu.ts` |\n| Prep / run orchestrators | `apps/dojo/scripts/{prep,run}-dojo-everything.js` | install/build + start services |\n| .NET e2e suite | `apps/dojo/e2e/tests/agUiDotnetTests/*.spec.ts` | Playwright tests |\n| CI | `.github/workflows/dojo-e2e.yml` | suite `ag-ui-dotnet` (triggers on `sdks/dotnet/**`) |\n\n## Run the dojo + .NET backend locally\n\nFrom the repo root (the scripts shell out to `git rev-parse`):\n\n```bash\npnpm install --no-frozen-lockfile\n\n# 1) Prep: builds the .NET backend AND the dojo (use the stable ids)\nnode apps/dojo/scripts/prep-dojo-everything.js --only dojo,ag-ui-dotnet\n\n# 2) Run: starts the dojo (9999) + AGUIDojoServer (8023) together, with LLMock env injected\nnode apps/dojo/scripts/run-dojo-everything.js --only dojo,ag-ui-dotnet\n```\n\n- Browse `http://localhost:9999/ag-ui-dotnet/feature/agentic_chat`.\n- `prep` for `ag-ui-dotnet` runs `dotnet restore && dotnet build` on\n  `AGUIDojoServer/AGUIDojoServer.csproj` in `sdks/dotnet/samples/AGUIClientServer`.\n- `run` for `ag-ui-dotnet` runs `dotnet run --project AGUIDojoServer/AGUIDojoServer.csproj\n  --urls \"http://localhost:8023\" --no-build` — **prep first or there's no build to run**.\n\nStart just the .NET backend by hand (e.g. to debug):\n\n```bash\ncd sdks/dotnet/samples/AGUIClientServer\ndotnet run --project AGUIDojoServer/AGUIDojoServer.csproj --urls \"http://localhost:8023\"\n```\n\nThe backend resolves its `ChatClient` from configuration (`ChatClientAgentFactory.Initialize`):\n`OPENAI_BASE_URL` (any OpenAI-compatible endpoint / LLMock), else `AZURE_OPENAI_ENDPOINT`\n(Entra ID), else public OpenAI with `OPENAI_API_KEY`. `run-dojo-everything.js` injects\n`OPENAI_BASE_URL=http://localhost:5555/v1` and `OPENAI_API_KEY=sk-mock` so it hits the LLMock.\n\n## How the .NET SDK is registered as an integration\n\nEach scenario is an AG-UI endpoint on the .NET host wired to a frontend feature. To add or\nchange a `.NET` dojo scenario, touch these in lockstep:\n\n1. **Backend endpoint** — `AGUIDojoServer/Program.cs`: add `app.MapDojoEndpoint(\"/<feature>\", ChatClientAgentFactory.Create…())`.\n   Agent logic lives in `ChatClientAgentFactory.cs`.\n2. **Agent mapping** — `apps/dojo/src/agents.ts` (`\"ag-ui-dotnet\"` block): add `<feature>: \"<feature>\"`\n   inside `mapAgents`; each maps to `new HttpAgent({ url: \\`${envVars.aguiDotnetUrl}/<feature>\\` })`.\n3. **Menu** — `apps/dojo/src/menu.ts` (`id: \"ag-ui-dotnet\"`): add the feature to `features`.\n4. **Source viewer** — `apps/dojo/scripts/generate-content-json.ts` already maps `ag-ui-dotnet` to\n   `Program.cs` + `ChatClientAgentFactory.cs`; then regenerate `files.json` (below).\n5. **env.ts** — only edit if changing the URL/port; `aguiDotnetUrl`/`AGUI_DOTNET_URL` already exist.\n\nRegenerate the committed source-viewer data after any `menu.ts` change:\n\n```bash\ncd apps/dojo && pnpm generate-content-json   # writes src/files.json\n```\n\n> ⚠️ CI job `check-generated-files` fails if `src/files.json` is stale. Always regenerate and\n> commit it after editing `menu.ts` (or feature/README files).\n\n## Run the .NET e2e suite locally\n\n```bash\ncd apps/dojo/e2e\npnpm install --ignore-scripts\npnpm exec playwright install --with-deps chromium   # first time only\n# dojo (9999) + AGUIDojoServer (8023) must already be running (see above)\nBASE_URL=http://localhost:9999 PLAYWRIGHT_SUITE=ag-ui-dotnet pnpm test -- tests/agUiDotnetTests\n```\n\nTests navigate to `/ag-ui-dotnet/feature/<feature>` and drive the chat UI via page objects in\n`apps/dojo/e2e/featurePages/`.\n\n## How CI runs it (`dojo-e2e.yml`)\n\n- Matrix suite `ag-ui-dotnet`: `test_path: tests/agUiDotnetTests`, `services: [\"dojo\", \"ag-ui-dotnet\"]`,\n  `wait_on: http://localhost:9999,tcp:localhost:8023`.\n- Triggers on `pull_request`/`push` paths including **`sdks/dotnet/**`**.\n- Installs .NET `9.0.x` + `10.0.x`, runs `prep-dojo-everything.js --only` then\n  `run-dojo-everything.js --only`, waits on the ports, then `pnpm test -- tests/agUiDotnetTests`.\n\n## Gotchas\n\n- **Ports are fixed**: dojo `9999`, AGUIDojoServer `8023`. The dojo's `AGUI_DOTNET_URL` must point\n  to `http://localhost:8023` (default in `run-dojo-everything.js` and `env.ts`).\n- **`--no-build` in run** means you must run the prep step first; otherwise the `dotnet run` fails.\n- **LLMock, not a real LLM**: `OPENAI_BASE_URL=http://localhost:5555/v1` + `OPENAI_API_KEY=sk-mock`\n  are injected. Backend tool-rendering scenarios also honor `AG_UI_MOCK_WEATHER=1` for determinism.\n- **`BASE_URL` is required** — `playwright.config.ts` calls `process.exit(1)` if it's unset.\n- **Stale `files.json`** is the most common CI failure after touching `menu.ts` — run\n  `pnpm generate-content-json` and commit the result.\n","frontmatter":{"name":"agui-dojo","description":"Run the AG-UI Dojo demo viewer locally and wire the AG-UI .NET SDK in as a dojo integration. USE FOR: starting the dojo app (apps/dojo), running the .NET dojo backend (AGUIDojoServer), registering or modifying the ag-ui-dotnet integration (agents.ts/menu.ts/env.ts/files.json), running the dojo Playwright e2e suite for the .NET integration (agUiDotnetTests), or understanding how dojo-e2e.yml runs it in CI. DO NOT USE FOR: generic Playwright validation of arbitrary pages (use agui-playwright-validate), or the docs site (use agui-dotnet-sdk-docs).\n"},"isInternal":false,"tokens":1862,"sizeBytes":6335},{"name":"SKILL.md","path":".github/skills/agui-dotnet-agents-sync/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-agents-sync/SKILL.md","title":"agui-dotnet-agents-sync","category":"anthropic-skill","format":"markdown","content":"---\nname: agui-dotnet-agents-sync\ndescription: >\n  Keep the AG-UI .NET SDK docs (sdks/dotnet/AGENTS.md and docs/architecture.md) in\n  sync with the real code tree after structural changes. USE FOR: \"update\n  AGENTS.md / docs/architecture.md\", \"check the dotnet docs are current\", verifying\n  docs after a .NET SDK refactor (package rename, added/removed project,\n  changed endpoint pattern, new/renamed test project, sample step added, new\n  convention). DO NOT USE FOR: writing product code or tests (follow AGENTS.md\n  itself), Python/TypeScript SDK docs, or generic markdown editing unrelated to\n  the dotnet SDK structure.\n---\n\n# AG-UI .NET SDK — Docs Sync\n\n`sdks/dotnet/AGENTS.md` (coding instructions) and `sdks/dotnet/docs/architecture.md`\n(design overview) describe the SDK's structure, naming, and conventions. They\ndrift silently after refactors because nothing fails the build when prose goes\nstale. This skill reconciles them against the live tree.\n\n> Typical drift this catches: a package rename, a moved/removed project, a changed\n> endpoint pattern, or a new sample step that the prose never caught up with. An agent\n> that edits these files from memory re-introduces the same kind of drift, so always\n> derive the truth from the tree first.\n\n## Process\n\n1. **Establish ground truth from the tree, not from the doc.** The authoritative\n   source is `sdks/dotnet/AGUI.slnx` plus the folder listing — never the prose\n   you are about to edit.\n   - Projects: read `<Project Path=...>` entries from `AGUI.slnx`.\n   - Folders: `Get-ChildItem src,tests,samples -Directory`.\n   - Samples/steps: list `samples/GettingStarted/Step*` to get the real range.\n2. **Drift scan — diff each doc claim against the tree.** For every concrete\n   claim in AGENTS.md / docs/architecture.md, confirm it against ground truth:\n   - Project & package names exist in `AGUI.slnx` (and in `src/`, `tests/`).\n   - Symbols the docs name still exist: `Select-String -Path src\\*\\*.cs,samples\\*\\*.cs -Pattern \"<Symbol>\"`.\n   - Renamed/removed symbols are GONE everywhere: grep the repo for the old\n     name (e.g. `AGUI.Hosting.AspNetCore`, `TypedResults.ServerSentEvents`); a\n     hit in prose-only is the drift to fix.\n3. **Fix surgically.** Edit only the stale lines. Match existing tone, tables,\n   and code-fence style. Do not restructure or invent conventions.\n4. **Verify.** Re-grep every symbol/name you wrote to confirm it exists in the\n   tree. Optionally `dotnet build` from `sdks/dotnet/` if you touched code-style\n   or build claims.\n\n## Drift checklist (the claims that rot)\n\n| Doc claim | Reconcile against |\n|---|---|\n| **src package list / names** | `AGUI.slnx` `/src/` folder + `src/` dirs |\n| **Package dependency table & framework refs** | `grep Microsoft.AspNetCore src\\*\\*.csproj` (must be empty — no src project references ASP.NET) |\n| **Where ASP.NET glue lives** | `samples/AGUI.Samples.Shared` (the only `FrameworkReference Microsoft.AspNetCore.App`) |\n| **Test-project table & count** | `AGUI.slnx` `/tests/` + `tests/` dirs |\n| **Sample step range / count** | `samples/GettingStarted/Step*` listing |\n| **Endpoint pattern code** | actual sample `Program.cs` + `samples/AGUI.Samples.Shared` |\n| **Project layout bullet list** | `src/`, `tests/`, `samples/` dirs |\n| **Code-style / naming / serialization rules** | `Directory.Build.props/.targets`, `Directory.Packages.props`, source |\n| **PublicAPI workflow** | presence of `PublicAPI.*.txt` in each `src/` project |\n\n## Deriving ground truth (commands, not a snapshot)\n\nDon't trust any embedded list (including this skill). Re-derive the current state\nfrom the tree every time:\n\n```powershell\n# from sdks/dotnet/\nSelect-String -Path AGUI.slnx -Pattern '<Project Path'   # all projects\nGet-ChildItem src,tests,samples -Directory               # folders\nGet-ChildItem samples/GettingStarted -Directory -Filter Step*  # sample step range\nSelect-String -Path src\\*\\*.csproj -Pattern Microsoft.AspNetCore  # must be empty (no ASP.NET in src/)\n```\n\nA couple of durable facts that are easy to get wrong: the server package is\n`AGUI.Server` (ASP.NET hosting glue lives only in `samples/AGUI.Samples.Shared`),\nand the integration-test **project name** stays `AGUI.Hosting.AspNetCore.IntegrationTests`\neven though its types are in namespace `AGUI.Server.IntegrationTests`. Everything else,\nderive from the commands above.\n\n## ❌ Critical anti-patterns\n\n1. **Never edit the docs from memory or from the doc's own current text.** The\n   stale prose is exactly what misleads you. Derive every name from `AGUI.slnx`\n   and the folder listing first.\n2. **Never rename a symbol in prose without grepping the whole tree** for the\n   old name — a lingering reference (or an unchanged code fence) is silent drift.\n3. **Don't invent conventions or restructure the docs.** Reconcile only what the\n   tree proves changed; keep tables, tone, and code-fence style intact.\n4. **Don't confuse a kept project name with a moved concept.** The integration\n   test project is still `AGUI.Hosting.AspNetCore.IntegrationTests` even though\n   the src package was renamed to `AGUI.Server`.\n\n## Files to mine\n\n`sdks/dotnet/AGENTS.md`, `sdks/dotnet/docs/architecture.md`, `sdks/dotnet/AGUI.slnx`,\n`sdks/dotnet/Directory.Build.props`, `Directory.Build.targets`,\n`Directory.Packages.props`, and the `src/`, `tests/`, `samples/` folder trees.\n","frontmatter":{"name":"agui-dotnet-agents-sync","description":"Keep the AG-UI .NET SDK docs (sdks/dotnet/AGENTS.md and docs/architecture.md) in sync with the real code tree after structural changes. USE FOR: \"update AGENTS.md / docs/architecture.md\", \"check the dotnet docs are current\", verifying docs after a .NET SDK refactor (package rename, added/removed project, changed endpoint pattern, new/renamed test project, sample step added, new convention). DO NOT USE FOR: writing product code or tests (follow AGENTS.md itself), Python/TypeScript SDK docs, or generic markdown editing unrelated to the dotnet SDK structure.\n"},"isInternal":false,"tokens":1390,"sizeBytes":5375},{"name":"rules.md","path":".github/skills/agui-dotnet-code-review/references/rules.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-code-review/references/rules.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `.github/skills/agui-dotnet-code-review/references/rules.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-code-review/references/rules.md)","tokens":300,"sizeBytes":236},{"name":"SKILL.md","path":".github/skills/agui-dotnet-code-review/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-code-review/SKILL.md","title":"agui-dotnet-code-review","category":"anthropic-skill","format":"markdown","content":"---\nname: agui-dotnet-code-review\ndescription: >\n  Review C#/.NET code changes to the AG-UI .NET SDK (sdks/dotnet/) against its\n  specific conventions and architectural rules — AOT serialization, the\n  \"no ASP.NET in src/\" boundary, the PublicAPI analyzer workflow, wire\n  compatibility with the TypeScript reference, and the house style\n  (sealed/no-records/ConfigureAwait). Runs a phased, rule-by-rule review.\n  USE FOR: reviewing a PR, diff, or branch that touches sdks/dotnet/; checking a\n  new event/message type; verifying serialization, package placement, or\n  public-API changes in the .NET SDK. DO NOT USE FOR: generic C# style nits\n  already enforced by analyzers/EditorConfig; reviewing the TypeScript SDK\n  (sdks/typescript/) or Python SDK (sdks/python/); writing new features (only\n  flag violations, never rewrite code).\n---\n\n# AG-UI .NET SDK Code Review\n\nEncodes the AG-UI .NET SDK's house rules so a reviewer flags real violations a\ngeneric C# reviewer misses. Authoritative sources: `sdks/dotnet/AGENTS.md`\n(house rules) and `sdks/dotnet/docs/architecture.md` (design boundaries). Each\nrule cites a real enforcement example in the repo; full BAD→GOOD examples and\nper-rule exceptions live in [`references/rules.md`](references/rules.md). The\nchange-footprint and test rules below distil the `minimize-change-footprint`,\n`ensure-test-coverage`, and `ensure-test-quality` review conventions for this SDK.\n\n## Reviewer discipline\n\n- **High signal-to-noise.** Only flag a genuine violation of a rule below, tied\n  to its cited convention. Don't invent nits or restate analyzer output.\n- **Verify before flagging.** Read the actual changed code and confirm the rule\n  applies. Automated reviewers have high false-positive rates.\n- **Scope.** Review only files under `sdks/dotnet/`. Skip generic style already\n  enforced by `TreatWarningsAsErrors`, nullable, and EditorConfig.\n- **Blast radius.** Fix nothing — this skill only reports. Local convention\n  violations get a finding; codebase-wide concerns are noted as out-of-scope\n  follow-ups, not per-line nits.\n- **Severity:** ❌ must fix (breaks AOT/wire/build/boundary); ⚠️ should fix\n  (convention drift); 💡 optional polish.\n\n## The review process\n\n**Step 0 — Ground truth & file classification.** Derive the package map from\n`AGUI.slnx`; skim `AGENTS.md` + `docs/architecture.md`. Classify each changed\nfile: `production | test | sample | proto | csproj | public-api | docs`. Rules\nare gated by class.\n\n**Step 1 — Determine and summarize the change set.** Resolve what is under\nreview, in order: an explicit target (PR number / branch / commit range); else\nthe current branch vs. its tracking/base branch (`git merge-base <base> HEAD`);\nplus **staged, unstaged, and untracked** working-tree changes. Then write a short\nsummary of what the diff does — new types, wire/protocol changes, public-surface\nchanges, new dependencies, src-vs-sample placement. This frames every phase and\ncatches scope creep early.\n\n**Step 2 — Walk the rules, phase by phase (A→G).** For each phase, check every\napplicable changed file against every rule in that phase. Write each finding\nimmediately: `file:line`, rule ID, severity, one-line fix. Verify the code first.\n\n**Step 3 — Self-validation.** Dedupe; confirm each finding cites a real rule and\na real line; confirm no rule was applied to the wrong file class; drop anything\nnot verifiable in the actual diff.\n\n**Step 4 — Emit the review summary** (see below) — a single human-readable comment,\nfindings grouped by severity with a verdict and coverage line.\n\n## Phase A — Scope / scenarios\n\n- `NET-SCOPE-01` Every change traces to a spec requirement or issue `[⚠️]`\n- `NET-SCOPE-02` No unrequested capability, configurability, or dependency `[⚠️]`\n- `NET-SCOPE-03` A wire/protocol change carries compatibility coverage `[❌]`\n- `NET-SCOPE-04` Sample-only behavior stays out of `src/` `[⚠️]`\n- `NET-SCOPE-05` Minimal footprint — every diff line serves the task; no unrelated\n  refactor, speculative abstraction, or cosmetic churn `[⚠️]`\n\n## Phase B — Design / architecture\n\nFrom `docs/architecture.md` \"Architectural constraints\".\n\n- `NET-ARCH-01` No `src/` project references `Microsoft.AspNetCore.App` `[❌]` —\n  `git grep \"Microsoft.AspNetCore\" -- sdks/dotnet/src` must be empty.\n- `NET-ARCH-02` Correct package placement (wire→Abstractions, SSE→Formatting,\n  proto→Protobuf, client/transport→Client, hosting→Server) `[❌]`\n- `NET-ARCH-03` Dependency direction — `Client` and `Server` never reference each\n  other `[❌]`. Cite: `src/AGUI.Server/AGUI.Server.csproj`.\n- `NET-ARCH-04` `IChatClient` is the only integration point — no bespoke agent\n  abstraction `[💡]`\n- `NET-ARCH-05` Every type has a single reason to change `[⚠️]`\n- `NET-ARCH-06` No interface without multiple implementations or a test-double need `[⚠️]`\n- `NET-ARCH-07` Make invalid states unrepresentable (enums/types over bool/string) `[⚠️]`\n- `NET-ARCH-08` One class per file; file name matches the type `[⚠️]`\n\n## Phase C — Implementation / correctness\n\nFrom `AGENTS.md` \"JSON serialization\" / \"Code style\".\n\n- `NET-IMPL-01` Every serializable type registered in `AGUIJsonSerializerContext`\n  via `[JsonSerializable(typeof(T))]` `[❌]`. Cite:\n  `src/AGUI.Abstractions/Serialization/AGUIJsonSerializerContext.cs`.\n- `NET-IMPL-02` No `JsonSerializer.Serialize<object>` and no reflection-based\n  serialization — go through the source-gen context `[❌]`\n- `NET-IMPL-03` Polymorphic JSON uses a hand-written discriminator `JsonConverter<T>` `[❌]`.\n  Cite: `src/AGUI.Abstractions/Events/BaseEventJsonConverter.cs`.\n- `NET-IMPL-04` Property attribute kit present: explicit `[JsonPropertyName]`, **no**\n  `[JsonIgnore(WhenWritingNull)]` on optionals (the context-wide default does that),\n  required strings = `string.Empty`, collections = `[]` `[⚠️]`.\n  Cite: `src/AGUI.Abstractions/Events/RunStartedEvent.cs`.\n- `NET-IMPL-05` `ConfigureAwait(false)` on every `await` in `src/` `[⚠️]`. Cite:\n  `src/AGUI.Client/AGUIChatClient.cs`.\n- `NET-IMPL-06` `[EnumeratorCancellation]` on the token of any `IAsyncEnumerable<T>`\n  method `[⚠️]`. Cite: `src/AGUI.Formatting/SseEventStreamFormatter.cs`.\n- `NET-IMPL-07` `ArgumentNullException.ThrowIfNull(...)` for public-API argument\n  validation `[⚠️]`\n- `NET-IMPL-08` Validate external input at the boundary, not deep in the stack `[⚠️]`\n- `NET-IMPL-09` Guard every code path — no silent `default`/fallthrough `[⚠️]`\n- `NET-IMPL-10` No swallowed exceptions (empty or log-only `catch`) `[⚠️]`\n- `NET-IMPL-11` Never log or expose sensitive data in errors `[❌]`\n- `NET-IMPL-12` No dead, commented-out, or impossible-condition defensive code `[⚠️]`\n- `NET-IMPL-13` No logic duplicated across the changeset — extract a shared helper\n  at 3+ uses (Rule of Three; don't extract for 1–2) `[⚠️]`\n- `NET-IMPL-14` Prefer BCL/platform APIs over hand-rolled equivalents `[⚠️]` —\n  exception: deliberate AOT-safe hand-written paths (the `JsonElement`↔`Value`\n  bridge, the discriminator converters) are intentional, not violations.\n\n## Phase D — Wire compatibility\n\n- `NET-WIRE-01` Protocol types match the TS reference — honor the\n  `// Keep in sync with sdks/typescript/...` markers `[❌]`. Cite:\n  `src/AGUI.Abstractions/Events/RunStartedEvent.cs`.\n- `NET-WIRE-02` Events are additive — unknown types round-trip via `RawEvent`;\n  don't remove or repurpose existing fields `[⚠️]`\n- `NET-WIRE-03` Protobuf parity preserved for the supported event set `[❌]`\n\n## Phase E — PublicAPI analyzer\n\n- `NET-API-01` Any public-surface change updates that project's\n  `PublicAPI.Unshipped.txt` (build fails RS0016 otherwise) `[❌]`. Cite:\n  `sdks/dotnet/Directory.Build.targets`, `src/AGUI.Abstractions/PublicAPI.Unshipped.txt`.\n- `NET-API-02` A new event type completes the full checklist (class in `Events/`\n  deriving `BaseEvent`; `Type` → `AGUIEventTypes` constant; `[JsonSerializable]`;\n  read case in `BaseEventJsonConverter`; `PublicAPI.Unshipped.txt`; round-trip\n  test) `[⚠️]`\n\n## Phase F — Style / naming\n\nFrom `AGENTS.md` \"Code style\" / \"Naming\" (not all analyzer-enforced).\n\n- `NET-STYLE-01` `sealed` on every non-abstract class `[⚠️]`\n- `NET-STYLE-02` No `record` types — use `sealed class` with properties `[❌]`\n- `NET-STYLE-03` No tuples in public APIs — define a named type `[⚠️]`\n- `NET-STYLE-04` Braces always on `if`/`for`/`foreach`/`while` `[⚠️]`\n- `NET-STYLE-05` Naming: events `{Name}Event`; discriminators `SCREAMING_SNAKE_CASE`\n  constants in `AGUIEventTypes`; outcome/role constants lowercase (never enums);\n  options `AGUI{Purpose}Options`; extensions `{Target}Extensions`; tests\n  `{TypeUnderTest}Test` `[⚠️]`\n- `NET-STYLE-06` DI-extension types use the `Microsoft.Extensions.DependencyInjection`\n  namespace; all other types use the project `RootNamespace` with no sub-namespaces `[⚠️]`\n- `NET-STYLE-07` No XML docs (`///`) on `internal`/`private` members `[⚠️]`\n- `NET-STYLE-08` Don't reformat code you didn't otherwise change `[⚠️]`\n\n## Phase G — Tests\n\nFrom `AGENTS.md` \"Running tests\"; coverage/quality rules distilled from\n`ensure-test-coverage` and `ensure-test-quality`.\n\nSDK-specific:\n- `NET-TEST-01` Serialization tests assert concrete JSON property names via\n  `JsonDocument` — not via the deserialized object `[⚠️]`\n- `NET-TEST-02` No full-JSON-string comparisons — assert individual properties `[❌]`\n- `NET-TEST-03` No reflection to enumerate types or verify membership `[❌]`\n- `NET-TEST-04` Wire-affecting change ⇒ compatibility fixture + round-trip in\n  `tests/AGUI.Abstractions.UnitTests/Compatibility/` `[⚠️]`\n- `NET-TEST-05` New public behavior ⇒ unit test; server-pipeline change ⇒\n  integration test (`tests/AGUI.Hosting.AspNetCore.IntegrationTests/`) `[⚠️/💡]`\n\nCoverage:\n- `NET-TEST-06` A new/changed class with branching logic has a test covering happy\n  path, primary error path, and boundary values (null/empty/zero/single) `[⚠️]`\n- `NET-TEST-07` Don't test trivial code — DTOs/records with no logic, one-line\n  delegations, constant returns `[💡]`\n- `NET-TEST-08` Test through DI + `InternalsVisibleTo`, not members made `public`\n  for tests `[⚠️]`\n\nQuality:\n- `NET-TEST-09` Every test asserts a specific observable value — no assertion-free\n  tests, no bare `Assert.NotNull`/`True`/`NotEmpty` standing in for the real value `[❌]`\n- `NET-TEST-10` Deterministic and isolated — no `Thread.Sleep`/`Task.Delay` for\n  synchronization, no execution-order dependence, side effects cleaned up\n  (files/ports/env) `[❌]`\n- `NET-TEST-11` Test behavior, not implementation — prefer hand-written fakes over\n  `mock.Verify(Times.*)` (unless the call count is the spec'd behavior); `[Theory]`\n  for data variation, `[Fact]` for behavior; AAA visible inline with factory\n  helpers (not shared mutable fixtures) below the tests; no `// TODO` or empty\n  test bodies `[⚠️]`\n\n## Self-validation\n\n- [ ] The change set was resolved (target / tracking branch / working tree) and summarized\n- [ ] Every applicable changed file was walked against every phase's rules\n- [ ] Each finding cites a real rule ID, file, and line, and was verified in the diff\n- [ ] No rule applied to the wrong file class; no duplicates\n- [ ] Clean diffs are reported as clean — no padding\n\n## Common pitfalls\n\n| Pitfall | Solution |\n|---------|----------|\n| Restating analyzer/EditorConfig output | Only flag rules above that tooling does not enforce |\n| Flagging a \"missing\" registration without checking the context | Open `AGUIJsonSerializerContext.cs` and confirm |\n| Treating a sample's ASP.NET usage as a `src/` violation | `NET-ARCH-01` applies to `src/` only |\n| Calling an additive new event a wire break | `NET-WIRE-02` — additive is allowed |\n| Nitpicking style in files with substantive changes | Focus on the substantive change |\n\n## Review summary\n\nProduce a single human-readable Markdown comment — a reviewer's summary the author\ncan read top to bottom. Lead with the verdict, then the findings grouped by\nseverity (most severe first), each one self-contained.\n\n```markdown\n## AG-UI .NET SDK code review\n\n**Verdict:** <Request changes | Comment | Looks good> — <one-sentence reason>\n**Change set:** <branch vs base, e.g. `feat/x` vs `main`> · <N files reviewed>\n(+<U untracked>) · **Findings:** ❌ <a> · ⚠️ <b> · 💡 <c>\n\n<One short paragraph: what the change does and the overall read.>\n\n### ❌ Must fix\n- **`src/AGUI.Abstractions/Events/FooEvent.cs:42`** · `NET-IMPL-01` — new event type\n  isn't registered in `AGUIJsonSerializerContext`; it fails under AOT.\n  **Fix:** add `[JsonSerializable(typeof(FooEvent))]`.\n\n### ⚠️ Should fix\n- **`src/AGUI.Client/AGUIChatClient.cs:88`** · `NET-IMPL-05` — bare `await` in\n  library code. **Fix:** append `.ConfigureAwait(false)`.\n\n### 💡 Optional\n- **`src/AGUI.Server/StreamAdapter.cs:17`** · `NET-ARCH-04` — bespoke agent\n  abstraction; the SDK integrates via `IChatClient`. **Fix:** drop the wrapper.\n\n### Coverage\nPhases checked: A–G. No findings in: **B Design**, **D Wire**, **E PublicAPI**.\n```\n\nRules for the summary:\n- **Order** findings by severity (❌ → ⚠️ → 💡), then by file. One bullet per finding:\n  bold `file:line`, the `RULE-ID`, a plain-language description, and an italic\n  **Fix:** with a one-line remedy. The reader can look the ID up in\n  [`references/rules.md`](references/rules.md).\n- **Omit empty severity sections.** Always include the **Coverage** line so the\n  author sees which phases were clean versus untouched.\n- **Clean diff:** skip the severity sections and write a single line —\n  `✅ No violations of the AG-UI .NET house rules — checked phases A–G across N files.`\n- **Verdict mapping:** any ❌ → *Request changes*; only ⚠️/💡 → *Comment*; none →\n  *Looks good*. The skill never approves or blocks automatically — the verdict is\n  advisory and the author decides.\n\n","frontmatter":{"name":"agui-dotnet-code-review","description":"Review C#/.NET code changes to the AG-UI .NET SDK (sdks/dotnet/) against its specific conventions and architectural rules — AOT serialization, the \"no ASP.NET in src/\" boundary, the PublicAPI analyzer workflow, wire compatibility with the TypeScript reference, and the house style (sealed/no-records/ConfigureAwait). Runs a phased, rule-by-rule review. USE FOR: reviewing a PR, diff, or branch that touches sdks/dotnet/; checking a new event/message type; verifying serialization, package placement, or public-API changes in the .NET SDK. DO NOT USE FOR: generic C# style nits already enforced by analyzers/EditorConfig; reviewing the TypeScript SDK (sdks/typescript/) or Python SDK (sdks/python/); writing new features (only flag violations, never rewrite code).\n"},"isInternal":false,"tokens":3813,"sizeBytes":14078},{"name":"SKILL.md","path":".github/skills/agui-dotnet-cross-language-tests/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-cross-language-tests/SKILL.md","title":"agui-dotnet-cross-language-tests","category":"anthropic-skill","format":"markdown","content":"---\nname: agui-dotnet-cross-language-tests\ndescription: >\n  Author cross-language interop tests that verify the AG-UI .NET SDK is\n  wire-compatible with the TypeScript SDK — a Vitest TS client driving a C#\n  CrossLanguage.TestServer over HTTP, both directions, including protobuf\n  byte-parity against @ag-ui/proto. USE FOR: adding or modifying cross-language\n  interop coverage, CrossLanguage.TestServer routes, the CrossLanguage.Vitest\n  suite, protobuf wire parity tests, TS-client-to-C#-server or\n  C#-client-to-TS-server scenarios. DO NOT USE FOR: .NET-only unit tests (use\n  agui-dotnet-unit-tests), ASP.NET Core hosting integration tests (use\n  agui-dotnet-integration-tests).\n---\n\n# AG-UI .NET Cross-Language Interop Tests\n\nHow to add tests proving the .NET AG-UI SDK interoperates with the TypeScript\nSDK on the wire. The harness lives under `sdks/dotnet/tests/`. Read\n`sdks/dotnet/docs/cross-language-testing.md` (design plus the \"Harness reference\"\nsection) for full background.\n\n## Interop philosophy\n\n- **The TypeScript SDK is the reference (oracle).** A round-trip through the TS\n  codec — `proto.decode(proto.encode(event))` — is the canonical normalised form\n  both SDKs must agree on. Assert .NET output against *that*, not against the raw\n  fixture object.\n- **Round-trip semantic equivalence is the real guarantee**, in both directions\n  (TS→.NET and .NET→TS). Byte-for-byte parity is a stronger claim asserted only\n  where deterministic.\n- Tests exercise *our* code via project references (`AGUI.Abstractions`,\n  `AGUI.Server`, `AGUI.Protobuf`), never the published NuGet packages.\n\n## Harness architecture\n\nTwo directions, two server processes (see the \"Harness reference\" section of\n`sdks/dotnet/docs/cross-language-testing.md`):\n\n| Direction | Driver | Target server | Runner |\n|---|---|---|---|\n| TS → .NET (Phase 1) | TS `HttpAgent` (`@ag-ui/client`) | C# `CrossLanguage.TestServer` on :8091 | Vitest |\n| .NET → TS (Phase 2) | C# `AGUIChatClient` | TS fake-agent server (`server/main.ts`) on :8092 | xUnit |\n\nPhase 1 mechanism: Vitest `globalSetup`\n(`CrossLanguage.Vitest/helpers/global-setup.ts`) starts LLMock\n(`@copilotkit/aimock`, deterministic LLM responses), then\n`helpers/dotnet-server.ts` runs `dotnet build` and spawns the produced\n`CrossLanguage.TestServer.exe` (not `dotnet run` — single PID for clean Windows\nteardown) with `OPENAI_BASE_URL` pointed at LLMock. It waits for the HTTP\nlistener, then test files `fetch` the routes. Both server and LLMock stay alive\nacross the whole run; `vitest.config.ts` sets `fileParallelism: false` so\nconcurrent SDK builds don't contend for artifact locks.\n\nPhase 2 mechanism: `TsServerFixture` (`IAsyncLifetime`, shared via\n`[Collection(nameof(TsServerCollection))]`) shells out `pnpm run server`\n(`tsx server/main.ts`) which emits canned AG-UI events via `@ag-ui/encoder`;\n`AGUIChatClient` consumes them.\n\n## Adding a TS → .NET scenario (Phase 1)\n\n1. **Add a server-side route** under `CrossLanguage.TestServer/` following the\n   endpoint pattern (`MapPost` → `input.ToChatRequestContext(...)` →\n   `GetStreamingResponseAsync` → `.AsAGUIEventStreamAsync(ctx)` →\n   `TypedResults.ServerSentEvents(AgenticChatRoute.WrapAsSseItems(...))`). See\n   `ParallelToolCallsRoute.cs`. For a route that must **negotiate the transport**\n   (SSE *or* protobuf from the `Accept` header), end with\n   `AGUIResults.Events(events, httpContext, cancellationToken)` instead and make\n   sure `Program.cs` registers `ProtobufEventStreamFormatter` as an `IAGUIEventStreamFormatter` — see `AgenticChatRoute.cs`.\n2. **Register it in `Program.cs`** (e.g. `app.MapParallelToolCalls(\"/parallel_tool_calls\")`).\n3. **Register any new payload types in `CrossLanguageJsonSerializerContext.cs`**\n   (`[JsonSerializable(typeof(YourReport))]`). This context is snake_case to\n   match the TS wire shape.\n4. **Add an aimock fixture** in `fixtures/*.json` keyed by `userMessage` /\n   `toolCallId` so LLM responses are deterministic (see\n   `fixtures/parallel-tool-calls.json`).\n5. **Add a `tests/<scenario>.test.ts`** that drives the route with `HttpAgent`\n   and asserts on the collected event stream (see `parallel-tool-calls.test.ts`).\n\n## Adding a .NET → TS scenario (Phase 2)\n\n1. Add a fake agent (`(RunAgentInput) => BaseEvent[]`) in `server/fakeAgents.ts`.\n2. Mount its route in `server/main.ts`.\n3. Add a `*.cs` test in `AGUI.CrossLanguage.IntegrationTests/`, decorated\n   `[Collection(nameof(TsServerCollection))]`, driving it with `AGUIChatClient`\n   (see `AgenticChatTests.cs`).\n\n## Protobuf wire-parity pattern\n\n`ProtobufParityRoute.cs` exposes three codec routes backed by `AGUIProtobuf`:\n\n| Route | In | Out | Backed by |\n|---|---|---|---|\n| `POST /protobuf/encode` | event JSON | raw proto bytes | `AGUIProtobuf.Encode` |\n| `POST /protobuf/decode` | raw proto bytes | event JSON | `AGUIProtobuf.Decode` |\n| `POST /protobuf/decode-framed` | 4-byte BE length-prefixed frames | event JSON array | `AGUIProtobuf.ReadFramedAsync` |\n\n`tests/protobuf-parity.test.ts` proves parity against `@ag-ui/proto`\n(`sdks/typescript/packages/proto/src/proto.ts`) and `@ag-ui/encoder` framing\n(`sdks/typescript/packages/encoder/src/encoder.ts`). For each fixture\n(`fixtures/protobuf-events.ts`):\n\n- `tsBytes = proto.encode(event)`; `reference = proto.decode(tsBytes)`.\n- **TS encode → .NET decode**: `expect(netDecode(tsBytes)).toEqual(reference)`.\n- **.NET encode → TS decode**: `expect(proto.decode(netEncode(event))).toEqual(reference)`.\n- **Byte parity** depends on the fixture's `byteParity` flag:\n  - `\"strict\"` — scalar-only events (only string/number fields, serialised in\n    field-number order): assert the TS and .NET bytes are byte-for-byte equal.\n  - `\"roundtrip\"` — payloads mapping to `google.protobuf.Struct`\n    (`map<string, Value>`): map-entry ordering is **not** canonical across\n    encoders, so do NOT assert byte equality. Assert both byte streams decode\n    (via the TS codec) to the same event instead.\n\nA framing test concatenates `encoder.encodeProtobuf(event)` frames (4-byte BE\nprefix) and posts them to `/protobuf/decode-framed` to exercise `ReadFramedAsync`.\nWhen adding a new protobuf event, add a fixture with the correct `byteParity`\nflag — scalar-only ⇒ `strict`, any object/array payload ⇒ `roundtrip`.\n\n## Transport parity (parameterize scenarios over SSE + protobuf)\n\nThe codec-parity pattern above isolates the **codecs** — it never goes through the\nTS `HttpAgent` or `Accept`-header negotiation. To prove the full **transport** path\n(TS client negotiates a protocol → .NET server encodes it → TS client decodes it),\nparameterize a scenario suite over both transports — the cross-language analogue of\nthe .NET integration tests' `TransportFormat {Json, Protobuf}` `[Theory]`.\n\n`helpers/transport.ts` is the shared mechanism: `TRANSPORTS = [\"sse\", \"protobuf\"]`,\n`TRANSPORT_MEDIA_TYPE`, and `createTransportAgent(config, transport)` which returns\nan `HttpAgent` that requests the transport (it opts into protobuf via the public\n`fetch` hook — the default agent hardcodes `Accept: text/event-stream` *after*\nspreading `headers`, so a `headers` option can't override it) and captures the\nresponse `Content-Type`. Drive the suite with `describe.each(TRANSPORTS)` and assert\n`lastResponseContentType() === TRANSPORT_MEDIA_TYPE[transport]` plus the usual\ndecoded-event assertions — see `tests/agentic-chat.test.ts`.\n\n```ts\ndescribe.each(TRANSPORTS)(\"… [%s]\", (transport) => {\n  it(\"…\", async () => {\n    const { agent, lastResponseContentType } = createTransportAgent(\n      { url: `${baseUrl()}/agentic_chat`, threadId: `t-${transport}` }, transport);\n    agent.messages = [{ id: \"u\", role: \"user\", content: \"Hi, I am duaa\" }];\n    const events: BaseEvent[] = [];\n    await agent.runAgent({}, { onEvent: ({ event }) => events.push(event) });\n    expect(lastResponseContentType()).toBe(TRANSPORT_MEDIA_TYPE[transport]);\n    // …assert decoded events (identical regardless of transport)…\n  });\n});\n```\n\nThe route under test must negotiate (`AGUIResults.Events`, with\n`ProtobufEventStreamFormatter` registered as an `IAGUIEventStreamFormatter` in\n`Program.cs`). `tests/agentic-chat.test.ts` and\n`tests/state-events.test.ts` are parameterized this way today.\n\n**Only parameterize protobuf-safe scenarios.** `ToolCallResult`, `Reasoning*`, and\n`Activity*` events have **no message/oneof entry in the shared `events.proto`** (the\none schema referenced by *both* `@ag-ui/proto` and .NET `AGUI.Protobuf`), so *neither*\nSDK can protobuf-encode them — the codec throwing `NotSupportedException` mirrors\nthe schema, it is not a .NET gap. A suite that emits any of those must stay SSE-only.\nAdding protobuf support for them is an **upstream schema change** (extend the canonical\nTS `events.proto`, regenerate both SDKs, add mappers) — see `agui-cross-sdk-parity`.\n\n`AGUI_MEDIA_TYPE` (`@ag-ui/proto`) and `ProtobufEventStreamFormatter.ProtobufMediaType` are the identical\nexact string, and `AGUIEventStreamResult` sets `Content-Type` to it with no charset\n— the client's exact `===` content-type match depends on that.\n\n## Running the suites\n\n```sh\n# TS → .NET + protobuf parity (builds + spawns the C# server automatically)\ncd sdks/dotnet/tests/CrossLanguage.Vitest\npnpm test\npnpm exec vitest run tests/protobuf-parity.test.ts   # just the parity suite\n\n# .NET → TS (shells out `pnpm run server`)\ncd sdks/dotnet/tests/AGUI.CrossLanguage.IntegrationTests\ndotnet test\n```\n\n`pnpm install` from the repo root once first. Requires .NET 10 SDK, Node at the\nversion in the repository's root `.node-version`, pnpm 10+.\n\n## ❌ Critical anti-patterns\n\n1. **Don't assert byte-equality for object/Struct payloads.** `google.protobuf.Struct`\n   map ordering is non-canonical; byte parity is only valid for scalar-only\n   (`\"strict\"`) fixtures. For object payloads, assert round-trip equivalence.\n2. **Don't make the .NET fixture the oracle.** The TS codec is the reference —\n   compare against `proto.decode(proto.encode(event))`, not the raw event object.\n3. **Don't add a route without registering it in BOTH `Program.cs` AND\n   `CrossLanguageJsonSerializerContext.cs`** (when it introduces new payload\n   types) — the server won't map the route or will fail AOT-safe serialization.\n4. **Don't depend on real LLM calls.** Phase 1 LLM responses come from aimock\n   fixtures keyed by `userMessage`/`toolCallId`; add a fixture for every new\n   prompt. Use fixed/deterministic tool outputs (see `ParallelToolCallsRoute`'s\n   frozen clock).\n5. **Don't use `dotnet run` to start the server in helpers, and don't assume\n   parallel test files.** The harness spawns the built `.exe` for a single\n   killable PID and runs files sequentially (`fileParallelism: false`) to avoid\n   build-lock contention and Windows port orphans.\n","frontmatter":{"name":"agui-dotnet-cross-language-tests","description":"Author cross-language interop tests that verify the AG-UI .NET SDK is wire-compatible with the TypeScript SDK — a Vitest TS client driving a C# CrossLanguage.TestServer over HTTP, both directions, including protobuf byte-parity against @ag-ui/proto. USE FOR: adding or modifying cross-language interop coverage, CrossLanguage.TestServer routes, the CrossLanguage.Vitest suite, protobuf wire parity tests, TS-client-to-C#-server or C#-client-to-TS-server scenarios. DO NOT USE FOR: .NET-only unit tests (use agui-dotnet-unit-tests), ASP.NET Core hosting integration tests (use agui-dotnet-integration-tests).\n"},"isInternal":false,"tokens":2764,"sizeBytes":10840},{"name":"SKILL.md","path":".github/skills/agui-dotnet-feature-workflow/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-feature-workflow/SKILL.md","title":"agui-dotnet-feature-workflow","category":"anthropic-skill","format":"markdown","content":"---\nname: agui-dotnet-feature-workflow\ndescription: >\n  Orchestrator/hub for implementing a feature or change in the AG-UI .NET SDK\n  (sdks/dotnet). USE FOR: \"what's the workflow\", \"what order do I do things in\",\n  \"how do I implement a feature in the .NET SDK\", starting any non-trivial\n  AG-UI .NET SDK change, planning the end-to-end steps and definition-of-done\n  (code + AOT serialization + client/server mapping + unit/integration/cross-language\n  tests + docs + PublicAPI + AGENTS.md sync). DO NOT USE FOR: the deep how-to of a\n  single step — this skill ROUTES to focused siblings: adding wire types\n  (agui-dotnet-wire-types), transport/encoding (agui-dotnet-transport), unit tests\n  (agui-dotnet-unit-tests), integration tests (agui-dotnet-integration-tests),\n  cross-language tests (agui-dotnet-cross-language-tests), porting from TS/Python\n  (agui-cross-sdk-parity), adding a GettingStarted sample Step\n  (agui-dotnet-sample-step), SDK docs (agui-dotnet-sdk-docs), AGENTS/Architecture\n  sync (agui-dotnet-agents-sync), the dojo (agui-dojo), review\n  (agui-dotnet-code-review).\n---\n\n# AG-UI .NET SDK — Feature Workflow (Orchestrator)\n\nThis is the **hub** skill. Given a request to build or change a feature in the AG-UI\n.NET SDK (`sdks/dotnet/`), it lays out the correct end-to-end order and **routes the\ndepth of each step to a focused sibling skill**. It does not duplicate their content.\n\nThe SDK has a multi-artifact **definition of done**. An agent working ad hoc forgets\nartifacts — most often cross-language parity, docs, `AGENTS.md`/`docs/architecture.md` sync,\nand `PublicAPI.Unshipped.txt`. Use this skill to avoid that.\n\n## Package map\n\n`sdks/dotnet/src/`:\n\n| Package | Responsibility |\n|---|---|\n| `AGUI.Abstractions` | Wire types: events, messages, tools, capabilities, `AGUIJsonSerializerContext` |\n| `AGUI.Formatting` | JSON formatter + SSE encode/decode |\n| `AGUI.Protobuf` | Protobuf encoding of the protocol |\n| `AGUI.Client` | `AGUIChatClient` (`IChatClient`) + transport negotiation |\n| `AGUI.Server` | Hosting-agnostic agent-side conversion (`ChatResponseUpdate` → events) |\n\nASP.NET hosting glue lives in `samples/AGUI.Samples.Shared` (not a `src/` package).\n`sdks/dotnet/AGENTS.md` and `docs/architecture.md` are the canonical description of\nthe layout and conventions (kept current via `agui-dotnet-agents-sync`); `AGUI.slnx`\nis the ground truth if you need to re-derive the package list.\n\n## Build & test commands\n\n```bash\n# from sdks/dotnet/\ndotnet build sdks/dotnet/AGUI.slnx        # whole solution\ndotnet test  tests/AGUI.Abstractions.UnitTests/   # per-project, fast feedback\n```\n\n`Directory.Build.props` **treats warnings as errors**, and `PublicApiAnalyzers` is on\nfor every `src/` project with a `PublicAPI.Shipped.txt`. **The build fails if you skip\nthe AOT serialization wiring or forget `PublicAPI.Unshipped.txt`** — these are not\noptional polish steps, they are enforced.\n\n## Definition of done (feature checklist)\n\n- [ ] Wire contract understood (matched against TS/Python reference if wire-affecting)\n- [ ] Type/behavior implemented in the **right package** (see map)\n- [ ] AOT serialization wired (`[JsonSerializable]` in `AGUIJsonSerializerContext`, converter case, `[JsonPropertyName]`)\n- [ ] Client/server mapping updated (`AGUI.Client` event→update and/or `AGUI.Server` update→event)\n- [ ] Unit tests (serialization round-trip + behavior)\n- [ ] Integration tests (full pipeline) if it crosses the HTTP/SSE boundary\n- [ ] Cross-language parity tests if wire-affecting\n- [ ] `PublicAPI.Unshipped.txt` updated for every changed public member\n- [ ] Docs updated (docs.ag-ui.com / SDK docs) if user-facing\n- [ ] `AGENTS.md` / `docs/architecture.md` synced if structure/recipe changed\n- [ ] `dotnet build sdks/dotnet/AGUI.slnx` and relevant `dotnet test` projects green\n\n## Ordered workflow → route each step\n\nDo the steps **in this order**. Skip a step only if it genuinely doesn't apply\n(e.g. a non-wire-affecting internal refactor skips cross-language parity).\n\n1. **Understand the wire contract.** Read the TypeScript (and Python) reference for\n   the type/behavior so the .NET shape matches the spec. Porting an existing feature\n   from another SDK? → **`agui-cross-sdk-parity`**.\n\n2. **Implement the type/behavior in the right package.**\n   - New/changed wire type (event, message, tool, capability) → **`agui-dotnet-wire-types`**\n     (covers the `AGUI.Abstractions` recipe: class in `Events/`, `AGUIEventTypes`\n     constant, converter case, AOT registration, `PublicAPI.Unshipped.txt`).\n   - New/changed transport or encoding (SSE, protobuf, formatter) →\n     **`agui-dotnet-transport`** (`AGUI.Formatting`, `AGUI.Protobuf`).\n\n3. **Wire AOT serialization.** Every protocol type goes through\n   `AGUIJsonSerializerContext` — no reflection. `agui-dotnet-wire-types` has the\n   per-type recipe; the build enforces it.\n\n4. **Update client/server mapping.** Server-side `ChatResponseUpdate` → event lives in\n   `AGUI.Server`; client-side event → `ChatResponseUpdate` lives in `AGUI.Client`\n   (`EventStreamConverter`, builders). Update both directions if the wire shape changed.\n\n5. **Unit tests** (round-trip + behavior) → **`agui-dotnet-unit-tests`**.\n\n6. **Integration tests** (HTTP + SSE pipeline, `WebApplicationFactory`,\n   `AGUIChatClient`) → **`agui-dotnet-integration-tests`**. Required when the change\n   crosses the transport boundary.\n\n7. **Cross-language parity tests** (if wire-affecting) →\n   **`agui-dotnet-cross-language-tests`** (`tests/AGUI.CrossLanguage.IntegrationTests`,\n   `CrossLanguage.TestServer`, `CrossLanguage.Vitest`). This is the step agents most\n   often forget — .NET must agree with TS/Python on the bytes.\n\n8. **Update `PublicAPI.Unshipped.txt`** for every changed public member, in each\n   affected `src/` project. The PublicAPI analyzer fails the build otherwise.\n\n9. **Docs** (user-facing change) → **`agui-dotnet-sdk-docs`** (docs.ag-ui.com).\n\n10. **Sync `AGENTS.md` / `docs/architecture.md`** if you changed structure, recipes, or\n    commands → **`agui-dotnet-agents-sync`**. Fix stale package references while here.\n\n11. **Build + test green.** `dotnet build sdks/dotnet/AGUI.slnx`, then the relevant\n    `dotnet test <project>` (unit + integration + cross-language as applicable).\n\n12. **Validate & review.** Run/inspect in the dojo → **`agui-dojo`**; manual UI/docs\n    checks → **`agui-playwright-validate`**; review the change → **`agui-dotnet-code-review`**.\n\n## Routing table (quick reference)\n\n| Step / need | Sibling skill |\n|---|---|\n| Add/modify a wire type | `agui-dotnet-wire-types` |\n| Add/modify transport or encoding | `agui-dotnet-transport` |\n| Port a feature from TS/Python | `agui-cross-sdk-parity` |\n| Write unit tests | `agui-dotnet-unit-tests` |\n| Write integration tests | `agui-dotnet-integration-tests` |\n| Write cross-language tests | `agui-dotnet-cross-language-tests` |\n| Add a GettingStarted sample Step (Server/Client pair) | `agui-dotnet-sample-step` |\n| Update SDK docs site | `agui-dotnet-sdk-docs` |\n| Keep AGENTS.md / docs/architecture.md current | `agui-dotnet-agents-sync` |\n| Run/validate in the dojo | `agui-dojo` |\n| Manual UI/docs validation | `agui-playwright-validate` |\n| Review the change | `agui-dotnet-code-review` |\n\n> The depth of each step lives in the sibling skill it routes to; fall back to the\n> recipes in `AGENTS.md` and the deep content in `docs/architecture.md` for anything a\n> sibling doesn't cover.\n\n## ❌ Anti-patterns\n\n1. **Don't stop at \"it compiles and unit tests pass.\"** Wire-affecting changes are not\n   done until cross-language parity tests and docs are updated.\n2. **Don't put protocol or server code in a sample.** It belongs in `src/`; the server is\n   `AGUI.Server`, hosting glue is in `samples/AGUI.Samples.Shared`, and no `src/` project\n   references ASP.NET.\n3. **Don't skip `PublicAPI.Unshipped.txt` or AOT registration** \"to fix later\" — the\n   warnings-as-errors build will block you immediately.\n4. **Don't do the deep work here.** This skill routes; the depth lives in the sibling\n   skills. Open the relevant one before implementing a step.\n","frontmatter":{"name":"agui-dotnet-feature-workflow","description":"Orchestrator/hub for implementing a feature or change in the AG-UI .NET SDK (sdks/dotnet). USE FOR: \"what's the workflow\", \"what order do I do things in\", \"how do I implement a feature in the .NET SDK\", starting any non-trivial AG-UI .NET SDK change, planning the end-to-end steps and definition-of-done (code + AOT serialization + client/server mapping + unit/integration/cross-language tests + docs + PublicAPI + AGENTS.md sync). DO NOT USE FOR: the deep how-to of a single step — this skill ROUTES to focused siblings: adding wire types (agui-dotnet-wire-types), transport/encoding (agui-dotnet-transport), unit tests (agui-dotnet-unit-tests), integration tests (agui-dotnet-integration-tests), cross-language tests (agui-dotnet-cross-language-tests), porting from TS/Python (agui-cross-sdk-parity), adding a GettingStarted sample Step (agui-dotnet-sample-step), SDK docs (agui-dotnet-sdk-docs), AGENTS/Architecture sync (agui-dotnet-agents-sync), the dojo (agui-dojo), review (agui-dotnet-code-review).\n"},"isInternal":false,"tokens":2167,"sizeBytes":8168},{"name":"wire-format.md","path":".github/skills/agui-dotnet-transport/references/wire-format.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-transport/references/wire-format.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `.github/skills/agui-dotnet-transport/references/wire-format.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-transport/references/wire-format.md)","tokens":300,"sizeBytes":244},{"name":"SKILL.md","path":".github/skills/agui-dotnet-transport/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-transport/SKILL.md","title":"agui-dotnet-transport","category":"anthropic-skill","format":"markdown","content":"---\nname: agui-dotnet-transport\ndescription: >\n  Add or modify a wire transport / event-stream encoding in the AG-UI .NET SDK — the protobuf\n  codec, the SSE format, content negotiation, the JsonElement-to-protobuf Value bridge, or a brand\n  new encoding — while preserving Native AOT compatibility and byte-level wire compatibility with\n  @ag-ui/proto. USE FOR: working on AGUI.Formatting / AGUI.Protobuf, IAGUIEventStreamFormatter,\n  transport content negotiation, the JsonElement-to-google.protobuf.Value bridge, SSE or protobuf\n  framing, server formatter registration / AGUIResults.Events negotiation. DO NOT USE FOR: adding a new wire event\n  TYPE (use agui-dotnet-wire-types), writing tests (use agui-dotnet-integration-tests).\n---\n\n# AG-UI .NET Transport & Encoding\n\nEncodes the non-obvious design constraints of the AG-UI .NET transport layer, discovered while\nbuilding protobuf support. Apply when adding/changing an encoding or the negotiation that selects\none. Read `references/wire-format.md` before touching the protobuf codec or framing.\n\n## Transport architecture\n\nOne bidirectional abstraction, `IAGUIEventStreamFormatter` (in `AGUI.Formatting`), serves every\ntransport and both directions:\n\n| Member | Role |\n|--------|------|\n| `MediaType` | Advertised in client `Accept` and written as server `Content-Type`. Registration order = preference. |\n| `CanRead(contentType)` | Client picks the decoder for the response `Content-Type`. |\n| `ReadAsync(body, ct)` | Decode body → `IAsyncEnumerable<BaseEvent>`. |\n| `WriteAsync(events, output, ct)` | Encode events → body. |\n\n`SseEventStreamFormatter` (`text/event-stream`) is the always-available default;\n`ProtobufEventStreamFormatter` (`ProtobufEventStreamFormatter.ProtobufMediaType`) is opt-in.\n\n**Client negotiation** = `DelegatingHandler` + decode helper:\n- `AGUIEventStreamHandler` (public, in `AGUI.Client`) advertises every registered formatter's\n  `MediaType` in `Accept`, then inspects the response `Content-Type`, finds the first `CanRead`\n  formatter, and records it on the request. The body is left untouched for lazy streaming.\n- `AGUIResponseExtensions.ReadAGUIEventStreamAsync` reads that recorded formatter (falling back to\n  SSE) and decodes. The SDK ships no `IHttpClientFactory` integration: a caller that wants protobuf\n  wires the handler into its own `HttpClient`, and constructs `AGUIChatClient` from\n  `AGUIChatClientOptions`.\n\n**Server negotiation** = `AGUIResults.Events` (samples `AGUI.Samples.Shared`): collects registered\n`IAGUIEventStreamFormatter` services (+ built-in SSE), then picks protobuf **only when its media\ntype is explicitly present** in `Accept` with non-zero quality, else SSE for `text/event-stream`/\nwildcard/absent, else `406`. Mirrors `preferredMediaTypes(accept, [proto])` in `@ag-ui/encoder`.\nA server opts in by registering the formatter (for example,\n`services.AddSingleton<IAGUIEventStreamFormatter, ProtobufEventStreamFormatter>()`).\n\n## Wire format facts\n\n- Protobuf media type: `application/vnd.ag-ui.event+proto` (`ProtobufEventStreamFormatter.ProtobufMediaType`).\n- Framing: **4-byte big-endian `uint32` length prefix + protobuf message bytes**, per event —\n  matches `@ag-ui/encoder` `encodeProtobuf` (`dataView.setUint32(0, length, false)`). See\n  `AGUIProtobuf.WriteFramed` / `ReadFramedAsync`.\n- `Encode`/`Decode` = single message, no length prefix (mirror TS `proto.encode`/`proto.decode`).\n- Dynamic payloads (state, args, results) use `google.protobuf.Value` (Struct/ListValue/scalars) —\n  **never `Any` and never a JSON-string field**.\n\n## The CRITICAL Native AOT rule\n\nImplement the `JsonElement` <-> `google.protobuf.Value` bridge **by hand over the generated\nWellKnownTypes** (`ProtoValueConverter`). **NEVER** use Google.Protobuf's reflection-based\n`JsonFormatter`/`JsonParser` or any descriptor reflection API — they are not trim/AOT safe and the\npackage multi-targets `net10/9/8/netstandard2.0/net472`.\n\n- **Number caveat**: `Value` is double-only. `long`/`decimal` beyond 2^53 lose precision on round\n  trip. This is intentional — it matches the JS `@ag-ui/proto` limitation.\n\n## Schema-first extension\n\nThe `.proto` schema is **canonical** and lives in the TS package. `AGUI.Protobuf.csproj`\n`<Protobuf>` references `sdks/typescript/packages/proto/src/proto/*.proto` directly\n(`csharp_namespace = AGUI.ProtocolBuffers`, generated types `Access=\"Internal\"`) — **do not fork or\ncopy it**. To add a wire-representable event:\n\n1. Extend the shared `.proto` (coordinated across all SDKs — it is the cross-language contract).\n2. Add a mapper case in `ProtoEventMapper` (event oneof) / `ProtoMessageMapper` (messages),\n   mirroring `sdks/typescript/packages/proto/src/proto.ts` reshaping verbatim.\n\nSubset coverage is intentional: .NET-only events that have no wire representation throw\n`NotSupportedException` from the mapper's `default` case. Don't invent a wire shape unilaterally.\n\n## How to verify\n\n- **Byte-parity** against `@ag-ui/proto` via the cross-language tests (see\n  `agui-dotnet-integration-tests` and `sdks/dotnet/docs/cross-language-testing.md`). The JSON\n  compatibility fixtures in `tests/AGUI.Abstractions.UnitTests/Compatibility/` guard SSE drift.\n- **Multi-TFM AOT build**: `dotnet build` from `sdks/dotnet/` (targets net10/9/8/netstandard2.0/\n  net472; warnings are errors). Update `PublicAPI.Unshipped.txt` for any public surface change.\n\n## ❌ Anti-patterns\n\n1. **Don't embed JSON-as-string inside a `Value`.** Map structured payloads recursively to\n   Struct/ListValue/scalars via `ProtoValueConverter`. A string field breaks @ag-ui/proto parity.\n2. **Don't use `JsonFormatter`/`JsonParser`/descriptor reflection.** Not AOT-safe — hand-write the\n   bridge over generated WellKnownTypes.\n3. **Don't copy or fork the `.proto`.** Reference the canonical TS schema from the `.csproj` so the\n   codec can't drift from the wire contract.\n4. **Don't make `AGUI.Protobuf` depend on `AGUI.Client` or the hosting/server package.** The codec\n   stays transport-neutral; it references only `AGUI.Abstractions` + `AGUI.Formatting`.\n5. **Don't change framing or use little-endian.** Length is big-endian `uint32`; both SDKs depend\n   on exact byte layout.\n\n## References\n\n- **Wire format & codec internals** (framing, oneof mapping, Value bridge, negotiation parity):\n  [references/wire-format.md](references/wire-format.md)\n","frontmatter":{"name":"agui-dotnet-transport","description":"Add or modify a wire transport / event-stream encoding in the AG-UI .NET SDK — the protobuf codec, the SSE format, content negotiation, the JsonElement-to-protobuf Value bridge, or a brand new encoding — while preserving Native AOT compatibility and byte-level wire compatibility with @ag-ui/proto. USE FOR: working on AGUI.Formatting / AGUI.Protobuf, IAGUIEventStreamFormatter, transport content negotiation, the JsonElement-to-google.protobuf.Value bridge, SSE or protobuf framing, server formatter registration / AGUIResults.Events negotiation. DO NOT USE FOR: adding a new wire event TYPE (use agui-dotnet-wire-types), writing tests (use agui-dotnet-integration-tests).\n"},"isInternal":false,"tokens":1576,"sizeBytes":6390},{"name":"SKILL.md","path":".github/skills/agui-dotnet-wire-types/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-wire-types/SKILL.md","title":"agui-dotnet-wire-types","category":"anthropic-skill","format":"markdown","content":"# agui-dotnet-wire-types\n\nPath: `.github/skills/agui-dotnet-wire-types/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-wire-types/SKILL.md)","tokens":300,"sizeBytes":218},{"name":"SKILL.md","path":".github/skills/agui-playwright-validate/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-playwright-validate/SKILL.md","title":"agui-playwright-validate","category":"anthropic-skill","format":"markdown","content":"# agui-playwright-validate\n\nPath: `.github/skills/agui-playwright-validate/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-playwright-validate/SKILL.md)","tokens":300,"sizeBytes":224},{"name":"flight_schema.json","path":"integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/flight_schema.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/flight_schema.json","title":"A2ui_fixed_schema_schemas Skill","category":"anthropic-skill","format":"json","content":"# A2ui_fixed_schema_schemas Skill\n\nPath: `integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/flight_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/flight_schema.json)","tokens":300,"sizeBytes":311},{"name":"hotel_schema.json","path":"integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/hotel_schema.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/hotel_schema.json","title":"A2ui_fixed_schema_schemas Skill","category":"anthropic-skill","format":"json","content":"# A2ui_fixed_schema_schemas Skill\n\nPath: `integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/hotel_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/hotel_schema.json)","tokens":300,"sizeBytes":309},{"name":"flight_schema.json","path":"integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/flight_schema.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/flight_schema.json","title":"Schemas Skill","category":"anthropic-skill","format":"json","content":"# Schemas Skill\n\nPath: `integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/flight_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/flight_schema.json)","tokens":300,"sizeBytes":297},{"name":"hotel_schema.json","path":"integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/hotel_schema.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/hotel_schema.json","title":"Schemas Skill","category":"anthropic-skill","format":"json","content":"# Schemas Skill\n\nPath: `integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/hotel_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/hotel_schema.json)","tokens":300,"sizeBytes":295},{"name":"SKILL.md","path":"sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-client-tools/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-client-tools/SKILL.md","title":"agui-dotnet-client-tools","category":"anthropic-skill","format":"markdown","content":"# agui-dotnet-client-tools\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-client-tools/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-client-tools/SKILL.md)","tokens":300,"sizeBytes":274},{"name":"SKILL.md","path":"sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-human-in-the-loop/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-human-in-the-loop/SKILL.md","title":"agui-dotnet-human-in-the-loop","category":"anthropic-skill","format":"markdown","content":"# agui-dotnet-human-in-the-loop\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-human-in-the-loop/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-human-in-the-loop/SKILL.md)","tokens":300,"sizeBytes":289},{"name":"SKILL.md","path":"sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-multimodal/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-multimodal/SKILL.md","title":"agui-dotnet-multimodal","category":"anthropic-skill","format":"markdown","content":"# agui-dotnet-multimodal\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-multimodal/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-multimodal/SKILL.md)","tokens":300,"sizeBytes":268},{"name":"SKILL.md","path":"sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-protobuf/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-protobuf/SKILL.md","title":"agui-dotnet-protobuf","category":"anthropic-skill","format":"markdown","content":"# agui-dotnet-protobuf\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-protobuf/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-protobuf/SKILL.md)","tokens":300,"sizeBytes":262},{"name":"SKILL.md","path":"sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-reasoning/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-reasoning/SKILL.md","title":"agui-dotnet-reasoning","category":"anthropic-skill","format":"markdown","content":"# agui-dotnet-reasoning\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-reasoning/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-reasoning/SKILL.md)","tokens":300,"sizeBytes":265},{"name":"SKILL.md","path":"sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-server-tools/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-server-tools/SKILL.md","title":"agui-dotnet-server-tools","category":"anthropic-skill","format":"markdown","content":"# agui-dotnet-server-tools\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-server-tools/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-server-tools/SKILL.md)","tokens":300,"sizeBytes":274},{"name":"SKILL.md","path":"sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-shared-state/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-shared-state/SKILL.md","title":"agui-dotnet-shared-state","category":"anthropic-skill","format":"markdown","content":"# agui-dotnet-shared-state\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-shared-state/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-shared-state/SKILL.md)","tokens":300,"sizeBytes":274},{"name":"SKILL.md","path":"sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-streaming-chat/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-streaming-chat/SKILL.md","title":"agui-dotnet-streaming-chat","category":"anthropic-skill","format":"markdown","content":"# agui-dotnet-streaming-chat\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-streaming-chat/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-streaming-chat/SKILL.md)","tokens":300,"sizeBytes":280},{"name":"SKILL.md","path":"sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-troubleshoot/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-troubleshoot/SKILL.md","title":"agui-dotnet-troubleshoot","category":"anthropic-skill","format":"markdown","content":"# agui-dotnet-troubleshoot\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-troubleshoot/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-troubleshoot/SKILL.md)","tokens":300,"sizeBytes":274},{"name":"CHANGELOG.md","path":"sdks/typescript/packages/a2ui-toolkit/CHANGELOG.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/CHANGELOG.md","title":"A2ui-toolkit Skill","category":"anthropic-skill","format":"markdown","content":"# A2ui-toolkit Skill\n\nPath: `sdks/typescript/packages/a2ui-toolkit/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/CHANGELOG.md)","tokens":300,"sizeBytes":222},{"name":"package.json","path":"sdks/typescript/packages/a2ui-toolkit/package.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/package.json","title":"A2ui-toolkit Skill","category":"anthropic-skill","format":"json","content":"# A2ui-toolkit Skill\n\nPath: `sdks/typescript/packages/a2ui-toolkit/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/package.json)","tokens":300,"sizeBytes":222},{"name":"tsconfig.json","path":"sdks/typescript/packages/a2ui-toolkit/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/tsconfig.json","title":"A2ui-toolkit Skill","category":"anthropic-skill","format":"json","content":"# A2ui-toolkit Skill\n\nPath: `sdks/typescript/packages/a2ui-toolkit/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/tsconfig.json)","tokens":300,"sizeBytes":224},{"name":"CHANGELOG.md","path":"sdks/typescript/packages/cli/CHANGELOG.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/CHANGELOG.md","title":"Cli Skill","category":"anthropic-skill","format":"markdown","content":"# Cli Skill\n\nPath: `sdks/typescript/packages/cli/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/CHANGELOG.md)","tokens":300,"sizeBytes":195},{"name":"package.json","path":"sdks/typescript/packages/cli/package.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/package.json","title":"Cli Skill","category":"anthropic-skill","format":"json","content":"# Cli Skill\n\nPath: `sdks/typescript/packages/cli/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/package.json)","tokens":300,"sizeBytes":195},{"name":"tsconfig.json","path":"sdks/typescript/packages/cli/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/tsconfig.json","title":"Cli Skill","category":"anthropic-skill","format":"json","content":"# Cli Skill\n\nPath: `sdks/typescript/packages/cli/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/tsconfig.json)","tokens":300,"sizeBytes":197},{"name":"CHANGELOG.md","path":"sdks/typescript/packages/client/CHANGELOG.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/CHANGELOG.md","title":"Client Skill","category":"anthropic-skill","format":"markdown","content":"# Client Skill\n\nPath: `sdks/typescript/packages/client/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/CHANGELOG.md)","tokens":300,"sizeBytes":204},{"name":"DEPRECATIONS.md","path":"sdks/typescript/packages/client/DEPRECATIONS.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/DEPRECATIONS.md","title":"Client Skill","category":"anthropic-skill","format":"markdown","content":"# Client Skill\n\nPath: `sdks/typescript/packages/client/DEPRECATIONS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/DEPRECATIONS.md)","tokens":300,"sizeBytes":210},{"name":"package.json","path":"sdks/typescript/packages/client/package.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/package.json","title":"Client Skill","category":"anthropic-skill","format":"json","content":"# Client Skill\n\nPath: `sdks/typescript/packages/client/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/package.json)","tokens":300,"sizeBytes":204},{"name":"strands-native-resume.json","path":"sdks/typescript/packages/client/src/apply/__tests__/fixtures/strands-native-resume.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/src/apply/__tests__/fixtures/strands-native-resume.json","title":"Fixtures Skill","category":"anthropic-skill","format":"json","content":"# Fixtures Skill\n\nPath: `sdks/typescript/packages/client/src/apply/__tests__/fixtures/strands-native-resume.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/src/apply/__tests__/fixtures/strands-native-resume.json)","tokens":300,"sizeBytes":292},{"name":"tsconfig.json","path":"sdks/typescript/packages/client/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/tsconfig.json","title":"Client Skill","category":"anthropic-skill","format":"json","content":"# Client Skill\n\nPath: `sdks/typescript/packages/client/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/tsconfig.json)","tokens":300,"sizeBytes":206},{"name":"CHANGELOG.md","path":"sdks/typescript/packages/core/CHANGELOG.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/CHANGELOG.md","title":"Core Skill","category":"anthropic-skill","format":"markdown","content":"# Core Skill\n\nPath: `sdks/typescript/packages/core/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/CHANGELOG.md)","tokens":300,"sizeBytes":198},{"name":"package.json","path":"sdks/typescript/packages/core/package.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/package.json","title":"Core Skill","category":"anthropic-skill","format":"json","content":"# Core Skill\n\nPath: `sdks/typescript/packages/core/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/package.json)","tokens":300,"sizeBytes":198},{"name":"tsconfig.json","path":"sdks/typescript/packages/core/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/tsconfig.json","title":"Core Skill","category":"anthropic-skill","format":"json","content":"# Core Skill\n\nPath: `sdks/typescript/packages/core/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/tsconfig.json)","tokens":300,"sizeBytes":200},{"name":"CHANGELOG.md","path":"sdks/typescript/packages/encoder/CHANGELOG.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/CHANGELOG.md","title":"Encoder Skill","category":"anthropic-skill","format":"markdown","content":"# Encoder Skill\n\nPath: `sdks/typescript/packages/encoder/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/CHANGELOG.md)","tokens":300,"sizeBytes":207},{"name":"package.json","path":"sdks/typescript/packages/encoder/package.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/package.json","title":"Encoder Skill","category":"anthropic-skill","format":"json","content":"# Encoder Skill\n\nPath: `sdks/typescript/packages/encoder/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/package.json)","tokens":300,"sizeBytes":207},{"name":"tsconfig.json","path":"sdks/typescript/packages/encoder/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/tsconfig.json","title":"Encoder Skill","category":"anthropic-skill","format":"json","content":"# Encoder Skill\n\nPath: `sdks/typescript/packages/encoder/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/tsconfig.json)","tokens":300,"sizeBytes":209},{"name":"CHANGELOG.md","path":"sdks/typescript/packages/proto/CHANGELOG.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/CHANGELOG.md","title":"Proto Skill","category":"anthropic-skill","format":"markdown","content":"# Proto Skill\n\nPath: `sdks/typescript/packages/proto/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/CHANGELOG.md)","tokens":300,"sizeBytes":201},{"name":"package.json","path":"sdks/typescript/packages/proto/package.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/package.json","title":"Proto Skill","category":"anthropic-skill","format":"json","content":"# Proto Skill\n\nPath: `sdks/typescript/packages/proto/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/package.json)","tokens":300,"sizeBytes":201},{"name":"tsconfig.json","path":"sdks/typescript/packages/proto/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/tsconfig.json","title":"Proto Skill","category":"anthropic-skill","format":"json","content":"# Proto Skill\n\nPath: `sdks/typescript/packages/proto/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/tsconfig.json)","tokens":300,"sizeBytes":203},{"name":"tsconfig.typecheck.json","path":"sdks/typescript/packages/proto/tsconfig.typecheck.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/tsconfig.typecheck.json","title":"Proto Skill","category":"anthropic-skill","format":"json","content":"# Proto Skill\n\nPath: `sdks/typescript/packages/proto/tsconfig.typecheck.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/tsconfig.typecheck.json)","tokens":300,"sizeBytes":223},{"name":"a2ui-runtime-and-renderer.md","path":"skills/ag-ui-a2ui-integration/references/a2ui-runtime-and-renderer.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/references/a2ui-runtime-and-renderer.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `skills/ag-ui-a2ui-integration/references/a2ui-runtime-and-renderer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/references/a2ui-runtime-and-renderer.md)","tokens":300,"sizeBytes":258},{"name":"framework-adapters.md","path":"skills/ag-ui-a2ui-integration/references/framework-adapters.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/references/framework-adapters.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `skills/ag-ui-a2ui-integration/references/framework-adapters.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/references/framework-adapters.md)","tokens":300,"sizeBytes":244},{"name":"verification.md","path":"skills/ag-ui-a2ui-integration/references/verification.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/references/verification.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `skills/ag-ui-a2ui-integration/references/verification.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/references/verification.md)","tokens":300,"sizeBytes":232},{"name":"SKILL.md","path":"skills/ag-ui-a2ui-integration/SKILL.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/SKILL.md","title":"ag-ui-a2ui-integration","category":"anthropic-skill","format":"markdown","content":"---\nname: ag-ui-a2ui-integration\ndescription: \"Use when adding A2UI rendering to any AG-UI-supported framework or custom AG-UI application, scaffolding an AG-UI app that should render A2UI, adapting an AG-UI integration to emit A2UI surfaces, or wiring the AG-UI A2UI middleware/toolkit with a compatible renderer.\"\nversion: 1.1.0\n---\n\n# AG-UI + A2UI Integration Skill\n\n## Overview\n\nUse this skill to add A2UI rendering to an AG-UI application. Treat AG-UI as\nthe transport and agent integration layer, `@ag-ui/a2ui-middleware` as the\nserver-side bridge that detects and paints A2UI operations, and A2UI as the UI\npayload format that the client renderer displays.\n\nThis is a developer-facing skill artifact. It is meant to be loaded by coding\nagents and used against a real app or repo, not published as a docs page.\n\n## When to Use\n\n- Adding A2UI rendering to an existing AG-UI app.\n- Creating an AG-UI quickstart that should display A2UI surfaces.\n- Connecting any AG-UI-supported framework or custom AG-UI agent to an\n  A2UI-capable frontend.\n- Adding or extending an A2UI component catalog.\n- Debugging why an A2UI surface does not render or why a user action does not\n  flow back to the agent.\n\n## When NOT to Use\n\n- For AG-UI protocol event semantics only, use the AG-UI protocol skill or\n  protocol docs.\n- For A2UI renderer internals outside an AG-UI app, use the A2UI renderer\n  docs or renderer-specific skills.\n- For generic CopilotKit frontend work without A2UI, use CopilotKit-specific\n  setup and React skills.\n\n## Workflow\n\n1. Inspect the app shape: framework adapter, AG-UI agent endpoint, runtime\n   host, frontend shell, and any existing A2UI renderer/catalog.\n2. Decide the A2UI mode before editing code:\n   - Fixed schema: backend tools return an `a2ui_operations` envelope with\n     `createSurface`, `updateComponents`, and `updateDataModel`.\n   - Dynamic schema: a framework A2UI tool (`generate_a2ui`) delegates to a\n     sub-agent that streams `render_a2ui` args through `A2UIMiddleware`.\n3. Select framework-specific wiring from\n   `references/framework-adapters.md`, or use that reference to find the\n   closest AG-UI integration pattern. Preserve the app's existing agent\n   architecture.\n4. Wire server middleware/runtime and client renderer using\n   `references/a2ui-runtime-and-renderer.md`. Avoid double-applying\n   `A2UIMiddleware`; use either runtime-level A2UI config or per-agent\n   `agent.use(new A2UIMiddleware(...))` for a given agent.\n5. Register a catalog on the client. With CopilotKit >= 1.61.2, forwarding it to\n   the provider (`a2ui={{ catalog }}`) auto-enables A2UI and auto-derives\n   `defaultCatalogId` from the catalog's id. Only when you are not forwarding a\n   catalog, ensure the middleware or adapter sets a `defaultCatalogId` matching\n   the renderer-registered catalog.\n6. Verify the streaming path with `references/verification.md`: AG-UI stream,\n   `a2ui-surface` activity snapshots or `a2ui_operations`, rendered A2UI\n   surface, and a user interaction flowing back through AG-UI.\n\n## AG-UI Framework Support\n\nThis skill is not limited to the framework examples below. For any target\nframework, first check the AG-UI repository's `integrations/` directory, the\nAG-UI docs, the framework adapter's A2UI files, and the current CLI source. If\nAG-UI supports the framework, use that integration's documented package,\nendpoint helper, A2UI tool factory, or scaffold path. If there is no framework\nA2UI adapter, implement the custom AG-UI agent path, return `a2ui_operations`\nfrom backend tools for fixed layouts, and keep the middleware/client wiring the\nsame.\n\n## Common AG-UI CLI Flags\n\nUse the CLI flags that exist in `sdks/typescript/packages/cli/src/index.ts`.\nThe table is a quick reference for known scaffold paths, not the full AG-UI\nsupport matrix. Do not invent flags.\n\n| Framework            | CLI flag         |\n| -------------------- | ---------------- |\n| ADK                  | `--adk`          |\n| LangGraph Python     | `--langgraph-py` |\n| LangGraph JavaScript | `--langgraph-js` |\n| CrewAI Flows         | `--crewai-flows` |\n| Mastra               | `--mastra`       |\n| Pydantic AI          | `--pydantic-ai`  |\n| LlamaIndex           | `--llamaindex`   |\n| Agno                 | `--agno`         |\n| AG2                  | `--ag2`          |\n\nStrands has AG-UI integration packages and examples, but no Strands CLI flag\nis present in the current AG-UI CLI source. Use the Strands integration docs\ninstead of guessing a scaffold command.\n\n## Key Rules\n\n- Keep the integration AG-UI-first for every supported framework. CopilotKit is\n  a common runtime/renderer path for web apps, but AG-UI owns the middleware,\n  framework adapters, and wire events.\n- Enable A2UI on both sides: `A2UIMiddleware` or runtime A2UI config on the\n  server, and an A2UI-capable renderer/catalog on the client.\n- For dynamic schema, prefer the framework adapter's A2UI tool factory or\n  auto-injection path. The model should call `generate_a2ui`; the sub-agent\n  should stream `render_a2ui` args so the middleware can progressively paint.\n- For fixed schema, return an `a2ui_operations` envelope from backend tools\n  rather than asking the model to invent component trees.\n- Emit `createSurface` once per `surfaceId`; use update operations for later\n  changes.\n- Do not let the model invent catalog ids. When the client forwards a catalog to\n  the provider (CopilotKit >= 1.61.2), its `catalogId` is derived automatically;\n  otherwise the host/middleware/adapter should stamp a `defaultCatalogId` that\n  matches the client-registered catalog.\n- Preserve AG-UI run boundaries and error events. Do not swallow server or\n  stream errors.\n- Verify with a real browser or client run when possible. A static typecheck is\n  not enough for streaming UI work.\n\n## References\n\n- `references/framework-adapters.md` - framework-specific AG-UI adapter\n  patterns.\n- `references/a2ui-runtime-and-renderer.md` - server/client A2UI wiring and\n  catalog patterns.\n- `references/verification.md` - checks to confirm the integration works.\n- `sources.md` - source files and docs used by this skill.\n","frontmatter":{"name":"ag-ui-a2ui-integration","description":"Use when adding A2UI rendering to any AG-UI-supported framework or custom AG-UI application, scaffolding an AG-UI app that should render A2UI, adapting an AG-UI integration to emit A2UI surfaces, or wiring the AG-UI A2UI middleware/toolkit with a compatible renderer.","version":"1.1.0"},"isInternal":false,"tokens":1512,"sizeBytes":6131},{"name":"sources.md","path":"skills/ag-ui-a2ui-integration/sources.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/sources.md","title":"Ag-ui-a2ui-integration Skill","category":"anthropic-skill","format":"markdown","content":"# Ag-ui-a2ui-integration Skill\n\nPath: `skills/ag-ui-a2ui-integration/sources.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/skills/ag-ui-a2ui-integration/sources.md)","tokens":300,"sizeBytes":212},{"name":"project-rules.mdc","path":"sdks/typescript/.cursor/rules/project-rules.mdc","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/.cursor/rules/project-rules.mdc","title":"Cursor Rule: project-rules","category":"cursor-rule","format":"mdc","content":"# Cursor Rule: project-rules\n\nPath: `sdks/typescript/.cursor/rules/project-rules.mdc`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/.cursor/rules/project-rules.mdc)","tokens":300,"sizeBytes":224},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# Claude Agent Guidelines & System Prompt\n\nPath: `CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/CLAUDE.md)","tokens":300,"sizeBytes":161},{"name":"marketplace.json","path":".claude-plugin/marketplace.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.claude-plugin/marketplace.json","title":"Claude Plugin Marketplace Catalog","category":"marketplace","format":"json","content":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.claude-plugin/marketplace.json)","tokens":300,"sizeBytes":199},{"name":"plugin.json","path":"sdks/dotnet/plugins/ag-ui-dotnet/.claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/.claude-plugin/plugin.json","title":"claude-plugin Plugin Manifest","category":"plugin-manifest","format":"json","content":"# claude-plugin Plugin Manifest\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/.claude-plugin/plugin.json)","tokens":300,"sizeBytes":251},{"name":"plugin.json","path":"sdks/dotnet/plugins/ag-ui-dotnet/plugin.json","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/plugin.json","title":"ag-ui-dotnet Plugin Manifest","category":"plugin-manifest","format":"json","content":"# ag-ui-dotnet Plugin Manifest\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/plugin.json)","tokens":300,"sizeBytes":220},{"name":"README.md","path":"sdks/dotnet/plugins/ag-ui-dotnet/README.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/README.md","title":"ag-ui-dotnet Documentation","category":"plugin-manifest","format":"markdown","content":"# ag-ui-dotnet Documentation\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/README.md)","tokens":300,"sizeBytes":214},{"name":"README.md","path":"sdks/typescript/packages/a2ui-toolkit/README.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/README.md","title":"a2ui-toolkit Documentation","category":"plugin-manifest","format":"markdown","content":"# a2ui-toolkit Documentation\n\nPath: `sdks/typescript/packages/a2ui-toolkit/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/README.md)","tokens":300,"sizeBytes":224},{"name":"README.md","path":"sdks/typescript/packages/cli/README.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/README.md","title":"cli Documentation","category":"plugin-manifest","format":"markdown","content":"# cli Documentation\n\nPath: `sdks/typescript/packages/cli/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/README.md)","tokens":300,"sizeBytes":197},{"name":"README.md","path":"sdks/typescript/packages/client/README.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/README.md","title":"client Documentation","category":"plugin-manifest","format":"markdown","content":"# client Documentation\n\nPath: `sdks/typescript/packages/client/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/client/README.md)","tokens":300,"sizeBytes":206},{"name":"README.md","path":"sdks/typescript/packages/core/README.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/README.md","title":"core Documentation","category":"plugin-manifest","format":"markdown","content":"# core Documentation\n\nPath: `sdks/typescript/packages/core/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/core/README.md)","tokens":300,"sizeBytes":200},{"name":"README.md","path":"sdks/typescript/packages/encoder/README.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/README.md","title":"encoder Documentation","category":"plugin-manifest","format":"markdown","content":"# encoder Documentation\n\nPath: `sdks/typescript/packages/encoder/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/encoder/README.md)","tokens":300,"sizeBytes":209},{"name":"README.md","path":"sdks/typescript/packages/proto/README.md","rawUrl":"https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/README.md","title":"proto Documentation","category":"plugin-manifest","format":"markdown","content":"# proto Documentation\n\nPath: `sdks/typescript/packages/proto/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/proto/README.md)","tokens":300,"sizeBytes":203}],"systemPromptSnippet":"<yakaai_skills repo=\"ag-ui-protocol/ag-ui\">\n<!-- File: AGENTS.md (Tokens: ~300 | Category: root-instruction) -->\n# AI Agent Protocol & Instructions\n\nPath: `AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/AGENTS.md)\n\n<!-- File: .github/skills/agui-cross-sdk-parity/SKILL.md (Tokens: ~2053 | Category: anthropic-skill) -->\n---\nname: agui-cross-sdk-parity\ndescription: >\n  Keep the AG-UI .NET SDK at feature and wire-format PARITY with the canonical\n  reference SDKs (TypeScript is the source of truth; Python is types/encoder only).\n  USE FOR: porting a feature/event/behavior that landed in the TS (or Python) SDK\n  into .NET, verifying the .NET wire format (JSON, SSE, protobuf) matches the\n  reference, locating where the reference implementation and compatibility fixtures\n  live, mapping a TS concept to the .NET event/client/encoder model, resolving an\n  upstream protocol fix (e.g. a Microsoft.Extensions.AI / Microsoft Agent Framework\n  issue) that needs a .NET counterpart, deciding which .NET package owns a change.\n  DO NOT USE FOR: the mechanics of writing a specific test (use agui-dotnet-unit-tests\n  for serialization round-trips, agui-dotnet-integration-tests for cross-language /\n  E2E harness mechanics, agui-dotnet-wire-types for JSON/proto type rules,\n  agui-dotnet-transport for SSE/HTTP transport details). This skill is about the\n  PARITY PROCESS and where the reference lives, not test authoring.\n---\n\n# AG-UI Cross-SDK Parity\n\nThe .NET SDK implements an upstream, multi-language protocol. This skill encodes the\n**parity process**: which SDK is authoritative, where its reference and fixtures live,\nhow to map reference concepts onto the .NET model, and how parity is guarded.\n\n## Parity Principle\n\n- **TypeScript is canonical** for wire format AND client run-loop behavior. When two\n  SDKs disagree, match TS.\n- **Python is types + encoder only.** It has `core` (types/events) and an `encoder`,\n  but **no client run-loop and no protobuf** (`sdks/python/ag_ui/` has `core/` and\n  `encoder/` but no `client/` or `proto/`). Use it only as a secondary check on\n  type/JSON shape — never for run-loop or proto questions.\n- Upstream protocol or SDK fixes (in the TS client run-loop, or in\n  Microsoft.Extensions.AI / Microsoft Agent Framework) sometimes need a .NET\n  counterpart; treat the TypeScript change as the contract to match.\n\n## Where the Reference Lives\n\n| Concern | TypeScript reference (source of truth) | .NET package it maps to |\n|---|---|---|\n| Event & type definitions | `sdks/typescript/packages/core/src/events.ts`, `types.ts`, `event-factories.ts` | `sdks/dotnet/src/AGUI.Abstractions/Events/`, `Messages/` |\n| Client run-loop / transport | `sdks/typescript/packages/client/src/run/`, `apply/`, `agent/`, `transform/` | `sdks/dotnet/src/AGUI.Client/` (`AGUIChatClient.cs`, `AGUIHttpTransport.cs`, `EventStreamConverter.cs`, `ToolCallBuilder.cs`) |\n| SSE / JSON wire framing | `sdks/typescript/packages/encoder/src/encoder.ts` | `sdks/dotnet/src/AGUI.Formatting/`, `AGUI.Abstractions/Serialization/` |\n| Protobuf wire format | `sdks/typescript/packages/proto/src/proto/events.proto`, `types.proto`, `patch.proto` | `sdks/dotnet/src/AGUI.Protobuf/` (`ProtoEventMapper.cs`, `ProtoMessageMapper.cs`) |\n\nThe `src/` packages are **AGUI.Abstractions, AGUI.Formatting, AGUI.Protobuf, AGUI.Client,\nAGUI.Server**; `sdks/dotnet/AGENTS.md` and `docs/architecture.md` are the canonical\ndescription of the layout and conventions.\n\n## Porting Workflow\n\n1. **Locate the feature in TS.** Find the change in `packages/core` (a new event/type),\n   `packages/client` (run-loop / event-application behavior), or\n   `packages/proto`+`encoder` (wire framing). Read the TS implementation and its tests\n   to capture the exact contract — field names, ordering, optionality, coalescing rules.\n2. **Identify the wire contract.** Determine the JSON shape, the proto schema impact\n   (if any), and whether client run-loop state changes. Cross-check the JSON property\n   names against `packages/core/src/events.ts`.\n3. **Map to the .NET model and the right package** (table above). Events/types →\n   `AGUI.Abstractions`; run-loop → `AGUI.Client`; SSE/JSON framing → `AGUI.Formatting`;\n   protobuf → `AGUI.Protobuf`. Follow the .NET conventions in `AGENTS.md` (one class\n   per file, `sealed`, source-generated JSON context, `PublicAPI.Unshipped.txt`).\n4. **Implement** the .NET change. For a new event, follow the \"Adding a new event type\"\n   checklist in `AGENTS.md` (class in `Events/`, `AGUIEventTypes` constant,\n   `[JsonSerializable]`, `BaseEventJsonConverter` case, PublicAPI entry).\n5. **Add parity assets** (see next section): a TS-produced JSON fixture under\n   `tests/AGUI.Abstractions.UnitTests/Compatibility/` and/or a cross-language test in\n   `tests/CrossLanguage.Vitest/tests/`.\n6. **Verify byte/semantic parity** — run the compatibility and cross-language tests.\n7. **Update docs.** Refresh `sdks/dotnet/AGENTS.md`, `docs/architecture.md`, and\n   `docs/cross-language-testing.md` if the change alters the model, package layout, or the\n   set of wire-supported events.\n\n## How Parity Is Guarded\n\nFour independent layers catch drift; add to whichever layer the change touches.\n\n- **Compatibility fixtures (catch JSON drift).**\n  `tests/AGUI.Abstractions.UnitTests/Compatibility/` holds TS-produced JSON fixtures\n  (`*-events.json`) loaded via `FixtureLoader` and deserialized into .NET types\n  (`{Category}CompatibilityTest.cs`, e.g. `RunEventsCompatibilityTest`,\n  `ToolCallEventsCompatibilityTest`). A new/changed event shape needs a fixture entry.\n- **Cross-language tests (catch end-to-end drift).** The harness in\n  `tests/CrossLanguage.TestServer/` (C# server) and `tests/CrossLanguage.Vitest/`\n  (TS client driving it) proves real interop — see `sdks/dotnet/docs/cross-language-testing.md`.\n  Scenario specs live in `tests/CrossLanguage.Vitest/tests/` (e.g.\n  `parallel-tool-calls.test.ts`, `state-events.test.ts`, `protobuf-parity.test.ts`).\n- **Protobuf byte-parity tests.** `protobuf-parity.test.ts` plus\n  `tests/AGUI.Protobuf.UnitTests/` verify the binary encoding matches the TS proto output.\n- **Shared cross-language fixtures (catch three-way drift).** `sdks/fixtures/` holds\n  language-neutral JSON that more than one SDK is held to, so an expectation is written down\n  once instead of three times. `null-omission.json` is the first: TypeScript, Python and .NET\n  each deserialize its `input` events, re-serialize through their own producer path, and\n  assert the result equals `expected`. A wire rule that all three must agree on belongs here\n  rather than in one SDK's test tree — see `sdks/fixtures/README.md`.\n\n## Known Parity Boundary: Proto Is a Subset\n\nThe protobuf schema covers a **subset** of events by design. `.NET`-only events\n(`Reasoning*`, `Activity*`, `ToolCallResult`) are not in the proto wire format and\n**throw `NotSupportedException`** when mapped — see `ProtoEventMapper.cs` (the `default`\ncase lists the 16 supported events: RUN_STARTED/FINISHED/ERROR, STEP_STARTED/FINISHED,\nTEXT_MESSAGE_START/CONTENT/END, TOOL_CALL_START/ARGS/END, STATE_SNAPSHOT/DELTA,\nMESSAGES_SNAPSHOT, RAW, CUSTOM) and `ProtoMessageMapper.cs`. This is a **deliberate,\ndocumented boundary** — do not \"fix\" it by inventing proto messages that don't exist in\n`events.proto`. JSON/SSE remains the full-fidelity wire; protobuf is the constrained one.\n\n## Critical Anti-patterns\n\n1. **Never treat .NET as the source of truth.** If the .NET behavior differs from TS,\n   the .NET side is the candidate for change — confirm against `packages/core` /\n   `packages/client` first.\n2. **Never consult Python for run-loop or proto parity.** Python has neither. Use it\n   only as a type/JSON cross-check.\n3. **Never add a proto mapping for a `.NET`-only event** (`Reasoning*`, `Activity*`,\n   `ToolCallResult`). The `NotSupportedException` is intentional.\n4. **Never land a wire change without a parity asset.** A JSON-shape change needs a\n   Compatibility fixture; an interop/behavioral change needs a cross-language test.\n\n## Routing to Sibling Skills\n\nThis skill governs *what* to port and *where the reference is* — delegate test\nmechanics:\n\n- **agui-dotnet-unit-tests** — serialization round-trips and Compatibility fixture tests.\n- **agui-dotnet-integration-tests** — cross-language / E2E harness (TestServer + Vitest).\n- **agui-dotnet-wire-types** — JSON/proto type and serialization-context rules.\n- **agui-dotnet-transport** — SSE / HTTP transport details.\n\n<!-- File: .github/skills/agui-dojo/SKILL.md (Tokens: ~1862 | Category: anthropic-skill) -->\n---\nname: agui-dojo\ndescription: >\n  Run the AG-UI Dojo demo viewer locally and wire the AG-UI .NET SDK in as a dojo\n  integration. USE FOR: starting the dojo app (apps/dojo), running the .NET dojo\n  backend (AGUIDojoServer), registering or modifying the ag-ui-dotnet integration\n  (agents.ts/menu.ts/env.ts/files.json), running the dojo Playwright e2e suite for\n  the .NET integration (agUiDotnetTests), or understanding how dojo-e2e.yml runs it\n  in CI. DO NOT USE FOR: generic Playwright validation of arbitrary pages (use\n  agui-playwright-validate), or the docs site (use agui-dotnet-sdk-docs).\n---\n\n# AG-UI Dojo (.NET integration)\n\nThe **Dojo** is a Next.js \"demo viewer\" (`apps/dojo`) that showcases AG-UI protocol\nfeatures (agentic chat, generative UI, human-in-the-loop, shared state, etc.) against\nmany framework integrations. The AG-UI .NET SDK is one integration, id **`ag-ui-dotnet`**.\n\n## Where the pieces live\n\n| Piece | Path | Role |\n|-------|------|------|\n| Dojo app (frontend) | `apps/dojo` | Next.js viewer, runs on port **9999** |\n| .NET backend | `sdks/dotnet/samples/AGUIClientServer/AGUIDojoServer/` | ASP.NET host exposing AG-UI endpoints, port **8023** |\n| Agent registry | `apps/dojo/src/agents.ts` | `ag-ui-dotnet` → `HttpAgent` per feature |\n| Menu / feature list | `apps/dojo/src/menu.ts` | integration id, name, enabled features |\n| Env config | `apps/dojo/src/env.ts` | `aguiDotnetUrl` ← `AGUI_DOTNET_URL` (default `http://localhost:8023`) |\n| Generated source viewer data | `apps/dojo/src/files.json` | generated, **committed** |\n| Content generator | `apps/dojo/scripts/generate-content-json.ts` | builds `files.json` from `menu.ts` |\n| Prep / run orchestrators | `apps/dojo/scripts/{prep,run}-dojo-everything.js` | install/build + start services |\n| .NET e2e suite | `apps/dojo/e2e/tests/agUiDotnetTests/*.spec.ts` | Playwright tests |\n| CI | `.github/workflows/dojo-e2e.yml` | suite `ag-ui-dotnet` (triggers on `sdks/dotnet/**`) |\n\n## Run the dojo + .NET backend locally\n\nFrom the repo root (the scripts shell out to `git rev-parse`):\n\n```bash\npnpm install --no-frozen-lockfile\n\n# 1) Prep: builds the .NET backend AND the dojo (use the stable ids)\nnode apps/dojo/scripts/prep-dojo-everything.js --only dojo,ag-ui-dotnet\n\n# 2) Run: starts the dojo (9999) + AGUIDojoServer (8023) together, with LLMock env injected\nnode apps/dojo/scripts/run-dojo-everything.js --only dojo,ag-ui-dotnet\n```\n\n- Browse `http://localhost:9999/ag-ui-dotnet/feature/agentic_chat`.\n- `prep` for `ag-ui-dotnet` runs `dotnet restore && dotnet build` on\n  `AGUIDojoServer/AGUIDojoServer.csproj` in `sdks/dotnet/samples/AGUIClientServer`.\n- `run` for `ag-ui-dotnet` runs `dotnet run --project AGUIDojoServer/AGUIDojoServer.csproj\n  --urls \"http://localhost:8023\" --no-build` — **prep first or there's no build to run**.\n\nStart just the .NET backend by hand (e.g. to debug):\n\n```bash\ncd sdks/dotnet/samples/AGUIClientServer\ndotnet run --project AGUIDojoServer/AGUIDojoServer.csproj --urls \"http://localhost:8023\"\n```\n\nThe backend resolves its `ChatClient` from configuration (`ChatClientAgentFactory.Initialize`):\n`OPENAI_BASE_URL` (any OpenAI-compatible endpoint / LLMock), else `AZURE_OPENAI_ENDPOINT`\n(Entra ID), else public OpenAI with `OPENAI_API_KEY`. `run-dojo-everything.js` injects\n`OPENAI_BASE_URL=http://localhost:5555/v1` and `OPENAI_API_KEY=sk-mock` so it hits the LLMock.\n\n## How the .NET SDK is registered as an integration\n\nEach scenario is an AG-UI endpoint on the .NET host wired to a frontend feature. To add or\nchange a `.NET` dojo scenario, touch these in lockstep:\n\n1. **Backend endpoint** — `AGUIDojoServer/Program.cs`: add `app.MapDojoEndpoint(\"/<feature>\", ChatClientAgentFactory.Create…())`.\n   Agent logic lives in `ChatClientAgentFactory.cs`.\n2. **Agent mapping** — `apps/dojo/src/agents.ts` (`\"ag-ui-dotnet\"` block): add `<feature>: \"<feature>\"`\n   inside `mapAgents`; each maps to `new HttpAgent({ url: \\`${envVars.aguiDotnetUrl}/<feature>\\` })`.\n3. **Menu** — `apps/dojo/src/menu.ts` (`id: \"ag-ui-dotnet\"`): add the feature to `features`.\n4. **Source viewer** — `apps/dojo/scripts/generate-content-json.ts` already maps `ag-ui-dotnet` to\n   `Program.cs` + `ChatClientAgentFactory.cs`; then regenerate `files.json` (below).\n5. **env.ts** — only edit if changing the URL/port; `aguiDotnetUrl`/`AGUI_DOTNET_URL` already exist.\n\nRegenerate the committed source-viewer data after any `menu.ts` change:\n\n```bash\ncd apps/dojo && pnpm generate-content-json   # writes src/files.json\n```\n\n> ⚠️ CI job `check-generated-files` fails if `src/files.json` is stale. Always regenerate and\n> commit it after editing `menu.ts` (or feature/README files).\n\n## Run the .NET e2e suite locally\n\n```bash\ncd apps/dojo/e2e\npnpm install --ignore-scripts\npnpm exec playwright install --with-deps chromium   # first time only\n# dojo (9999) + AGUIDojoServer (8023) must already be running (see above)\nBASE_URL=http://localhost:9999 PLAYWRIGHT_SUITE=ag-ui-dotnet pnpm test -- tests/agUiDotnetTests\n```\n\nTests navigate to `/ag-ui-dotnet/feature/<feature>` and drive the chat UI via page objects in\n`apps/dojo/e2e/featurePages/`.\n\n## How CI runs it (`dojo-e2e.yml`)\n\n- Matrix suite `ag-ui-dotnet`: `test_path: tests/agUiDotnetTests`, `services: [\"dojo\", \"ag-ui-dotnet\"]`,\n  `wait_on: http://localhost:9999,tcp:localhost:8023`.\n- Triggers on `pull_request`/`push` paths including **`sdks/dotnet/**`**.\n- Installs .NET `9.0.x` + `10.0.x`, runs `prep-dojo-everything.js --only` then\n  `run-dojo-everything.js --only`, waits on the ports, then `pnpm test -- tests/agUiDotnetTests`.\n\n## Gotchas\n\n- **Ports are fixed**: dojo `9999`, AGUIDojoServer `8023`. The dojo's `AGUI_DOTNET_URL` must point\n  to `http://localhost:8023` (default in `run-dojo-everything.js` and `env.ts`).\n- **`--no-build` in run** means you must run the prep step first; otherwise the `dotnet run` fails.\n- **LLMock, not a real LLM**: `OPENAI_BASE_URL=http://localhost:5555/v1` + `OPENAI_API_KEY=sk-mock`\n  are injected. Backend tool-rendering scenarios also honor `AG_UI_MOCK_WEATHER=1` for determinism.\n- **`BASE_URL` is required** — `playwright.config.ts` calls `process.exit(1)` if it's unset.\n- **Stale `files.json`** is the most common CI failure after touching `menu.ts` — run\n  `pnpm generate-content-json` and commit the result.\n\n<!-- File: .github/skills/agui-dotnet-agents-sync/SKILL.md (Tokens: ~1390 | Category: anthropic-skill) -->\n---\nname: agui-dotnet-agents-sync\ndescription: >\n  Keep the AG-UI .NET SDK docs (sdks/dotnet/AGENTS.md and docs/architecture.md) in\n  sync with the real code tree after structural changes. USE FOR: \"update\n  AGENTS.md / docs/architecture.md\", \"check the dotnet docs are current\", verifying\n  docs after a .NET SDK refactor (package rename, added/removed project,\n  changed endpoint pattern, new/renamed test project, sample step added, new\n  convention). DO NOT USE FOR: writing product code or tests (follow AGENTS.md\n  itself), Python/TypeScript SDK docs, or generic markdown editing unrelated to\n  the dotnet SDK structure.\n---\n\n# AG-UI .NET SDK — Docs Sync\n\n`sdks/dotnet/AGENTS.md` (coding instructions) and `sdks/dotnet/docs/architecture.md`\n(design overview) describe the SDK's structure, naming, and conventions. They\ndrift silently after refactors because nothing fails the build when prose goes\nstale. This skill reconciles them against the live tree.\n\n> Typical drift this catches: a package rename, a moved/removed project, a changed\n> endpoint pattern, or a new sample step that the prose never caught up with. An agent\n> that edits these files from memory re-introduces the same kind of drift, so always\n> derive the truth from the tree first.\n\n## Process\n\n1. **Establish ground truth from the tree, not from the doc.** The authoritative\n   source is `sdks/dotnet/AGUI.slnx` plus the folder listing — never the prose\n   you are about to edit.\n   - Projects: read `<Project Path=...>` entries from `AGUI.slnx`.\n   - Folders: `Get-ChildItem src,tests,samples -Directory`.\n   - Samples/steps: list `samples/GettingStarted/Step*` to get the real range.\n2. **Drift scan — diff each doc claim against the tree.** For every concrete\n   claim in AGENTS.md / docs/architecture.md, confirm it against ground truth:\n   - Project & package names exist in `AGUI.slnx` (and in `src/`, `tests/`).\n   - Symbols the docs name still exist: `Select-String -Path src\\*\\*.cs,samples\\*\\*.cs -Pattern \"<Symbol>\"`.\n   - Renamed/removed symbols are GONE everywhere: grep the repo for the old\n     name (e.g. `AGUI.Hosting.AspNetCore`, `TypedResults.ServerSentEvents`); a\n     hit in prose-only is the drift to fix.\n3. **Fix surgically.** Edit only the stale lines. Match existing tone, tables,\n   and code-fence style. Do not restructure or invent conventions.\n4. **Verify.** Re-grep every symbol/name you wrote to confirm it exists in the\n   tree. Optionally `dotnet build` from `sdks/dotnet/` if you touched code-style\n   or build claims.\n\n## Drift checklist (the claims that rot)\n\n| Doc claim | Reconcile against |\n|---|---|\n| **src package list / names** | `AGUI.slnx` `/src/` folder + `src/` dirs |\n| **Package dependency table & framework refs** | `grep Microsoft.AspNetCore src\\*\\*.csproj` (must be empty — no src project references ASP.NET) |\n| **Where ASP.NET glue lives** | `samples/AGUI.Samples.Shared` (the only `FrameworkReference Microsoft.AspNetCore.App`) |\n| **Test-project table & count** | `AGUI.slnx` `/tests/` + `tests/` dirs |\n| **Sample step range / count** | `samples/GettingStarted/Step*` listing |\n| **Endpoint pattern code** | actual sample `Program.cs` + `samples/AGUI.Samples.Shared` |\n| **Project layout bullet list** | `src/`, `tests/`, `samples/` dirs |\n| **Code-style / naming / serialization rules** | `Directory.Build.props/.targets`, `Directory.Packages.props`, source |\n| **PublicAPI workflow** | presence of `PublicAPI.*.txt` in each `src/` project |\n\n## Deriving ground truth (commands, not a snapshot)\n\nDon't trust any embedded list (including this skill). Re-derive the current state\nfrom the tree every time:\n\n```powershell\n# from sdks/dotnet/\nSelect-String -Path AGUI.slnx -Pattern '<Project Path'   # all projects\nGet-ChildItem src,tests,samples -Directory               # folders\nGet-ChildItem samples/GettingStarted -Directory -Filter Step*  # sample step range\nSelect-String -Path src\\*\\*.csproj -Pattern Microsoft.AspNetCore  # must be empty (no ASP.NET in src/)\n```\n\nA couple of durable facts that are easy to get wrong: the server package is\n`AGUI.Server` (ASP.NET hosting glue lives only in `samples/AGUI.Samples.Shared`),\nand the integration-test **project name** stays `AGUI.Hosting.AspNetCore.IntegrationTests`\neven though its types are in namespace `AGUI.Server.IntegrationTests`. Everything else,\nderive from the commands above.\n\n## ❌ Critical anti-patterns\n\n1. **Never edit the docs from memory or from the doc's own current text.** The\n   stale prose is exactly what misleads you. Derive every name from `AGUI.slnx`\n   and the folder listing first.\n2. **Never rename a symbol in prose without grepping the whole tree** for the\n   old name — a lingering reference (or an unchanged code fence) is silent drift.\n3. **Don't invent conventions or restructure the docs.** Reconcile only what the\n   tree proves changed; keep tables, tone, and code-fence style intact.\n4. **Don't confuse a kept project name with a moved concept.** The integration\n   test project is still `AGUI.Hosting.AspNetCore.IntegrationTests` even though\n   the src package was renamed to `AGUI.Server`.\n\n## Files to mine\n\n`sdks/dotnet/AGENTS.md`, `sdks/dotnet/docs/architecture.md`, `sdks/dotnet/AGUI.slnx`,\n`sdks/dotnet/Directory.Build.props`, `Directory.Build.targets`,\n`Directory.Packages.props`, and the `src/`, `tests/`, `samples/` folder trees.\n\n<!-- File: .github/skills/agui-dotnet-code-review/references/rules.md (Tokens: ~300 | Category: anthropic-skill) -->\n# References Skill\n\nPath: `.github/skills/agui-dotnet-code-review/references/rules.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-code-review/references/rules.md)\n\n<!-- File: .github/skills/agui-dotnet-code-review/SKILL.md (Tokens: ~3813 | Category: anthropic-skill) -->\n---\nname: agui-dotnet-code-review\ndescription: >\n  Review C#/.NET code changes to the AG-UI .NET SDK (sdks/dotnet/) against its\n  specific conventions and architectural rules — AOT serialization, the\n  \"no ASP.NET in src/\" boundary, the PublicAPI analyzer workflow, wire\n  compatibility with the TypeScript reference, and the house style\n  (sealed/no-records/ConfigureAwait). Runs a phased, rule-by-rule review.\n  USE FOR: reviewing a PR, diff, or branch that touches sdks/dotnet/; checking a\n  new event/message type; verifying serialization, package placement, or\n  public-API changes in the .NET SDK. DO NOT USE FOR: generic C# style nits\n  already enforced by analyzers/EditorConfig; reviewing the TypeScript SDK\n  (sdks/typescript/) or Python SDK (sdks/python/); writing new features (only\n  flag violations, never rewrite code).\n---\n\n# AG-UI .NET SDK Code Review\n\nEncodes the AG-UI .NET SDK's house rules so a reviewer flags real violations a\ngeneric C# reviewer misses. Authoritative sources: `sdks/dotnet/AGENTS.md`\n(house rules) and `sdks/dotnet/docs/architecture.md` (design boundaries). Each\nrule cites a real enforcement example in the repo; full BAD→GOOD examples and\nper-rule exceptions live in [`references/rules.md`](references/rules.md). The\nchange-footprint and test rules below distil the `minimize-change-footprint`,\n`ensure-test-coverage`, and `ensure-test-quality` review conventions for this SDK.\n\n## Reviewer discipline\n\n- **High signal-to-noise.** Only flag a genuine violation of a rule below, tied\n  to its cited convention. Don't invent nits or restate analyzer output.\n- **Verify before flagging.** Read the actual changed code and confirm the rule\n  applies. Automated reviewers have high false-positive rates.\n- **Scope.** Review only files under `sdks/dotnet/`. Skip generic style already\n  enforced by `TreatWarningsAsErrors`, nullable, and EditorConfig.\n- **Blast radius.** Fix nothing — this skill only reports. Local convention\n  violations get a finding; codebase-wide concerns are noted as out-of-scope\n  follow-ups, not per-line nits.\n- **Severity:** ❌ must fix (breaks AOT/wire/build/boundary); ⚠️ should fix\n  (convention drift); 💡 optional polish.\n\n## The review process\n\n**Step 0 — Ground truth & file classification.** Derive the package map from\n`AGUI.slnx`; skim `AGENTS.md` + `docs/architecture.md`. Classify each changed\nfile: `production | test | sample | proto | csproj | public-api | docs`. Rules\nare gated by class.\n\n**Step 1 — Determine and summarize the change set.** Resolve what is under\nreview, in order: an explicit target (PR number / branch / commit range); else\nthe current branch vs. its tracking/base branch (`git merge-base <base> HEAD`);\nplus **staged, unstaged, and untracked** working-tree changes. Then write a short\nsummary of what the diff does — new types, wire/protocol changes, public-surface\nchanges, new dependencies, src-vs-sample placement. This frames every phase and\ncatches scope creep early.\n\n**Step 2 — Walk the rules, phase by phase (A→G).** For each phase, check every\napplicable changed file against every rule in that phase. Write each finding\nimmediately: `file:line`, rule ID, severity, one-line fix. Verify the code first.\n\n**Step 3 — Self-validation.** Dedupe; confirm each finding cites a real rule and\na real line; confirm no rule was applied to the wrong file class; drop anything\nnot verifiable in the actual diff.\n\n**Step 4 — Emit the review summary** (see below) — a single human-readable comment,\nfindings grouped by severity with a verdict and coverage line.\n\n## Phase A — Scope / scenarios\n\n- `NET-SCOPE-01` Every change traces to a spec requirement or issue `[⚠️]`\n- `NET-SCOPE-02` No unrequested capability, configurability, or dependency `[⚠️]`\n- `NET-SCOPE-03` A wire/protocol change carries compatibility coverage `[❌]`\n- `NET-SCOPE-04` Sample-only behavior stays out of `src/` `[⚠️]`\n- `NET-SCOPE-05` Minimal footprint — every diff line serves the task; no unrelated\n  refactor, speculative abstraction, or cosmetic churn `[⚠️]`\n\n## Phase B — Design / architecture\n\nFrom `docs/architecture.md` \"Architectural constraints\".\n\n- `NET-ARCH-01` No `src/` project references `Microsoft.AspNetCore.App` `[❌]` —\n  `git grep \"Microsoft.AspNetCore\" -- sdks/dotnet/src` must be empty.\n- `NET-ARCH-02` Correct package placement (wire→Abstractions, SSE→Formatting,\n  proto→Protobuf, client/transport→Client, hosting→Server) `[❌]`\n- `NET-ARCH-03` Dependency direction — `Client` and `Server` never reference each\n  other `[❌]`. Cite: `src/AGUI.Server/AGUI.Server.csproj`.\n- `NET-ARCH-04` `IChatClient` is the only integration point — no bespoke agent\n  abstraction `[💡]`\n- `NET-ARCH-05` Every type has a single reason to change `[⚠️]`\n- `NET-ARCH-06` No interface without multiple implementations or a test-double need `[⚠️]`\n- `NET-ARCH-07` Make invalid states unrepresentable (enums/types over bool/string) `[⚠️]`\n- `NET-ARCH-08` One class per file; file name matches the type `[⚠️]`\n\n## Phase C — Implementation / correctness\n\nFrom `AGENTS.md` \"JSON serialization\" / \"Code style\".\n\n- `NET-IMPL-01` Every serializable type registered in `AGUIJsonSerializerContext`\n  via `[JsonSerializable(typeof(T))]` `[❌]`. Cite:\n  `src/AGUI.Abstractions/Serialization/AGUIJsonSerializerContext.cs`.\n- `NET-IMPL-02` No `JsonSerializer.Serialize<object>` and no reflection-based\n  serialization — go through the source-gen context `[❌]`\n- `NET-IMPL-03` Polymorphic JSON uses a hand-written discriminator `JsonConverter<T>` `[❌]`.\n  Cite: `src/AGUI.Abstractions/Events/BaseEventJsonConverter.cs`.\n- `NET-IMPL-04` Property attribute kit present: explicit `[JsonPropertyName]`, **no**\n  `[JsonIgnore(WhenWritingNull)]` on optionals (the context-wide default does that),\n  required strings = `string.Empty`, collections = `[]` `[⚠️]`.\n  Cite: `src/AGUI.Abstractions/Events/RunStartedEvent.cs`.\n- `NET-IMPL-05` `ConfigureAwait(false)` on every `await` in `src/` `[⚠️]`. Cite:\n  `src/AGUI.Client/AGUIChatClient.cs`.\n- `NET-IMPL-06` `[EnumeratorCancellation]` on the token of any `IAsyncEnumerable<T>`\n  method `[⚠️]`. Cite: `src/AGUI.Formatting/SseEventStreamFormatter.cs`.\n- `NET-IMPL-07` `ArgumentNullException.ThrowIfNull(...)` for public-API argument\n  validation `[⚠️]`\n- `NET-IMPL-08` Validate external input at the boundary, not deep in the stack `[⚠️]`\n- `NET-IMPL-09` Guard every code path — no silent `default`/fallthrough `[⚠️]`\n- `NET-IMPL-10` No swallowed exceptions (empty or log-only `catch`) `[⚠️]`\n- `NET-IMPL-11` Never log or expose sensitive data in errors `[❌]`\n- `NET-IMPL-12` No dead, commented-out, or impossible-condition defensive code `[⚠️]`\n- `NET-IMPL-13` No logic duplicated across the changeset — extract a shared helper\n  at 3+ uses (Rule of Three; don't extract for 1–2) `[⚠️]`\n- `NET-IMPL-14` Prefer BCL/platform APIs over hand-rolled equivalents `[⚠️]` —\n  exception: deliberate AOT-safe hand-written paths (the `JsonElement`↔`Value`\n  bridge, the discriminator converters) are intentional, not violations.\n\n## Phase D — Wire compatibility\n\n- `NET-WIRE-01` Protocol types match the TS reference — honor the\n  `// Keep in sync with sdks/typescript/...` markers `[❌]`. Cite:\n  `src/AGUI.Abstractions/Events/RunStartedEvent.cs`.\n- `NET-WIRE-02` Events are additive — unknown types round-trip via `RawEvent`;\n  don't remove or repurpose existing fields `[⚠️]`\n- `NET-WIRE-03` Protobuf parity preserved for the supported event set `[❌]`\n\n## Phase E — PublicAPI analyzer\n\n- `NET-API-01` Any public-surface change updates that project's\n  `PublicAPI.Unshipped.txt` (build fails RS0016 otherwise) `[❌]`. Cite:\n  `sdks/dotnet/Directory.Build.targets`, `src/AGUI.Abstractions/PublicAPI.Unshipped.txt`.\n- `NET-API-02` A new event type completes the full checklist (class in `Events/`\n  deriving `BaseEvent`; `Type` → `AGUIEventTypes` constant; `[JsonSerializable]`;\n  read case in `BaseEventJsonConverter`; `PublicAPI.Unshipped.txt`; round-trip\n  test) `[⚠️]`\n\n## Phase F — Style / naming\n\nFrom `AGENTS.md` \"Code style\" / \"Naming\" (not all analyzer-enforced).\n\n- `NET-STYLE-01` `sealed` on every non-abstract class `[⚠️]`\n- `NET-STYLE-02` No `record` types — use `sealed class` with properties `[❌]`\n- `NET-STYLE-03` No tuples in public APIs — define a named type `[⚠️]`\n- `NET-STYLE-04` Braces always on `if`/`for`/`foreach`/`while` `[⚠️]`\n- `NET-STYLE-05` Naming: events `{Name}Event`; discriminators `SCREAMING_SNAKE_CASE`\n  constants in `AGUIEventTypes`; outcome/role constants lowercase (never enums);\n  options `AGUI{Purpose}Options`; extensions `{Target}Extensions`; tests\n  `{TypeUnderTest}Test` `[⚠️]`\n- `NET-STYLE-06` DI-extension types use the `Microsoft.Extensions.DependencyInjection`\n  namespace; all other types use the project `RootNamespace` with no sub-namespaces `[⚠️]`\n- `NET-STYLE-07` No XML docs (`///`) on `internal`/`private` members `[⚠️]`\n- `NET-STYLE-08` Don't reformat code you didn't otherwise change `[⚠️]`\n\n## Phase G — Tests\n\nFrom `AGENTS.md` \"Running tests\"; coverage/quality rules distilled from\n`ensure-test-coverage` and `ensure-test-quality`.\n\nSDK-specific:\n- `NET-TEST-01` Serialization tests assert concrete JSON property names via\n  `JsonDocument` — not via the deserialized object `[⚠️]`\n- `NET-TEST-02` No full-JSON-string comparisons — assert individual properties `[❌]`\n- `NET-TEST-03` No reflection to enumerate types or verify membership `[❌]`\n- `NET-TEST-04` Wire-affecting change ⇒ compatibility fixture + round-trip in\n  `tests/AGUI.Abstractions.UnitTests/Compatibility/` `[⚠️]`\n- `NET-TEST-05` New public behavior ⇒ unit test; server-pipeline change ⇒\n  integration test (`tests/AGUI.Hosting.AspNetCore.IntegrationTests/`) `[⚠️/💡]`\n\nCoverage:\n- `NET-TEST-06` A new/changed class with branching logic has a test covering happy\n  path, primary error path, and boundary values (null/empty/zero/single) `[⚠️]`\n- `NET-TEST-07` Don't test trivial code — DTOs/records with no logic, one-line\n  delegations, constant returns `[💡]`\n- `NET-TEST-08` Test through DI + `InternalsVisibleTo`, not members made `public`\n  for tests `[⚠️]`\n\nQuality:\n- `NET-TEST-09` Every test asserts a specific observable value — no assertion-free\n  tests, no bare `Assert.NotNull`/`True`/`NotEmpty` standing in for the real value `[❌]`\n- `NET-TEST-10` Deterministic and isolated — no `Thread.Sleep`/`Task.Delay` for\n  synchronization, no execution-order dependence, side effects cleaned up\n  (files/ports/env) `[❌]`\n- `NET-TEST-11` Test behavior, not implementation — prefer hand-written fakes over\n  `mock.Verify(Times.*)` (unless the call count is the spec'd behavior); `[Theory]`\n  for data variation, `[Fact]` for behavior; AAA visible inline with factory\n  helpers (not shared mutable fixtures) below the tests; no `// TODO` or empty\n  test bodies `[⚠️]`\n\n## Self-validation\n\n- [ ] The change set was resolved (target / tracking branch / working tree) and summarized\n- [ ] Every applicable changed file was walked against every phase's rules\n- [ ] Each finding cites a real rule ID, file, and line, and was verified in the diff\n- [ ] No rule applied to the wrong file class; no duplicates\n- [ ] Clean diffs are reported as clean — no padding\n\n## Common pitfalls\n\n| Pitfall | Solution |\n|---------|----------|\n| Restating analyzer/EditorConfig output | Only flag rules above that tooling does not enforce |\n| Flagging a \"missing\" registration without checking the context | Open `AGUIJsonSerializerContext.cs` and confirm |\n| Treating a sample's ASP.NET usage as a `src/` violation | `NET-ARCH-01` applies to `src/` only |\n| Calling an additive new event a wire break | `NET-WIRE-02` — additive is allowed |\n| Nitpicking style in files with substantive changes | Focus on the substantive change |\n\n## Review summary\n\nProduce a single human-readable Markdown comment — a reviewer's summary the author\ncan read top to bottom. Lead with the verdict, then the findings grouped by\nseverity (most severe first), each one self-contained.\n\n```markdown\n## AG-UI .NET SDK code review\n\n**Verdict:** <Request changes | Comment | Looks good> — <one-sentence reason>\n**Change set:** <branch vs base, e.g. `feat/x` vs `main`> · <N files reviewed>\n(+<U untracked>) · **Findings:** ❌ <a> · ⚠️ <b> · 💡 <c>\n\n<One short paragraph: what the change does and the overall read.>\n\n### ❌ Must fix\n- **`src/AGUI.Abstractions/Events/FooEvent.cs:42`** · `NET-IMPL-01` — new event type\n  isn't registered in `AGUIJsonSerializerContext`; it fails under AOT.\n  **Fix:** add `[JsonSerializable(typeof(FooEvent))]`.\n\n### ⚠️ Should fix\n- **`src/AGUI.Client/AGUIChatClient.cs:88`** · `NET-IMPL-05` — bare `await` in\n  library code. **Fix:** append `.ConfigureAwait(false)`.\n\n### 💡 Optional\n- **`src/AGUI.Server/StreamAdapter.cs:17`** · `NET-ARCH-04` — bespoke agent\n  abstraction; the SDK integrates via `IChatClient`. **Fix:** drop the wrapper.\n\n### Coverage\nPhases checked: A–G. No findings in: **B Design**, **D Wire**, **E PublicAPI**.\n```\n\nRules for the summary:\n- **Order** findings by severity (❌ → ⚠️ → 💡), then by file. One bullet per finding:\n  bold `file:line`, the `RULE-ID`, a plain-language description, and an italic\n  **Fix:** with a one-line remedy. The reader can look the ID up in\n  [`references/rules.md`](references/rules.md).\n- **Omit empty severity sections.** Always include the **Coverage** line so the\n  author sees which phases were clean versus untouched.\n- **Clean diff:** skip the severity sections and write a single line —\n  `✅ No violations of the AG-UI .NET house rules — checked phases A–G across N files.`\n- **Verdict mapping:** any ❌ → *Request changes*; only ⚠️/💡 → *Comment*; none →\n  *Looks good*. The skill never approves or blocks automatically — the verdict is\n  advisory and the author decides.\n\n<!-- File: .github/skills/agui-dotnet-cross-language-tests/SKILL.md (Tokens: ~2764 | Category: anthropic-skill) -->\n---\nname: agui-dotnet-cross-language-tests\ndescription: >\n  Author cross-language interop tests that verify the AG-UI .NET SDK is\n  wire-compatible with the TypeScript SDK — a Vitest TS client driving a C#\n  CrossLanguage.TestServer over HTTP, both directions, including protobuf\n  byte-parity against @ag-ui/proto. USE FOR: adding or modifying cross-language\n  interop coverage, CrossLanguage.TestServer routes, the CrossLanguage.Vitest\n  suite, protobuf wire parity tests, TS-client-to-C#-server or\n  C#-client-to-TS-server scenarios. DO NOT USE FOR: .NET-only unit tests (use\n  agui-dotnet-unit-tests), ASP.NET Core hosting integration tests (use\n  agui-dotnet-integration-tests).\n---\n\n# AG-UI .NET Cross-Language Interop Tests\n\nHow to add tests proving the .NET AG-UI SDK interoperates with the TypeScript\nSDK on the wire. The harness lives under `sdks/dotnet/tests/`. Read\n`sdks/dotnet/docs/cross-language-testing.md` (design plus the \"Harness reference\"\nsection) for full background.\n\n## Interop philosophy\n\n- **The TypeScript SDK is the reference (oracle).** A round-trip through the TS\n  codec — `proto.decode(proto.encode(event))` — is the canonical normalised form\n  both SDKs must agree on. Assert .NET output against *that*, not against the raw\n  fixture object.\n- **Round-trip semantic equivalence is the real guarantee**, in both directions\n  (TS→.NET and .NET→TS). Byte-for-byte parity is a stronger claim asserted only\n  where deterministic.\n- Tests exercise *our* code via project references (`AGUI.Abstractions`,\n  `AGUI.Server`, `AGUI.Protobuf`), never the published NuGet packages.\n\n## Harness architecture\n\nTwo directions, two server processes (see the \"Harness reference\" section of\n`sdks/dotnet/docs/cross-language-testing.md`):\n\n| Direction | Driver | Target server | Runner |\n|---|---|---|---|\n| TS → .NET (Phase 1) | TS `HttpAgent` (`@ag-ui/client`) | C# `CrossLanguage.TestServer` on :8091 | Vitest |\n| .NET → TS (Phase 2) | C# `AGUIChatClient` | TS fake-agent server (`server/main.ts`) on :8092 | xUnit |\n\nPhase 1 mechanism: Vitest `globalSetup`\n(`CrossLanguage.Vitest/helpers/global-setup.ts`) starts LLMock\n(`@copilotkit/aimock`, deterministic LLM responses), then\n`helpers/dotnet-server.ts` runs `dotnet build` and spawns the produced\n`CrossLanguage.TestServer.exe` (not `dotnet run` — single PID for clean Windows\nteardown) with `OPENAI_BASE_URL` pointed at LLMock. It waits for the HTTP\nlistener, then test files `fetch` the routes. Both server and LLMock stay alive\nacross the whole run; `vitest.config.ts` sets `fileParallelism: false` so\nconcurrent SDK builds don't contend for artifact locks.\n\nPhase 2 mechanism: `TsServerFixture` (`IAsyncLifetime`, shared via\n`[Collection(nameof(TsServerCollection))]`) shells out `pnpm run server`\n(`tsx server/main.ts`) which emits canned AG-UI events via `@ag-ui/encoder`;\n`AGUIChatClient` consumes them.\n\n## Adding a TS → .NET scenario (Phase 1)\n\n1. **Add a server-side route** under `CrossLanguage.TestServer/` following the\n   endpoint pattern (`MapPost` → `input.ToChatRequestContext(...)` →\n   `GetStreamingResponseAsync` → `.AsAGUIEventStreamAsync(ctx)` →\n   `TypedResults.ServerSentEvents(AgenticChatRoute.WrapAsSseItems(...))`). See\n   `ParallelToolCallsRoute.cs`. For a route that must **negotiate the transport**\n   (SSE *or* protobuf from the `Accept` header), end with\n   `AGUIResults.Events(events, httpContext, cancellationToken)` instead and make\n   sure `Program.cs` registers `ProtobufEventStreamFormatter` as an `IAGUIEventStreamFormatter` — see `AgenticChatRoute.cs`.\n2. **Register it in `Program.cs`** (e.g. `app.MapParallelToolCalls(\"/parallel_tool_calls\")`).\n3. **Register any new payload types in `CrossLanguageJsonSerializerContext.cs`**\n   (`[JsonSerializable(typeof(YourReport))]`). This context is snake_case to\n   match the TS wire shape.\n4. **Add an aimock fixture** in `fixtures/*.json` keyed by `userMessage` /\n   `toolCallId` so LLM responses are deterministic (see\n   `fixtures/parallel-tool-calls.json`).\n5. **Add a `tests/<scenario>.test.ts`** that drives the route with `HttpAgent`\n   and asserts on the collected event stream (see `parallel-tool-calls.test.ts`).\n\n## Adding a .NET → TS scenario (Phase 2)\n\n1. Add a fake agent (`(RunAgentInput) => BaseEvent[]`) in `server/fakeAgents.ts`.\n2. Mount its route in `server/main.ts`.\n3. Add a `*.cs` test in `AGUI.CrossLanguage.IntegrationTests/`, decorated\n   `[Collection(nameof(TsServerCollection))]`, driving it with `AGUIChatClient`\n   (see `AgenticChatTests.cs`).\n\n## Protobuf wire-parity pattern\n\n`ProtobufParityRoute.cs` exposes three codec routes backed by `AGUIProtobuf`:\n\n| Route | In | Out | Backed by |\n|---|---|---|---|\n| `POST /protobuf/encode` | event JSON | raw proto bytes | `AGUIProtobuf.Encode` |\n| `POST /protobuf/decode` | raw proto bytes | event JSON | `AGUIProtobuf.Decode` |\n| `POST /protobuf/decode-framed` | 4-byte BE length-prefixed frames | event JSON array | `AGUIProtobuf.ReadFramedAsync` |\n\n`tests/protobuf-parity.test.ts` proves parity against `@ag-ui/proto`\n(`sdks/typescript/packages/proto/src/proto.ts`) and `@ag-ui/encoder` framing\n(`sdks/typescript/packages/encoder/src/encoder.ts`). For each fixture\n(`fixtures/protobuf-events.ts`):\n\n- `tsBytes = proto.encode(event)`; `reference = proto.decode(tsBytes)`.\n- **TS encode → .NET decode**: `expect(netDecode(tsBytes)).toEqual(reference)`.\n- **.NET encode → TS decode**: `expect(proto.decode(netEncode(event))).toEqual(reference)`.\n- **Byte parity** depends on the fixture's `byteParity` flag:\n  - `\"strict\"` — scalar-only events (only string/number fields, serialised in\n    field-number order): assert the TS and .NET bytes are byte-for-byte equal.\n  - `\"roundtrip\"` — payloads mapping to `google.protobuf.Struct`\n    (`map<string, Value>`): map-entry ordering is **not** canonical across\n    encoders, so do NOT assert byte equality. Assert both byte streams decode\n    (via the TS codec) to the same event instead.\n\nA framing test concatenates `encoder.encodeProtobuf(event)` frames (4-byte BE\nprefix) and posts them to `/protobuf/decode-framed` to exercise `ReadFramedAsync`.\nWhen adding a new protobuf event, add a fixture with the correct `byteParity`\nflag — scalar-only ⇒ `strict`, any object/array payload ⇒ `roundtrip`.\n\n## Transport parity (parameterize scenarios over SSE + protobuf)\n\nThe codec-parity pattern above isolates the **codecs** — it never goes through the\nTS `HttpAgent` or `Accept`-header negotiation. To prove the full **transport** path\n(TS client negotiates a protocol → .NET server encodes it → TS client decodes it),\nparameterize a scenario suite over both transports — the cross-language analogue of\nthe .NET integration tests' `TransportFormat {Json, Protobuf}` `[Theory]`.\n\n`helpers/transport.ts` is the shared mechanism: `TRANSPORTS = [\"sse\", \"protobuf\"]`,\n`TRANSPORT_MEDIA_TYPE`, and `createTransportAgent(config, transport)` which returns\nan `HttpAgent` that requests the transport (it opts into protobuf via the public\n`fetch` hook — the default agent hardcodes `Accept: text/event-stream` *after*\nspreading `headers`, so a `headers` option can't override it) and captures the\nresponse `Content-Type`. Drive the suite with `describe.each(TRANSPORTS)` and assert\n`lastResponseContentType() === TRANSPORT_MEDIA_TYPE[transport]` plus the usual\ndecoded-event assertions — see `tests/agentic-chat.test.ts`.\n\n```ts\ndescribe.each(TRANSPORTS)(\"… [%s]\", (transport) => {\n  it(\"…\", async () => {\n    const { agent, lastResponseContentType } = createTransportAgent(\n      { url: `${baseUrl()}/agentic_chat`, threadId: `t-${transport}` }, transport);\n    agent.messages = [{ id: \"u\", role: \"user\", content: \"Hi, I am duaa\" }];\n    const events: BaseEvent[] = [];\n    await agent.runAgent({}, { onEvent: ({ event }) => events.push(event) });\n    expect(lastResponseContentType()).toBe(TRANSPORT_MEDIA_TYPE[transport]);\n    // …assert decoded events (identical regardless of transport)…\n  });\n});\n```\n\nThe route under test must negotiate (`AGUIResults.Events`, with\n`ProtobufEventStreamFormatter` registered as an `IAGUIEventStreamFormatter` in\n`Program.cs`). `tests/agentic-chat.test.ts` and\n`tests/state-events.test.ts` are parameterized this way today.\n\n**Only parameterize protobuf-safe scenarios.** `ToolCallResult`, `Reasoning*`, and\n`Activity*` events have **no message/oneof entry in the shared `events.proto`** (the\none schema referenced by *both* `@ag-ui/proto` and .NET `AGUI.Protobuf`), so *neither*\nSDK can protobuf-encode them — the codec throwing `NotSupportedException` mirrors\nthe schema, it is not a .NET gap. A suite that emits any of those must stay SSE-only.\nAdding protobuf support for them is an **upstream schema change** (extend the canonical\nTS `events.proto`, regenerate both SDKs, add mappers) — see `agui-cross-sdk-parity`.\n\n`AGUI_MEDIA_TYPE` (`@ag-ui/proto`) and `ProtobufEventStreamFormatter.ProtobufMediaType` are the identical\nexact string, and `AGUIEventStreamResult` sets `Content-Type` to it with no charset\n— the client's exact `===` content-type match depends on that.\n\n## Running the suites\n\n```sh\n# TS → .NET + protobuf parity (builds + spawns the C# server automatically)\ncd sdks/dotnet/tests/CrossLanguage.Vitest\npnpm test\npnpm exec vitest run tests/protobuf-parity.test.ts   # just the parity suite\n\n# .NET → TS (shells out `pnpm run server`)\ncd sdks/dotnet/tests/AGUI.CrossLanguage.IntegrationTests\ndotnet test\n```\n\n`pnpm install` from the repo root once first. Requires .NET 10 SDK, Node at the\nversion in the repository's root `.node-version`, pnpm 10+.\n\n## ❌ Critical anti-patterns\n\n1. **Don't assert byte-equality for object/Struct payloads.** `google.protobuf.Struct`\n   map ordering is non-canonical; byte parity is only valid for scalar-only\n   (`\"strict\"`) fixtures. For object payloads, assert round-trip equivalence.\n2. **Don't make the .NET fixture the oracle.** The TS codec is the reference —\n   compare against `proto.decode(proto.encode(event))`, not the raw event object.\n3. **Don't add a route without registering it in BOTH `Program.cs` AND\n   `CrossLanguageJsonSerializerContext.cs`** (when it introduces new payload\n   types) — the server won't map the route or will fail AOT-safe serialization.\n4. **Don't depend on real LLM calls.** Phase 1 LLM responses come from aimock\n   fixtures keyed by `userMessage`/`toolCallId`; add a fixture for every new\n   prompt. Use fixed/deterministic tool outputs (see `ParallelToolCallsRoute`'s\n   frozen clock).\n5. **Don't use `dotnet run` to start the server in helpers, and don't assume\n   parallel test files.** The harness spawns the built `.exe` for a single\n   killable PID and runs files sequentially (`fileParallelism: false`) to avoid\n   build-lock contention and Windows port orphans.\n\n<!-- File: .github/skills/agui-dotnet-feature-workflow/SKILL.md (Tokens: ~2167 | Category: anthropic-skill) -->\n---\nname: agui-dotnet-feature-workflow\ndescription: >\n  Orchestrator/hub for implementing a feature or change in the AG-UI .NET SDK\n  (sdks/dotnet). USE FOR: \"what's the workflow\", \"what order do I do things in\",\n  \"how do I implement a feature in the .NET SDK\", starting any non-trivial\n  AG-UI .NET SDK change, planning the end-to-end steps and definition-of-done\n  (code + AOT serialization + client/server mapping + unit/integration/cross-language\n  tests + docs + PublicAPI + AGENTS.md sync). DO NOT USE FOR: the deep how-to of a\n  single step — this skill ROUTES to focused siblings: adding wire types\n  (agui-dotnet-wire-types), transport/encoding (agui-dotnet-transport), unit tests\n  (agui-dotnet-unit-tests), integration tests (agui-dotnet-integration-tests),\n  cross-language tests (agui-dotnet-cross-language-tests), porting from TS/Python\n  (agui-cross-sdk-parity), adding a GettingStarted sample Step\n  (agui-dotnet-sample-step), SDK docs (agui-dotnet-sdk-docs), AGENTS/Architecture\n  sync (agui-dotnet-agents-sync), the dojo (agui-dojo), review\n  (agui-dotnet-code-review).\n---\n\n# AG-UI .NET SDK — Feature Workflow (Orchestrator)\n\nThis is the **hub** skill. Given a request to build or change a feature in the AG-UI\n.NET SDK (`sdks/dotnet/`), it lays out the correct end-to-end order and **routes the\ndepth of each step to a focused sibling skill**. It does not duplicate their content.\n\nThe SDK has a multi-artifact **definition of done**. An agent working ad hoc forgets\nartifacts — most often cross-language parity, docs, `AGENTS.md`/`docs/architecture.md` sync,\nand `PublicAPI.Unshipped.txt`. Use this skill to avoid that.\n\n## Package map\n\n`sdks/dotnet/src/`:\n\n| Package | Responsibility |\n|---|---|\n| `AGUI.Abstractions` | Wire types: events, messages, tools, capabilities, `AGUIJsonSerializerContext` |\n| `AGUI.Formatting` | JSON formatter + SSE encode/decode |\n| `AGUI.Protobuf` | Protobuf encoding of the protocol |\n| `AGUI.Client` | `AGUIChatClient` (`IChatClient`) + transport negotiation |\n| `AGUI.Server` | Hosting-agnostic agent-side conversion (`ChatResponseUpdate` → events) |\n\nASP.NET hosting glue lives in `samples/AGUI.Samples.Shared` (not a `src/` package).\n`sdks/dotnet/AGENTS.md` and `docs/architecture.md` are the canonical description of\nthe layout and conventions (kept current via `agui-dotnet-agents-sync`); `AGUI.slnx`\nis the ground truth if you need to re-derive the package list.\n\n## Build & test commands\n\n```bash\n# from sdks/dotnet/\ndotnet build sdks/dotnet/AGUI.slnx        # whole solution\ndotnet test  tests/AGUI.Abstractions.UnitTests/   # per-project, fast feedback\n```\n\n`Directory.Build.props` **treats warnings as errors**, and `PublicApiAnalyzers` is on\nfor every `src/` project with a `PublicAPI.Shipped.txt`. **The build fails if you skip\nthe AOT serialization wiring or forget `PublicAPI.Unshipped.txt`** — these are not\noptional polish steps, they are enforced.\n\n## Definition of done (feature checklist)\n\n- [ ] Wire contract understood (matched against TS/Python reference if wire-affecting)\n- [ ] Type/behavior implemented in the **right package** (see map)\n- [ ] AOT serialization wired (`[JsonSerializable]` in `AGUIJsonSerializerContext`, converter case, `[JsonPropertyName]`)\n- [ ] Client/server mapping updated (`AGUI.Client` event→update and/or `AGUI.Server` update→event)\n- [ ] Unit tests (serialization round-trip + behavior)\n- [ ] Integration tests (full pipeline) if it crosses the HTTP/SSE boundary\n- [ ] Cross-language parity tests if wire-affecting\n- [ ] `PublicAPI.Unshipped.txt` updated for every changed public member\n- [ ] Docs updated (docs.ag-ui.com / SDK docs) if user-facing\n- [ ] `AGENTS.md` / `docs/architecture.md` synced if structure/recipe changed\n- [ ] `dotnet build sdks/dotnet/AGUI.slnx` and relevant `dotnet test` projects green\n\n## Ordered workflow → route each step\n\nDo the steps **in this order**. Skip a step only if it genuinely doesn't apply\n(e.g. a non-wire-affecting internal refactor skips cross-language parity).\n\n1. **Understand the wire contract.** Read the TypeScript (and Python) reference for\n   the type/behavior so the .NET shape matches the spec. Porting an existing feature\n   from another SDK? → **`agui-cross-sdk-parity`**.\n\n2. **Implement the type/behavior in the right package.**\n   - New/changed wire type (event, message, tool, capability) → **`agui-dotnet-wire-types`**\n     (covers the `AGUI.Abstractions` recipe: class in `Events/`, `AGUIEventTypes`\n     constant, converter case, AOT registration, `PublicAPI.Unshipped.txt`).\n   - New/changed transport or encoding (SSE, protobuf, formatter) →\n     **`agui-dotnet-transport`** (`AGUI.Formatting`, `AGUI.Protobuf`).\n\n3. **Wire AOT serialization.** Every protocol type goes through\n   `AGUIJsonSerializerContext` — no reflection. `agui-dotnet-wire-types` has the\n   per-type recipe; the build enforces it.\n\n4. **Update client/server mapping.** Server-side `ChatResponseUpdate` → event lives in\n   `AGUI.Server`; client-side event → `ChatResponseUpdate` lives in `AGUI.Client`\n   (`EventStreamConverter`, builders). Update both directions if the wire shape changed.\n\n5. **Unit tests** (round-trip + behavior) → **`agui-dotnet-unit-tests`**.\n\n6. **Integration tests** (HTTP + SSE pipeline, `WebApplicationFactory`,\n   `AGUIChatClient`) → **`agui-dotnet-integration-tests`**. Required when the change\n   crosses the transport boundary.\n\n7. **Cross-language parity tests** (if wire-affecting) →\n   **`agui-dotnet-cross-language-tests`** (`tests/AGUI.CrossLanguage.IntegrationTests`,\n   `CrossLanguage.TestServer`, `CrossLanguage.Vitest`). This is the step agents most\n   often forget — .NET must agree with TS/Python on the bytes.\n\n8. **Update `PublicAPI.Unshipped.txt`** for every changed public member, in each\n   affected `src/` project. The PublicAPI analyzer fails the build otherwise.\n\n9. **Docs** (user-facing change) → **`agui-dotnet-sdk-docs`** (docs.ag-ui.com).\n\n10. **Sync `AGENTS.md` / `docs/architecture.md`** if you changed structure, recipes, or\n    commands → **`agui-dotnet-agents-sync`**. Fix stale package references while here.\n\n11. **Build + test green.** `dotnet build sdks/dotnet/AGUI.slnx`, then the relevant\n    `dotnet test <project>` (unit + integration + cross-language as applicable).\n\n12. **Validate & review.** Run/inspect in the dojo → **`agui-dojo`**; manual UI/docs\n    checks → **`agui-playwright-validate`**; review the change → **`agui-dotnet-code-review`**.\n\n## Routing table (quick reference)\n\n| Step / need | Sibling skill |\n|---|---|\n| Add/modify a wire type | `agui-dotnet-wire-types` |\n| Add/modify transport or encoding | `agui-dotnet-transport` |\n| Port a feature from TS/Python | `agui-cross-sdk-parity` |\n| Write unit tests | `agui-dotnet-unit-tests` |\n| Write integration tests | `agui-dotnet-integration-tests` |\n| Write cross-language tests | `agui-dotnet-cross-language-tests` |\n| Add a GettingStarted sample Step (Server/Client pair) | `agui-dotnet-sample-step` |\n| Update SDK docs site | `agui-dotnet-sdk-docs` |\n| Keep AGENTS.md / docs/architecture.md current | `agui-dotnet-agents-sync` |\n| Run/validate in the dojo | `agui-dojo` |\n| Manual UI/docs validation | `agui-playwright-validate` |\n| Review the change | `agui-dotnet-code-review` |\n\n> The depth of each step lives in the sibling skill it routes to; fall back to the\n> recipes in `AGENTS.md` and the deep content in `docs/architecture.md` for anything a\n> sibling doesn't cover.\n\n## ❌ Anti-patterns\n\n1. **Don't stop at \"it compiles and unit tests pass.\"** Wire-affecting changes are not\n   done until cross-language parity tests and docs are updated.\n2. **Don't put protocol or server code in a sample.** It belongs in `src/`; the server is\n   `AGUI.Server`, hosting glue is in `samples/AGUI.Samples.Shared`, and no `src/` project\n   references ASP.NET.\n3. **Don't skip `PublicAPI.Unshipped.txt` or AOT registration** \"to fix later\" — the\n   warnings-as-errors build will block you immediately.\n4. **Don't do the deep work here.** This skill routes; the depth lives in the sibling\n   skills. Open the relevant one before implementing a step.\n\n<!-- File: .github/skills/agui-dotnet-transport/references/wire-format.md (Tokens: ~300 | Category: anthropic-skill) -->\n# References Skill\n\nPath: `.github/skills/agui-dotnet-transport/references/wire-format.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-transport/references/wire-format.md)\n\n<!-- File: .github/skills/agui-dotnet-transport/SKILL.md (Tokens: ~1576 | Category: anthropic-skill) -->\n---\nname: agui-dotnet-transport\ndescription: >\n  Add or modify a wire transport / event-stream encoding in the AG-UI .NET SDK — the protobuf\n  codec, the SSE format, content negotiation, the JsonElement-to-protobuf Value bridge, or a brand\n  new encoding — while preserving Native AOT compatibility and byte-level wire compatibility with\n  @ag-ui/proto. USE FOR: working on AGUI.Formatting / AGUI.Protobuf, IAGUIEventStreamFormatter,\n  transport content negotiation, the JsonElement-to-google.protobuf.Value bridge, SSE or protobuf\n  framing, server formatter registration / AGUIResults.Events negotiation. DO NOT USE FOR: adding a new wire event\n  TYPE (use agui-dotnet-wire-types), writing tests (use agui-dotnet-integration-tests).\n---\n\n# AG-UI .NET Transport & Encoding\n\nEncodes the non-obvious design constraints of the AG-UI .NET transport layer, discovered while\nbuilding protobuf support. Apply when adding/changing an encoding or the negotiation that selects\none. Read `references/wire-format.md` before touching the protobuf codec or framing.\n\n## Transport architecture\n\nOne bidirectional abstraction, `IAGUIEventStreamFormatter` (in `AGUI.Formatting`), serves every\ntransport and both directions:\n\n| Member | Role |\n|--------|------|\n| `MediaType` | Advertised in client `Accept` and written as server `Content-Type`. Registration order = preference. |\n| `CanRead(contentType)` | Client picks the decoder for the response `Content-Type`. |\n| `ReadAsync(body, ct)` | Decode body → `IAsyncEnumerable<BaseEvent>`. |\n| `WriteAsync(events, output, ct)` | Encode events → body. |\n\n`SseEventStreamFormatter` (`text/event-stream`) is the always-available default;\n`ProtobufEventStreamFormatter` (`ProtobufEventStreamFormatter.ProtobufMediaType`) is opt-in.\n\n**Client negotiation** = `DelegatingHandler` + decode helper:\n- `AGUIEventStreamHandler` (public, in `AGUI.Client`) advertises every registered formatter's\n  `MediaType` in `Accept`, then inspects the response `Content-Type`, finds the first `CanRead`\n  formatter, and records it on the request. The body is left untouched for lazy streaming.\n- `AGUIResponseExtensions.ReadAGUIEventStreamAsync` reads that recorded formatter (falling back to\n  SSE) and decodes. The SDK ships no `IHttpClientFactory` integration: a caller that wants protobuf\n  wires the handler into its own `HttpClient`, and constructs `AGUIChatClient` from\n  `AGUIChatClientOptions`.\n\n**Server negotiation** = `AGUIResults.Events` (samples `AGUI.Samples.Shared`): collects registered\n`IAGUIEventStreamFormatter` services (+ built-in SSE), then picks protobuf **only when its media\ntype is explicitly present** in `Accept` with non-zero quality, else SSE for `text/event-stream`/\nwildcard/absent, else `406`. Mirrors `preferredMediaTypes(accept, [proto])` in `@ag-ui/encoder`.\nA server opts in by registering the formatter (for example,\n`services.AddSingleton<IAGUIEventStreamFormatter, ProtobufEventStreamFormatter>()`).\n\n## Wire format facts\n\n- Protobuf media type: `application/vnd.ag-ui.event+proto` (`ProtobufEventStreamFormatter.ProtobufMediaType`).\n- Framing: **4-byte big-endian `uint32` length prefix + protobuf message bytes**, per event —\n  matches `@ag-ui/encoder` `encodeProtobuf` (`dataView.setUint32(0, length, false)`). See\n  `AGUIProtobuf.WriteFramed` / `ReadFramedAsync`.\n- `Encode`/`Decode` = single message, no length prefix (mirror TS `proto.encode`/`proto.decode`).\n- Dynamic payloads (state, args, results) use `google.protobuf.Value` (Struct/ListValue/scalars) —\n  **never `Any` and never a JSON-string field**.\n\n## The CRITICAL Native AOT rule\n\nImplement the `JsonElement` <-> `google.protobuf.Value` bridge **by hand over the generated\nWellKnownTypes** (`ProtoValueConverter`). **NEVER** use Google.Protobuf's reflection-based\n`JsonFormatter`/`JsonParser` or any descriptor reflection API — they are not trim/AOT safe and the\npackage multi-targets `net10/9/8/netstandard2.0/net472`.\n\n- **Number caveat**: `Value` is double-only. `long`/`decimal` beyond 2^53 lose precision on round\n  trip. This is intentional — it matches the JS `@ag-ui/proto` limitation.\n\n## Schema-first extension\n\nThe `.proto` schema is **canonical** and lives in the TS package. `AGUI.Protobuf.csproj`\n`<Protobuf>` references `sdks/typescript/packages/proto/src/proto/*.proto` directly\n(`csharp_namespace = AGUI.ProtocolBuffers`, generated types `Access=\"Internal\"`) — **do not fork or\ncopy it**. To add a wire-representable event:\n\n1. Extend the shared `.proto` (coordinated across all SDKs — it is the cross-language contract).\n2. Add a mapper case in `ProtoEventMapper` (event oneof) / `ProtoMessageMapper` (messages),\n   mirroring `sdks/typescript/packages/proto/src/proto.ts` reshaping verbatim.\n\nSubset coverage is intentional: .NET-only events that have no wire representation throw\n`NotSupportedException` from the mapper's `default` case. Don't invent a wire shape unilaterally.\n\n## How to verify\n\n- **Byte-parity** against `@ag-ui/proto` via the cross-language tests (see\n  `agui-dotnet-integration-tests` and `sdks/dotnet/docs/cross-language-testing.md`). The JSON\n  compatibility fixtures in `tests/AGUI.Abstractions.UnitTests/Compatibility/` guard SSE drift.\n- **Multi-TFM AOT build**: `dotnet build` from `sdks/dotnet/` (targets net10/9/8/netstandard2.0/\n  net472; warnings are errors). Update `PublicAPI.Unshipped.txt` for any public surface change.\n\n## ❌ Anti-patterns\n\n1. **Don't embed JSON-as-string inside a `Value`.** Map structured payloads recursively to\n   Struct/ListValue/scalars via `ProtoValueConverter`. A string field breaks @ag-ui/proto parity.\n2. **Don't use `JsonFormatter`/`JsonParser`/descriptor reflection.** Not AOT-safe — hand-write the\n   bridge over generated WellKnownTypes.\n3. **Don't copy or fork the `.proto`.** Reference the canonical TS schema from the `.csproj` so the\n   codec can't drift from the wire contract.\n4. **Don't make `AGUI.Protobuf` depend on `AGUI.Client` or the hosting/server package.** The codec\n   stays transport-neutral; it references only `AGUI.Abstractions` + `AGUI.Formatting`.\n5. **Don't change framing or use little-endian.** Length is big-endian `uint32`; both SDKs depend\n   on exact byte layout.\n\n## References\n\n- **Wire format & codec internals** (framing, oneof mapping, Value bridge, negotiation parity):\n  [references/wire-format.md](references/wire-format.md)\n\n<!-- File: .github/skills/agui-dotnet-wire-types/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# agui-dotnet-wire-types\n\nPath: `.github/skills/agui-dotnet-wire-types/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-dotnet-wire-types/SKILL.md)\n\n<!-- File: .github/skills/agui-playwright-validate/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# agui-playwright-validate\n\nPath: `.github/skills/agui-playwright-validate/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/.github/skills/agui-playwright-validate/SKILL.md)\n\n<!-- File: integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/flight_schema.json (Tokens: ~300 | Category: anthropic-skill) -->\n# A2ui_fixed_schema_schemas Skill\n\nPath: `integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/flight_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/flight_schema.json)\n\n<!-- File: integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/hotel_schema.json (Tokens: ~300 | Category: anthropic-skill) -->\n# A2ui_fixed_schema_schemas Skill\n\nPath: `integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/hotel_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/crew-ai/python/examples/agents/a2ui_fixed_schema_schemas/hotel_schema.json)\n\n<!-- File: integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/flight_schema.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Schemas Skill\n\nPath: `integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/flight_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/flight_schema.json)\n\n<!-- File: integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/hotel_schema.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Schemas Skill\n\nPath: `integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/hotel_schema.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/integrations/langgraph/python/examples/agents/a2ui_fixed_schema/schemas/hotel_schema.json)\n\n<!-- File: sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-client-tools/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# agui-dotnet-client-tools\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-client-tools/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-client-tools/SKILL.md)\n\n<!-- File: sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-human-in-the-loop/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# agui-dotnet-human-in-the-loop\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-human-in-the-loop/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-human-in-the-loop/SKILL.md)\n\n<!-- File: sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-multimodal/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# agui-dotnet-multimodal\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-multimodal/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-multimodal/SKILL.md)\n\n<!-- File: sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-protobuf/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# agui-dotnet-protobuf\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-protobuf/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-protobuf/SKILL.md)\n\n<!-- File: sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-reasoning/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# agui-dotnet-reasoning\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-reasoning/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-reasoning/SKILL.md)\n\n<!-- File: sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-server-tools/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# agui-dotnet-server-tools\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-server-tools/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-server-tools/SKILL.md)\n\n<!-- File: sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-shared-state/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# agui-dotnet-shared-state\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-shared-state/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-shared-state/SKILL.md)\n\n<!-- File: sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-streaming-chat/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# agui-dotnet-streaming-chat\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-streaming-chat/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-streaming-chat/SKILL.md)\n\n<!-- File: sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-troubleshoot/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# agui-dotnet-troubleshoot\n\nPath: `sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-troubleshoot/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/dotnet/plugins/ag-ui-dotnet/skills/agui-dotnet-troubleshoot/SKILL.md)\n\n<!-- File: sdks/typescript/packages/a2ui-toolkit/CHANGELOG.md (Tokens: ~300 | Category: anthropic-skill) -->\n# A2ui-toolkit Skill\n\nPath: `sdks/typescript/packages/a2ui-toolkit/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/CHANGELOG.md)\n\n<!-- File: sdks/typescript/packages/a2ui-toolkit/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# A2ui-toolkit Skill\n\nPath: `sdks/typescript/packages/a2ui-toolkit/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/package.json)\n\n<!-- File: sdks/typescript/packages/a2ui-toolkit/tsconfig.json (Tokens: ~300 | Category: anthropic-skill) -->\n# A2ui-toolkit Skill\n\nPath: `sdks/typescript/packages/a2ui-toolkit/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/a2ui-toolkit/tsconfig.json)\n\n<!-- File: sdks/typescript/packages/cli/CHANGELOG.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Cli Skill\n\nPath: `sdks/typescript/packages/cli/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/CHANGELOG.md)\n\n<!-- File: sdks/typescript/packages/cli/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Cli Skill\n\nPath: `sdks/typescript/packages/cli/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/ag-ui-protocol/ag-ui/HEAD/sdks/typescript/packages/cli/package.json)\n\n<!-- ... +33 more modular skills available via /api/skills/ag-ui-protocol/ag-ui?path={path} -->\n</yakaai_skills>"}