Skip to content

Domain Packs ​

CARC governs AI agents that make consequential decisions. The core platform (sessions, Agent Runs, evidence, policies, risk, review, replay) makes no assumption about which kind of decision it is governing. Each kind is a domain pack that registers everything domain-specific:

A domain pack registersHealthcareLending
Roles, on top of the core requester, human_reviewer, and systemclinician, nurse, pharmacist, care_coordinatorloan_officer, underwriter
Task types, each with the roles allowed to request itdischarge_summary, ...loan_application_review
A subject type and synthetic casespatientloan_applicant
Claim types and recommendation categoriesdiagnosis; medicationadverse_action_reason; approve, decline, credit_limit
Policies scoped to the domainmedication_requires_review, ...decline_requires_review, ...
Risk weights per recommendation categorymedication: 25decline: 15
Reference agents and a managed-execution prompt builderdischarge-summary-agentloan-review-agent

List what is installed with GET /runtime/domains (SDK: runtime.listDomains()).

What the domain decides ​

  • Which agents can register. An agent's domain must be an installed pack, and every entry in allowed_tasks must be a task type that pack registered. Anything else is rejected with a 400.
  • Who can request a task. The request's user_role must be in the task type's allowed_roles.
  • Which policies apply. Core policies (domain: null) apply to every run. A pack's policies apply only to runs whose task type that pack registered.
  • How risk is weighted. Recommendations in a category the domain weights add that weight to the runtime risk score.

The domain-neutral output shape ​

Every agent, in every domain, returns the same AgentOutput:

ts
interface AgentOutput {
  identity: { agent_id; agent_version; model_provider; model_version; task_type };
  generated_at: string;
  narrative: string;
  claims: Claim[]; // claim_type is an open string: core types plus the domain's own
  recommendations: Recommendation[]; // grouped by category, optionally with a numeric value
  required_sections: Record<string, boolean>; // e.g. { discharge_instructions: true }
}

Parameterized policies ​

Policy conditions are domain-neutral. What makes a policy specific to a domain is its condition_params and its domain:

condition_typecondition_paramsTriggers when
recommendation_category_present{ category }Any recommendation has that category
recommendation_value_above{ category, threshold }A recommendation of that category has a value above the threshold
claim_type_unsupported{ claim_type }A claim of that type has no supporting source
required_section_missing{ section, task_types?, when_recommendation_category? }The section is not true in required_sections (optionally only for some task types, or only when a recommendation of a category is present)
unsupported_claim_present{}Any claim is unsupported
risk_level_high{}The runtime risk level is high
critical_unsafe_recommendation{}High risk and two or more unsupported claims

Every PolicyResult on a Decision Context Record snapshots the condition_type and condition_params that were evaluated, so a record stays self-describing even if a policy later changes.

Installed domains ​

Healthcare ​

Clinical documentation and decision support. Subject type patient.

  • Task types: discharge_summary, diagnosis_support, medication_reconciliation, care_plan_summary, radiology_follow_up_recommendation
  • Policies: medication_requires_review (any medication recommendation requires review), diagnosis_requires_evidence (an unsupported diagnosis claim requires review, risk weight 25), discharge_instructions_required (a discharge summary without the discharge_instructions section requires review, risk weight 20)
  • Agents: discharge-summary-agent (active, in-process reference agent), radiology-follow-up-agent (draft), and openai-discharge-summary-agent (managed execution, active only when OpenAI is configured)

Lending ​

Consumer credit decisions. Subject type loan_applicant. Subjects carry underwriting inputs only (purpose, requested amount, income, debt-to-income ratio, credit score, employment), never attributes a lender must not consider.

  • Task type: loan_application_review (roles: loan_officer, underwriter, system, requester)
  • Policies:
    • decline_requires_review: any decline recommendation requires an underwriter's review.
    • credit_limit_above_threshold_escalates: a credit_limit recommendation with a value above 25,000 requires review (risk weight 20).
    • adverse_action_reasons_required: a decline without the adverse_action_reasons section is blocked (risk weight 25).
  • Agent: loan-review-agent (active, in-process reference agent, a deterministic rule set)
  • Synthetic applicants, one per control path:
CaseApplicantAgent recommendsOutcome
case-loan-0001Strong file, $15,000Approve, limit $15,000Auto-finalized
case-loan-0002Strong file, $40,000Approve, limit $40,000Human review (limit above threshold)
case-loan-0003Score 598, DTI 51%Decline with two adverse action reasonsHuman review (decline)
case-loan-0004No credit fileDecline with no reasonsBlocked (adverse action reasons missing)

A lending agent's output uses the same shape as any other domain:

ts
const agentOutput = {
  identity: { agent_id: "acme-underwriter", agent_version: "2.0.0", model_provider: "acme-ai", model_version: "uw-7", task_type: "loan_application_review" },
  generated_at: new Date().toISOString(),
  narrative: "Decline: debt-to-income ratio above policy.",
  claims: [
    { claim_id: "r1", claim_type: "adverse_action_reason", statement: "Debt-to-income ratio of 51% exceeds the maximum of 43%.", supporting_source_ids: ["src-income"] },
  ],
  recommendations: [
    { recommendation_id: "d1", category: "decline", item: "Decline $22,000 auto loan", instruction: "Send an adverse action notice.", rationale: "DTI above policy.", value: null, unit: null, supporting_source_ids: ["src-income"] },
  ],
  required_sections: { adverse_action_reasons: true },
};

Adding a domain ​

A domain pack is a package that exports a DomainPack (@carc/types): its definition (roles, task types, claim types, recommendation categories, risk weights), cases, seed agents, policies, in-process adapters, and an optional prompt_builder. Install it by adding it to the list the engine composes at boot (services/runtime-control-engine/src/index.ts). The engine validates every pack together at startup and refuses to start if a pack is inconsistent (a task type registered twice, a case or agent using another pack's task type, a policy scoped to another domain).

Developer Platform v1: Consequential Agent Runtime Control Platform