M3: Agent bound to a seat — configure an AI seat

OrgBoard: Agent entity (name, monogram, autonomy dial, ApiConfigId + optional fallback,
skill keys, docs) + AddAgents migration; one agent per seat. References Skills by key and
the BYOK config by id — never reaches into those modules.

Endpoints: POST/GET /api/orgboard/seats (create/list seats), POST/GET
/api/orgboard/seats/{id}/agent (configure/read the agent) — ConfigureAgents at [team, org].
Configuring an agent flips the seat to the AI state and points it at the agent; audited.

Verified: build green; ArchitectureTests 8/8; IntegrationTests 27/27 incl. the M3 acceptance
flow — owner adds a BYOK config, then configures "Aria" (gated autonomy, skills, that config)
on a seat, flipping it to AI, with the key never exposed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-09 23:49:28 +03:30
parent 1559975518
commit e202246a1c
10 changed files with 658 additions and 1 deletions
@@ -0,0 +1,54 @@
using TeamUp.SharedKernel.Access;
using TeamUp.SharedKernel.Domain;
namespace TeamUp.Modules.OrgBoard.Domain;
/// <summary>
/// The AI staffing an open seat: identity (name, monogram) + matched skill atoms + autonomy +
/// the model config + docs. References Skills by key and the BYOK ApiConfig by id — never reaches
/// into those modules' tables. One agent per seat.
/// </summary>
internal sealed class Agent : Entity
{
public Guid SeatId { get; private set; }
public string Name { get; private set; } = null!;
public string? Monogram { get; private set; }
public Autonomy Autonomy { get; private set; }
public Guid ApiConfigId { get; private set; }
public Guid? FallbackApiConfigId { get; private set; }
public List<string> SkillKeys { get; private set; } = [];
public List<string> Docs { get; private set; } = [];
public DateTimeOffset CreatedAtUtc { get; private set; }
public DateTimeOffset UpdatedAtUtc { get; private set; }
private Agent()
{
}
public Agent(Guid seatId, DateTimeOffset createdAtUtc)
{
SeatId = seatId;
CreatedAtUtc = createdAtUtc;
UpdatedAtUtc = createdAtUtc;
}
public void Configure(
string name,
string? monogram,
Autonomy autonomy,
Guid apiConfigId,
Guid? fallbackApiConfigId,
List<string> skillKeys,
List<string> docs,
DateTimeOffset nowUtc)
{
Name = name;
Monogram = monogram;
Autonomy = autonomy;
ApiConfigId = apiConfigId;
FallbackApiConfigId = fallbackApiConfigId;
SkillKeys = skillKeys;
Docs = docs;
UpdatedAtUtc = nowUtc;
}
}