A Unified Claim Agent

Created Jul 23, 2026 public

A design for a single rule-driven agent that knows every courier, client, and claim rule, watches claims as they are ingested, and drives each one all the way through to submission and credit.

The central finding: ClaimIt already contains all the machinery. What it lacks is a single brain to tie it together. This document maps what exists, names the problem precisely, and proposes the one component worth building.

The thesis

Today the rules a claim agent should know are smeared across five subsystems — code constants, environment variables, and three separate database config tables. The "agent" is really two different agents plus a fleet of per-courier workflows that each re-derive policy locally.

So the design goal is consolidation, not greenfield: introduce one policy resolver as the source of truth, keep Temporal as the durable execution substrate, and feed a thin dispatcher from ingestion and sweeps.

Three layers that already exist

Every claim-automation system decomposes into the same three layers. ClaimIt has all three — they are just not unified.

What backs each layer today

Layer Component Where it lives
Knowledge Courier rules (code) CourierRegistry / CourierDefinitionEnabled, RunsOnSelfHosted, EmailHandledByWorkflow, AllowsPortalCreatedWorkflows
Knowledge Per-brand rollout gates *WorkflowConstants.EnabledCclIds (e.g. ColissimoWorkflowConstants)
Knowledge Which LLM categories may act AICommsClientConfigServiceEnableCreditLLM, EnableRejectionLLM, … per courier × client
Knowledge Allowed rejection reasons EnabledRejectionReasonIds JSON
Knowledge Bulk-doc eligibility ClaimsAgentGate (remittance / claims_report / bulk_import)
Knowledge Brand on/off switch AICommsClientExclusionService (AgentEnabled / AutoEscalate / NoAction)
Trigger Ingest → classify → dispatch ClassifyLoopProcessEmailDispatcherProcessEmailWorkflow
Trigger Time-based sweeps Temporal schedules (UPS / Erin / stuck-New)
Execution Per-claim state machine ClaimLifecycleBase / ClaimLifecycle<TState>
Execution Sanctioned transitions ClaimTransition.To*() + ClaimStatuses.DatabaseIds
Execution Submission (browser / API / email) per-courier OnSubmissionAsync hook

The end-to-end already works

Colissimo is the clean reference implementation — the per-claim Temporal submission layer built under TECH-923 by Trevor Daniel. A claim runs the full distance today without a human touching it:

ClaimTransition.To*() is the only sanctioned way to change status (never set ClaimStatusId directly), and each transition writes a tagged ClaimLogEntry. The status ids are canonical constants in ClaimStatuses.DatabaseIds.

The problem: no single brain

Here is the crux. The question "can this claim be auto-progressed right now?" has no single owner. Five subsystems each hold a slice, with different mechanisms and different storage:

So "the agent knows the rules" is not true today — five subsystems each know a slice. Onboarding a new brand means editing code constants and database rows and hoping the two agree. There is no place to answer the whole question at once, and no single audit trail for why a claim did or did not advance.

There are also two ClaimTransition.cs files (backend/SDK/ClaimTransition.cs and backend/SDK/Objects/ClaimTransition.cs). Confirming which is canonical is a prerequisite to building anything on top of the transition layer.

Target architecture

Introduce one new component — a ClaimPolicyResolver — and route every gate decision through it. Ingestion and sweeps feed a thin dispatcher; the dispatcher asks the resolver for a policy; the per-claim Temporal workflow carries it out.

The ClaimPolicy object

The resolver returns one immutable record answering the whole question at once:

record ClaimPolicy
{
    bool                IsLive;               // AllowsEmail/PortalCreated + CclId ∈ EnabledCclIds
    Cluster             Cluster;              // from RunsOnSelfHosted
    SubmissionChannel   Channel;              // Browser | Api | Email | Batch
    AgentMode           AgentMode;            // AgentEnabled | AutoEscalate | NoAction
    IReadOnlySet<Category> AutoActionable;    // from the Enable*LLM flags
    IReadOnlySet<int>   AllowedRejectReasons; // EnabledRejectionReasonIds
    EvidenceRequirement Evidence;             // PoP / PoC required?
    TimeSpan?           FilingWindow;
    bool                AllowAccepted;        // [ALLOW_ACCEPTED]; Credited stays agent-blocked
}

The key property is that it wraps the existing sources rather than replacing them. It reads CourierRegistry, the EnabledCclIds constants, AICommsClientConfigService, and AICommsClientExclusionService behind one interface. Every call site that today re-derives policy locally instead asks the resolver. That makes the change low-risk, incremental, and unit-testable in isolation.

Build vs. reuse

The scope is deliberately narrow. Only one box is genuinely new.

Piece Effort
ClaimPolicyResolver + ClaimPolicy model Build — the real work, but a read-only facade over existing sources
Migrate call sites to ask the resolver Refactor — mechanical, incremental, one courier at a time
Dispatcher, ingestion, classification Reuse as-is
Per-claim lifecycle + transitions + submission Reuse as-is
Resolve the duplicate ClaimTransition.cs Cleanup — prerequisite hygiene

The single highest-leverage move is the resolver. It turns "five subsystems each know a slice" into "the agent knows the rules," without rewriting the execution engine that already works.

Two things to decide first

The agent's authority ceiling is a policy decision, not a code detail. Today Credited is hard-blocked for agent auto-execution and Accepted needs an explicit [ALLOW_ACCEPTED] marker. A unified agent makes widening that easier — so the resolver should treat those ceilings as first-class, auditable fields, never incidental flags.

The code-vs-DB split exists for a reason. EnabledCclIds is deliberately a code gate — a rollout safety brake that configuration cannot override. If the resolver flattens everything into DB config, that brake is lost. The resolver should read both tiers but must not collapse them.

Summary

You are not building a claim agent from nothing. You already have the knowledge sources, the triggers, and a durable execution engine that carries claims to credit — the Colissimo path (TECH-923, Trevor Daniel) proves the full New-to-Credited distance is already achievable per courier. What is missing is the one component that lets the system answer "what are the rules for this claim, and what am I allowed to do?" in a single place. Build the ClaimPolicyResolver, route every gate through it, and the fleet of per-courier workflows becomes a single rule-driven agent.