WALKTHROUGH

Follow one submission across five systems

One identifier, five services, fifteen steps. The whole thread of a broker submission from arrival to underwriter queue, with nothing left out.

Tracing 11 min read Key figure · 15 spans, 7 actions, 3 events All posts

One identifier. Five services. Fifteen steps. This is the complete thread of a single broker submission — from a prospect being found, through a refusal, through document assembly, to a queue item landing on an underwriter's desk. Nothing omitted, including the part where the agent was told no.

The submission reference is VS-2027-0832950. That string is also the correlation id, which is the single most useful decision in the whole design.

The shape of the run

sequenceDiagram
    autonumber
    participant BR as Broker agent
    participant PU as Data service
    participant DS as Document store
    participant UW as Underwriting
    participant LN as InsightLense

    BR->>PU: find_prospects(class, state, size band)
    PU-->>BR: 12 candidates with filings data
    BR->>UW: check_appetite(candidate A)
    UW-->>BR: refused — class outside appetite
    Note over BR,UW: Refusal recorded, run continues
    BR->>UW: check_appetite(candidate B)
    UW-->>BR: in appetite
    BR->>UW: open_account(candidate B)
    UW-->>BR: account opened, ref VS-2027-0832950
    BR->>BR: assemble_package() — 6 documents
    BR->>DS: store pack
    DS-->>BR: 6 object keys
    BR->>UW: send_to_underwriter(ref, attachments)
    UW->>UW: intake, persist attachments
    UW-->>BR: queue item assigned
    BR->>LN: run finished — 15 spans, 7 actions, 3 events
Steps 3 and 4 are the interesting ones. The first candidate was refused on appetite. The agent did not fail, retry the same account, or argue — it moved to the next prospect, and the refusal is in the record.

What lands in each of the three records

The same run produces three different views. Each is useful to a different person, as covered in the data model post.

The run — 15 spans

The engineer's view. Every step in order, with what went in, what came out, tokens, latency and cost. Total for this run: $0.31.

step name tokens cost ms 1 plan 1,240 $0.019 980 2 find_prospects 890 $0.011 340 → tool 3 evaluate_candidates 3,110 $0.047 2,140 4 check_appetite(A) 420 $0.006 210 → refused 5 reconsider 1,880 $0.028 1,320 6 check_appetite(B) 420 $0.006 190 → allowed 7 open_account 510 $0.008 420 8 draft_acord125 2,940 $0.044 2,880 9 draft_sov 2,110 $0.032 2,010 10 draft_loss_runs 1,760 $0.026 1,650 11 draft_narrative 1,540 $0.023 1,480 12 assemble_package 680 $0.010 1,120 → 6 files 13 store_pack 210 $0.003 890 → tool 14 send_to_underwriter 390 $0.006 640 → tool 15 finish 420 $0.006 380 ------ $0.31

Step 5 is worth noticing. After the refusal the agent spent 1,880 tokens reconsidering before picking another candidate — that is the reasoning step that a refusal-as-exception design would have thrown away along with the refusal itself.

The authority record — 7 agent actions

The supervisor's view. Every capability the agent invoked, what it was permitted to do, and the outcome.

CapabilityLevel requiredLevel heldOutcome
find_prospectsL1L1allowed
check_appetite (A)L1L1refused — outside appetite
check_appetite (B)L1L1allowed
open_accountL2L2allowed
assemble_packageL1L1allowed
store_packL2L2allowed
send_to_underwriterL2L2allowed

Note that the refusal here is not an authority refusal — the agent had the right to ask. It was a business refusal: the account did not fit appetite. Both kinds are recorded the same way, which is deliberate. A supervisor reviewing this wants to see everything the agent was told no about, regardless of which layer said it.

The business events — 3 records

The auditor's view. What actually changed.

14:22:07 account_opened VS-2027-0832950 agent BR-LOCKTON-02 14:31:44 documents_stored 6 objects agent BR-LOCKTON-02 14:32:19 submission_received VS-2027-0832950 system → queue UW-CASUALTY

Three events, eighteen months from now, still readable by someone who has never heard of a span.

The documents

The pack is six documents, generated to be internally consistent rather than to look plausible individually — which is a harder problem and the one that matters.

DocumentContainsConsistent with
ACORD 125Applicant, class code, coverage requestedThe prospect's real filing data
Statement of valuesLocations, building and contents valuesTotal insured value on the application
Loss runsFive years of claims historyExposure size and class hazard
Exposure schedulePayroll, headcount by classFiled employee count
NarrativeOperations description, risk controlsThe class code and the loss history
Broker cover letterSubmission summary, target termsEverything above

Six documents that disagree with each other teach you nothing. The consistency is the test.

If the loss runs show a $2M claim against a $400k total insured value, an underwriting agent will reason about an impossible risk and you learn nothing about your appetite logic. Making the pack cohere is what makes the downstream behaviour meaningful.

Following it yourself

What this looks like in practice for the three people who care:

The underwriter searches VS-2027-0832950 in their own system and finds the queue item, the six documents, and — because the correlation id is the submission reference — the agent work that produced it, without needing a different tool or a different identifier.

The engineer opens the run and sees fifteen steps. When a submission stalls, the step list shows where: a tool that timed out, a document generator that produced an empty file, an intake call that returned 422.

The auditor queries business events for the reference and gets three rows with actors and timestamps. They do not need to know that steps 4 and 5 existed.

What this looks like in InsightLense

Everything above is one screen. Searching the submission reference opens the thread, and the three record types are interleaved in time with the run steps collapsible underneath.

Thread VS-2027-0832950 15 spans · 7 actions · 3 events · $0.31
14:18:02runbroker agent started — 15 steps
14:19:40authoritycheck_appetite(A) — refused class outside appetite
14:21:15authoritycheck_appetite(B) — allowed
14:22:07businessaccount_opened — VS-2027-0832950
14:31:44businessdocuments_stored — 6 objects
14:32:19businesssubmission_received — queue UW-CASUALTY, attachments: 0
The last two rows are the bug. Six objects stored, zero attachments received — two records that must agree, adjacent in one thread, where the contradiction is visible at a glance. No test caught it because every call returned 200.

That is the case for the thread view in a single screenshot. The information needed to spot the defect was split across two services, and neither of them was wrong on its own terms — the document store really did write six objects, and intake really did receive none.

The bug this walkthrough found

Worth ending on, because it is the reason to build the walkthrough at all.

The first time we ran this, step 14 succeeded and the attachment table stayed empty. The intake route accepted attachments, constructed its request object with an empty list, and the request schema had no attachments field anyway — two independent breaks in one path. Submissions arrived with documents referenced in the body and nothing stored.

No test caught it. The route returned 200, the queue item was created, and the run looked clean. What caught it was a business event that said "6 objects stored" sitting next to an attachment count of zero — two records that should have agreed, in one thread, where a person could see both at once.

That is the argument for the whole model, in one incident.

Where do your agents already act on real records?

Tell us that, and what you would need to prove about those actions to an auditor. We will set up a hands-on walkthrough within two weeks.

Request a demo →