<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Development on AGW</title><link>https://agw-docs.pages.dev/docs/development/</link><description>Recent content in Development on AGW</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Fri, 25 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://agw-docs.pages.dev/docs/development/index.xml" rel="self" type="application/rss+xml"/><item><title>Development setup</title><link>https://agw-docs.pages.dev/docs/development/setup/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://agw-docs.pages.dev/docs/development/setup/</guid><description>&lt;p&gt;Prerequisites: .NET 10 SDK, Node.js 24, pnpm 12.5.1 (pinned by &lt;code&gt;packageManager&lt;/code&gt; in &lt;code&gt;src/clients/package.json&lt;/code&gt;), and Git. Docker Buildx is needed only for container images. These application commands run in the AGW repository; the documentation site does not depend on this toolchain.&lt;/p&gt;&#10;&lt;h2 id="backend"&gt;Backend&#10;&lt;/h2&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-19f1c2b7-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="6"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-19f1c2b7-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git clone https://github.com/zxyao145/agw.git&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; agw&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git config core.hooksPath .githooks&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet restore Agw.slnx&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet tool restore&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet run --project src/server/Agw.Standalone.Host&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Initialize at &lt;code&gt;http://localhost:30816/setup&lt;/code&gt;. Replace &lt;code&gt;dotnet run&lt;/code&gt; with &lt;code&gt;dotnet watch&lt;/code&gt; for hot reload.&lt;/p&gt;</description></item><item><title>Architecture and module boundaries</title><link>https://agw-docs.pages.dev/docs/development/architecture/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://agw-docs.pages.dev/docs/development/architecture/</guid><description>&lt;p&gt;Prerequisite: a working source setup. Identify the business owner of a use case before tracing cross-module capabilities through Contracts.&lt;/p&gt;&#10;&lt;h2 id="backend-organization"&gt;Backend organization&#10;&lt;/h2&gt;&#10;&lt;p&gt;AGW is a modular monolith. &lt;code&gt;Agw.Host&lt;/code&gt; supplies shared hosting; Control Plane, Data Plane, and Standalone compose the modules they need. Business modules follow &lt;code&gt;Api → Application → Domain ← Infrastructure&lt;/code&gt;, creating only necessary layers.&lt;/p&gt;&#10;&lt;pre class="td-mermaid-source"&gt;&lt;code class="language-mermaid"&gt;flowchart LR&#10; API[Api] --&amp;gt; APP[Application]&#10; APP --&amp;gt; DOMAIN[Domain]&#10; INFRA[Infrastructure] --&amp;gt; DOMAIN&lt;/code&gt;&lt;/pre&gt;&lt;div class="td-table-scroll td-table-scroll--static"&gt;&#10;&lt;table&gt;&#10; &lt;thead&gt;&#10; &lt;tr&gt;&#10; &lt;th scope="col"&gt;Layer&lt;/th&gt;&#10; &lt;th scope="col"&gt;Responsibility&lt;/th&gt;&#10; &lt;th scope="col"&gt;What to inspect&lt;/th&gt;&#10; &lt;/tr&gt;&#10; &lt;/thead&gt;&#10; &lt;tbody&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;Api&lt;/td&gt;&#10; &lt;td&gt;Receive requests and return responses&lt;/td&gt;&#10; &lt;td&gt;Routes, inputs, and outputs&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;Application&lt;/td&gt;&#10; &lt;td&gt;Complete a business operation&lt;/td&gt;&#10; &lt;td&gt;Authorization, queries, transactions, and call order&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;Domain&lt;/td&gt;&#10; &lt;td&gt;Hold business data and express rules&lt;/td&gt;&#10; &lt;td&gt;Entities, Behaviors, and DomainServices&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;Infrastructure&lt;/td&gt;&#10; &lt;td&gt;Connect databases and external systems&lt;/td&gt;&#10; &lt;td&gt;Persistence and concrete adapters&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;p&gt;Domain entities hold state. A Behavior handles rules within one Aggregate, while a DomainService handles rules that need facts beyond it. Application loads data, coordinates these calls, and persists changes. Ordinary CRUD stays in Application without creating a Behavior for every entity.&lt;/p&gt;</description></item><item><title>APIs and execution protocols</title><link>https://agw-docs.pages.dev/docs/development/api/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://agw-docs.pages.dev/docs/development/api/</guid><description>&lt;p&gt;Prerequisites: access to a development Server and a valid authenticated identity, such as an API Key or a browser session. Use current OpenAPI and owning-module Contracts for exact fields; this site does not duplicate the complete schema.&lt;/p&gt;&#10;&lt;h2 id="protocol-boundaries"&gt;Protocol boundaries&#10;&lt;/h2&gt;&#10;&lt;div class="td-table-scroll td-table-scroll--static"&gt;&#10;&lt;table&gt;&#10; &lt;thead&gt;&#10; &lt;tr&gt;&#10; &lt;th scope="col"&gt;Interface&lt;/th&gt;&#10; &lt;th scope="col"&gt;Purpose and contract&lt;/th&gt;&#10; &lt;/tr&gt;&#10; &lt;/thead&gt;&#10; &lt;tbody&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;Management JSON APIs&lt;/td&gt;&#10; &lt;td&gt;Bens.Results &lt;code&gt;ApiResult&lt;/code&gt; envelopes, unwrapped by typed client helpers&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;&lt;code&gt;/api/hubs/exec&lt;/code&gt;&lt;/td&gt;&#10; &lt;td&gt;SignalR execution commands, state, and events; mapped by Data Plane and Standalone only and accepts only the WebSocket transport. The official client connects with &lt;code&gt;skipNegotiation: true&lt;/code&gt;&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;&lt;code&gt;/api/agents/permission-capabilities&lt;/code&gt;&lt;/td&gt;&#10; &lt;td&gt;Query supported permissions for a target&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;&lt;code&gt;/api/auth/oidc/providers&lt;/code&gt;&lt;/td&gt;&#10; &lt;td&gt;Enabled sign-in providers, used to render the sign-in buttons&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;&lt;code&gt;/api/auth/oidc/login&lt;/code&gt;&lt;/td&gt;&#10; &lt;td&gt;Redirects to the provider; &lt;code&gt;client&lt;/code&gt; is &lt;code&gt;web&lt;/code&gt; or &lt;code&gt;desktop&lt;/code&gt;&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;&lt;code&gt;/api/auth/desktop/exchange&lt;/code&gt;&lt;/td&gt;&#10; &lt;td&gt;Desktop exchanges a one-time code plus its verifier for an API Key&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;A2A&lt;/td&gt;&#10; &lt;td&gt;Protocol-specific responses, mapped by Data Plane and Standalone only&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;&lt;code&gt;/openapi/*&lt;/code&gt;&lt;/td&gt;&#10; &lt;td&gt;Contract entry point; served, together with the Scalar API reference, only in the Development environment by Control Plane or Standalone&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;p&gt;Sign-in routes are served by Control Plane and Standalone. An API Key obtained by Desktop behaves like a manually created one and accesses resources as its creator.&lt;/p&gt;</description></item><item><title>Extend tools and integrations</title><link>https://agw-docs.pages.dev/docs/development/extensions/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://agw-docs.pages.dev/docs/development/extensions/</guid><description>&lt;p&gt;Prerequisites: understand module boundaries and decide whether the capability is general-purpose or business-owned. Begin with one small, verifiable capability.&lt;/p&gt;&#10;&lt;h2 id="tool-extension-path"&gt;Tool extension path&#10;&lt;/h2&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Put hand-written &lt;code&gt;IAgwTool&lt;/code&gt;, &lt;code&gt;IContextualTool&lt;/code&gt;, and &lt;code&gt;IToolBlock&lt;/code&gt; implementations in &lt;code&gt;Agw.Tools&lt;/code&gt;; the global catalog scans only that assembly for hand-written tools. Business tools belong in their module&amp;rsquo;s &lt;code&gt;Application/Tools&lt;/code&gt;, declared as attributed containers or supplied through a Skill, with DTOs in &lt;code&gt;Contracts/Tools&lt;/code&gt;.&lt;/li&gt;&#10;&lt;li&gt;Reference &lt;code&gt;Agw.Tools.Abstractions&lt;/code&gt;; add &lt;code&gt;Agw.Tools.Generators&lt;/code&gt; as an Analyzer for attributed declarations.&lt;/li&gt;&#10;&lt;li&gt;Explicitly declare permissions, argument descriptions, and return types. Standalone tools and attributed containers stay stateless; session state belongs in a Provider, session, or owned storage.&lt;/li&gt;&#10;&lt;li&gt;Register services and generated declarations in the owning module. Choose Skill exposure or explicit global catalog inclusion.&lt;/li&gt;&#10;&lt;li&gt;Verify discovery, arguments, permissions, project binding, and error mapping.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;The generator emits metadata, JSON Schema, and direct invocation delegates. Do not add runtime reflection scanning as a fallback. Skill tools come from two members: &lt;code&gt;IAgentSkillRegistration.Tools&lt;/code&gt; supplies hand-written &lt;code&gt;IProjectScopedAgwTool&lt;/code&gt; instances, and &lt;code&gt;ToolTypes&lt;/code&gt; supplies attributed container types generated through &lt;code&gt;IAgwToolSet&amp;lt;T&amp;gt;&lt;/code&gt;. They bind to a Project during execution. Registering a generated module does not automatically expose every tool globally.&lt;/p&gt;</description></item><item><title>Testing and contribution</title><link>https://agw-docs.pages.dev/docs/development/testing/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://agw-docs.pages.dev/docs/development/testing/</guid><description>&lt;p&gt;Prerequisite: dependencies are installed. Read root &lt;code&gt;AGENTS.md&lt;/code&gt; and the relevant rules under &lt;code&gt;docs/human/&lt;/code&gt; before changes, and preserve unrelated local work.&lt;/p&gt;&#10;&lt;h2 id="backend-checks"&gt;Backend checks&#10;&lt;/h2&gt;&#10;&lt;p&gt;From the repository root:&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-ab12e404-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="3"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-ab12e404-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet build Agw.slnx&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet &lt;span class="nb"&gt;test&lt;/span&gt; Agw.slnx&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet csharpier check .&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Test projects use xUnit v3 and run on Microsoft.Testing.Platform, selected by the root &lt;code&gt;global.json&lt;/code&gt;. Start with relevant tests when investigating a failure, such as &lt;code&gt;dotnet test tests/Agw.Files.Tests&lt;/code&gt;. Unit and composition tests use real implementations and pure option helpers, never mocks or fake implementations. Constructing &lt;code&gt;CodexAIAgent&lt;/code&gt; or &lt;code&gt;ClaudeCodeAIAgent&lt;/code&gt; probes the CLI, so those tests run as real CLI tests: they are opt-in, require the executable, and stay out of the default suite.&lt;/p&gt;</description></item></channel></rss>