Agents
Purpose
Each module draws its agent tree at the head of its own page — Configuration Module § 0, Support Module § 0, Data and Information Module § 0, Development Module § 0 — with its memory branch and its skills under it (D145); this page is the detail behind every node: the profile, what it boots from, what it reads and may write, which tools and environments it may use, what it receives and returns, who it escalates to, and what it is denied. The graph is instantiated as TASKS rows at run time (Agent Runtime § 1, § 3); this page is the static catalogue those rows are created from. Every row is P; the case studies of the module pages are the test of this catalogue.
Conventions: Boots from = own AGENTS.md node + task prompt (the whole tree is readable); Writes = the single owned memory domain — an entry marked proposal is a case-local draft that the domain's owning profile confirms into shared storage (Agents Memory § 2 rule 7); Tools = connector operations by environment scope, read unless marked; In / Out = the typed messages of Agent Runtime § 4 with the artefact each carries; Escalates = parent, after N failed attempts where stated.
0. The profile — what one node is
"Profiled agents" is the noun the whole platform is built on — module roots, stage agents, investigators, verifiers, connectors and write executors are all profiles. A profile is what makes an agent reproducible: the same profile, the same memory domain and the same skills produce the same behaviour whoever starts the case, and a changed profile is a versioned, testable, revertible event rather than a prompt someone edited.
This document defines the profile. Everything else in the wiki that says "profiled" means an instance of this.
0.1 The fields
P Profiles declare execution_kind=llm or deterministic. Model profiles bind a published prompt and route; deterministic profiles bind a registered handler key and framework version, and use no invented model route. The task/ledger identity is common to both (Model Execution).
P A profile is a versioned row set in SRD_SUPPORT (Architecture § 1) — data, not code, not an enum.
P Three things are distinct and must not be conflated: the profile (this definition, versioned), the instance (one running agent in one case, which the ledger identifies), and the memory domain (a knowledge namespace). "Agent == memory domain" (Agents Memory) means one domain has exactly one writing profile — not that profile and domain are the same object. Several instances of one profile run at once; a profile writes only its explicitly owned domains; each domain has one canonical owning profile. What any other profile produces for a domain is never a write but a proposal — case-local first, confirmed into the shared tree by the owning profile (Agents Memory § 2, Agents Memory § 7.4b).
| Field | Content | Why it is a field and not a convention |
|---|---|---|
key, name |
stable identity, e.g. configuration.abacus.stage |
audit records and metrics group by it; a renamed profile is a new key |
module |
configuration · support · source · platform · connector | decides the data boundary (§ 0.3) and which eval sets re-run |
role |
root · stage · sub-agent · connector | decides who it may escalate to: only a root reaches the human (Architecture CR-2) |
instruction |
reference to the published prompt version, never inline text | prompts are governed: draft → test → publish (Agent Framework) |
model_route |
the adapter route, resolved per § 0.3 | changing a model never rewrites session history (PG-7); records store profile + adapter version, never a bare model id |
memory_read |
the whole tree, always — the profile may not narrow it | an agent must be aware of all available knowledge and read what it judges relevant (decision 01.09.2026); boot loads only the own node's AGENTS.md plus the task prompt |
memory_write |
the explicit owned-domain set in MEMORY_DOMAINS — anything meant for another owner is filed as a proposal the owning profile confirms, never a direct write | the write rule of the memory tree (Agents Memory § 2); case-local findings stay with the case regardless |
tools |
the connector operations it may call, per environment scope; the case's live grants are rendered into the prompt so the agent plans inside the boundary (Trust and Data § 2) | the connector refuses before contact when out of scope [F: the PC environment lock] |
denied_context |
what is deliberately withheld (§ 0.2) | isolation is provisioning, not instruction |
escalation |
after how many failed attempts, and to whom | the two-failed-attempts rule is a profile setting, not a habit [F: the PC 9951 run] |
budget |
time, in minutes — the one budget dimension (decision Vladimir, 04.09.2026 — D135): a case's budget is its predicted delivery time, set at classification from the case type's default and the solution packet's prediction (where the two differ the maximum stands); a task's budget is a share of the case's. Provider usage, expensive reads, DB sessions and sub-agent count are caps that protect the estate and the spend envelope, recorded in the ledger as facts, not budget dimensions; consult_concurrency — the slice reserved for answering other agents' consults (default 2) — stays a cap. Two thresholds on the minutes (decision 01.09.2026; platform-policy defaults, Whitelabel Catalogue): a soft warning to the root agent at 80 %, a hard refusal at 100 % — so the agent can wind down and write its papers rather than being cut off mid-apply (Failure and Recovery) |
the estate's caps are real: INSIS allows 6 sessions/user → ORA-02391 F: [rule] |
eval_set |
the golden cases that must pass before this profile publishes | CR-4: eval sets re-run when the domain, skills or route change |
version, state |
draft · testing · published · retired | § 0.4 |
0.2 Isolation is provisioning
F The proven mechanism is denied context, not an instruction to ignore something: the tariff analyst's scope contains no database connector, so storage cannot bend its reading of a tariff; the grader sees two artefacts and no provenance, so it grades output rather than remembered reasoning [F: the PC sub-agents].
P In the C# host this is an explicit task context/tool facade: standard DI scopes do not remove parent registrations; the interpreter exposes only the declared readers/tools (Architecture § 1). A profile cannot widen its own grants; widening is a gate decision.
Standing isolated profiles: tariff analyst (no DB), estate prober (no product intent — it returns counts, never advice, and keeps permitted distinct from used), write auditor (no author transcript and no reasoning — it checks that a write packet is exact, bounded and revertable before any gate sees it, Gating § 6), verifier (no author transcript — it re-derives the mechanism from evidence alone), reviewer (no author context; its checklist is data: test placement, i18n set, csproj bumps, appsettings hunks, cross-repo contract, lineage of the change — Development Module § 5 G6), grader (no provenance).
0.3 Model route and the data boundary
P The route a profile declares is validated against its module's allowed provider class at governed route selection (Platform Details PG-7). Not at adapter construction: F the inspected predecessor registers singleton clients with one endpoint per kind (verified 01.09.2026). P The owned host keys clients by endpoint/credential configuration; residency is validated for the selected deployment on every route decision (Model Execution § 5).
| Module | Allowed | Consequence |
|---|---|---|
| Configuration | an estate-approved adapter covering the actual input class; configuration structure itself contains no personal data (CG-9) | identifiers in intake are handle-substituted at the connector before storage — the case is operator-agnostic (D57); only material that is personal data is rejected as wrong input |
| Support | GDPR-compliant, EU-resident only (Azure OpenAI, EU region, under DPA) | a profile declaring another route does not publish |
Development (id source) |
as Support wherever a reproduction touches real data |
The boundary is therefore code at the route selector — which already resolves a versioned route from DB rows and already constrains ProviderCode — and not discipline in a prompt. Support traffic additionally gets its own EU-resident deployment, because the selected endpoint's data zone is verified; the owned registry keys clients by endpoint/credential configuration, not provider name alone.
0.4 Lifecycle
P draft → testing → published → retired, over the estate's existing prompt governance (Agent Framework). A profile publishes only when its eval set passes and the publisher holds the prompt-publisher role. Published versions are immutable; a change is a new version, and rollback publishes a new version containing the previously accepted content. Session records name the profile version that ran, so a case is reproducible after the profile has moved on.
0.5 A worked profile — the example
P One row, as the layering rule allows (D145). Each module's full profile table — what a profile owns, its hardest judgement, what it boots from and writes, its tools per environment scope, what it is denied, where it escalates and the eval set that proves it — is that module's Components § 3: Configuration · Support · Development.
| Profile | Module / role | Writes to | Denied | Notes |
|---|---|---|---|---|
source.implementer.backend |
source / stage | source/serdica-backend/<service> |
pushes to protected branches, deploy | the id scheme is source.implementer.<source> (D101); one child domain per microservice, auto-created by the summarizer (§ 0.6) |
0.6 Auto-learning a missing domain
P A domain node is never a prerequisite for work (decision 01.09.2026). When an agent needs a domain that does not exist yet — most often source/serdica-backend/<microservice> — the platform launches a summarizer sub-agent that reads the subject (the service's code, its AGENTS.md, its build and test surface, its recent history) and drafts the missing material for the owning profile before work continues.
- The summarizer writes a case-local proposal for the node it was launched for, under the Agents Memory § 2 writing practice.
- An existing but stale node receives a proposed new revision — the belief order applies: running system → consuming code → memory.
- Its output is an audited proposal, visible in the case chat; only the owner activates it.
- The node-creation gate (Agents Memory § 2) still applies to manual node creation; this is the automatic path, and its justification is that an agent actually needed it.
C How deep a summarizer goes on first creation, and what triggers a refresh of a node that already exists — a staleness signal, a schedule, or the next case that finds it wrong.
1. Platform profiles (used by every module)
| Profile | Role | Boots from | Writes | Tools | In → Out | Denied | Escalates |
|---|---|---|---|---|---|---|---|
platform.intake |
monitor + router (§ 5c) | platform/intake |
platform/intake |
queue sweeps and mailbox scans (read); case open | normalised arrival → origin key, duplicate verdict, customer, initiation outcome, then Spawn support.root (§ 5c, D143) |
investigation of any kind; naming the working module, the case type, the severity and the clocks — all of them the desk's S1 and the route at H2 (D143, D147) | administrator (connector down); the operator (low-confidence route) |
platform.compactor |
utility | none | none | none | transcript → summary artefact (decisions, facts + sources, open items, result refs) | tools, memory writes | the spawning task |
platform.summarizer |
utility | source/ or the target parent node |
case-local proposal for the named node | GitLab read, build/test surface read | missing node → proposed content; owner confirms | writes elsewhere | the spawning task |
platform.verifier (base) |
sub-agent | own node | none | read connectors as granted | evidence artefacts → Verdict (agree / disagree + separating evidence) |
author transcript and identity; evidence provenance retained | the spawning task |
platform.grader |
sub-agent | none | none | none | two artefacts → score per rubric dimension, with "Unknown" | provenance, both authors' reasoning | eval runner |
platform.write_auditor |
sub-agent | platform/ |
none | read connectors on the packet's target, under the case's grants | write packet + approved shape + grants → Verdict per the four checks (exactness, boundedness, reversibility, scope), with the failing item and its evidence (Gating § 6) |
author transcript, author reasoning and identity; evidence provenance retained; every write operation; spawning | the requesting stage agent; a refusal blocks the instance |
platform.write_executor |
deterministic handler | connectors/<system> |
none | write operations (shape A = collapsed connector call; shape B = deterministic leased transaction; form E = external/DDL effect), dry-run, teardown — only with a grant | packet + grant id → what actually ran, counts, verification | planning tools, memory writes | the requesting stage agent; refuses without grant |
connector.<system> (one per system) |
connector agent | connectors/<system> |
connectors/<system> |
that system's operations, per environment scope | operation request → labelled envelope; capability gap → DeadEnd |
every other system | the requesting agent |
2. Configuration module
P Described where it is built: Components — Configuration § 3 carries every profile of this module in one table — what it owns, its hardest judgement, what it boots from and writes, its tools per environment scope, what it is denied, where it escalates, and the eval set that proves it. The tree is drawn at the head of Configuration Module § 0.
3. Support module — the root — and the Data and information module
P Described where it is built: Components — Support § 3 carries every support.* profile in one table — what it owns, its hardest judgement, what it boots from and writes, its tools per environment scope, what it is denied, where it escalates, and the eval set that proves it. The desk's tree (root, triage, the route, the communicator) is drawn at the head of Support Module § 0; the working stages' tree (investigators, verifier, resolution, curator) at the head of Data and Information Module § 0. The two share support.root (D144).
4. Development module (id source)
P Described where it is built: Components — Development § 3 carries every profile of this module in one table — what it owns, its hardest judgement, what it boots from and writes, its tools per environment scope, what it is denied, where it escalates, and the eval set that proves it. The tree is drawn at the head of Development Module § 0.
5. How the modules reach each other
P There are exactly two ways — and conflating them is the mistake that turns a graph into a mesh nobody can reason about.
| A consult | A handover (Hd) | |
|---|---|---|
| What is asked for | knowledge | a changed system |
| What comes back | an answer, labelled evidence, never authority | an artefact, produced by that module's own stages |
| Who answers | the domain owner profile, spawned as a read-only sub-agent inside the asking case | that module's root, which opens a sub-case |
| Budget | reads, charged to the asking case, inside its budget | a gate, a plan, writes, its own clocks |
| Gate | none | Hd, with prior human confirmation |
| Fails how | "I do not know", with what would answer it | accept, or reject with a reason — it never hangs |
P The consult rule (decision Vladimir, 03.09.2026 — D92). A consult is addressed to a knowledge domain, never to a case and never to a person:
- The asking agent names the domain and the question. It may not name an agent, because which profile owns a domain is that module's business.
- The platform spawns that domain's owning profile as an isolated, read-only sub-agent of the asking case, booted from the domain's
AGENTS.mdnode and given the asking case's grants narrowed to reads. No case is opened in the other module, no queue is joined, no gate fires — which is why a consult is cheap and a handover is not. - The answer returns as a paper in the asking case, carrying the domain, the question, the answer and its evidence, so a decision made on a consult is auditable months later.
- A consult that turns out to need a write is not a consult. The consulted profile cannot write — it has no write connector — so it answers "this needs a change in my module", and the asking root raises Hd. The rule is enforced by provisioning, not by instruction.
- Depth one. A consulted profile may not consult onward. If it needs a third domain to answer, it says so and returns; the asking agent decides whether to ask that domain itself. This is what stops a question from touring the estate.
- The trigger is the existing two-failed-attempts rule: an agent that has twice failed to establish an unknown contract or state consults the owning domain instead of trying a third time.
P The consult catalogue — who answers what. It is configuration (consults.catalogue, Whitelabel Catalogue § 5b), not a rule of the architecture, because a second customer's estate has different domains. The platform row below is the example (D145); the module rows are catalogued where the work is, in each module's what it asks of the others section — Support Module § 3, Configuration Module § 4b, Development Module § 2b.
| The question | Asked by | Domain that answers | Why it is a consult and not a handover |
|---|---|---|---|
| "What did this customer already accept?" | every module, at intake | platform/experience, the case ledger |
a read of the platform's own record |
P The four handover directions, each a sub-case inside the same case, each behind Hd:
| From → to | What is asked for |
|---|---|
| Support → Configuration | re-configure something: a configuration cell, a product change, a tariff correction |
| Support → Development | code: a defect in a service, a stored procedure, a UI dependency |
| Configuration → Development | a new kind of process, a plug-in, a column too short, a rule no layer can hold |
| Development → Configuration | a change that turns out to be configuration after all |
The worked example (D145): a print template's gate row is wrong and the fix is configuration, not code — Support → Configuration. The examples for the other three directions are on the module pages (Support Module § 3, Configuration Module § 4b, Development Module § 2b).
P Handover protocol (D66): the receiving root accepts — its sub-case opens inside the same case, with its own stages and gates — or rejects with a reason (out of scope, missing information, wrong module) that returns to the requesting root as a DeadEnd-carrying message; the requester re-plans or raises H6. It never hangs. The requesting case parks on the sub-case like on a question (Agent Runtime § 11.4): its SLA clock follows its own class, the parked state and the sub-case's age are first-class fields on the Sessions screen, and a sub-case exceeding the requesting case's gate-escalation interval escalates to the requesting case's human the way a parked gate does (PG-12). Completion returns the result artefact to the requesting case, which owns the customer-facing closure — the customer hears one voice, not three.
P The handover packet is one paper in three parts, the same for all four directions (D142, 04.09.2026 — draft contract handover-packet.schema.json, Contracts § 2): the request — what is asked, why the requester cannot do it (the mechanism or placement finding), the kind (configure · build_or_fix · process · plugin · ddl), what the sub-case inherits (paper references, the grants narrowed to reads, the same handle map so no identifier is re-exposed), what done means for the requester, and the dependency on other sub-cases (G-12); the response — accepted with the sub-case id and its predicted minutes, or rejected with one of the three reasons; the completion — result, proof level reached, what changed with the WRITE_LOG ids and the standing revert path, and the done-means list ticked item by item. A module may extend the body per case (D139) — the receiving root reads the core and never the requester's transcript.
P source.root → the estate's development process is neither of the two: it is an exit. A core-change proposition leaves the platform for the estate development lead as a GitLab issue on master; the Development task returns the issue as an external-owner result; the owning case retains its delivery obligation and receives its state changes as ledger events (D108; Stage Planning § PL-1).
5b. What a root knows, and what it deliberately does not
P A module root is the only profile that reaches a human and the only one that may open a sub-case in another module. That makes what it boots from a design decision, not a convenience:
| It boots from | Because it decides |
|---|---|
its module's branch root — configuration/, support/ or source/AGENTS.md |
the case type, the stage set, which gates fire where, and the module's routing table |
platform/ |
how sessions, gates, grants, budgets and the ledger behave — the mechanics it operates |
platform/experience |
whether this case has been seen: a duplicate to attach, a precedent to follow, or genuinely new |
| the consult catalogue and the handover contracts | which domain answers a question and what a handover packet must carry per direction |
P A root does not boot from its stage domains, and that is deliberate: a root that knows the catalogue's dependency order starts making catalogue decisions, and the stage agent it delegates to becomes decoration. The root owns whether and who; a stage owns how. P For the same reason a root holds no write connector and no skill: everything it decides is a plan, a gate or a message.
5c. Who routes an arrival, before any module owns it
P Intake is a deterministic entry protocol with model-assisted briefing only after a case's authority and data boundary exist. Channel readers normalise metadata, stamp the source request/revision key, resolve explicit mirrors, resolve customer and verified sender, and store ARRIVALS. Sender role hints in a message are untrusted; roles come from authenticated identity or the configured channel identity mapping.
P A client arrival first checks the right to open a Support intake case. Granted intake opens the case automatically with the configured read-only case type, allocates its handles/papers and schedules support.root/S1. It does not wait for an Inbox click. Missing identity or denied intake stays a refused/awaiting-authorisation arrival; no investigation runs. An explicit operator start checks the named module's initiation rule before opening its root.
P S1 owns classification, severity, precedent retrieval and clock calculation. Intake supplies channel hints, never a conclusion about the working module. Before the route starts Configuration or Development work, the service checks the destination entitlement against the classified work and the verified initiator. This removes the circular dependency of deciding a destination before classification. An Operator's recorded handover authority can sponsor that work; the customer's message alone cannot.
| Destination entitlement | Result |
|---|---|
| granted | continue through the declared route/Hd protocol; target writes still need their own gates |
| may_request | keep the request and its age visible while the organisation's configured approver decides; no destination work starts |
| not_granted | record the clause and commercial/external-owner path; do not silently re-route to obtain more authority |
P Customer representatives may start Support by default and request Configuration; an organisation enables direct Configuration initiation by its existing intake.initiation policy. That is a setup entitlement, not a repeated vendor request per tool call. The four client screens show which outcome applies. Development placement/core-change boundaries remain unchanged.
P Deduplication uses source identity and explicit mirror links. Similar subjects or object handles create a duplicate candidate, not proof that two requests are identical. Source updates add immutable material revisions to the existing case; they do not overwrite an approved paper or silently reopen a closed case. The root invalidates affected plan/gate revisions when material changes.
P Scheduled channel scans run as administrative, read-only maintenance tasks under configured customer/channel grants; they are excluded from business-case throughput metrics. Source bytes remain at the channel or in a restricted intake staging store until the destination case can own its papers and handle map. This avoids creating a PAPERS/CASE_HANDLES row before its required CASES parent.
6. Budgets and caps per role P
The budget is time (D135): the case's predicted delivery minutes, shared out by the root. The other columns are caps — fixed protections that do not draw down the budget.
| Role | Time (share of the case's minutes) | Sub-agents (cap) | DB sessions (cap) | Turns (cap) |
|---|---|---|---|---|
| root | 10 % | as many stages as the stage set | 0 | unbounded within budget |
| stage agent | up to 60 % of the case, split by the root | ≤ 4 concurrent | 1 per environment | — (the 80 % / 100 % minute thresholds of § 0.1 apply to every role) |
| sub-agent (verifier, analyst, reviewer) | fixed slice set by the profile (BUDGET_MINUTES_FIXED) |
0 | 1 | capped (profile) |
| write executor | small, fixed | 0 | 1 per write | 1 write per turn |
| connector agent | metered per operation | 0 | the environment's cap minus humans' sessions | — |
| consults answered for other cases | 10 % of the asking case's minutes, all its consults together (consults.budget_share, Whitelabel Catalogue § 5b) |
0 | 1 | bounded by the consult deadline (10 min memory-only, 30 min with reads) |
Numbers are starting values for the T1 experiment, revised from the ledger. Provider usage per task is recorded in COST_LEDGER (tokens, calls) beside the minutes charged, so the spend envelope of Metrics remains a control without becoming a second budget dimension.
Challenges
- P Which investigator leads a cross-system symptom — set on the first ten Support cases (Stage Investigation § 2); until then the root picks by the customer's phrase and records the choice.
- P Consult mechanics P (Challenge Rounds § R2 § 2). A consult is a
TASKSrowkind = consultwithdeadlineandpriority; the per-domain queue is a view over open consults, taken by any pooled worker. Every consultable profile reservesbudget.consult_concurrency(default 2 — a configuration value) that stage work cannot consume. A consult spawns an isolated read-only sub-agent inside the asking case (§ 5, D92) and never writes; it reads only under the requester's grant subset. Deadlines: 10 min for a memory-only consult, 30 min when reads are needed, never past the requester's remaining budget. On expiry the runtime writesConsultReply {no_answer, reason, waited_s, queue_depth}with trust class absent; the verifier treats it as unsettled; the same question hash in one case returns the earlier reply. Priority = the requesting case's SLA class, FIFO within it, one step up at ≥ 80 % budget or a waiting gate; no preemption. Unanswered consults emit aFindingto the owning domain — the dreaming pass reads them as missing articles. Confirmed when: T1 targets:no_answer< 5 %, p95 wait < half the deadline. - P Profile inheritance — decided (Vladimir, 02.09.2026 — D50): whole profiles, no runtime inheritance; a module default is an authoring template only. The example. The five Configuration stage profiles share most fields: budget thresholds 80 % / 100 %, escalation to
configuration.rootafter two failed attempts, route class "any" (no personal data), memory read = the whole tree, denied context none, eval-set policy. They differ in four: the prompt version, the memory write node, the tool set (S2oracle-anlt+ gateway, S3oracle-iprod+ browser …) and the stage skill. Runtime inheritance would declareconfiguration.abacus.stage extends configuration.stage.defaultand let the runtime resolve the chain at each turn — so a change to the default silently changes every published stage, which is what versioning exists to prevent. Whole profiles with an authoring template (the proposal):configuration.stage.defaultexists only as a template; "new profile from template" copies its values into a self-contained draft row; the ledger's profile version is complete on its own; a default change changes nothing published; revisit past 40 published profiles or when one change must touch more than 10.