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

# The shared substrate

> The common agent contracts, plus the lane-specific database and persistence boundaries they do not all share.

# The shared substrate

This package is a catalogue of reusable contracts, not a promise that every agent imports every module.
Typewriter deliberately imports no database channel, while Auditor and Accountant use their separately proven read-only connection instead of the ordinary pool.

Five agents, one set of shared components.

The rule behind it: **anything two agents must agree about lives in exactly one place.**
Two copies of the document registry, or of the identity comparison, or of the validation rules, is two agents that agree until they do not, and the day they diverge nothing fails - the system just starts giving two answers.

## What is in it

| Module                                            | What it owns                                                                                                                                                         |
| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `kb.py`, `sop_index.py`                           | the knowledge base: the 146-record document registry, the in-process Git-rendered SOP index, the master-data reader, the GL and chart reader, the JSON Schema loader |
| `model.py`                                        | the keyless Claude Agent SDK path, schema-driven, shared by the Clerk's extractor and the Typewriter's proposer                                                      |
| `checks.py`                                       | shape and semantic validation. It **flags, never fixes**                                                                                                             |
| `provenance.py`                                   | the flag shape every agent produces, so a finding drops into the review inbox unchanged                                                                              |
| `sod.py`                                          | [separation of duties](/greatbook/capabilities/maker-checker), pure and dependency-free                                                                              |
| `db.py`                                           | the shared connection pool                                                                                                                                           |
| `checkpointer.py`                                 | the Postgres checkpointer that makes a paused run survive a restart                                                                                                  |
| `action_required.py`                              | the deterministic gate deciding whether a turn warrants a durable task                                                                                               |
| `tasks.py`                                        | the Audit desk's human-action worklist                                                                                                                               |
| `tools.py`                                        | the boxed tool surface an agent's model may call                                                                                                                     |
| `sops.py`, `sop_index.py`, `sop_index_release.py` | the [SOP corpus](/greatbook/agents/sops), deterministic retrieval and release verification                                                                           |
| `doc_registry.json`, `gen_doc_registry.py`        | the [document registry](/greatbook/capabilities/document-registry) and its generator                                                                                 |

## Four pieces worth their own explanation

### `checks.py` flags, it never fixes

The validation layer reports what is wrong with an extracted record.
It does not correct it.

That is the governance boundary in one sentence.
An agent that silently repairs a value has made an accounting decision nobody reviewed, and the flag that would have told a human about it is gone.

So a shape failure or a semantic failure becomes a **flag on the record**, the record goes to review as `FLAGGED`, and a person decides.

### `model.py` is the one model path

Both the Clerk's extractor and the Typewriter's proposer go through it.

The Typewriter's graph deliberately reuses the Clerk's extractor protocol rather than introducing a second model path with its own authentication, its own cost and its own thing to secure.

Model access is **keyless**: the SDK path shells out to the local CLI with an OAuth token rather than carrying an API key.
That has one consequence worth knowing, which is [recorded on the tracing page](/greatbook/agents/tracing): the tracer sees node spans but not token counts.

### `checkpointer.py` is what makes a gate durable

A paused run is a row in Postgres, not an object in memory.

So a container restart does not lose a document waiting at the posting gate, and a resume restores the checkpoint rather than re-running the expensive pipeline from scratch.

<Warning>
  Use the **session-mode** database DSN (port 5432), not the transaction pooler (6543).
  Both the checkpoint saver and the GL's advisory lock need a stable session.
  With the pooler it works, then intermittently does not, in a way that looks like a model problem.
</Warning>

### `action_required.py` decides what earns a task

Not every message an agent receives is work.

The human worklist at **Audit → Actions** is an operator's to-do list, so a row must be created for real work only.
The top-level **Actions** run ledger has a separate completeness rule and retains failed and legitimate no-change runs.
Otherwise the tab fills with noise and stops meaning anything.

The rules, in the order they fire:

1. an **attachment** is always an action - handing the Clerk a document *is* the request to process it;
2. empty text is never an action;
3. a polite wrapper ("please...", "can you...") is stripped, then the remainder is judged as an imperative;
4. an **informational question** is never an action, even when it names a document. "How do I process an invoice?" asks for the procedure; it does not hand over an invoice;
5. an **imperative work verb** aimed at a finance artifact or a demonstrative is an action;
6. everything else is conversation.

Rule 4 before rule 5 is the whole point.
**Ambiguity resolves to "no task".**
A user whose genuine request is misread as chat gets an answer and can restate it; a user whose greeting mints a task loses trust in the tab.

The gate runs at the **write** in the graph, so the read endpoint is a plain read with no "is this noise?" filtering to get wrong later.

## Design rules the substrate encodes

**Never pass raw text between agent steps.**
Nodes exchange validated typed structures.
The model decides *when* to act; deterministic code controls *how* the act executes.

**Only the model-facing nodes are non-deterministic.**
In the Clerk, only `classify` and `extract` use the model.
Everything else - registry loading, master resolution, validation, routing, queueing - is deterministic, so a weak proposal cannot reach the queue marked clean.

**Retries are typed and bounded.**
Only transient faults are retried: network, timeout, 5xx, rate limit.
Never a permanent shape error, which would just fail again more slowly.

<Note>
  **One runtime gotcha that costs an afternoon.**
  Under the development runtime's blocking detector, any `async def` node doing blocking I/O aborts the run.
  Sync nodes are threadpooled and fine, but the model-facing and knowledge-base-facing nodes are async, so their blocking calls are wrapped in a thread.
  The production runtime has no such detector, but the event loop still stalls on blocking I/O, so the wrapping is right either way.
</Note>

## Where it is enforced

All of it lives in `langgraph_chat/agents/common/`.

The guard against a substrate regression is `agents/tests/test_integration.py`, which loads the **real** registry, builds the dependencies and compiles the graph.
Graph-logic tests use a deterministic stub instead, so a logic test never depends on a model call.

## Related

* [The agent org](/greatbook/agents/index) - the five agents that import this
* [The SOP store](/greatbook/agents/sops) - the knowledge half
* [Guardrails and refusals](/greatbook/agents/guardrails) - the scope gates that sit on top
* [The 146-document registry](/greatbook/capabilities/document-registry) - the knowledge base's largest asset
