> ## Documentation Index
> Fetch the complete documentation index at: https://docs.uselayerup.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Tool Pattern Library

> The Logic Plane exposes capability only as tools: typed, versioned, idempotent, permissioned, audited, eval-gated functions. Ten patterns cover every capability.

# 09 — Tool pattern library.

The Logic Plane exposes capability to agents and humans only as *tools*: typed,
versioned, idempotent, permissioned, audited, eval-gated functions. There are no
"skills," no "abilities," no "loose-text actions." Every capability fits one of ten
patterns. This section is the contract.

## 9.1  Universal contract

Every tool, regardless of pattern, satisfies the same six contract clauses:

| Clause           | Requirement                                                                                                                                |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| **Typed**        | Inputs and outputs are JSON-Schema-validated against an Ontology-typed signature. Untyped `any` is forbidden.                              |
| **Versioned**    | Semver per signature; breaking signature changes are major bumps. Pinned in agent definitions.                                             |
| **Idempotent**   | Re-invocation with the same arguments and idempotency key yields the same result and does not produce a second side-effect.                |
| **Permissioned** | Declares required scopes, marking-clearances, and purpose tags. Dispatch is gated by the PDP (§16).                                        |
| **Audited**      | Every dispatch produces a typed AuditEvent with caller, args hash, result hash, decision linkage.                                          |
| **Eval-gated**   | Promotion of a new tool version is gated by a contract test pack (golden set of inputs, side-effect probes, idempotency probes) — see §13. |

## 9.2  Side-effect taxonomy

Tools are classified by their effect class. The PDP and the Action Plane treat each class differently.

| Class             | Touches                                  | Reversible?        | Approval default                     |
| ----------------- | ---------------------------------------- | ------------------ | ------------------------------------ |
| **pure**          | Compute only                             | n/a                | none                                 |
| **read-internal** | Layerup objects                          | n/a                | scope check                          |
| **read-external** | SoR / partner reads                      | n/a                | scope + purpose                      |
| **stage**         | Action Plane staging area                | yes                | scope                                |
| **commit-low**    | Internal only (Tasks, Exceptions, notes) | yes (compensation) | scope + policy                       |
| **commit-high**   | External SoR mutations                   | compensation only  | scope + policy + human approval gate |

## 9.3  Pattern catalog

Ten patterns. Together they cover every capability a tenant ever needs to expose. Specific
tools are tenant artefacts; this documentation defines only the patterns.

<Card title="Pattern 1 · Extraction" icon="magnifying-glass">
  **effect: pure**

  Lifts a typed Property out of a source artefact (document, email, structured payload). Produces both the value and the EvidenceSpan that justifies it.

  #### Shape

  `extract<TargetProperty>(source: SourceRef, hints?: Hints) → { value: TargetProperty, evidence: EvidenceSpan, confidence: number }`

  #### Schema skeleton

  ```json theme={null}
  {
    "request":  { "source": { "$ref": "SourceRef" }, "hints": { "type": "object" } },
    "response": {
      "value":      { "$ref": "<TargetProperty>" },
      "evidence":   { "$ref": "EvidenceSpan" },
      "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
      "exceptions": { "type": "array", "items": { "$ref": "ExceptionRef" } }
    }
  }
  ```

  **Side-effects:** none. **Governance:** read-internal scope on the source. **Observability:** emits `tool.extract.dispatch` + `tool.extract.result` spans with model lineage.
</Card>

<Card title="Pattern 2 · Lookup" icon="database">
  **effect: read-external**

  Resolves an identifier to an authoritative record from a system of record or a registry.

  #### Shape

  `lookup<TargetObject>(identifier: string, source: SoRRef, asOf?: datetime) → TargetObject | NotFound`

  **Side-effects:** none. **Governance:** declared SoR scope + purpose tag. Cached per `(identifier, sourceVersion)` for the run; cache invalidated by source-version change.

  **Failure modes:** `not_found`, `source_unavailable`, `permission_denied`, `stale_replica`. Each produces a typed Exception.
</Card>

<Card title="Pattern 3 · Validation" icon="check-circle">
  **effect: pure**

  Runs a candidate value (or candidate Object) against a typed ruleset and returns a verdict plus a rule-trace.

  #### Shape

  `validate(candidate: any, rulePack: RulePackRef, ontologyPin?: string) → { verdict: 'pass'|'warn'|'block', trace: RuleTrace[] }`

  Rule packs are themselves versioned; verdicts are reproducible given `(rulePackVersion, candidate)`. Validation is bit-exact and is the basis for the Verifier (§11).
</Card>

<Card title="Pattern 4 · Classification" icon="tags">
  **effect: pure**

  Maps a typed subject into a typed band: severity, fast-track eligibility, jurisdiction class, risk tier, document type, intent type, etc.

  #### Shape

  `classify<Subject, Band>(subject: Subject, schema: ClassificationSchemaRef) → { band: Band, confidence: number, rationale: string, evidence: EvidenceSpan[] }`

  Classifications must declare an exhaustive band set; out-of-band cases produce an Exception of kind `classify.out_of_distribution` rather than a default band.
