# Use cases

Source: https://docs.littlebigbrain.com/start/use-cases/

The cases below are agent decisions with a real cost when the answer is
wrong. They follow the same three steps:

1. **Find the starting record.** The user asks in their own words. Search by
   meaning finds the recall notice, the payment or the advisory.
2. **Prove the answer by path.** A SPARQL query follows the stored links from
   that record. The rows it returns are the evidence.
3. **Record the decision.** The agent stores its outcome with the commit it
   read. Anyone can replay the query later against the same data.

Each case names the records to store, the query that answers it and what to
record. All of them work with JSON records and the SDKs.
[Build with JSON records](https://docs.littlebigbrain.com/guides/without-rdf/) walks through the first case
end to end. [Load your data](https://docs.littlebigbrain.com/start/load-data/) shows how a database and your
documents become such records.

The queries use the prefixes for names you declare in JSON. Add these lines
at the top of each query. [Core concepts](https://docs.littlebigbrain.com/start/concepts/#graph-queries-with-sparql)
explains them.

```sparql
PREFIX dclass: <https://littlebigbrain.com/class/>
PREFIX dr: <https://littlebigbrain.com/r/>
PREFIX dp: <https://littlebigbrain.com/p/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
```

| The agent must decide | Pattern | Answered by |
| --- | --- | --- |
| Which batches and sites were exposed to a recalled lot | Chain of unknown length, identity across systems | Property paths, keyed entities |
| Whether a payment needs escalation | Chain to a designated party, as of the payment date | Property paths, retained commits |
| Which journal entries lacked independent approval | A required fact is absent | `FILTER NOT EXISTS` |
| Which agreements need consent for an acquisition | One concept under several source labels, control chains | Class hierarchy, subclass entailment |
| Which services were exposed to a vulnerability | Dependency paths through many unrelated records | Bounded property paths |
| Which claims belong to one fraud ring | Records connected through shared things | Alternation and inverse paths |

## Recall exposure

**Question.** A supplier recalls one ingredient lot. Which released batches
contain its material, and which active study sites received those batches?

**Records.** `IngredientLot`, `IntermediateLot`, `ReleasedBatch`, `StudySite`
with the subtype `ActiveStudySite`, and `RecallNotice`.

**Links.** `PRODUCED_FROM` between lots and batches, `RECALLS` from the notice
and `RECEIVED_BATCH` from a site. Give lots a `key` from the manufacturing
system. A lot recorded under a supplier id and an ERP id then stays one record.

**Query.** `dr:produced_from+` follows the genealogy however deep it goes.
The `activestudysite` type leaves a closed site out of the report.

```sparql
SELECT ?batchNumber ?site WHERE {
  ?lot dp:lot_number "ZH-VAL-2018-07" .
  ?batch a dclass:releasedbatch ; dr:produced_from+ ?lot ; dp:batch_number ?batchNumber .
  OPTIONAL { ?siteNode a dclass:activestudysite ; dr:received_batch ?batch ; rdfs:label ?site . }
}
```

**Afterwards.** Store an `AgentDecision` whose `based_on_commit_seq` is the
`served_at_seq` of the response. The full walkthrough, with schema, writes,
validation, and replay, is [Build with JSON records](https://docs.littlebigbrain.com/guides/without-rdf/).

## Payment escalation

**Question.** Does transaction TXN-884 require escalation, and which
beneficiary, control, and designation chain proves it?

**Records.** `Transaction`, `Party` and `Designation`. Store the designation's
`listed_at` as a `date_time` field.

**Links.** `PAID_TO` from a transaction to its beneficiary. `CONTROLLED_BY`
between parties. `DESIGNATED_UNDER` from a party to a sanctions designation.

**Query.** Walk zero or more control links, then look for a designation. An
`ASK` returns the yes or no; the `SELECT` form returns the chain.

```sparql
SELECT ?beneficiary ?owner ?designation WHERE {
  ?txn dp:transaction_id "TXN-884" ; dr:paid_to ?beneficiary .
  ?beneficiary dr:controlled_by* ?owner .
  ?owner dr:designated_under ?designation .
}
```

**Afterwards.** Screening runs at a moment in time. Store the response's
`served_at_seq` with the decision. A reviewer may ask what the list held on the
payment date. Replay the query with `as_of_commit_seq` to answer.

A designation added the next day is absent from the replay. That is the
correct answer to "what did the agent know". See
[Replay an answer](https://docs.littlebigbrain.com/guides/time-travel-audit/).

## Quarter-close audit

**Question.** Which material journal entries in the quarter lacked
independent approval? The policy in force at the time sets the rules.

**Records.** `JournalEntry` with `amount` (`f64`) and `posted_at`
(`date_time`), `Person`, and `Policy` with `effective_from` and
`effective_to`.

**Links.** `POSTED_BY` and `APPROVED_BY` from an entry to a person.
`SCOPED_BY` from an entry to its policy.

**Query.** A missing approval is an absent fact. In a graph, absence means
"not recorded". A query asks for it with `FILTER NOT EXISTS`. The independence
test compares the two people.

```sparql
SELECT ?entry ?amount WHERE {
  ?entry a dclass:journalentry ; dp:amount ?amount ; dr:posted_by ?poster .
  FILTER(?amount >= 250000)
  FILTER NOT EXISTS {
    ?entry dr:approved_by ?approver .
    FILTER(?approver != ?poster)
  }
}
```

The threshold comes from the policy in force on the posting date. Join the
entry to its policy. Then compare `posted_at` with the policy window, with the
same datatype on both sides. [FILTER comparisons and
datatypes](https://docs.littlebigbrain.com/guides/sparql-and-shacl/#filter-comparisons-and-datatypes)
explains why a mismatched datatype silently drops the row.

**Afterwards.** The audit finding cites the commit it was computed from. Read
the published conformance report at the same time. Keep its `validated_at_seq`
with the finding, so the record also names the rules in force.

## Acquisition consent

**Question.** A company is being acquired. Which active agreements require
counterparty consent?

**Records.** `Agreement`, `Company`, and clause types. Contract data has two
common problems.

- One company appears under a contract id in one system and a registry id in
  another. Give the record one `key` and write both source records against it.
- Each source names the clause differently. Declare `ChangeOfControlClause` and
  `AssignmentConsentClause` as types with `super_types: ["ConsentClause"]`.
  The graph stores both links as `rdfs:subClassOf` statements. See
  [Add a type hierarchy](https://docs.littlebigbrain.com/guides/reasoning/#add-a-type-hierarchy-to-json-records).

**Query.** Ask for the parent type with `entailment: "subclass"`, and the
subtypes match. `dr:controlled_by+` follows any number of ownership links. It
finds a counterparty anywhere inside the acquired group.

```sparql
SELECT ?agreement ?counterparty WHERE {
  ?agreement a dclass:agreement ; dp:status "active" ;
             dr:has_clause ?clause ; dr:counterparty ?counterparty .
  ?clause a dclass:consentclause .
  ?counterparty dr:controlled_by+ ?acquired .
  ?acquired dp:registry_id "HRB-123456" .
}
```

OWL can go one step further. It can declare `requiresConsentFor` as a derived
link. The agent's query is then a single pattern with the proof attached. That
rule is a Turtle document. See [Reasoning & inference](https://docs.littlebigbrain.com/guides/reasoning/).

**Afterwards.** Store the decision with its `served_at_seq`. The registry may
later merge two companies. The earlier read stays reproducible.

## Vulnerability exposure

**Question.** On the day an advisory is published, which customer-facing
services embed the affected library version?

**Records.** `Service` with a `customer_facing` boolean, `Artifact` with
`version`, and `Advisory`.

**Links.** `DEPENDS_ON` from a service to its artifacts, and between
artifacts. `AFFECTS` from an advisory to an artifact version. A real corpus
holds hundreds of unrelated service paths. The query must leave them out.

**Query.** Start at the advisory. Then walk the dependencies backwards to the
services that reach it. `^dr:depends_on+` reads "one or more `DEPENDS_ON`
links, followed in reverse".

```sparql
SELECT DISTINCT ?service WHERE {
  ?advisory dp:cve_id "CVE-2021-44228" ; dr:affects ?artifact .
  ?artifact ^dr:depends_on+ ?service .
  ?service a dclass:service ; dp:customer_facing true .
}
```

Paths run under the same read limits as any query. A very large dependency
graph returns a typed limit error. It never returns a partial list. Keep the
start fixed, as above, so the walk starts from one record.

**Afterwards.** Pin the query to the commit that held the dependency graph on
disclosure day. A deployment the next week changes the latest data. The pinned
read still returns the exposure list as it stood.

## Claims investigation

**Question.** Which open claims belong to a coordinated repair-shop ring?

**Records.** `Claim` with `status`, `Device`, `PayoutAccount` and `Repairer`.

**Links.** `FILED_FROM` to a device, `PAID_TO` to an account, `REPAIRED_BY` to
a repairer.

**Query.** Two claims are connected when they share any of the three. The path
below takes a link forward, then a link in reverse. It steps from a claim to a
shared thing and back to another claim.

```sparql
SELECT DISTINCT ?claim ?other WHERE {
  ?claim a dclass:claim ; dp:status "open" .
  ?claim (dr:filed_from|dr:paid_to|dr:repaired_by)/^(dr:filed_from|dr:paid_to|dr:repaired_by) ?other .
  ?other a dclass:claim ; dp:status "open" .
  FILTER(?claim != ?other)
}
```

Repeat the alternation with `+` to follow the ring through several shared
things. For large networks, page the result with `LIMIT` and `OFFSET`. Keep the
start claim fixed.

**Afterwards.** Store the investigation with the commit it read. A device may
turn up in a new claim later. You can reopen the case, and the earlier network
is still queryable at its own commit.

## What every case records

Each decision above stores the same three things, all as ordinary records:

- **The decision record.** Set its `based_on_commit_seq` to the
  `served_at_seq` of the query response. Store the outcome as a controlled
  value; `allowed_values` enforces the list.
- **A link from the decision to its subject**, with an `evidence` string. The
  evidence stays on the fact. The change log shows when it was added.
- **Nothing overwritten.** Later corrections are new commits. The replay with
  `as_of_commit_seq` returns the rows the agent read. The latest data shows the
  corrected state.

- [Build with JSON records](https://docs.littlebigbrain.com/guides/without-rdf/): The recall case end to end: schema, writes, the chain query, validation, and replay.
- [Replay answers & history](https://docs.littlebigbrain.com/guides/time-travel-audit/): Pin a read to a commit, replay an answer and find when it changed.
- [Reasoning & inference](https://docs.littlebigbrain.com/guides/reasoning/): Subclass, RDFS, and OWL regimes, selected per query.
- [MCP for agents](https://docs.littlebigbrain.com/sdks/mcp/): Give an agent the schema, query, and commit tools these cases use.
