Architecture
The home of this section. Where everything lives and how it communicates. Detailed diagrams live here and in the module documents (Configuration, Development module (id source), Support, Data and Information); the goals chapter carries no diagrams — the platform picture below is the one place it is drawn (D150), in the four states of Gating § 1b (D148). Memory and skills are one page: Agents Memory and Skills.
0. The platform, and the modules on it
P The middle of this picture is the product: five platform parts that do not change per customer, and the modules — each one a graph of profiled agents — that run on them. Support is the root module (decision Vladimir, 04.09.2026 — D143): every client request enters there, is classified and identified, and either waits or is routed to one of the three working modules — Configuration, Development, or Data and information, the former Support module's working stages (D144). The channels above and the estate below are the Bulstrad case study; a second customer replaces those bricks and nothing else (PG-23, D77).
Every box is clickable. A module opens its page, whose head carries its agent tree, its branch of the memory tree and its skills, in that order (D145); everything else opens the document that specifies it — and a channel or a system opens the Whitelabel Catalogue, because which channels and which systems is a plug-in value, not a rule of the architecture. Every profile, with what it boots from, what it may write and what it is denied, is in Agents and the modules' components pages.
flowchart TB H["People teach and decide"]:::owner K["Reviewed knowledge
and executable skills"]:::learn A["Trainable agent profiles"]:::work R["Support root
one durable case"]:::owner C["Configuration"]:::work D["Data and information"]:::work S["Development"]:::work G["Audited proposal
required decisions"]:::decision X["Backend executes
through connectors"]:::work V["Prove the requested result"]:::proof L["Retain experience
evaluate proposed changes"]:::learn W["Wait on an explicit trigger"]:::store H -->|"teach"| K K -->|"context and skills"| A A -->|"work as a case"| R R --> C R --> D R --> S R -.->|"when needed"| W C -->|"propose"| G D -->|"propose"| G S -->|"propose"| G H -.->|"role or eligible policy"| G G -->|"authorised packet"| X X -->|"current evidence"| V V -.->|"queue after result"| L L -.->|"review and publish"| K classDef work fill:#eef4ff,stroke:#6889ba,color:#17365b,stroke-width:1.3px classDef decision fill:#fff4df,stroke:#b78c36,color:#65470d,stroke-width:1.5px classDef proof fill:#e9f5ef,stroke:#689b81,color:#224e39,stroke-width:1.3px classDef learn fill:#f1edf9,stroke:#9580b9,color:#534172,stroke-width:1.3px classDef store fill:#f5f7fa,stroke:#98a6b7,color:#34445a,stroke-width:1.2px classDef owner fill:#24486b,stroke:#24486b,color:#ffffff,stroke-width:1.4px click H href "ui.html" "People define outcomes, review learning and hold the required decisions." click K href "50-agents/agents-memory.html" "Owned, versioned knowledge informs future work; it never grants authority." click A href "50-agents/agent-framework.html" "Prompts, skills and model routes change through evaluation and publication." click R href "40-support/support-module.html" "Authorised requests enter here; the root retains clocks and the customer outcome." click C href "20-configuration/configuration-module.html" "Existing-product deltas, rating templates and scoped product changes." click D href "40-support/data-and-information-module.html" "Answers and repairs under the same Support root." click S href "30-source/source-module.html" "Bounded code changes across the actual source lineage." click G href "gating.html" "Compose checkpoint and effect requirements for the exact revision and target." click X href "software-architecture.html" "Deterministic software owns grants, execution, persistence and recovery." click V href "case-protocol.html" "Join family members, targets and external obligations; distinguish preview from delivery." click L href "50-agents/agents-memory.html" "Learning is durably queued from every module; only confirmed knowledge is reused." click W href "40-support/support-module.html" "Customer action, external work or a future release stays visible with its age."
The operating model: teach → apply → prove → retain. Solid arrows carry work; dashed arrows show conditional work or feedback. All modules use the same governed execution path.
Stage ids name the stage documents, not a running order (D83).
Inside the platform, in the order a case travels: the interface is the only place a person answers anything; the backend owns the case, its papers, its grants and the ledger; the framework runs the turn loop and the tool pipeline; the graphs are the profiles the framework instantiates; and every profile reads one memory tree and writes only its own node. The concrete map — which library, which table, which transport — is § 1. Every module reaches every system it needs; the single arrows below are drawn to keep the picture legible, not to say a module is limited to one target.
| Area | Goal in one sentence | Documents |
|---|---|---|
| Platform · UI | One administration section in serdica-ui — Inbox, Cases with the case chat, Decisions, Studio, Knowledge, Metrics, Control; many viewers, one controller; every card says where it is about; the Customer representative's client app. | Platform § UI · UI |
| Platform · Backend | A C# service in serdica-backend, one deployment on the Bulstrad QA host reaching every environment directly through connectors (D132): cases and sessions, the append-only ledger, gates and grants, SRD_SUPPORT (Data Model), retention as configuration, operational controls. |
Platform § Backend · Software Architecture |
| Platform · Agent framework | What every agent gets: a native turn loop over a copied, owned provider abstraction — tools under grants, memory access, gates, records, spawning, governance and evaluation, operations — with no framework dependency unless it saves work. | Platform § Agent framework · Agent Framework · Agent Runtime |
| Platform · Agent graphs | Each module is a graph of profiled agents: a root that converses with the operator, stage agents, isolated verifiers and write executors, connector agents; consults are evidence, handovers are gates; the graph is data — and each module draws its own at the head of its page. | Platform § Agent graphs · Agents |
| Platform · Knowledge domains | One memory tree with an AGENTS.md index per node; one writing profile owns each domain; articles governed, versioned and pinned; a past-case index; an inherited corpus migrated per domain on a measured hit-rate — the principles on the framework page, each module's branch on its own page. |
Platform § Knowledge domains · Agents Memory and Skills |
| Support — the root | Every client request classified against the contract, identified, and routed: waiting, Configuration, Development, or Data and information; the case, its clocks and its closure stay here — one voice to the customer. | Support · Support Module |
| Configuration | From stray input documents to a normalized specification to a configured, tested product — deployed as far as the user chooses, through defined human gates. | Configuration · Configuration Module |
| Data and information | The former Support module's working stages: methodology-driven investigation, the take by kind (skill / memory / combination), gated writes and sends, verification on the customer's surface, precipitation into skills and memory. | Support · Data and Information Module |
| Development | The Development module (id source) handles ad-hoc fixes and small extensions: staging-first, customer-specific placement first, mandatory deployment + testing + reversal. |
Development · Development Module |
P Where the agent trees are (D145). Each module page opens with its agent tree, then its branch of the memory tree, then its skills and tools: Configuration Module § 0 · Support Module § 0 · Data and Information Module § 0 · Development Module § 0. The platform pages of this chapter state the rules those trees obey and one example each; they draw no module.
1. Where and how — the concrete map
P Developer entry. Implementation Guide gives the first build increments and acceptance tests. Modules binds the business graphs to versioned data. Model Execution explains the actual provider seam and LLM/software boundary. Runtime defines the transactions and recovery; the proposed schema includes its journal, inbox and impact claims.
| Concern | Where | How |
|---|---|---|
| Libraries | __Libraries of the AI.Support module + libraries copied from the health branch and owned (D37, D48; Software Architecture § 9) |
referenced projects; customer specifics only in __Plugins |
| Delegations | in-process: root → stage → sub-agents inside the session worker (explicit task context/tool facades; standard DI scopes do not remove services). Cross-service: peer agents (backend/frontend/db owners, long stages) via the ServiceActivity contract + RabbitMQ outbox [F: inspected 31.08.2026] | plans/results as versioned payloads; every delegation is an audit record |
| Configurations | agent profiles, skills, policies, model routes, connector scopes = versioned rows in SRD_SUPPORT (data, not enums); service config = appsettings per env branch; secrets = Vault via make prepare_files [F: inspected 31.08.2026] |
governance flow for anything model-facing: draft → test → publish (Agent Framework § 6 skill lifecycle) |
| UI screens | one serdica-ui administration section, workspaces (D119): Inbox (arrivals re-briefed from their source), Cases (list: state, where, controller, waiting on, clocks) with the case chat (one thread of cards: brief, agent steps with stated reasoning for a step — not raw model chain-of-thought, which is neither a dependable API nor appropriate operational output —, tool calls with where-chips and result summaries, questions, plans, decision packets, verdicts, writes, memory reads and writes; papers in the Where rail), Decisions (pending H-decisions with decision packets, held batches, shape training), Studio (prompts, skills, eval sets: versions, eval runs, publish, rollback), Knowledge (the memory tree, proposals, articles), Metrics (ledger parsers' output), Control (connectors, roles & policies, exceptions & kill switch) | realtime feed over SignalR on the health path's proven topology — hub + one-use Redis ticket + HMAC group alias + Rabbit fan-out + transactional outbox [F: working code, S14.1-T2 DONE, verified 01.09.2026]; the AI.Support module reuses that pattern and the workflow-generic workflow.execution.changed.v1 event, not the claim-keyed hub, whose admin counterpart the program deliberately deferred to polling; auth = Authority; endpoints registered like any service (SRD_SYS."EndPoints" + core appsettings.json for old-style) [F: inspected 31.08.2026] |
| Workspaces | per-case working directory holding the papers (plan, contract artifact, write log, build state, MISSING, report — Agent Runtime); per-repository git worktrees for Development cases; scenario workspaces for evals [F: local-setup precedent, inspected 31.08.2026; PC products/<code>/ layout] |
created on case open, survives workers, archived on close |
| DB | the target schema SRD_SUPPORT (not yet created — verified 03.09.2026; D30/D47) on db.serdicaqa.bulstrad.bg (Bulstrad QA, 10.239.82.106, SID orcl1), alongside the QA SRD_INTEGR, with its own connection identity and role set [P: decision 02.09.2026 — the development target is Bulstrad QA, not the Ablera dev database; per-environment placement is in Software Architecture] [F: SRD_AI is hard-coded in 390 places with no HasDefaultSchema — the count, its unit and its date are Software Architecture § 9.2, inventory 02.09.2026 — and it holds no case/session/task tables, so this is new tables on a copied pattern rather than a rename] |
the table set is § 3.1; script layout, twice-runnable idempotency, per-table grants and immutability triggers copied from AI.Persistence; retention evaluator from day one. ⚠ Sharing a database with SRD_INTEGR means the PL/SQL snapshot store shares a failure domain with the packages it exists to protect (Stage Planning § 3b) — accepted, and the reason the snapshots are append-only and mirrored to a git repository the agent owns |
| Skills | source of truth = Markdown in the memory tree (domain-owned); runtime copy = DB catalogue with versions/permissions; customer packs = plugins | executable skills (getRates/offer/policy tests, diagnostic packs) bind an instruction to connector tools + assertions; governed via test→publish |
| Tools | one connector library per system — the complete set is Software Architecture § 3 — instantiated per environment scope | refusal-before-contact, statement logging (never rows), dry-run defaults, and a capability description per operation — accepted input, target identity, expected effects, authorization needed, timeout behaviour, recovery properties (Failure and Recovery § 4). Registering a connector does not establish live access. Seeds: v1 CLIs, PC gates, McpProxy [F: inspected 31.08.2026] |
3.1 SRD_SUPPORT — the table set P
Versioned DbScripts in the reused pattern: baseline → numbered upgrades → grants → verify → retention (Software Architecture § 9.2). The scripts exist (D140, 04.09.2026): Data Model lists them, draws the schema and names what the DDL adds beyond this table — 50 tables, 26 unique guard triggers after the runtime upgrade; linted, not yet executed (no SRD_SUPPORT user — D47).
| Group | Tables | Key columns |
|---|---|---|
| Work | CASES, SESSIONS, TASKS |
case type, module, objective, state, controller, SLA clock; task parent, dependencies, assigned profile |
| Planning | PLANS, PLAN_STEPS, PLAN_REVISIONS |
step id (stable), assertion, effect class, status; revision lineage |
| Decisions | GATES, GATE_DECISIONS, GRANTS, WRITE_SHAPES |
gate kind (the gate kinds of Gating § 1), decision packet, approver, scope; grant scope, expiry, issuing decision; write-shape state |
| Evidence | PAPERS, WRITE_LOG, BUILD_STATE, MISSING, PLSQL_SNAPSHOTS, CASE_HANDLES |
the working-paper set (Agent Runtime § 11.2); write log records statement + target + mode + row count, never rows; handles are case-local |
| Ledger | AUDIT_LEDGER, COST_LEDGER |
append-only, per § 3.2; extends AiCostLedgerStore / AiProviderAttemptStore |
| Registry | PROFILES, PROMPTS, SKILLS, CONNECTOR_SCOPES, EVAL_SETS, MEMORY_ARTICLES |
versioned rows with state draft/testing/published/retired (Agents, Agent Framework); memory article projection rows |
| Queues | HELD_BATCHES |
approved-but-unapplied work, with age — the fix for v1's 12-week HDesk plateau (Baseline § 5) |
3.2 The ledger P
Append-only and tamper-evident — the mechanism, not just the adjective:
| Layer | What it is |
|---|---|
| Append-only | BEFORE UPDATE OR DELETE triggers on the ledger tables, the pattern the AI branch already uses for prompt immutability (002-immutability-and-payload-guards.sql). Enforced in the database rather than the service, because the service is the thing being audited |
| Hash chain | each record carries prev_hash and record_hash = H(prev_hash ‖ canonical(record)), so a silent edit or deletion breaks the chain from that point on. Canonicalisation reuses SERDICA-JCS-1 from AI.Contracts rather than inventing a second one |
| Sealing | the chain head is sealed periodically — head hash, record count, timestamp. P The sealer is owned, not ambient (D66): a hosted job inside the Support webservice (ISealer, Software Architecture § 3) computes the seal on the configured interval (ledger.seal_interval), and the exporter — the same job — writes the seal plus the delta since the previous seal as canonical JSONL to the agent-owned GitLab repository through the GitLab connector (D45). verify-ledger.sql compares the chain head against the last exported seal; a seal/export lag beyond one interval is an operations alert (Software Architecture § 10.5) and a ledger event of its own |
| Correction | a new linked record of kind CORRECTION naming what it supersedes. Nothing is rewritten; a reader sees both and their order |
| Projections | search indexes and the evidence graph are rebuildable. Losing them costs time; losing the ledger loses the audit |
P The threat model is the honest gap. These controls stop the service and its agents from rewriting history, which is what they are for. They do not stop a DBA: triggers can be disabled, and whoever can restore a backup can replace the chain wholesale. Defeating that needs an anchor outside the database — the periodic seal written where the DB account cannot reach, or countersigned externally. P The DBA is in the threat model for detection, not prevention (Challenge Rounds § R2 § 11): the 15-minute seal export to a repository/storage boundary unavailable to the database credential (D45) is the anchor the database account cannot reach; verify-ledger.sql compares the chain head against the last exported seal, so a rewrite of already anchored history is detectable against that export; the unsealed tail is bounded by the export interval; external countersigning is not built. P The restore rehearsal must detect a deliberately shortened chain from the export; no rehearsal has run yet.
P After a point-in-time restore the chain is intact but shorter: the gap between restore point and failure is lost audit. A restore is itself a ledger event and the retention policy must say so.
A mistake is corrected by a linked correction record, never by rewriting. Each record carries actor and case/task ancestry · profile, prompt and adapter versions · plan revision and parent decision · applicable policy and grant · the exact requested action · what actually ran · verification result · payload hash and artefact hashes, never payloads or result rows (Trust and Data § 5).
The evidence graph is a projection over it: sources, extracted statements, queries, logs, code references, interpretations, plans, clarifications, changes, test results and recovery evidence, related by support / contradiction / derivation / confirmation / supersession. It answers, per case: what did the agent know before proposing this · which source or precedent supports the interpretation · what did the parent confirm and what authority permitted execution · what was requested and what actually changed · what was verified · what remains uncertain.
Metrics are parsed from the ledger by tools, never counted by agents (CR-1, Metrics).
2. Communication
sequenceDiagram
autonumber
actor U as Person or channel
participant B as Case service
participant A as Root and specialist
participant X as Executor and connector
participant K as Knowledge owner
U->>B: Request or scoped response
B->>A: Durable task and pinned context
A-->>B: Plan, evidence or question
opt Required decision
B->>U: Exact packet and decision role
U->>B: Verdict on revision and hash
end
B->>X: Permitted operation
X-->>B: Observed result or uncertainty
B->>A: Evidence for complete-scope verification
A-->>B: Typed result and remaining obligations
B-->>U: Achieved outcome and acceptance scope
B-->>K: Durable learning task
K-->>B: Reviewed version for future cases
The backend mediates every boundary. Agents exchange typed plans and evidence; current authority governs target execution. Learning is durably queued from the verified result.
Peer agents (backend/frontend/db owners) and module handovers (gate Hd) use the same delegation contract over RabbitMQ; lateral consults are evidence, never authority.
Authorization, the trust boundary and the data classes that constrain every arrow above are defined in Trust and Data; what happens when an arrow fails mid-flight is Failure and Recovery.
3. Common rules
3.1 The rules
| # | Rule |
|---|---|
| CR-1 | Every action lands in the audit/cost ledger in the fixed, tool-parsable format; metrics are parsed, not counted by agents. |
| CR-2 | The human decides: writes to protected targets, materially missing information, and the module's declared gates. Parent confirmation never substitutes for a gate. |
| CR-3 | Verification is per stage and reports the level actually reached, never an implied higher one. |
| CR-4 | Every module and profiled agent keeps eval sets (golden cases) that re-run when its memory domain, skills, or model routes change. |
| CR-5 | Sessions: stoppable, resumable, deletable; many viewers, one controller (Agent Runtime). |
| CR-6 | Agents boot from their own AGENTS.md node plus the task prompt and write only inside their own domain — the dreaming protocol (Agents Memory, D106). |
| CR-7 | Every applied change carries its plan step, verification evidence, and revert path; deployment scope is chosen per case, and reversal is gated. |
| CR-8 | Content is data; authority comes from grants and gates, never from content. Nothing observed through a connector can widen what a case may do (Trust and Data). |
| CR-9 | No agent turn spans an uncommitted write; every plan step declares its effect class — transactional, compensable, irreversible, or DDL (auto-committed; compensated by re-applying the pre-apply snapshot) (Failure and Recovery). |
| CR-10 | The platform is whitelabel. Every contract clause, calendar, severity scale, identifier pattern, threshold, schedule, host, channel behaviour and role mapping is a configuration value with a default, held in SRD_SUPPORT policy rows or the customer plug-in — never a constant in code, never a rule of the architecture. The same holds for the working structures (D67): the agent graphs (stage sets, profiles), the memory domain tree and the SLA/escalation protocols are configuration instantiated as data — TASKS from the profile catalogue, the tree's nodes as rows, the clocks as policy rows. The architecture defines the components; what they run on is configuration. The pages state the Bulstrad defaults; the Whitelabel Catalogue lists every value and its scope (D51). |
4. Runtime P
P The agent loop is native C# in the Support webservice, continuing the AI program's stated direction ("replace MCP Proxy, IntentGPT and long-lived AI sessions with native C# services" [F: docs/architecture/health-ai/00-program.md, inspected 31.08.2026]) — decision 01.09.2026.
P No third-party harness is adopted as the runtime (decision 02.09.2026). The design of the loop, the instantiation of the agent graph, inter-agent communication and the write-approval flow — with the patterns taken from surveyed harnesses and their sources — is Agent Runtime.
The loop is reached through one internal contract — start/continue, lineage, plan submission, parent responses, interruption, recovery, model selection, event correlation — so the choice stays reversible. Model adapters per profile; session records store profile + adapter version, never bare model ids.