</Card>

<Card title="Pattern 5 · Composition" icon="layer-group">
  **effect: pure**

  Assembles a typed draft Object from typed parts plus typed templates. Used to draft Submissions, Quotes, Endorsement requests, loss-notice drafts, correspondence — all *before* any Action Plane staging.

  #### Shape

  `compose<Draft>(parts: PartSet, template: TemplateRef) → Draft`

  Output is always a *draft*: it is never persisted as a live Object. Persistence requires the Action Plane.
</Card>

<Card title="Pattern 6 · Action-staging" icon="arrow-right">
  **effect: stage**

  Translates a typed effect intent into an Action in state `staged`. Issues an idempotency key, attaches the authoring Decision, and enqueues the Action for approval and commit.

  #### Shape

  `stage(action: { kind, targetSor, targetRef?, payload }, idempotencyKey?: string) → Action`

  Re-invocation with the same idempotency key returns the existing Action; never produces a duplicate. Action-staging is the only path from reasoning to commit (§14).
</Card>

<Card title="Pattern 7 · Approval-request" icon="thumbs-up">
  **effect: commit-low**

  Creates a Task addressed to a queue or named principal, requesting human approval for a staged Action or a Decision. Carries the subject, the rationale, the cited evidence, and the SLA.

  #### Shape

  `requestApproval(subject: Ref<Decision|Action>, queue: string, sla?: Duration) → Task`

  Approvals are themselves Decisions (kind `approval.granted` | `approval.denied`) and are linked back to the original Action.
</Card>

<Card title="Pattern 8 · Aggregation" icon="chart-bar">
  **effect: read-internal**

  Computes a typed metric over a window of Objects: portfolio exposure, queue depth, claim frequency, recovery ratio, etc. Used as input to other tools or for surface rendering.

  #### Shape

  `aggregate<Metric>(objects: Ref[], window: Window, op: AggOp) → Metric`

  Aggregations declare and enforce marking propagation: a metric over PII-marked rows is itself PII-marked.
</Card>

<Card title="Pattern 9 · Conversion / Arithmetic" icon="calculator">
  **effect: pure**

  Pure deterministic transforms: currency conversion (with rate-source pin), date arithmetic, unit conversion, hash, tabulation. Bit-exact, replayable, never network-dependent at run time except through resolved-and-pinned rate sources.

  #### Shape

  `convert<In, Out>(value: In, target: TargetSpec) → Out`

  Rate sources used for currency / unit conversion are pinned at run start; replay uses the same pin.
</Card>

<Card title="Pattern 10 · Search / Retrieval" icon="search">
  **effect: read-internal**

  Returns a ranked list of EvidenceSpans matching a query against an indexed corpus. The retrieval snapshot id is recorded; downstream EvidenceSpans back-reference it.

  #### Shape

  `search(query: Query, corpus: CorpusRef, k: int) → { spans: EvidenceSpan[], retrievalSnapshotId: string }`

  Marking propagation: results inherit corpus marking; queries with insufficient clearance are rejected at the PDP, not silently filtered.
</Card>

## 9.4  What is *not* a tool

* Free-text "do whatever" prompts: forbidden.
* Direct database access from agents: forbidden.
* SoR writes outside the Action Plane: forbidden.
* Network access from inside reasoning sandbox: forbidden.
* Holding state across runs in tool memory: forbidden.

## 9.5  Tool registry record

```yaml theme={null}
id:           tool.<namespace>.<name>
version:      <semver>
pattern:      extraction | lookup | validation | classification |
              composition | action-staging | approval-request |
              aggregation | conversion | search
ontologyPin:  <ontology-version>
effectClass:  pure | read-internal | read-external |
              stage | commit-low | commit-high
scopes:       [tool.<name>.invoke, ...]
markings:     [allowed: pii.medium, regulated.kvkk, ...]
purposes:     [underwriting.review, claims.adjustment, ...]
signature:    <json-schema-ref for request and response>
idempotency:  { key: derive(args), ttl: PT24H }
sla:          { p50: 200ms, p99: 1.5s }
evalPack:     pack.tool.<name>.<semver>
release:      { gate: passed, drift: ok, deprecation: null }
```

## 9.6  Per-tool observability

Every dispatch emits the following spans and metrics (see §18):

* `tool.<name>.dispatch` — caller, scopes, args hash, idempotency key, PDP verdict.
* `tool.<name>.run` — duration, retry count, downstream span links.
* `tool.<name>.result` — outcome, result hash, exceptions emitted.
* Metrics: `throughput · success_ratio · p50 · p99 · error_class_distribution · cost_per_call`.
