Why did we open-source our inference engine? Read the post
← All Posts

Ten model calls per contract review, zero external APIs

Ten model calls per contract review, zero external APIs

This article walks through contract-review-agent, a workable example from the open-source SIE repo on GitHub: a multi-agent contract reviewer built on the OpenAI Agents SDK, with every model call served locally. SIE is Superlinked’s self-hosted inference engine, one cluster that serves embedding, reranking, OCR, vision, entity-extraction, and generation models behind three primitives (extract, encode, score). The example is a complete project you can clone and run against real SEC-filed contracts. Built by Superlinked.

Count the model calls in a serious contract review agent. Triage to decide what kind of document arrived. Vision to read the signature page. OCR for the scanned exhibit. Embeddings to find relevant clauses, a reranker to order them, entity extraction to pull parties and dates, text-to-SQL to check the obligations database, a reasoning model to assess clause risk, an orchestrator to run the whole show, and a safety guardrail watching everything.

That’s ten. In most stacks, that’s also four or five vendor accounts, a pile of API keys, per-token bills arriving from companies that now hold fragments of your contracts, and four status pages to watch during an outage.

The contract-review-agent example in the SIE repo makes a different bet: every one of those ten calls is served by one SIE cluster through native APIs (local by default; SIE_CLUSTER_URL can point at a managed cluster). The agent framework is the OpenAI Agents SDK, but there’s no OpenAI API anywhere in the request path.

The two-agent split

The design decision worth stealing here is the separation of investigation from synthesis.

An Investigator agent (Qwen/Qwen3.6-27B with a 64K context window) does the actual work through seven tools. It classifies the document, reads the signature page with a vision model, runs OCR, searches clauses via embeddings and reranking, extracts entities, and queries an SQLite obligations database through text-to-SQL. The critical property: it can only assert facts it gathered through tool calls. No tool call, no claim.

A separate Synthesizer agent takes the Investigator’s findings and formats them into a strict ContractReview JSON schema. Splitting the roles prevents the failure mode where a model starts emitting the output schema halfway through gathering evidence and fills the gaps with plausible fiction. Investigation and formatting are different jobs; the example treats them as different agents.

The model catalog

Each role maps to a model sized for the task, all listed in config.yaml:

Qwen3.5-4B handles triage, vision, clause-risk reasoning, and text-to-SQL. LightOnOCR-2-1B does OCR. BAAI/bge-m3 provides dense embeddings; Qwen3-Reranker-4B reorders retrieved clauses. GLiNER large-v2.1 extracts entities without training, and ibm-granite/granite-guardian-3.0-2b runs as the safety guardrail. The 27B orchestrator wants an H100 or RTX PRO 6000; the 4B models run on far less.

Swapping any of these is a config edit, not a code change. And if a model is unavailable, the run degrades gracefully: the ledger records what was skipped instead of the whole review failing.

The sizing logic rewards attention. Nobody needs 27B parameters to decide whether a document is an NDA or a supply agreement; a 4B model triages in a fraction of the time and cost. Meanwhile the orchestrator, the one model that has to plan across all seven tools and a 64K context, gets the big weights. Right-sizing per role is the cost story most single-model architectures never get to tell.

Binding the Agents SDK to the cluster takes one adapter:

Agent(
name="Risk Analyst",
model=SIENativeModel(
"Qwen/Qwen3.5-4B",
sie_client,
provision_timeout_s=900,
),
)

That SIENativeModel wraps SIEAsyncClient.generate and builds strict JSON schemas for constrained generation, so the Agents SDK works exactly as documented while every token is produced on your own GPUs.

Guardrails that are actually guardrails

Two constraints in the example deserve mention because they’re the kind of thing production teams add after an incident, and this repo has them on day one. Text-to-SQL is SELECT-only; the agent can query the obligations database but structurally cannot write to it. And no generated code executes, ever. No Python sandboxes, no shell. The agent’s power is bounded by its seven tools, and the tools are bounded by design.

Meanwhile the observability layer captures per-model latency, data volume, and throughput, so you can see which of the ten models is your bottleneck rather than guessing.

Real contracts, one command away

The default corpus is CUAD: 510 real commercial contracts from SEC filings, licensed CC BY 4.0. A fetch script pulls the ~18MB archive, parses it, seeds the SQLite obligations database, and renders a page image so the vision and OCR paths have something real to chew on.

docker run -d --gpus all -p 8080:8080 \
-v sie-hf-cache:/app/.cache/huggingface \
ghcr.io/superlinked/sie-server:latest-cuda12-default
cd examples/contract-review-agent && uv sync --frozen
uv run fetch-contracts
uv run review

No GPU handy for the corpus fetch? uv run make-sample generates synthetic contracts offline.

Why this matters beyond contracts

Contract review is the demo, but the pattern is the product: one cluster, one client, many specialized models, each doing the job it’s actually good at. The alternative (one giant general model for everything, or a spiderweb of vendor APIs) costs more and tells you less about where your latency and errors live.

If your organization has documents it can’t send to third parties, this example is the closest thing to a working blueprint you’ll find. Clone it, point it at the CUAD corpus, and read the review it produces. Then read the ledger and see all ten models that produced it.

Try it on GitHub: superlinked/sie/examples/contract-review-agent

Open source inference for agents

Open-source inference for the models behind your agents. Run it yourself, or let us run it for you.

Github 2.7K

Contact us

Tell us about your use case and we'll get back to you shortly.

Apply for an inference grant

Free capacity on our hosted cluster for selected projects. Tell us what you run and we reply by email.