From bc7e4e8d084df44761391a269f761b826c05d59a Mon Sep 17 00:00:00 2001 From: "Robert J. Good" Date: Fri, 28 Aug 2026 22:47:52 -0700 Subject: [PATCH 1/2] governance --- .../Chat/CreateMyChatMessageCommand.cs | 14 ++- .../Chat/CreateMyChatSessionCommand.cs | 10 ++- src/Core.Application/ConfigureServices.cs | 2 + src/Core.Application/Core.Application.csproj | 1 + .../Governance/ChatGovernanceGate.cs | 86 +++++++++++++++++++ .../ChatGovernanceInvocationTests.cs | 44 ++++++++++ src/Tests.Integration/Mocks/MockAIAgent.cs | 6 +- 7 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 src/Core.Application/Governance/ChatGovernanceGate.cs create mode 100644 src/Tests.Integration/Governance/ChatGovernanceInvocationTests.cs diff --git a/src/Core.Application/Chat/CreateMyChatMessageCommand.cs b/src/Core.Application/Chat/CreateMyChatMessageCommand.cs index 03a6795..90cd4d7 100644 --- a/src/Core.Application/Chat/CreateMyChatMessageCommand.cs +++ b/src/Core.Application/Chat/CreateMyChatMessageCommand.cs @@ -1,4 +1,5 @@ using Goodtocode.AgentFramework.Core.Domain.Chat; +using Goodtocode.AgentFramework.Core.Application.Governance; using Microsoft.Agents.AI; using Microsoft.Extensions.AI; @@ -11,10 +12,11 @@ public class CreateMyChatMessageCommand : UserScopedRequest, IRequest> +public class CreateChatMessageCommandHandler(AIAgent agent, IAgentFrameworkContext context, ChatGovernanceGate governanceGate) : IRequestHandler> { private readonly AIAgent _agent = agent; private readonly IAgentFrameworkContext _context = context; + private readonly ChatGovernanceGate _governanceGate = governanceGate; public async Task> Handle(CreateMyChatMessageCommand request, CancellationToken cancellationToken) { @@ -30,7 +32,15 @@ public async Task> Handle(CreateMyChatMessageComma ChatGuard.GuardAgainstUnauthorized(chatSession, request!.UserContext!); - var chatHistory = new List(); + var governed = _governanceGate.Enforce( + request.UserContext, + chatSession.Id, + request.Message!); + + var chatHistory = new List + { + new(ChatRole.System, governed.PromptContext.SystemInstruction) + }; foreach (ChatMessageEntity message in chatSession.Messages) { chatHistory.Add(new ChatMessage( diff --git a/src/Core.Application/Chat/CreateMyChatSessionCommand.cs b/src/Core.Application/Chat/CreateMyChatSessionCommand.cs index 3448730..9bb7d21 100644 --- a/src/Core.Application/Chat/CreateMyChatSessionCommand.cs +++ b/src/Core.Application/Chat/CreateMyChatSessionCommand.cs @@ -1,5 +1,6 @@ using Goodtocode.AgentFramework.Core.Domain.Actor; using Goodtocode.AgentFramework.Core.Domain.Chat; +using Goodtocode.AgentFramework.Core.Application.Governance; using Microsoft.Agents.AI; using Microsoft.Extensions.AI; @@ -14,10 +15,11 @@ public class CreateMyChatSessionCommand : UserScopedRequest, IRequest +public class CreateMyChatSessionCommandHandler(AIAgent kernel, IAgentFrameworkContext context, ChatGovernanceGate governanceGate) : IRequestHandler { private readonly AIAgent _agent = kernel; private readonly IAgentFrameworkContext _context = context; + private readonly ChatGovernanceGate _governanceGate = governanceGate; public async Task Handle(CreateMyChatSessionCommand request, CancellationToken cancellationToken) { @@ -41,8 +43,14 @@ public async Task Handle(CreateMyChatSessionCommand request, Can await _context.SaveChangesAsync(cancellationToken); } + var governed = _governanceGate.Enforce( + request.UserContext, + Guid.Empty, + request.Message!); + var chatHistory = new List { + new(ChatRole.System, governed.PromptContext.SystemInstruction), new(ChatRole.User, request!.Message!) }; diff --git a/src/Core.Application/ConfigureServices.cs b/src/Core.Application/ConfigureServices.cs index c319eea..9f36b97 100644 --- a/src/Core.Application/ConfigureServices.cs +++ b/src/Core.Application/ConfigureServices.cs @@ -1,4 +1,5 @@ using Goodtocode.AgentFramework.Core.Application.Common.Behaviors; +using Goodtocode.AgentFramework.Core.Application.Governance; using Microsoft.Extensions.DependencyInjection; namespace Goodtocode.AgentFramework.Core.Application; @@ -15,6 +16,7 @@ public static IServiceCollection AddApplicationServices(this IServiceCollection services.AddTransient(typeof(IPipelineBehavior<,>), typeof(CustomValidationBehavior<,>)); services.AddTransient(typeof(IPipelineBehavior<,>), typeof(CustomPerformanceBehavior<,>)); services.AddValidationServices(); + services.AddSingleton(); return services; } diff --git a/src/Core.Application/Core.Application.csproj b/src/Core.Application/Core.Application.csproj index 78d9828..4b74243 100644 --- a/src/Core.Application/Core.Application.csproj +++ b/src/Core.Application/Core.Application.csproj @@ -21,6 +21,7 @@ + diff --git a/src/Core.Application/Governance/ChatGovernanceGate.cs b/src/Core.Application/Governance/ChatGovernanceGate.cs new file mode 100644 index 0000000..71225c8 --- /dev/null +++ b/src/Core.Application/Governance/ChatGovernanceGate.cs @@ -0,0 +1,86 @@ +using Goodtocode.Agent.Governance.Application; +using Goodtocode.Agent.Governance.Domain; + +namespace Goodtocode.AgentFramework.Core.Application.Governance; + +/// +/// Builds and enforces the governance envelope for one chat inference operation. +/// +public sealed class ChatGovernanceGate +{ + private readonly GovernanceEnforcer _enforcer = new( + new EvaluationGovernancePromptComposer()); + + /// + /// Enforces governance and returns the system instruction for the chat inference. + /// + public GovernedEvaluationResult Enforce( + IUserContext userContext, + Guid chatSessionId, + string prompt) + { + ArgumentNullException.ThrowIfNull(userContext); + ArgumentException.ThrowIfNullOrWhiteSpace(prompt); + + var correlationId = Guid.NewGuid(); + var request = new GovernanceEvaluationRequest + { + Governance = new EvaluationGovernanceRecord + { + PolicyProfileVersion = "v1", + Observability = new ObservabilityRecord + { + TraceId = correlationId.ToString("N"), + CorrelationId = correlationId, + EvidenceRefs = [GovernanceReference.Parse($"evidence://chat/{chatSessionId:N}")] + }, + Repeatability = new RepeatabilityRecord + { + ModelRef = "model://microsoft-agent-framework/chat-agent", + ModelVersion = typeof(ChatGovernanceGate).Assembly.GetName().Version?.ToString() ?? "unknown", + DeterministicReplaySupported = false, + Seed = null + }, + Auditability = new AuditabilityRecord + { + OwnerId = userContext.OwnerId, + TenantId = userContext.TenantId, + PrincipalDisplay = userContext.Email, + ToolRefs = + [ + GovernanceReference.Parse("tool://agent-framework/chat-sessions"), + GovernanceReference.Parse("tool://agent-framework/actors"), + GovernanceReference.Parse("tool://agent-framework/chat-messages"), + GovernanceReference.Parse("tool://agent-framework/web-search") + ] + }, + Defensibility = new DefensibilityRecord + { + PoliciesApplied = [GovernanceReference.Parse("policy://goodtocode-agent-governance/v1")], + JustificationRefs = [GovernanceReference.Parse("justification://chat/user-request")], + ReasoningSummary = "Respond using applicable tools only when needed and preserve the user and tenant scope of every tool request.", + ConfidenceScore = 1 + } + }, + ExistingSystemInstruction = "You are a helpful assistant operating in a governed chat application.", + RepeatabilityPromptContent = prompt, + RepeatabilityInputs = new Dictionary(StringComparer.Ordinal) + { + ["chatSessionId"] = chatSessionId, + ["ownerId"] = userContext.OwnerId, + ["tenantId"] = userContext.TenantId, + ["prompt"] = prompt + } + }; + + try + { + return _enforcer.Enforce(request); + } + catch (GovernanceValidationException exception) + { + throw new CustomValidationException( + [.. exception.Issues.Select(issue => new ValidationFailure(issue.Field, issue.Message))]); + } + } +} \ No newline at end of file diff --git a/src/Tests.Integration/Governance/ChatGovernanceInvocationTests.cs b/src/Tests.Integration/Governance/ChatGovernanceInvocationTests.cs new file mode 100644 index 0000000..eb32bd1 --- /dev/null +++ b/src/Tests.Integration/Governance/ChatGovernanceInvocationTests.cs @@ -0,0 +1,44 @@ +using Goodtocode.AgentFramework.Core.Application.Chat; +using Goodtocode.AgentFramework.Core.Domain.Chat; +using Microsoft.Extensions.AI; + +namespace Goodtocode.AgentFramework.Tests.Integration.Governance; + +[TestClass] +public class ChatGovernanceInvocationTests : TestBase +{ + [TestMethod] + public async Task CreateChatSessionUsesGovernedSystemInstruction() + { + await Sender.Send(new CreateMyChatSessionCommand + { + Message = "Start a governed chat session" + }, CancellationToken.None); + + (agent.LastMessages.Count > 1).ShouldBeTrue(); + agent.LastMessages[0].Role.ShouldBe(ChatRole.System); + string.IsNullOrWhiteSpace(agent.LastMessages[0].Text).ShouldBeFalse(); + } + + [TestMethod] + public async Task CreateChatMessageUsesGovernedSystemInstruction() + { + var session = ChatSessionEntity.Create( + ownerId: rlsContext.OwnerId, + tenantId: rlsContext.TenantId, + actorId: Guid.NewGuid(), + title: "Governed chat"); + context.ChatSessions.Add(session); + await context.SaveChangesAsync(CancellationToken.None); + + await Sender.Send(new CreateMyChatMessageCommand + { + ChatSessionId = session.Id, + Message = "Continue the governed chat" + }, CancellationToken.None); + + (agent.LastMessages.Count > 1).ShouldBeTrue(); + agent.LastMessages[0].Role.ShouldBe(ChatRole.System); + string.IsNullOrWhiteSpace(agent.LastMessages[0].Text).ShouldBeFalse(); + } +} \ No newline at end of file diff --git a/src/Tests.Integration/Mocks/MockAIAgent.cs b/src/Tests.Integration/Mocks/MockAIAgent.cs index 08af171..dcfb889 100644 --- a/src/Tests.Integration/Mocks/MockAIAgent.cs +++ b/src/Tests.Integration/Mocks/MockAIAgent.cs @@ -6,6 +6,7 @@ namespace Goodtocode.AgentFramework.Tests.Integration.Mocks; public class MockAIAgent : AIAgent { + public IReadOnlyList LastMessages { get; private set; } = []; protected override ValueTask CreateSessionCoreAsync(CancellationToken cancellationToken = default) => new(new MockAgentSession("mock-session")); @@ -20,7 +21,10 @@ protected override ValueTask DeserializeSessionCoreAsync(JsonEleme => new(new MockAgentSession("mock-deserialized-session")); protected override Task RunCoreAsync(IEnumerable messages, AgentSession? session = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default) - => Task.FromResult(new MockAgentResponse("mock-response")); + { + LastMessages = [.. messages]; + return Task.FromResult(new MockAgentResponse("mock-response")); + } protected override async IAsyncEnumerable RunCoreStreamingAsync(IEnumerable messages, AgentSession? session = null, AgentRunOptions? options = null, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default) { From f34b3a1626b9b7cd8bee30c743a9d55a13475bc6 Mon Sep 17 00:00:00 2001 From: "Robert J. Good" Date: Fri, 28 Aug 2026 22:58:57 -0700 Subject: [PATCH 2/2] missing docs added --- .../governance/agent-governance-principles.md | 40 ++++++++++++++++ .../governance/agent-runtime-observability.md | 20 ++++++++ docs/governance/architecture.md | 6 ++- docs/governance/coding-standards.md | 5 ++ docs/governance/development-workflow.md | 2 + .../project-guide-agent-framework.md | 3 +- docs/governance/style-guide-admin.md | 23 ++++++++++ .../tool-design-and-implementation.md | 46 +++++++++++++++++++ docs/product/features/agent-execution.md | 16 +++++++ .../features/feature-definition-of-done.md | 18 ++++++++ docs/product/features/feature-template.md | 15 ++++++ docs/product/features/intent-gap-register.md | 7 +++ .../core/agent-capability-registry.md | 10 ++++ .../sprint-0/agent-runtime-architecture.md | 12 +++++ docs/product/sprint-0/context-diagram.md | 16 +++++++ .../sprint-0/information-architecture.md | 9 ++++ docs/product/sprint-0/journey-roadmap.md | 14 ++++++ docs/product/sprint-0/ontology.md | 27 ++++++----- docs/product/sprint-0/overview.md | 11 +++-- docs/product/sprint-0/user-flows.md | 25 +++++----- docs/product/sprint-0/ux-foundation.md | 10 ++++ 21 files changed, 304 insertions(+), 31 deletions(-) create mode 100644 docs/governance/agent-governance-principles.md create mode 100644 docs/governance/agent-runtime-observability.md create mode 100644 docs/governance/style-guide-admin.md create mode 100644 docs/governance/tool-design-and-implementation.md create mode 100644 docs/product/features/agent-execution.md create mode 100644 docs/product/features/feature-definition-of-done.md create mode 100644 docs/product/features/intent-gap-register.md create mode 100644 docs/product/libraries/core/agent-capability-registry.md create mode 100644 docs/product/sprint-0/agent-runtime-architecture.md create mode 100644 docs/product/sprint-0/context-diagram.md create mode 100644 docs/product/sprint-0/information-architecture.md create mode 100644 docs/product/sprint-0/journey-roadmap.md create mode 100644 docs/product/sprint-0/ux-foundation.md diff --git a/docs/governance/agent-governance-principles.md b/docs/governance/agent-governance-principles.md new file mode 100644 index 0000000..957275c --- /dev/null +++ b/docs/governance/agent-governance-principles.md @@ -0,0 +1,40 @@ +# Agent Governance Principles + +## Purpose +Establish a portable governance baseline for inference-driven applications, independent of model provider, agent framework, or product domain. + +## Mandatory Principles +1. **Observability**: every inference has a trace or correlation identifier and relevant evidence references. +2. **Auditability**: the acting principal, tenant, model, and available tool capabilities are attributable. +3. **Defensibility**: policy, justification context, and confidence assumptions are explicit. +4. **Repeatability**: prompt and input baselines are hashed so equivalent runs and drift can be distinguished. + +## Runtime Boundary +Governance is a precondition for every inference action. Construct a typed governance record, enforce it, and send the resulting system instruction and metadata to the model runtime. When enforcement fails, do not invoke the model. + +```text +Request -> governance record -> governance enforcement -> governed prompt context -> agent/model invocation +``` + +## Baseline Record +Each governed operation records: +- policy-profile version; +- trace and correlation identifiers; +- evidence references; +- owner, tenant, and principal display information; +- model reference and version; +- available or invoked tool references; +- applied policies and justification references; +- raw prompt and typed replay inputs for deterministic hashes. + +## Profiles and Drift +Policy profiles are versioned. A durable workflow may persist a deterministic profile hash and validate it before execution or replay. Simple stateless chat can retain the same metadata in execution telemetry without introducing persistent workflow entities. + +## Optional Evaluation Output +Features that evaluate or score data should use typed output contracts containing score, confidence, criteria, evidence, justification, and audit trace. This is optional for conversational chat and general utility tools. + +## Non-Bypass Rules +- Do not add model calls that skip governance enforcement. +- Do not replace typed governance metadata with unstructured prompt text. +- Do not report a governed outcome without its policy and evidence context. +- Do not claim deterministic replay unless model, configuration, prompt, and inputs are sufficiently captured. \ No newline at end of file diff --git a/docs/governance/agent-runtime-observability.md b/docs/governance/agent-runtime-observability.md new file mode 100644 index 0000000..45b49fb --- /dev/null +++ b/docs/governance/agent-runtime-observability.md @@ -0,0 +1,20 @@ +# Agent Runtime Observability + +## Purpose +Define the minimum evidence needed to diagnose, audit, and improve an agent operation. + +## Correlation +Generate one correlation ID for each user-initiated agent run. Propagate it to inference, tool calls, logs, outbound requests, and persisted run records when the product has them. + +## Minimum Events +- Agent run started and completed or failed. +- Governance enforcement outcome and policy-profile version. +- Model reference and version. +- Tool name, operation, duration, and outcome. +- Validation, authorization, and external-provider failures. + +## Data Handling +Log identifiers, durations, outcome codes, and metadata by default. Treat prompt, tool arguments, model responses, credentials, and customer data as sensitive; redact, hash, or persist them only under an explicit data-retention policy. + +## Replay Evidence +Capture the prompt hash, input hash, model/configuration identity, tool capability version, and policy-profile version. These fields establish whether a later run is comparable to the original. \ No newline at end of file diff --git a/docs/governance/architecture.md b/docs/governance/architecture.md index ed858f1..5267b32 100644 --- a/docs/governance/architecture.md +++ b/docs/governance/architecture.md @@ -31,9 +31,11 @@ This document is the primary architectural authority for the repository. ## Agent Architecture - Use Microsoft Agent Framework integrations in `src/Infrastructure.AgentFramework/`. -- Add plugins in `src/Infrastructure.AgentFramework/Plugins/` and register through service configuration. - Keep orchestration in Application services and infrastructure adapters. -- Tool invocation should be explicit, observable, and testable. +- Use the tool path `Tool -> scoped execution gateway -> mediator pipeline -> command/query handler -> domain/infrastructure`. +- Tools must not query persistence, implement domain policy, or bypass request validation and authorization behavior. +- Enforce governance before every model inference and apply the resulting system instruction at the runtime boundary. +- Preserve correlation, principal, tenant, model, tool, policy, and evidence metadata for agent operations. - Design adapters for future tool and model replacement. ## Definition of Done (Architecture) diff --git a/docs/governance/coding-standards.md b/docs/governance/coding-standards.md index a1dd63d..3881d9d 100644 --- a/docs/governance/coding-standards.md +++ b/docs/governance/coding-standards.md @@ -19,6 +19,9 @@ Define implementation expectations for contributors and AI agents. - Use structured logging with meaningful context. - Validate inbound commands/requests consistently. - Use explicit error handling and return stable outcomes. +- Convert wire or JSON inputs to typed contracts at the application boundary. +- Keep AI tool methods thin: map typed arguments to application requests and shape typed outcomes for conversation. +- Include correlation IDs and outcome metadata in agent and tool logs; never log credentials or sensitive prompt content by default. ## Testing Expectations - Unit tests for domain and application logic. @@ -39,3 +42,5 @@ Generated code must: - Follow naming and coding standards. - Include or update relevant tests. - Follow existing code patterns in the relevant folder before introducing new patterns. +- Use `Description` attributes to define a tool's intent, scope, prerequisites, and side effects. +- Add an architecture guard when a new tool boundary prohibits direct persistence or mediator access. diff --git a/docs/governance/development-workflow.md b/docs/governance/development-workflow.md index 3d2bc9f..8b1de7b 100644 --- a/docs/governance/development-workflow.md +++ b/docs/governance/development-workflow.md @@ -59,3 +59,5 @@ This loop is the default workflow for every session and branch unless the develo - Validate ontology terms before behavior implementation. - Implement smallest complete vertical slice. - Validate build and tests before completion. +- For agent features, document tool side effects, access scope, prompt/model configuration, governance evidence, quality criteria, and rollback or failure behavior. +- Record unresolved product ambiguity in `docs/product/features/intent-gap-register.md` with an owner and closure evidence. diff --git a/docs/governance/project-guide-agent-framework.md b/docs/governance/project-guide-agent-framework.md index 159cf1a..b67b1b3 100644 --- a/docs/governance/project-guide-agent-framework.md +++ b/docs/governance/project-guide-agent-framework.md @@ -6,7 +6,8 @@ Define standards for Agent Framework implementation and operations. ## Standards - Register agents and dependencies through composition roots. - Keep orchestration in Application workflows and infrastructure adapters. -- Implement tools with clear contracts and controlled side effects. +- Implement tools according to [tool-design-and-implementation.md](tool-design-and-implementation.md): typed contracts, scoped execution gateway, application-owned policy, and controlled side effects. +- Enforce [agent-governance-principles.md](agent-governance-principles.md) before every inference action. - Keep prompts versioned and discoverable. - Use memory intentionally; avoid hidden coupling. - Keep dependency registration explicit for testability. diff --git a/docs/governance/style-guide-admin.md b/docs/governance/style-guide-admin.md new file mode 100644 index 0000000..3e8edf1 --- /dev/null +++ b/docs/governance/style-guide-admin.md @@ -0,0 +1,23 @@ +# Administrative Application UX/UI Style Guide + +## Scope +Apply this guide when the template is extended into an administration, operations, configuration, monitoring, or runtime-management application. It does not replace chat or consumer UX guidance. + +## Principles +- Start with existing records and current state before creation forms. +- Make the selected record the center of the working context. +- Progress from collection to selection, details, relationships, history, diagnostics, then actions. +- Show provenance: what happened, why, when, under which configuration, and by whom. +- Present context before mutation or execution. + +## Standard Workspace Order + +```text +Existing records -> selected record -> related records -> runtime/history -> actions -> create or edit forms +``` + +## Operational Questions +Every screen should help answer at least one of: What exists? What is selected? What changed? What ran? What failed? What is related? What should happen next? + +## States +Design empty, loading, error, unauthorized, degraded, and success states explicitly. Preserve keyboard navigation, accessible labels, visible selected state, and status text. \ No newline at end of file diff --git a/docs/governance/tool-design-and-implementation.md b/docs/governance/tool-design-and-implementation.md new file mode 100644 index 0000000..1b90688 --- /dev/null +++ b/docs/governance/tool-design-and-implementation.md @@ -0,0 +1,46 @@ +# Tool Design and Implementation Governance + +## Purpose +Define project-agnostic standards for AI tools that preserve Clean Architecture boundaries. + +## Principles +- Tools translate conversational intent; application and domain layers own business behavior. +- Tool inputs and outputs are explicit, typed, stable, and suitable for model consumption. +- Authorization, tenant scope, ownership, validation, and error semantics flow through application handlers. +- Every tool invocation is observable and every mutation is auditable. + +## Required Invocation Path + +```text +Tool method -> scoped tool base -> application execution gateway -> mediator pipeline -> command/query handler -> domain or infrastructure +``` + +Tools must use a shared scoped execution pattern such as `ScopedAgentTool` and `IToolApplicationExecutor`. They must not access a `DbContext`, repository, ORM, SQL connection, or mediator directly. + +## Tool Responsibilities +- Validate argument shape that the runtime cannot validate. +- Map an operation to a typed command or query. +- Invoke that request through the shared gateway. +- Return a clear, concise response without changing its underlying meaning. +- Describe purpose, scope, prerequisites, side effects, and intended use with `Description` attributes. + +## Application Responsibilities +- Own use cases, invariants, authorization, and tenant/owner filtering. +- Return typed results and explicit validation, not-found, conflict, or forbidden outcomes. +- Apply governance and observability requirements before inference or side effects. + +## Side Effects +- Read tools are side-effect free. +- Write tools require explicit user confirmation when the action is consequential. +- A successful write may return a compact follow-up action for the chat UI, but it must never bypass the normal user-message to assistant-message flow. + +## Testing and Guardrails +- Unit test tool argument mapping and conversational result shaping. +- Integration test the command/query behavior, including authorization and RLS. +- Add architecture tests that reject direct persistence access, direct mediator resolution, direct scope creation outside the shared base, and direct `AITool` inheritance outside that base. + +## Definition of Done +- Tool behavior is implemented through typed application requests. +- Tool descriptions tell the model when to call the tool and its scope. +- Side effects are explicit and auditable. +- Relevant handler, tool, and architecture tests pass. \ No newline at end of file diff --git a/docs/product/features/agent-execution.md b/docs/product/features/agent-execution.md new file mode 100644 index 0000000..fcc0c27 --- /dev/null +++ b/docs/product/features/agent-execution.md @@ -0,0 +1,16 @@ +# Agent Execution Feature + +## Overview +The reference agent-execution feature accepts a chat message, applies governance, invokes a Microsoft Agent Framework agent, optionally routes tools through typed application requests, and persists the resulting conversation. + +## Acceptance Criteria +- [ ] Every model invocation is governed before it runs. +- [ ] User and assistant messages remain ordered and tenant/owner scoped. +- [ ] Tools use the shared scoped execution gateway rather than direct persistence access. +- [ ] Suggested prompts and follow-up actions reuse the normal message submission flow. +- [ ] Tool descriptions define intended use and side effects. + +## Out of Scope +- Long-running workflow orchestration. +- Domain-specific scoring and evaluation schemas. +- Cross-service agent coordination. \ No newline at end of file diff --git a/docs/product/features/feature-definition-of-done.md b/docs/product/features/feature-definition-of-done.md new file mode 100644 index 0000000..dcd109b --- /dev/null +++ b/docs/product/features/feature-definition-of-done.md @@ -0,0 +1,18 @@ +# Feature Definition of Done + +## Intent and Contracts +- [ ] User outcome, non-goals, and acceptance criteria are documented. +- [ ] Ontology terms and ownership boundaries are explicit. +- [ ] API, application, and persistence contracts are typed and stable. + +## Agent Features +- [ ] Agent prompts, model configuration, tools, and memory boundaries are documented. +- [ ] Inference enforces observability, auditability, defensibility, and repeatability requirements. +- [ ] Tool side effects, confirmation requirements, and authorization scope are explicit. + +## Quality +- [ ] Empty, error, unauthorized, and success states are designed. +- [ ] Domain/application tests cover changed behavior and invariants. +- [ ] Integration tests cover contracts, access boundaries, and relevant error paths. +- [ ] Build and targeted tests pass. +- [ ] Feature documentation and any resolved intent gaps are updated. \ No newline at end of file diff --git a/docs/product/features/feature-template.md b/docs/product/features/feature-template.md index 5527ce3..edb1925 100644 --- a/docs/product/features/feature-template.md +++ b/docs/product/features/feature-template.md @@ -33,6 +33,21 @@ Describe entities, value objects, aggregates, or domain events impacted. ## Application Changes Describe handlers/use cases, validation, orchestration, and contracts. +## Agent and Tool Contract +Describe the agent action, available tools, typed arguments/results, authorization scope, and any write confirmation requirement. + +## Prompt, Model, and Memory +Describe system instructions, prompt inputs, model/configuration identity, memory boundaries, and expected fallback behavior. + +## Observability and Audit +Describe correlation, evidence references, policy profile, audit metadata, retention, and sensitive-data handling. + +## Runtime States +Describe loading, empty, streaming or pending, failed, unauthorized, degraded, and successful states. + +## Evaluation and Quality Criteria +Describe quality measurements, acceptance examples, and any evaluator or replay baseline. Mark this section not applicable when the feature has no evaluative behavior. + ## UI Changes Describe pages, components, routing, and UX behavior. diff --git a/docs/product/features/intent-gap-register.md b/docs/product/features/intent-gap-register.md new file mode 100644 index 0000000..1775f99 --- /dev/null +++ b/docs/product/features/intent-gap-register.md @@ -0,0 +1,7 @@ +# Intent Gap Register + +Track unresolved product or technical intent before implementation. Remove a row only when closure evidence is recorded in the related feature document or decision record. + +| Gap | Consequence | Owner | Required artifact | Closure evidence | +|---|---|---|---|---| +| Example: retention policy for governed prompts | Sensitive data may be retained inconsistently | Product owner | Feature decision | Linked approved policy | \ No newline at end of file diff --git a/docs/product/libraries/core/agent-capability-registry.md b/docs/product/libraries/core/agent-capability-registry.md new file mode 100644 index 0000000..85f03a8 --- /dev/null +++ b/docs/product/libraries/core/agent-capability-registry.md @@ -0,0 +1,10 @@ +# Agent Capability Registry + +## Purpose +Optional pattern for products that need a durable, typed catalog of available agents, tools, model configurations, or external capabilities. + +## Guidance +- Use typed descriptors with stable IDs, version, display name, allowed tenants, required permissions, and input/output contract references. +- Validate registrations at startup or deployment. +- Keep capability resolution in Application or Infrastructure composition, never in UI markup. +- Do not introduce a registry for the baseline template until capabilities must be configured independently of code. \ No newline at end of file diff --git a/docs/product/sprint-0/agent-runtime-architecture.md b/docs/product/sprint-0/agent-runtime-architecture.md new file mode 100644 index 0000000..e77f8ef --- /dev/null +++ b/docs/product/sprint-0/agent-runtime-architecture.md @@ -0,0 +1,12 @@ +# Agent Runtime Architecture + +## Lifecycle +1. An authenticated user submits a chat message. +2. The application validates tenant and owner context. +3. Governance produces a governed system instruction and execution metadata. +4. The agent receives the governed instruction and conversation history. +5. When needed, the agent invokes a scoped tool through the application execution gateway. +6. The application persists the user message and assistant result, then the UI refreshes the ordered conversation. + +## Boundaries +The agent chooses whether to request a tool. Application handlers own authorization, business behavior, and persistence. The UI can offer suggested prompts and tool follow-up actions, but both must use the normal message submission path. \ No newline at end of file diff --git a/docs/product/sprint-0/context-diagram.md b/docs/product/sprint-0/context-diagram.md new file mode 100644 index 0000000..7d4b953 --- /dev/null +++ b/docs/product/sprint-0/context-diagram.md @@ -0,0 +1,16 @@ +# Context Diagram + +```mermaid +flowchart LR + User[Authenticated user] --> Web[Blazor web application] + Web --> Api[Web API] + Api --> App[Application commands and queries] + App --> Governance[Governance enforcement] + Governance --> Agent[Microsoft Agent Framework agent] + Agent --> Tools[Scoped AI tools] + Tools --> App + App --> Sql[(SQL Server)] + Tools --> External[Approved external providers] +``` + +The web application never accesses persistence directly. Tools are infrastructure adapters that invoke typed application requests. Governance is applied before each model inference. \ No newline at end of file diff --git a/docs/product/sprint-0/information-architecture.md b/docs/product/sprint-0/information-architecture.md new file mode 100644 index 0000000..74e9f6e --- /dev/null +++ b/docs/product/sprint-0/information-architecture.md @@ -0,0 +1,9 @@ +# Information Architecture + +## Baseline Surfaces +- **Home**: anonymous entry point. +- **Dashboard**: authenticated summary when the product requires one. +- **Chat**: conversation list, active transcript, suggested prompts, follow-up actions, and message input. +- **Administration**: optional record-first operational surfaces for configuration, agents, tools, and runtime history. + +The chat transcript remains the primary context. Suggested prompts and follow-up actions sit adjacent to input controls, never inside or between persisted message bubbles. \ No newline at end of file diff --git a/docs/product/sprint-0/journey-roadmap.md b/docs/product/sprint-0/journey-roadmap.md new file mode 100644 index 0000000..f0771f2 --- /dev/null +++ b/docs/product/sprint-0/journey-roadmap.md @@ -0,0 +1,14 @@ +# Journey Roadmap + +## Baseline +1. Authenticate and provision the user-facing actor. +2. Start, resume, and review a chat session. +3. Submit a governed agent request. +4. Read tenant- and owner-scoped data through tools. +5. Confirm and perform an explicit write tool action. + +## Optional Extensions +- Durable agent run history and replay. +- Agent and tool administration. +- Domain-specific evaluations and typed outcomes. +- Operational dashboards and diagnostics. \ No newline at end of file diff --git a/docs/product/sprint-0/ontology.md b/docs/product/sprint-0/ontology.md index dcfc8d8..1f47cca 100644 --- a/docs/product/sprint-0/ontology.md +++ b/docs/product/sprint-0/ontology.md @@ -9,27 +9,32 @@ Authoritative source for domain terminology and ubiquitous language. - Resolve synonyms here before feature implementation. ## Core Concepts -- **Tenant**: organizational boundary for users and assets. -- **User**: person interacting with application capabilities. -- **Asset**: monitored digital resource requiring classification and actions. -- **Agent**: AI-driven component that orchestrates analysis or mitigation. -- **Work Item**: actionable unit generated from detections or user intent. +- **Tenant**: organizational boundary for protected data and capabilities. +- **User**: authenticated person interacting with application capabilities. +- **Actor**: the persisted representation of a user used by application records. +- **Chat Session**: an owned conversation context containing ordered messages. +- **Chat Message**: a user, assistant, or system message in a chat session. +- **Agent**: an AI-driven component that receives governed chat context and may invoke tools. +- **Tool**: a typed, scoped capability exposed to the agent through the application request pipeline. +- **Governed Inference**: an agent invocation with explicit observability, auditability, defensibility, and repeatability metadata. ## Relationships -- A Tenant contains many Users and Assets. -- Assets can generate multiple Work Items. -- Agents analyze Assets and propose actions for Work Items. +- A Tenant contains Users, Actors, Chat Sessions, and Chat Messages. +- A User maps to an Actor and owns Chat Sessions within a Tenant. +- A Chat Session contains ordered Chat Messages. +- An Agent responds to Chat Messages and can invoke scoped Tools. +- A Governed Inference records the context for an Agent response. ## Synonyms -- Work Item: task, ticket (avoid in code unless required by integration). -- Asset: resource, monitored entity (prefer **Asset**). +- Conversation: chat session (prefer **Chat Session** for persisted context). +- Plugin/function: tool (prefer **Tool** for an agent capability). ## Invariants - Each concept has one canonical term. - Terms in feature documents must map to concepts here. ## Out of Scope / Deferred -- Detailed event timelines and workflow ordering (captured in event storming/user flows). +- Durable workflow orchestration, long-running runs, and domain-specific evaluation are optional extensions. ## Definitions When new terms are introduced, add definitions here before feature implementation. diff --git a/docs/product/sprint-0/overview.md b/docs/product/sprint-0/overview.md index 0de8e63..a2db439 100644 --- a/docs/product/sprint-0/overview.md +++ b/docs/product/sprint-0/overview.md @@ -7,7 +7,7 @@ Sprint 0 establishes the minimum viable design and delivery foundation for a new Sprint 0 is strictly time-boxed to two weeks. ## Product Purpose -Provide a practical Microsoft Agent Framework quick start that accelerates delivery of AI-enabled business applications with strong architecture and maintainable defaults. +Provide a practical Microsoft Agent Framework quick start for building authenticated, governed, tool-enabled chat applications with Blazor, Web API, SQL Server, and Clean Architecture. ## Target Audience - Solution architects @@ -22,8 +22,8 @@ Provide a practical Microsoft Agent Framework quick start that accelerates deliv ## Core Design Sequence 1. Ontology definition (what exists). -2. Event storming (what happens). -3. Scope and bounded context definition. +2. User journeys and state transitions (what happens). +3. Agent, tool, and governance contract definition. 4. Architecture and delivery scaffolding. ## Success Metrics @@ -32,6 +32,7 @@ Provide a practical Microsoft Agent Framework quick start that accelerates deliv - Fewer architecture and standards violations in pull requests. ## High-Level Scope -- Clean architecture baseline with Web API, Blazor UI, SQL persistence, and Agent Framework integration. -- Reusable governance and feature documentation structure. +- Clean architecture baseline with Web API, Blazor UI, SQL persistence, and Microsoft Agent Framework integration. +- Governed inference and scoped tool-execution baseline. +- Reusable governance, sprint-0, and feature documentation structure. - AI-ready knowledge hierarchy (governance, sprint-0, features). diff --git a/docs/product/sprint-0/user-flows.md b/docs/product/sprint-0/user-flows.md index 5bc3760..431b65d 100644 --- a/docs/product/sprint-0/user-flows.md +++ b/docs/product/sprint-0/user-flows.md @@ -8,26 +8,27 @@ Authoritative source for user journeys and expected behavior paths. - Keep flows implementation-agnostic. - Capture success, alternate, and error paths explicitly. -## Actor: Operations User +## Actor: Authenticated User ### Entry Points -- Sign in and open dashboard. -- Open asset detail page. -- Review AI-generated recommendations. +- Sign in and open chat. +- Start or select a chat session. +- Submit a message or choose a suggested prompt. ### Success Path -1. User selects an asset. -2. System loads status, classifications, and recommendations. -3. User confirms an action. -4. System creates or updates a work item and records outcome. +1. User submits a message. +2. System constructs governance context and invokes the agent. +3. Agent responds and may use a scoped tool through the application pipeline. +4. System persists and displays the ordered user and assistant messages. +5. When a write tool returns a follow-up action, the user can select it and the normal message flow continues. ### Alternate Paths -- User defers recommendation and marks for later review. -- User updates recommendation parameters before execution. +- User selects a suggested prompt to auto-send it through the normal chat input. +- Agent requests confirmation before invoking a consequential write tool. ### Error Paths -- Asset data unavailable: show recoverable error and retry option. -- Recommendation execution failure: return actionable ProblemDetails and audit event. +- Agent or tool failure: return a clear, recoverable error and retain the conversation context. +- Unauthorized or unavailable data: do not disclose protected data; return the application outcome. ## Notes - Use these flows to derive acceptance criteria in feature documents. diff --git a/docs/product/sprint-0/ux-foundation.md b/docs/product/sprint-0/ux-foundation.md new file mode 100644 index 0000000..b0f39cf --- /dev/null +++ b/docs/product/sprint-0/ux-foundation.md @@ -0,0 +1,10 @@ +# UX Foundation + +## Chat +- Preserve ordered user and assistant bubbles as the durable conversation record. +- Auto-send suggested prompts through the same path as typed input. +- Render tool follow-up actions outside the transcript and remove their transport metadata from assistant content. +- Disable input while a message is submitting and make failure states actionable. + +## Operations +When an admin surface is added, follow [style-guide-admin.md](../../governance/style-guide-admin.md): records first, selected context second, actions after context. \ No newline at end of file